Item 32: Seja criterioso ao combinar os genéricos com os varargs

RMAG news

Introdução:
Métodos varargs e genéricos foram introduzidos no Java 5.
Interação entre eles nem sempre é pacífica devido a vazamentos de abstração.

Problemas com varargs e genéricos:
Criação de arrays para parâmetros varargs torna-se visível, resultando em advertências do compilador.
Tipos não reificados (parametrizados ou genéricos) causam advertências na declaração e invocação de métodos varargs.

Poluição do heap:
Ocorre quando uma variável de tipo parametrizado referencia um objeto de outro tipo, podendo causar falhas de ClassCastException.

Exemplo de problema:
Um método aparentemente seguro pode falhar com ClassCastException devido a casts invisíveis gerados pelo compilador.

Inconsistências permitidas:
Métodos com parâmetros varargs genéricos são permitidos, apesar das inconsistências, devido à sua utilidade prática.
Exemplos de métodos seguros incluem Arrays.asList, Collections.addAll, e EnumSet.of.

Introdução do @SafeVarargs:
Introduzido no Java 7 para suprimir automaticamente advertências de métodos varargs genéricos que são seguros.
Representa uma promessa do autor do método de que ele é seguro.

Garantia de segurança:
Não armazene nada no array de parâmetros varargs.
Não permita que referências ao array escapem para código não confiável.

Exemplo de método perigoso:
Métodos que retornam um array de parâmetros varargs podem propagar poluição do heap.

Uso seguro de varargs:
Passar arrays varargs para métodos adequadamente anotados ou que apenas calculam funções do conteúdo do array.

Exemplo de uso seguro:
Método que aceita várias listas e retorna uma lista contendo todos os elementos.

Regras para @SafeVarargs:
Use em métodos com parâmetros varargs genéricos para evitar advertências desnecessárias.
Métodos anotados devem ser estáticos ou finais (Java 8), ou privados (Java 9).

Alternativa com List:
Substituir varargs por List para provar que o método é seguro.
Pode resultar em código cliente mais verboso e ligeiramente mais lento.

Conclusão:
Varargs e genéricos não interagem bem devido a vazamentos de abstração e diferenças nas regras de tipagem.
Garanta que métodos com parâmetros varargs genéricos sejam seguros e anote-os com @SafeVarargs.

Este resumo captura os pontos principais do artigo, destacando os problemas, soluções e boas práticas ao combinar varargs com genéricos no Java.