Esta é uma versão simplificada do código em questão, uma classe genérica usa outra classe com parâmetros de tipo genérico e precisa passar um dos tipos genéricos para um método com parâmetros varargs:
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);
}
}
Existe alguma maneira correta de passar o parâmetro genérico para um método varargs sem encontrar esse aviso?
Claro que algo como
assembler.assemble("hello", new T[] { something });
não funciona, pois você não pode criar matrizes genéricas.
Respostas:
Além de adicionar
@SuppressWarnings("unchecked")
, acho que não.Este relatório de erros tem mais informações, mas resume-se ao compilador que não gosta de matrizes de tipos genéricos.
fonte
Tom Hawtin apontou isso em um comentário, mas para ser mais explícito: sim, você pode resolver isso no site da declaração (em vez dos (potencialmente muitos) sites de chamada): alterne para o JDK7.
Como você pode ver na postagem do blog de Joseph Darcy , o projeto Project Coin para selecionar algumas pequenas melhorias incrementais de linguagem para o Java 7 aceitou a proposta de Bob Lee de permitir que algo como
@SuppressWarnings("varargs")
no lado do método faça esse aviso desaparecer em situações em que era conhecido seguro.Isso foi implementado no OpenJDK com esse commit .
Isso pode ou não ser útil ao seu projeto (muitas pessoas não ficariam felizes em mudar para uma versão instável da JVM antes do lançamento!), Mas talvez seja - ou talvez alguém que encontre essa pergunta mais tarde (depois que o JDK7 for lançado) ) achará útil.
fonte
Se você procura uma interface do tipo fluente, pode experimentar o padrão do construtor. Não é tão conciso quanto o varargs, mas é do tipo seguro.
Um método estático de tipo genérico pode eliminar parte do padrão ao usar o construtor, mantendo a segurança do tipo.
O construtor
Usando isso
fonte
Collection
(neste caso, umArrayList
) é imposto ao chamador, enquanto eles podem saber que aLinkedList
é mais apropriado ou uma matriz imutável (como as variáveis da pergunta OP). Em um caso de uso não especializado, isso pode ser apropriado, mas apenas apontando que isso também é uma limitação, de certa forma, dependendo do código que envolve isso e suas necessidades.A conversão explícita de parâmetros para Object na invocação do método vararg fará o compilador feliz sem recorrer a @SuppressWarnings.
Acredito que a questão aqui é que o compilador precisa descobrir que tipo concreto de matriz criar. Se o método não for genérico, o compilador pode usar informações de tipo do método. Se o método for genérico, ele tenta descobrir o tipo de matriz com base nos parâmetros usados na chamada. Se os tipos de parâmetros forem homogêneos, essa tarefa será fácil. Se eles variarem, o compilador tenta ser muito inteligente na minha opinião e cria uma matriz genérica do tipo união. Então ele se sente obrigado a avisá-lo sobre isso. Uma solução mais simples seria criar Object [] quando o tipo não puder ser melhor refinado. A solução acima força exatamente isso.
Para entender isso melhor, brinque com invocações para o método list acima, comparado ao método list2 a seguir.
fonte
Você pode adicionar @SafeVarargs ao método desde o Java 7 e não precisa anotar no código do cliente.
fonte
Você pode sobrecarregar os métodos. Isso não resolve o seu problema, mas minimiza o número de avisos (e sim, é um hack!)
fonte
É um problema muito fácil de resolver: Use
List<T>
!Matrizes do tipo de referência devem ser evitadas.
Na versão atual do Java (1.7), você pode marcar o método com o
@SafeVargs
qual removerá o aviso do chamador. Cuidado com isso, porém, e você ainda está melhor sem matrizes herdadas.Consulte também as notas técnicas e avisos aprimorados do compilador ao usar parâmetros formais não reificáveis com a Varargs Methods .
fonte
Quando trabalhos com matrizes do tipo genérico, sou forçado a passar uma referência ao tipo genérico. Com isso, eu posso realmente fazer o código genérico, usando java.lang.reflect.Array.
http://java.sun.com/javase/6/docs/api/java/lang/reflect/Array.html
fonte