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");
 }
..