"A generic array of T is created for a vararargs parameter" 컴파일러 경고를 해결할 수 있습니까?
이것은 문제의 코드를 간략화한 버전입니다.어떤 범용 클래스는 범용 타입 파라미터가 있는 다른 클래스를 사용하며 범용 타입 중 하나를 vararargs 파라미터가 있는 메서드에 전달해야 합니다.
class Assembler<X, Y> {
void assemble(X container, Y... args) { ... }
}
class Component<T> {
void useAssembler(T something) {
Assembler<String, T> assembler = new Assembler<String, T>();
//generates warning:
// Type safety : A generic array of T is
// created for a varargs parameter
assembler.assemble("hello", something);
}
}
이 경고를 받지 않고 범용 파라미터를 varargs 메서드에 전달할 수 있는 올바른 방법이 있습니까?
물론 뭐랄까...
assembler.assemble("hello", new T[] { something });
범용 배열을 생성할 수 없기 때문에 작동하지 않습니다.
6에서는 6을 추가하는 것 @SuppressWarnings("unchecked")
하지 않습니다
이 버그 리포트에는 더 많은 정보가 포함되어 있습니다만, 그 이유는 컴파일러가 범용 타입의 배열을 좋아하지 않기 때문입니다.
Java 7에서는 메서드 선언에 @SafeVarargs 주석을 붙입니다.
fluent 타입의 인터페이스를 원하신다면 빌더 패턴을 사용해 보세요.varargs만큼 간결하지는 않지만 type safe입니다.
정적 범용형 방식은 빌더를 사용할 때 보일러 플레이트의 일부를 제거하는 동시에 타입의 안전성을 유지할 수 있습니다.
건축업자
public class ArgBuilder<T> implements Iterable<T> {
private final List<T> args = new ArrayList<T>();
public ArgBuilder<T> and(T arg) {
args.add(arg);
return this;
}
@Override
public Iterator<T> iterator() {
return args.iterator();
}
public static <T> ArgBuilder<T> with(T firstArgument) {
return new ArgBuilder<T>().and(firstArgument);
}
}
사용법
import static com.example.ArgBuilder.*;
public class VarargsTest {
public static void main(String[] args) {
doSomething(new ArgBuilder<String>().and("foo").and("bar").and("baz"));
// or
doSomething(with("foo").and("bar").and("baz"));
}
static void doSomething(Iterable<String> args) {
for (String arg : args) {
System.out.println(arg);
}
}
}
vararg 메서드 호출에서 오브젝트에 파라미터를 명시적으로 캐스팅하면 컴파일러는 @SuppressWarnings에 의존하지 않고 만족할 수 있습니다.
public static <T> List<T> list( final T... items )
{
return Arrays.asList( items );
}
// This will produce a warning.
list( "1", 2, new BigDecimal( "3.5" ) )
// This will not produce a warning.
list( (Object) "1", (Object) 2, (Object) new BigDecimal( "3.5" ) )
// This will not produce a warning either. Casting just the first parameter to
// Object appears to be sufficient.
list( (Object) "1", 2, new BigDecimal( "3.5" ) )
여기서의 문제는 컴파일러가 구체적으로 어떤 종류의 어레이를 작성해야 하는지 알아내야 한다는 것입니다.메서드가 일반적이지 않은 경우 컴파일러는 메서드의 유형 정보를 사용할 수 있습니다.메서드가 일반인 경우 호출 시 사용된 매개 변수를 기준으로 배열 유형을 파악하려고 합니다.파라미터 타입이 균일한 경우 그 작업은 간단합니다.다른 경우에는 컴파일러가 너무 영리하다고 생각하여 유니언 타입의 범용 어레이를 만듭니다.그럼 어쩔 수 없이 경고를 해야 할 것 같네요.더 간단한 해결책은 유형을 더 잘 좁힐 수 없는 경우 개체 []를 작성하는 것입니다.상기의 솔루션은, 그것을 강요하고 있습니다.
이것을 보다 잘 이해하려면 , 다음의 list2 메서드에 비해, 상기의 리스트 메서드에의 호출을 사용해 주세요.
public static List<Object> list2( final Object... items )
{
return Arrays.asList( items );
}
해결할 수 있습니다: 을 사용합니다.List<T>
!
참조 유형의 배열은 피해야 합니다.
Java의 현재 버전(1.7)에서는 발신자로부터 경고를 삭제하는 방법을 표시할 수 있습니다.다만, 이 점에 주의해 주세요.레거시 어레이가 없는 것이 좋습니다.
List.of()
(수정 불가)를 비교적 간결하게 기술하는 방법을 제공합니다.List
Java가 적절한 리터럴 표현을 얻을 때까지.
"Varargs 메서드에서 복구 불가능한 형식 매개 변수를 사용할 때 향상된 컴파일러 경고 및 오류" 기술 노트를 참조하십시오.
Java 7 이후 메서드에 @SafeVarargs를 추가할 수 있으며 클라이언트 코드에 주석을 달 필요가 없습니다.
class Assembler<X, Y> {
@SafeVarargs
final void assemble(X container, Y... args) {
//has to be final...
}
}
메서드에 과부하가 걸릴 수 있습니다.이 방법은 문제를 해결하지는 않지만 경고 수를 최소화합니다(예, 해킹입니다).
class Assembler<X, Y> {
void assemble(X container, Y a1) { ... }
void assemble(X container, Y a1, Y a2) { ... }
void assemble(X container, Y a1, Y a2, Y a3) { ... }
void assemble(X container, Y a1, Y a2, Y a3, Y a4) { ... }
void assemble(X container, Y... args) { ... }
}
범용 타입의 배열로 작업하는 경우, 범용 타입에 대한 참조를 전달하지 않을 수 없습니다.이를 통해 java.lang.reflect를 사용하여 범용 코드를 만들 수 있습니다.어레이
http://java.sun.com/javase/6/docs/api/java/lang/reflect/Array.html
언급URL : https://stackoverflow.com/questions/1445233/is-it-possible-to-solve-the-a-generic-array-of-t-is-created-for-a-varargs-param
'programing' 카테고리의 다른 글
vee-validate: 조건을 충족하는 경우에만 필요합니다. (0) | 2022.09.01 |
---|---|
c의 scanf를 사용하여 이중 값 판독 (0) | 2022.08.25 |
v-for 루프 Vue 2의 동적 V-모델 이름 (0) | 2022.08.25 |
사용자가 vue js에 로그인한 후 인증 토큰을 저장하려면 어떻게 해야 합니까? (0) | 2022.08.25 |
레지스터 값을 C 변수로 읽기 (0) | 2022.08.25 |