Java匿名类唯一标识
假设我想使用使用匿名类的命令模式。在调用程序中,我要应用缓存。大概是这样的:Java匿名类唯一标识,java,oop,design-patterns,reflection,Java,Oop,Design Patterns,Reflection,假设我想使用使用匿名类的命令模式。在调用程序中,我要应用缓存。大概是这样的: // command abstract class public static abstract class ViewScopeCacheCommand<T> { public abstract T invoke(); } // innvoker public static class ViewScopeCache<T> { // cache private Map&
// command abstract class
public static abstract class ViewScopeCacheCommand<T> {
public abstract T invoke();
}
// innvoker
public static class ViewScopeCache<T> {
// cache
private Map<String,T> pageCache = null;
public ViewScopeCache() {
pageCache = new HashMap<String,T>();
}
// get from cache
public T get(String key) {
return pageCache.get(key);
}
// put to cache
public void put(String key, T t) {
pageCache.put(key, t);
}
// I want to say how to load the result of not in cache - given by command
public T getLazy(String key, ViewScopeCacheCommand<T> command) {
if(get(key) == null) {
T t = command.invoke();
pageCache.put(key, t);
}
return get(key);
}
public void invalidate() {
pageCache.clear();
}
// I want to identify the cache by command
/*
public T getLazy(ViewScopeCacheCommand<T> command) {
String magicKey = .. derive from command
if(get(key) == null) {
T t = command.invoke();
pageCache.put(key, t);
}
return get(key);
}
*/
}
//命令抽象类
公共静态抽象类ViewScopeCacheCommand{
公共摘要T invoke();
}
//innvoker
公共静态类ViewScopeCache{
//缓存
私有映射pageCache=null;
公共ViewScopeCache(){
pageCache=newHashMap();
}
//从缓存中获取
公共T获取(字符串键){
返回pageCache.get(key);
}
//缓存
公共void put(字符串键,T){
pageCache.put(key,t);
}
//我想说的是如何加载不在缓存中的结果-由命令给出
public T getLazy(字符串键,ViewScopeCacheCommand){
if(get(key)==null){
T=command.invoke();
pageCache.put(key,t);
}
返回get(键);
}
公共无效{
pageCache.clear();
}
//我想通过命令识别缓存
/*
public T getLazy(ViewScopeCacheCommand命令){
字符串magicKey=…从命令派生
if(get(key)==null){
T=command.invoke();
pageCache.put(key,t);
}
返回get(键);
}
*/
}
假设我有两个点使用这个:
..
Result getResult1() {
viewScopeCache.get("key1", new ViewScopeCacheCommand<Result>() {
..invoke(){ call DB SQLX }}); // does not need to be SQL, can be a service A call
}
..
Result getResult2() {
viewScopeCache.get("key2", new ViewScopeCacheCommand<Result>() {
..invoke(){ call DB SQLY}}); // does not need to be SQL, can be a service B call
}
..
。。
结果getResult1(){
获取(“key1”,新的ViewScopeCacheCommand(){
..invoke(){call DB SQLX}});//不需要是SQL,可以是服务调用
}
..
结果getResult2(){
获取(“key2”,新的ViewScopeCacheCommand(){
..invoke(){call DB SQLY}});//不需要是SQL,可以是服务B调用
}
..
好的,这项工作可以完成,但是我可以识别匿名ViewScopeCache命令吗?因此,使用将简化为
..
Result getResult1() {
viewScopeCache.get(new ViewScopeCacheCommand<Result>() {
..invoke(){ call DB SQLX }}); // does not need to be SQL, can be a service A call
}
..
Result getResult2() {
viewScopeCache.get(new ViewScopeCacheCommand<Result>() {
..invoke(){ call DB SQLY}}); // does not need to be SQL, can be a service B call
}
..
。。
结果getResult1(){
获取(新的ViewScopeCacheCommand(){
..invoke(){call DB SQLX}});//不需要是SQL,可以是服务调用
}
..
结果getResult2(){
获取(新的ViewScopeCacheCommand(){
..invoke(){call DB SQLY}});//不需要是SQL,可以是服务B调用
}
..
如果我做了普通的类扩展,我可以使用instanceof、reflection等。。但是,是否有某种机制可以识别调用SQLX的command1和调用SQLY的command2之间的差异
它可以是基于反射的,也可以是代码行
我脑子里唯一的想法是注释:(…但那是站不住脚的.)
有更好的主意/建议吗?
问题是:我能否推断出在类级别上唯一的键来标识特定命令
我可以在命令{abstract String getUniqueKey(){}}中添加第二个方法,并强制对其进行定义..但这很难看:)抽象类可以有匿名类可以调用的构造函数:
public static abstract class ViewScopeCacheCommand<T> {
private final String uniqueKey;
public ViewScopeCacheCommand(String uniqueKey) {
this.uniqueKey= uniqueKey;
}
public String getUniqueKey() {
return uniqueKey;
}
public abstract T invoke();
}
公共静态抽象类ViewScopeCacheCommand{
私有最终字符串唯一密钥;
公共ViewScopeCacheCommand(字符串uniqueKey){
this.uniqueKey=uniqueKey;
}
公共字符串getUniqueKey(){
返回唯一键;
}
公共摘要T invoke();
}
用法如下:
..
Result getResult1() {
viewScopeCache.get(new ViewScopeCacheCommand<Result>("key1") {
..invoke(){ call DB SQLX }}); // does not need to be SQL, can be a service A call
}
..
Result getResult2() {
viewScopeCache.get(new ViewScopeCacheCommand<Result>("key2") {
..invoke(){ call DB SQLY}}); // does not need to be SQL, can be a service B call
}
..
。。
结果getResult1(){
获取(新的ViewScopeCacheCommand(“key1”){
..invoke(){call DB SQLX}});//不需要是SQL,可以是服务调用
}
..
结果getResult2(){
获取(新的ViewScopeCacheCommand(“key2”){
..invoke(){call DB SQLY}});//不需要是SQL,可以是服务B调用
}
..
Oliver Charlesworth在评论中建议:
匿名类在JVM级别上并不是真正的匿名类。它仍然有一个与之关联的唯一类实例 他是正确的,内部(匿名)类在JVM级别上具有唯一标识符 以下是我的测试:
public class Demo {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
loop();
}
}
private static void loop() {
test(new TestMe() {
@Override
int getKey() {
return 100;
}
});
test(new TestMe() {
@Override
int getKey() {
return 200;
}
});
}
public abstract static class TestMe {
abstract int getKey();
}
public static void test(TestMe testMe) {
System.out.println(testMe.getClass() + " " + testMe.getKey());
}
}
因此,问题中的代码可以简化为
// command abstract class
public static abstract class ViewScopeCacheCommand<T> {
public abstract T invoke();
}
// innvoker
public static class ViewScopeCache<T> {
// cache
private Map<String,T> pageCache = null;
public ViewScopeCache() {
pageCache = new HashMap<String,T>();
}
// get from cache
public T get(String key) {
return pageCache.get(key);
}
// put to cache
public void put(String key, T t) {
pageCache.put(key, t);
}
/*
// I want to say how to load the result of not in cache - given by command
public T getLazy(String key, ViewScopeCacheCommand<T> command) {
if(get(key) == null) {
T t = command.invoke();
pageCache.put(key, t);
}
return get(key);
}
*/
public void invalidate() {
pageCache.clear();
}
// I want to identify the cache by command
/*** solution ***/
public T getLazy(ViewScopeCacheCommand<T> command) {
String magicKey = command.getClass().toString(); // <--- solution
if(get(key) == null) {
T t = command.invoke();
pageCache.put(key, t);
}
return get(key);
}
}
谢谢大家的讨论和解答。我很困惑。为什么密钥不能决定调用哪个SQL?匿名类在JVM级别上并不是真正的匿名类。它仍然有一个唯一的
类
实例与之关联。但总的来说,这不会有帮助。如果您有Result getResult(final int foo){return cache.get(new Command(){invoke(){return foo+something();}}}}
,其中foo
是一个参数,该怎么办?>\u我很困惑。为什么键不能决定调用哪个SQL?\这可以是一个方法调用或服务调用,我知道我在主体中放了什么参数,这通常我不需要将键与SQL的参数关联起来>一个匿名类在JVM级别上不是真正的匿名类。它仍然有一个与之关联的唯一类实例。第二部分我试图解决的问题是添加参数。例如,我试图找到一种方法来确定调用了哪些命令,例如,第77行的命令和第88行的命令(对应于getResult1/2中的new ViewScopeCacheCommand())是否是要重构的案例的类型T
始终Result
?如果不是,您需要处理多少种不同类型的T
?这看起来不错,但是Java是否允许我进一步从根本上减少制作“Key1”和“Key2”的需要?也许这根本不可能,如果需要反思的话,但我不知道有什么方法可以得到有用的信息。不过,给匿名类一个标识似乎是一个更干净的解决方案。
// command abstract class
public static abstract class ViewScopeCacheCommand<T> {
public abstract T invoke();
}
// innvoker
public static class ViewScopeCache<T> {
// cache
private Map<String,T> pageCache = null;
public ViewScopeCache() {
pageCache = new HashMap<String,T>();
}
// get from cache
public T get(String key) {
return pageCache.get(key);
}
// put to cache
public void put(String key, T t) {
pageCache.put(key, t);
}
/*
// I want to say how to load the result of not in cache - given by command
public T getLazy(String key, ViewScopeCacheCommand<T> command) {
if(get(key) == null) {
T t = command.invoke();
pageCache.put(key, t);
}
return get(key);
}
*/
public void invalidate() {
pageCache.clear();
}
// I want to identify the cache by command
/*** solution ***/
public T getLazy(ViewScopeCacheCommand<T> command) {
String magicKey = command.getClass().toString(); // <--- solution
if(get(key) == null) {
T t = command.invoke();
pageCache.put(key, t);
}
return get(key);
}
}
..
Result getResult1() {
viewScopeCache.get(new ViewScopeCacheCommand<Result>() {
..invoke(){ call anything X }}); // does not need to be SQL, can be a service A call
}
..
Result getResult2() {
viewScopeCache.get(new ViewScopeCacheCommand<Result>() {
..invoke(){ call anything Y}}); // does not need to be SQL, can be a service B call
}
..
Result getResult3() {
if(something empty) {
//fetch it
viewScopeCache.put("key3",..Z..);
}
viewScopeCache.get("key3");
}
..