2011-11-17 2 views
1

자바 리플렉션을 사용하여 놀고 있었고 다른 클래스에서 선언 된 메서드에서 메커니즘 캐싱 메서드를 만들고 싶습니다. 임의의 동작을 방지하기 위해 캐시에 동일한 서명이있는 메서드를로드하는 것을 금지하고 싶습니다 (다른 클래스에 선언 된 메서드는 동일한 서명을 가질 수 있습니다).Set의 contains() 메서드를 재정의해도 되나요?

이 작업을 수행하는 유일한 방법은 메서드를 캐시하는 집합의 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 : 나는 어떤 요구 조건도 가지고 있지 않습니다. 나는 단지 놀고 있습니다. 그러나 나에게 이상하지 않은 것처럼 보입니다. 웹 서버에서 메소드를 실행해야하는 웹 서블릿이 있다면 어떨까요? 코드 가독성을 높이기 위해 다른 클래스의 실행 가능 메소드를 선언 할 수 있기를 원할 것입니다. 클라이언트가 메소드를 선언 한 위치에 대해 걱정할 필요가 없다고 확신 할 수 있습니다. – nbarraille

답변

2

은 단순히 캐시 키에 대해 다음의 조합을 사용 :

클래스 이름 + 메소드 이름 + 메소드 매개 변수이 무시할 완전히 괜찮

+0

그건 내 문제를 해결하지 못합니다. 메소드가 선언 된 클래스를 모른 채 메소드를 호출 할 수있게하려면 어떻게해야합니까? – nbarraille

+1

다음 메소드 이름 + 메서드 매개 변수 형식을 사용하십시오 – soulcheck

+0

@ 체크 첵 감사합니다 – nbarraille

1

유형 "포함()"방법 - 그러나, 그것을 일반적으로 불필요합니다. contains() 메서드의 목적은 단순히 컬렉션에있는 해당 객체가 이미 있는지 확인하는 것입니다.

특정 개체 컬렉션에 대한 "같음"방법이이를 확인하는 데 사용됩니다.

그러나 객체에 포함 할 수없는 contains에 대한 사용자 정의 동작을 원한다면 contains() 메소드를 해킹하는 것이 좋습니다. 내 생각에, 자바 메소드를 캐시하려고한다는 사실을 감안할 때 이러한 메소드를 포함하는 세트에 "포함하는"논리를 붙이기를 원할 수있다.

0

나는 위의 게시물 (@ jayunit100)에 동의합니다. 그러나, 나는 이것을 위해 contains()를 재정의 (override)하지 않을 것이다. 대신 Comparator의 구현을 작성하고 SortedSet을 사용합니다. 예 :

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

나는 Comparator가 내장 속성을 기반으로 요소를 비교하도록 설계된 것 같아요. 삽입 시간은 본질적인 속성이 아닙니다. 그러므로, 불변의 a.compareTo (b)> 0은 b.compareTo (a) <0'와 동등하지 않고 삽입 순서를 존중하는 Comparator를 구축하는 것이 가능하다고 생각하지 않습니다. 그래서 항상 '1'을 반환하는 비교기가 작동 할지라도, 나는 그것이 바람직하다고 생각하지 않는다. – nbarraille

+0

'Comparable'과 혼동스러워하고 있다고 생각합니다. 'Comparable'은 당연히 주문한 객체 (즉, 내장 순서)에 사용되는 반면, 'Comparator'는 (일반적으로) 일부 비 자연 순서를 적용하는 데 사용됩니다. 문제의 핵심은 두 개의 '방법'을 비교하고 그 두 가지가 동등한 것입니다. 이를 위해'contains()'를 오버라이드하지 않고'Comparator'를 사용합니다. – Muel

+0

죄송합니다. 다른 문제에 대해 이야기하고있었습니다. 하지만 내 요점은 여전히 ​​유효합니다.두 개의 객체가 같음 (여기서는 같음)으로 간주되지 않는 경우 0을 반환하는 Comparator를 만드는 것은 'equals와 일치하지 않습니다.'라고 말합니다. 여기에 설명 된 것처럼 Set이 이상하게 동작하게하므로 권장하지 않습니다. http : //download.oracle.com/javase/6/docs/api/java/util/Comparator.html – nbarraille

관련 문제