2011-11-17 117 views
1

我在玩Java反射,并且想从不同类中声明的方法创建方法缓存机制。为了防止随机行为,我想禁止加载具有相同签名的方法到Cache(在不同类中声明的方法可以具有相同的签名)。重写Set的contains()方法可以吗?

我发现这样做的唯一方法是重写集缓存方法的Set的contains()方法。

这样做有危险吗?你有什么更好的主意来实现这一目标?

private final Set<Method> methodsCache; 

public MyMethodCachingClass(Set<Class<?>> classes) { 
    methodsCache = new HashSet<Method>(){ 
     private static final long serialVersionUID = -1467698582662452923L; 

     /** 
     * Overwriting the contains method of this Set so that we don't allow multiple methods with the same signature, 
     * even if they are declared in different classes. 
     */ 
     @Override 
     public boolean contains(Object o) { 
      if (!(o instanceof Method)) { 
       return false; 
      } 

      Method method = (Method) o; 
      for (Method m : this) { 
       if (method.getName().equals(m.getName()) && method.getParameterTypes().equals(m.getParameterTypes())) { 
        return true; 
       } 
      } 
      return false; 
     } 

    }; 

    for (Class<?> c : classes) { 
     for (Method m : c.getDeclaredMethods()) { 
      if (methodsCache.contains(m)) { 
       throw new IllegalArgumentException("The method " + m.getName() + " exists with the same signature in two different classes."); 
      } 
      methodsCache.add(m); 
     } 
    } 
} 

谢谢!

+0

您真的只想缓存方法的一个版本,无论它声明的类是什么?这似乎是一个奇怪的要求... – ig0774

+0

@ ig0774:我没有任何要求,我只是在玩耍。但对我来说这似乎并不奇怪,如果你有一个web servlet应该在你的web服务器上执行一个方法呢?您可能希望能够在不同类中声明可执行方法以提高代码的可读性,并且您当然不希望客户不必担心您声明方法的位置...... – nbarraille

回答

2

只需使用您的缓存键以下组合:

类名+方法名+方法的参数类型

+0

这并不能解决我的问题。如果我想能够在不知道哪个类被声明的情况下调用某个方法,该怎么办? – nbarraille

+1

然后您只使用方法名称+方法参数类型 – soulcheck

+0

@soulcheck谢谢 – nbarraille

1

这是完全没关系覆盖“包括()”方法 - 然而,通常是不必要的。 contains()方法的目的仅仅是检查集合中是否存在相同的对象。

您的特定对象集合的“equals”方法将用于确定这一点。

但是,如果您希望包含哪些不能嵌入对象的自定义行为,则可能有必要破解contains()方法。我认为,鉴于你试图缓存Java方法,你可能想将“包含”逻辑粘贴到包含这些方法的集合中....但是,它并不完全清楚。

0

我同意上面的帖子(@ jayunit100)。不过,我不会为此重写contains()。相反,我会编写比较器的实现并使用SortedSet。例如:

SortedSet<Method> cachedMethods = new TreeSet<Method>(new Comparator<Method>() { 
    // compare() implementation omitted 
}); 
+0

我认为比较器是用来比较基于它们的内在属性的元素。插入时间不是内在属性。因此,我不认为有可能构建一个比较器,该比较器在不破坏不变的情况下尊重插入顺序。a.compareTo(b)> 0等同于b.compareTo(a)<0>。所以,即使总是返回'1'的比较器可能工作,我也不认为这是可取的。 – nbarraille

+0

我觉得你对“Comparable”感到困惑。 “Comparable”用于_naturally ordered_(即内部顺序)的对象,而“Comparator”(通常)用于应用某些非自然顺序。 你问题的症结在于你想要比较两个'Method'并且说它们是等价的。为此,我会使用'Comparator'而不是重写'contains()'。 – Muel

+0

对不起,我正在谈论一个不同的问题,我的不好。但我的观点仍然有效。创建一个比较器,如果两个对象不被认为是等于(这将是这种情况),则返回0,这被称为“与equals不一致”,并且不推荐这样做,因为它会使Set的行为奇怪,如下所述:http ://download.oracle.com/javase/6/docs/api/java/util/Comparator.html – nbarraille

相关问题