Programming

메소드는 다른 유형의 메소드와 동일한 지우기를 갖습니다.

procodes 2020. 2. 29. 15:38
반응형

메소드는 다른 유형의 메소드와 동일한 지우기를 갖습니다.


같은 클래스에서 두 가지 방법을 사용하는 것이 왜 합법적이지 않습니까?

class Test{
   void add(Set<Integer> ii){}
   void add(Set<String> ss){}
}

나는 compilation error

메소드 add (Set)는 Test 유형의 다른 메소드와 동일한 삭제 add (Set)를 갖습니다.

나는 그것을 해결할 수 있지만 javac가 왜 이것을 좋아하지 않는지 궁금했다.

많은 경우에,이 두 가지 방법의 논리는 매우 유사하고 단일로 대체 될 수 있음을 알 수 있습니다

public void add(Set<?> set){}

방법이지만 항상 그런 것은 아닙니다.

constructors인수를 취하는 두 개의 인수를 원한다면이 중 하나의 이름 만 변경할 수 없기 때문에 이것은 더욱 성가신 일입니다 constructors.


이 규칙은 여전히 ​​원시 유형을 사용하는 레거시 코드에서 충돌을 피하기위한 것입니다.

다음 은 JLS에서 가져온 것이 허용되지 않는 이유를 보여줍니다 . 제네릭이 Java에 도입되기 전에 다음과 같은 코드를 작성했다고 가정 해보십시오.

class CollectionConverter {
  List toList(Collection c) {...}
}

다음과 같이 내 수업을 확장하십시오.

class Overrider extends CollectionConverter{
  List toList(Collection c) {...}
}

제네릭을 도입 한 후 라이브러리를 업데이트하기로 결정했습니다.

class CollectionConverter {
  <T> List<T> toList(Collection<T> c) {...}
}

업데이트 할 준비가되지 않았으므로 Overrider수업을 내버려 두십시오 . toList()방법 을 올바르게 재정의하기 위해 언어 디자이너는 원시 유형이 생성 된 유형과 "재정의"한다고 결정했습니다. 즉, 메소드 서명이 더 이상 공식적으로 내 슈퍼 클래스의 서명과 같지 않지만 메소드는 여전히 재정의됩니다.

이제 시간이 흐르면서 수업을 업데이트 할 준비가되었습니다. 그러나 약간 망쳐 놓고 기존의 원시 toList()메소드 를 편집하는 대신 다음과 같은 새로운 메소드 추가 하십시오.

class Overrider extends CollectionConverter {
  @Override
  List toList(Collection c) {...}
  @Override
  <T> List<T> toList(Collection<T> c) {...}
}

원시 유형의 재정의 동등성으로 인해 두 메소드 모두 메소드를 대체 할 수있는 올바른 형식 toList(Collection<T>)입니다. 물론 컴파일러는 단일 방법을 해결해야합니다. 이러한 모호성을 제거하기 위해 클래스는 재정의와 동등한 여러 메소드, 즉 삭제 후 동일한 매개 변수 유형을 가진 여러 메소드를 가질 수 없습니다.

핵심은 이것이 원시 유형을 사용하여 이전 코드와의 호환성을 유지하도록 설계된 언어 규칙이라는 것입니다. 타입 파라미터의 소거에 의해 요구되는 제한은 아니다; 메서드 확인시 컴파일시 발생하기 때문에 메서드 식별자에 일반 형식을 추가하면 충분합니다.


Java 제네릭은 형식 지우기를 사용합니다. 꺾쇠 괄호 ( <Integer><String>) 의 비트 가 제거되므로 동일한 서명 ( add(Set)오류에 표시되는) 이있는 두 가지 방법으로 끝납니다 . 런타임은 각 경우에 사용할 것을 알 수 없기 때문에 허용되지 않습니다.

Java가 제네릭 제네릭을 얻는다면 이것을 할 수는 있지만 아마도 지금은 아닐 것입니다.


Java Generics가 Type Erasure 로 구현 되었기 때문 입니다.

컴파일 타임에 메소드는 다음과 같이 변환됩니다.

메서드 확인은 컴파일 타임에 발생하며 형식 매개 변수를 고려하지 않습니다. ( 에릭슨의 답변 참조 )

void add(Set ii);
void add(Set ss);

두 메소드 모두 유형 매개 변수없이 동일한 서명을 가지므로 오류가 발생합니다.


문제는이다 Set<Integer>Set<String>실제로으로 처리됩니다 SetJVM을에서. 집합의 유형을 선택하면 (문자열 또는 정수) 컴파일러에서 사용하는 구문 설탕 일뿐입니다. JVM은 구별 할 수 없습니다 Set<String>Set<Integer>.


다음과 같은 유형없이 단일 메소드를 정의하십시오. void add(Set ii){}

선택에 따라 메소드를 호출하는 동안 유형을 언급 할 수 있습니다. 모든 유형의 세트에서 작동합니다.


컴파일러가 Java 바이트 코드에서 Set (Integer)를 Set (Object)로 변환 할 수 있습니다. 이 경우 Set (Integer)은 구문 검사를 위해 컴파일 단계에서만 사용됩니다.

참고 : https://stackoverflow.com/questions/1998544/method-has-the-same-erasure-as-another-method-in-type



반응형