Pergunta

Às vezes quando se olha através do código, vejo muitos métodos especificar uma anotação:

@SuppressWarnings("unchecked")

O que isso significa?

Foi útil?

Solução

Às vezes genéricos Java simplesmente não deixar você fazer o que você quer, e você precisa dizer de forma eficaz o compilador que o que você está fazendo realmente irá ser legal em tempo de execução.

Normalmente, eu encontrar este uma dor quando estou zombando de uma interface genérica, mas há outros exemplos também. É geralmente vale a pena tentar descobrir uma maneira de evitar o aviso ao invés de suprimi-la (a Java Generics FAQ ajuda aqui), mas, por vezes, mesmo que é possível, ele se curva o código fora de forma tanto que suprimir o aviso é mais puro. Sempre adicionar um comentário explicativo, nesse caso!

O mesmo genéricos FAQ tem várias seções sobre este tema, começando com "O que é um aviso "desmarcada" " -?. é bem uma leitura vale a pena

Outras dicas

É uma anotação de avisos de compilação suprimir cerca de operações não verificadas genéricos (não exceções), tais como moldes. É essencialmente implica que o programador não deseja ser notificado sobre estes que ele já está ciente de quando compilar um pouco de código específico.

Você pode ler mais sobre esta anotação específica aqui:

SuppressWarnings

Além disso, a Oracle oferece alguma documentação tutorial sobre o uso de anotações aqui:

Anotações

Como eles dizem,

"O aviso 'desmarcada' pode ocorrer quando a interface com código legado escrito antes do advento dos genéricos (discutidas na lição intitulada Genéricos)."

Pode significar também que a versão atual sistema de tipo Java não é bom o suficiente para o seu caso. Havia várias JSR proposições / hacks para corrigir isto: Tipo fichas, Super Tipo Tokens , Class.cast ().

Se você realmente precisa dessa supressão, reduzi-lo tanto quanto possível (por exemplo, não colocá-lo para a própria classe ou em um método de comprimento). Um exemplo:

public List<String> getALegacyListReversed() {
   @SuppressWarnings("unchecked") List<String> list =
       (List<String>)legacyLibrary.getStringList();

   Collections.reverse(list);
   return list;
}

O SuppressWarning anotação é utilizado para avisos do compilador suprimir para o elemento anotado. Especificamente, a categoria unchecked permite a supressão de avisos do compilador geradas como um resultado de moldes do tipo não verificadas.

Simplesmente:. É um aviso de que o compilador indica que ele não pode garantir a segurança de tipos

método de serviço JPA por exemplo:

@SuppressWarnings("unchecked")
public List<User> findAllUsers(){
    Query query = entitymanager.createQuery("SELECT u FROM User u");
    return (List<User>)query.getResultList();
}

Se eu didn'n anotate os @SuppressWarnings ( "unchecked") aqui, ele teria um problema com a linha, onde eu quero voltar a minha resultList.

Em meio Tipo de segurança de atalho:. Um programa é considerado de tipo seguro se ele compila sem erros e avisos e não levantar qualquer ClassCastException inesperado s em tempo de execução

Eu construir sobre http://www.angelikalanger.com/GenericsFAQ/FAQSections/Fundamentals .html

Em Java, os genéricos são implementados por meio de eliminação de tipo. Por exemplo, o código a seguir.

List<String> hello = List.of("a", "b");
String example = hello.get(0);

é compilado para o seguinte.

List hello = List.of("a", "b");
String example = (String) hello.get(0);

E List.of é definido como.

static <E> List<E> of(E e1, E e2);

O que após eliminação de tipo torna-se.

static List of(Object e1, Object e2);

O compilador não tem idéia de quais são os tipos genéricos em tempo de execução, por isso, se você escrever algo como isto.

Object list = List.of("a", "b");
List<Integer> actualList = (List<Integer>) list;

Java Virtual Machine não tem idéia do que tipos genéricos são durante a execução de um programa, de modo que este compila e roda, como por Java Virtual Machine, este é um elenco de tipo List (esta é a única coisa que ele pode verificar, por isso, ele verifica só isso).

