"Equals"메소드를 우선적으로 수행 : 매개 변수의 유형을 파악하는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/1628718

  •  06-07-2019
  •  | 
  •  

문제

나는 무시하려고합니다 equals 매개 변수화 된 클래스를위한 메소드.

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (!(obj instanceof Tuple))
        return false;

    Tuple<E> other = (Tuple<E>) obj; //unchecked cast
    if (!a0.equals(other.a0) && !a0.equals(other.a1)) {
        return false;
    }
    if (!a1.equals(other.a1) && !a1.equals(other.a0)) {
        return false;
    }

    return true;
}

어떻게 확인할 수 있습니까? <E>other 객체는 동일합니다 this?

도움이 되었습니까?

해결책

참조를 유지함으로써 할 수 있습니다 Class<E> 유형. 그러나 내 생각에 평등 테스트는 콘크리트 유형이 아니라 객체가 표현하는 값에 관한 것입니다..

이것의 전형적인 예는 예를 들어 컬렉션 API입니다. new ArrayList<String>().equals(new LinkedList<Object>()) 보고 true. 이것들은 완전히 다른 유형을 가지고 있지만, 동일한 값, 즉 "빈 컬렉션"을 나타냅니다.

개인적으로 두 가지 Tuple동일한 데이터를 나타내는 s (예 : ("a", "b")) 유형이기 때문에 동일하지 않습니다. Tuple<String> 다른 하나는 Tuple<Object>?

다른 팁

지우기 때문에 당신은 할 수 없습니다. 최선을 다하면 튜플 클래스에 튜플이 "java.lang.class"필드 멤버로 잡을 계획입니다. 그런 다음 해당 필드를 비교하여 튜플 클래스가 동일한 유형을 유지하고 있는지 확인할 수 있습니다.

또한이 스레드를 참조하십시오.C ++ 쌍과 동등한 것은 무엇입니까?u003CL,R> 자바에서?

수업에 대해 더 많이 게시하면 도움이 될 것입니다. 나는 확인되지 않은 캐스트와 당신의 필드 수를 동등하게 생각하고 있다고 생각합니다.u003CE,F> 아니요?

편집 : 다음은 정기적으로 사용하는 유용한 쌍 클래스입니다 (필요한 경우 튜플 클래스를 조정할 수 있음). 참고, 다른 사람들의 제안에 대한 동시이 수업은 포함 된 회원들이 평등 문제를 결정할 수있게합니다. 유스 케이스는 평등이 실제로 포함 된 구성원의 유형을 기반으로하는지 여부를 결정해야합니다.

/**
 * Adapted from http://forums.sun.com/thread.jspa?threadID=5132045
 * 
 * 
 * @author Tim Harsch
 *
 * @param <L>
 * @param <R>
 */
public class Pair<L, R> {

    private final L left;
    private final R right;

    public R getRight() {
        return right;
    } // end getter

    public L getLeft() {
        return left;
    } // end getter

    public Pair(final L left, final R right) {
        this.left = left;
        this.right = right;
    } // end constructor

    public static <A, B> Pair<A, B> create(A left, B right) {
        return new Pair<A, B>(left, right);
    } // end factory method

    @Override
    public final boolean equals(Object o) {
        if (!(o instanceof Pair<?,?>))
            return false;

        final Pair<?, ?> other = (Pair<?, ?>) o;
        return equal(getLeft(), other.getLeft()) && equal(getRight(), other.getRight());
    } // end method

    public static final boolean equal(Object o1, Object o2) {
        if (o1 == null) {
            return o2 == null;
        }
        return o1.equals(o2);
    } // end method

    @Override
    public int hashCode() {
        int hLeft = getLeft() == null ? 0 : getLeft().hashCode();
        int hRight = getRight() == null ? 0 : getRight().hashCode();

        return hLeft + (37 * hRight);
    } // end method

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append('<');
        if( left == null ) {
            sb.append("null");
        } else {
            sb.append(left.toString());
        } // end if
        sb.append(',');
        if( right == null ) {
            sb.append("null");
        } else {
            sb.append(right.toString());
        } // end if
        sb.append('>');
        return sb.toString();
    } // end method
} // end class

나는 방금이 문제를 직접 만났고, 내 파괴적인 경우에 나는 E 형을 알 필요가 없었다.

예를 들어:

