메소드는 다른 유형의 메소드와 동일한 지우기를 갖습니다.
같은 클래스에서 두 가지 방법을 사용하는 것이 왜 합법적이지 않습니까?
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>
실제로으로 처리됩니다 Set
JVM을에서. 집합의 유형을 선택하면 (문자열 또는 정수) 컴파일러에서 사용하는 구문 설탕 일뿐입니다. 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
'Programming' 카테고리의 다른 글
SQL Server에서 행을 열로 효율적으로 변환 (0) | 2020.03.01 |
---|---|
Apache ZooKeeper 설명 (0) | 2020.02.29 |
요청에 필수 매개 변수가없는 경우 어떤 HTTP 상태 응답 코드를 사용해야합니까? (0) | 2020.02.29 |
ASP.NET 웹 API에서 오류를 반환하는 모범 사례 (0) | 2020.02.29 |
express.js에서 HTTPS 사용 (0) | 2020.02.29 |