Mas agora adicionar esta linha.

Integer hello = actualList.get(0);

E JVM irá lançar uma ClassCastException inesperado, como compilador Java inserido uma conversão implícita.

java.lang.ClassCastException: java.base/java.lang.String cannot be cast to java.base/java.lang.Integer

Um aviso unchecked diz um programador que um elenco pode causar um programa para lançar uma exceção em outro lugar. Suprimindo o aviso com @SuppressWarnings("unchecked") diz ao compilador que o programador acredita que o código para ser seguro e não causará exceções inesperadas.

Por que você iria querer fazer isso? sistema de tipo Java não é bom o suficiente para representar todos os possíveis padrões de uso tipo. Às vezes você pode saber que um elenco é seguro, mas não Java não fornece uma maneira de dizê-lo - para ocultar avisos como este, @SupressWarnings("unchecked") pode ser usado, para que um programador pode focar avisos reais. Por exemplo, Optional.empty() retorna um singleton para alocação evitar de opcionais vazias que não armazenam um valor.

private static final Optional<?> EMPTY = new Optional<>();
public static<T> Optional<T> empty() {
    @SuppressWarnings("unchecked")
    Optional<T> t = (Optional<T>) EMPTY;
    return t;
}

Este elenco é seguro, como o valor armazenado em um opcional vazio não pode ser recuperada por isso não há risco de exceções classe elenco inesperados.

Você pode suprimir os avisos do compilador e contar os genéricos que o código que você escreveu está de acordo legal a ele.

Exemplo:

@SuppressWarnings("unchecked")
public List<ReservationMealPlan> retreiveMealPlan() {
     List<ReservationMealPlan> list=new ArrayList<ReservationMealPlan>();
    TestMenuService testMenuService=new TestMenuService(em, this.selectedInstance);
    list = testMenuService.getMeal(reservationMealPlan);
    return list;
 }

Um truque é criar uma interface que estende uma base genérica interface de ...

public interface LoadFutures extends Map<UUID, Future<LoadResult>> {}

Depois, você pode verificá-lo com instanceof antes de o elenco ...

Object obj = context.getAttribute(FUTURES);
if (!(obj instanceof LoadFutures)) {
    String format = "Servlet context attribute \"%s\" is not of type "
            + "LoadFutures. Its type is %s.";
    String msg = String.format(format, FUTURES, obj.getClass());
    throw new RuntimeException(msg);
}
return (LoadFutures) obj;

Até eu sei, por enquanto, tem a ver com supressão de avisos sobre os genéricos; genéricos são uma nova construção de programação não é suportado em versões do JDK mais cedo do que o JDK 5, portanto, quaisquer misturas dos velhos construções com os novos podem representar alguns resultados inesperados.

O compilador avisa o programador sobre isso, mas se o programador já sabe, eles podem transformar esses avisos temidas fora de usar SuppressWarnings.

Um aviso pelo qual o compilador indica que ele não pode garantir a segurança de tipos. O termo de advertência "desmarcada" é enganosa. Isso não significa que o aviso é desmarcada de qualquer forma. O termo "sem controle" refere-se ao fato de que o compilador eo sistema de execução não tem informações de tipo suficiente para realizar todas as verificações de tipo que seriam necessárias para garantir a segurança tipo. Neste sentido, algumas operações são "sem controle".

A fonte mais comum de avisos "não verificados" é o uso de tipos de matérias. avisos "não verificados" são emitidos quando um objeto é acessado através de uma variável do tipo cru, porque o tipo de matéria não fornece informações de tipo suficiente para realizar todas as verificações de tipo necessárias.

Exemplo (de aviso não verificado em conjunção com os tipos de matérias-):

TreeSet set = new TreeSet(); 
set.add("abc");        // unchecked warning 
set.remove("abc");
warning: [unchecked] unchecked call to add(E) as a member of the raw type java.util.TreeSet 
               set.add("abc");  
                      ^