public class Example<E> {
    E value;

    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Example<?> other = (Example<?>) obj;
        if (value == null) {
            if (other.value != null)
                return false;
        } else if (!value.equals(other.value))
            return false;
        return true;
    }
}

위의 코드에는 사용으로 인해 확인되지 않은 캐스트가 없습니다. Example<?>. 유형 매개 변수 와일드 카드 '?' 하루를 절약합니다.

슬프게도, 당신은 컴파일 시간에 이것을 할 수 없습니다. 정보가 사라졌습니다. 이것이 바로 결과입니다 삭제를 입력하십시오. 대안은 매개 변수를 a로 저장하는 것입니다 Class 인스턴스, 나중에 찾아보십시오.

부터 제네릭은 컴파일 시간에 지워집니다, 당신은 기본적으로 할 수 없습니다. 런타임에 모든 유형 매개 변수가 사라지고 JVM에 관한 한 모든 측면에서 정확히 동일합니다.

주변에서 일하는 방법은 Class 유형을 나타내는 필드이고 생성자에서 해당 유형의 객체를 만듭니다.

샘플 생성자 :

public class Tuple < E > {

    public Tuple(Class<E> c) {
        //store the class
    }

}

또는 공장을 사용할 수 있습니다.

public static <E> Tuple <E> getTuple(Class<E> type) {
    // Create and return the tuple, 
    // just store that type variable in it 
    // for future use in equals.
}

참조를 유지하기위한 제안 Ea의 유형 Class 물체가 보인다 무능한 (그것은에 대한 많은 무의미한 언급입니다. Class 메모리를 가져 가면) 문제에 대해 무의미합니다.

일반적으로 사실이 아닙니다 Foo<Bar> 그리고Foo<Baz> 불평등해야합니다. 그래서 당신은 필요하지 않습니다 E. 그리고 당신이 쓴 코드에서 당신은 그것을 컴파일 할 필요조차 없습니다. 단순히 캐스트 Tuple<?>, 그것이 당신이 알고있는 전부이기 때문입니다 Tuple 그 시점에서. 여전히 컴파일됩니다.

당신이 지나간 경우 Tuple두 가지 유형의 데이터가있는 S는 다음과 같은 요소가 아닙니다. equals, 그리고 당신의 방법이 돌아올 것입니다 false, 바라는대로. (한 가지 희망 - 이러한 유형 구현에 따라 다릅니다 equals 산리.)

주제 외 - 구현에 따라 튜플 (A0, A1)이 튜플 (A1, A1)과 동일하다는 것을 알고 있습니까? 나는 그것이 당신이 원하는 것이 아니라고 생각합니다 ...

다른 사람들이 말했듯이 주제는 삭제가 불가능하게 만듭니다. 그러나 당신은 당신이 왜 이것을 원하는지 재고해야합니다 - 평등 점검은 런타임에만 발생합니다. 제네릭은 컴파일 타임입니다. 개념적으로, a 변하기 쉬운 일반 매개 변수는 있지만 an 물체 하지 않습니다. 따라서 물체의 평등을 비교할 때 일반 매개 변수는 전혀 중요하지 않습니다. 어쨌든 런타임에 따라 적절한 조치를 취할 수 없습니다.

객체 평등과 일반 매개 변수 공동/콘트라 분산은 두 가지 직교 문제입니다.

위의 의견에 동의합니다. 왜 클래스 E가 동등해야합니까? 그리고 E의 서브 클래스를 어떻게 처리하고 싶습니까?

어쨌든, 여기에 도움이 될 수있는 코드 샘플이 있습니다.

public class Example<T> {

  T t;

  public Example(T t) {
    this.t = t;
  }

  public static void main(String[] args) {
    final String s = "string";
    final Integer i = 1;
    final Number n = 1;

    final Example<String> exampleString = new Example<String>(s);
    final Example<Integer> exampleInteger = new Example<Integer>(i);
    final Example<Number> exampleNumber = new Example<Number>(n);

    System.out.println("exampleString subclass "  + exampleString.t.getClass());
    System.out.println("exmapleIntger subclass " + exampleInteger.t.getClass());
    System.out.println("exmapleNumber subclass " + exampleNumber.t.getClass());
    System.out.println("Integer equals Number = " + 
        exampleInteger.t.equals(exampleNumber.t));
  }
}

T.getClass ()에게 전화하여 T 유형에 대한 클래스 정보를 얻을 수 있습니다 (물론 널이 아니라고 가정하십시오.)

이게 도움이 되길 바란다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top