1) 인터넷과 StackOverflow에는 제네릭 및 varargs의 특정 문제에 대한 많은 예가 있습니다. 기본적으로 유형 매개 변수 유형의 가변 개수의 인수가있는 경우입니다.
<T> void foo(T... args);
Java에서 varargs는 컴파일 타임에 간단한 "다시 쓰기"를 수행하는 구문 설탕입니다. type의 varargs 매개 변수는 type X...
의 매개 변수로 변환됩니다 X[]
. 이 varargs 메소드를 호출 할 때마다 컴파일러는 varargs 매개 변수에 포함 된 모든 "변수 인수"를 수집하고 다음과 같은 배열을 작성합니다 new X[] { ...(arguments go here)... }
.
이것은 varargs 유형이 콘크리트와 같은 경우에 효과적 String...
입니다. 와 같은 유형 변수 인 T...
경우 T
해당 호출에 대한 구체적인 유형으로 알려진 경우에도 작동 합니다. 방법은 위의 클래스의 일부 예를 들어 경우 Foo<T>
, 당신은이 Foo<String>
참조, 다음 호출 foo
우리가 알고 있기 때문에 괜찮을 것에 T
인 String
코드에서 그 시점에서.
그러나의 "값" T
이 다른 유형 매개 변수 인 경우에는 작동하지 않습니다 . Java에서는 유형 매개 변수 구성 요소 유형 ( new T[] { ... }
) 의 배열을 작성할 수 없습니다 . 따라서 Java는 대신 new Object[] { ... }
(여기 Object
의 상한이 있습니다 T
. 상한이 다르면 대신 대신 사용됩니다 Object
) 컴파일러 경고를 제공합니다.
그렇다면 무엇을 만드는 new Object[]
대신에 new T[]
무엇이 잘못 되었나요 ? Java의 배열은 런타임에 구성 요소 유형을 알고 있습니다. 따라서 전달 된 배열 객체는 런타임에 잘못된 구성 요소 유형을 갖습니다.
varargs를 가장 일반적으로 사용하는 경우 요소를 반복하기 만하면 문제가되지 않으므로 (배열의 런타임 유형에 신경 쓰지 않아도 됨) 안전합니다.
@SafeVarargs
final <T> void foo(T... args) {
for (T x : args) {
// do stuff with x
}
}
그러나 전달 된 배열의 런타임 구성 요소 유형에 의존하는 것은 안전하지 않습니다. 안전하지 않고 충돌하는 간단한 예는 다음과 같습니다.
class UnSafeVarargs
{
static <T> T[] asArray(T... args) {
return args;
}
static <T> T[] arrayOfTwo(T a, T b) {
return asArray(a, b);
}
public static void main(String[] args) {
String[] bar = arrayOfTwo("hi", "mom");
}
}
문제는 여기에 우리의 유형에 따라 달라집니다 것입니다 args
될 수 T[]
로 복귀하기 위해 T[]
. 그러나 실제로 런타임에 인수의 유형은의 인스턴스가 아닙니다 T[]
.
3) 메소드에 type 인수가있는 경우 T...
(여기서 T는 모든 유형 매개 변수 임)
- 안전 : 메소드가 배열의 요소가 인스턴스라는 사실에만 의존하는 경우
T
- 안전하지 않은 경우 : 어레이가 인스턴스라는 사실에 의존하는 경우
T[]
어레이의 런타임 타입에 의존하는 상황이 포함 형으로 리턴 T[]
형의 매개 인자로 전달 T[]
이용 어레이 형 점점 .getClass()
처럼 배열의 실행 종류에 따라 메소드에 전달 List.toArray()
하고 Arrays.copyOf()
등
2) 위에서 언급 한 구별이 너무 복잡하여 자동으로 쉽게 구별 할 수 없습니다.