Quando o método add é invocado o compilador não sabe se é seguro para adicionar um objeto String à coleção. Se o TreeSet é uma coleção que contém String s (ou um supertipo do mesmo), então seria seguro. Mas a partir da informação do tipo fornecido pelo tipo de matéria-TreeSet o compilador não pode contar. Daí a chamada é potencialmente insegura e um aviso "não verificado" é emitido.

advertências "não verificados" também são relatados quando o compilador encontra um elenco cujo tipo de destino é um tipo parametrizado ou um parâmetro de tipo.

Exemplo (de um aviso não verificado em conjunção com um molde para um tipo com parâmetros ou tipo variável):

  class Wrapper<T> { 
  private T wrapped ; 
  public Wrapper (T arg) {wrapped = arg;} 
  ... 
  public Wrapper <T> clone() { 
    Wrapper<T> clon = null; 
     try {  
       clon = (Wrapper<T>) super.clone(); // unchecked warning 
     } catch (CloneNotSupportedException e) {  
       throw new InternalError();  
     } 
     try {  
       Class<?> clzz = this.wrapped.getClass(); 
       Method   meth = clzz.getMethod("clone", new Class[0]); 
       Object   dupl = meth.invoke(this.wrapped, new Object[0]); 
       clon.wrapped = (T) dupl; // unchecked warning 
     } catch (Exception e) {} 
     return clon; 
  } 
} 
warning: [unchecked] unchecked cast 
found   : java.lang.Object 
required: Wrapper <T> 
                  clon = ( Wrapper <T>)super.clone();  
                                                ^ 
warning: [unchecked] unchecked cast 
found   : java.lang.Object 
required: T 
                  clon. wrapped = (T)dupl;

Um elenco cuja meta tipo é um tipo parametrizado um parâmetro de tipo (concreto ou curinga limitada) ou não é seguro, se um cheque tipo dinâmico em tempo de execução está envolvido. Em tempo de execução, apenas o tipo de apagamento é, não o tipo estático exata disponível que é visível no código fonte. Como resultado, a parte de tempo de execução do elenco é realizada com base no tipo de apagamento, não sobre o tipo estático exato.

No exemplo, o elenco para Wrapper iria verificar se o objeto retornado de super.clone é um wrapper, não se é um invólucro com um tipo particular de membros. Da mesma forma, os moldes para o tipo de parâmetro T são lançados com o tipo de objeto em tempo de execução, e provavelmente otimizado afastado completamente. Devido à eliminação de tipo, o tempo de execução do sistema é incapaz de executar verificações de tipo mais úteis no tempo de execução.

De certa forma, o código fonte é enganosa, porque sugere que um elenco com o respectivo tipo de destino é realizada, quando na verdade a parte dinâmica do elenco verifica apenas contra o tipo de apagamento do tipo de destino. O aviso "não verificado" é emitido para chamar a atenção do programador para esse descompasso entre o estático e aspecto dinâmico do elenco.

Por favor, consulte: O que é um aviso "desmarcada"?

@SuppressWarnings anotação é um dos três built-in anotações disponíveis no JDK e adicionados ao lado @Override e @deprecated em Java 1.5.

@SuppressWarnings instruir o compilador para ignorar ou suprimir, aviso do compilador especificado no elemento anotado e todos os elementos do programa dentro desse elemento. Por exemplo, se uma classe é anotada para suprimir um aviso especial, em seguida, um aviso gerado num método dentro dessa classe também será separado.

@SuppressWarnings

Você pode ter visto ( "unchecked") e @SuppressWarnings ( "serial"), dois dos exemplos mais populares de @SuppressWarnings anotação. Primeiro é usado para aviso suprimir gerado devido à fundição desmarcada enquanto a advertência posterior é usado para lembrar sobre a adição de serialVersionUID em uma classe Serializable.

Leia mais: https://javarevisited.blogspot.com/2015/09/what-is-suppresswarnings-annotation-in-java-unchecked-raw-serial.html#ixzz5rqQaOLUa

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top