Wat is SuppressWarnings (“niet aangevinkt”) in Java?

Soms als ik door de code kijk, zie ik dat veel methoden een annotatie specificeren:

@SuppressWarnings("unchecked")

Wat betekent dit?


Antwoord 1, autoriteit 100%

Soms laten generieke Java-generieken je gewoon niet doen wat je wilt, en moet je de compiler effectief vertellen dat wat je doet echt zallegaal zijn op het moment van uitvoering.

Ik vind dit meestal vervelend als ik een generieke interface bespot, maar er zijn ook andere voorbeelden. Het is meestal de moeite waard om een manier te bedenken om de waarschuwing te vermijden in plaats van deze te onderdrukken (de Java Generics FAQhelpt hier) maar soms, zelfs als het ismogelijk, buigt het de code zo veel uit vorm dat het onderdrukken van de waarschuwing netter is. Voeg in dat geval altijd een toelichting toe!

Dezelfde veelgestelde vragen over generieke geneesmiddelen hebben verschillende secties over dit onderwerp, te beginnen met “Wat is een “niet-aangevinkte” waarschuwing?”– het is de moeite van het lezen waard.


Antwoord 2, autoriteit 11%

Het is een annotatie om compileerwaarschuwingen over ongecontroleerde generieke bewerkingen (geen uitzonderingen), zoals casts, te onderdrukken. Het houdt in wezen in dat de programmeur niet op de hoogte wenste te worden gesteld van deze dingen waarvan hij al op de hoogte is bij het compileren van een bepaald stukje code.

Je kunt hier meer lezen over deze specifieke annotatie:

SuppressWarnings

Bovendien biedt Oracle hier enige tutorialdocumentatie over het gebruik van annotaties:

Annotaties

Zoals ze het zeggen,

“De ‘niet-aangevinkte’ waarschuwing kan optreden bij interactie met verouderde code die is geschreven vóór de komst van generieke geneesmiddelen (besproken in de les met de titel Generics).”


Antwoord 3, autoriteit 5%

Het kan ook betekenen dat de huidige systeemversie van het Java-type niet goed genoeg is voor uw geval. Er waren verschillende JSR-proposities/ hacks om dit op te lossen: Typ tokens, Super Type-tokens, Class.cast().

Als je deze onderdrukking echt nodig hebt, beperk het dan zo veel mogelijk (plaats het bijvoorbeeld niet op de klasse zelf of op een lange methode). Een voorbeeld:

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

Antwoord 4, autoriteit 2%

De SuppressWarningannotatie wordt gebruikt om compilerwaarschuwingen voor het geannoteerde element te onderdrukken. Met name de categorie uncheckedstaat onderdrukking toe van compilerwaarschuwingen die zijn gegenereerd als gevolg van niet-aangevinkte typecasts.


Antwoord 5, autoriteit 2%

Gewoon: het is een waarschuwing waarmee de compiler aangeeft dat hij de typeveiligheid niet kan garanderen.

JPA-servicemethode bijvoorbeeld:

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

Als ik de @SuppressWarnings(“niet aangevinkt”) hier niet had genoteerd, zou er een probleem zijn met de regel, waar ik mijn ResultList wil retourneren.

In snelkoppeling betekent type-veiligheid: een programma wordt als type-veilig beschouwd als het compileert zonder fouten en waarschuwingen en tijdens runtime geen onverwachte ClassCastExceptions genereert.

Ik bouw voort op http://www.angelikalanger.com/GenericsFAQ/FAQSections/Fundamentals .html


Antwoord 6, autoriteit 2%

In Java worden generieke geneesmiddelen geïmplementeerd door middel van typeverwijdering. Bijvoorbeeld de volgende code.

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

Is als volgt gecompileerd.

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

En List.ofis gedefinieerd als.

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

Wat na typeverwijdering wordt.

static List of(Object e1, Object e2);

De compiler heeft geen idee wat generieke typen zijn tijdens runtime, dus als je zoiets schrijft.

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

Java Virtual Machine heeft geen idee wat generieke typen zijn tijdens het uitvoeren van een programma, dus dit compileert en draait, net als voor Java Virtual Machine, dit is een cast naar het type List(dit is het enige het kan verifiëren, dus het verifieert alleen dat).

Maar voeg nu deze regel toe.

Integer hello = actualList.get(0);

En JVM zal een onverwachte ClassCastExceptiongenereren, omdat de Java-compiler een impliciete cast heeft ingevoegd.

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

Een unchecked-waarschuwing vertelt een programmeur dat een cast een programma ergens anders een uitzondering kan veroorzaken. Het onderdrukken van de waarschuwing met @SuppressWarnings("unchecked")vertelt de compiler dat de programmeur gelooft dat de code veilig is en geen onverwachte uitzonderingen zal veroorzaken.

Waarom zou je dat willen doen? Het Java-systeem is niet goed genoeg om alle mogelijke gebruikspatronen van het type weer te geven. Soms weet je misschien dat een cast veilig is, maar Java biedt geen manier om dit te zeggen – om waarschuwingen als deze te verbergen, kan @SupressWarnings("unchecked")worden gebruikt, zodat een programmeur kan focussen op echte waarschuwingen. Optional.empty()retourneert bijvoorbeeld een singleton om te voorkomen dat lege optionals worden toegewezen die geen waarde opslaan.

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

Deze cast is veilig, omdat de waarde die is opgeslagen in een lege optional niet kan worden opgehaald, dus er is geen risico op onverwachte klassecast-uitzonderingen.


Antwoord 7

Je kunt de compilerwaarschuwingen onderdrukken en de generieke gebruikers vertellen dat de code die je hebt geschreven volgens deze wet legaal is.

Voorbeeld:

@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;
 }

Antwoord 8

Een truc is om een interface te maken die een algemene basisinterface uitbreidt…

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

Dan kun je het controleren met instanceof voor de cast…

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;

Antwoord 9

Voor zover ik weet, heeft het voorlopig te maken met het onderdrukken van waarschuwingen over generieke geneesmiddelen; generieken zijn een nieuwe programmeerconstructie die niet wordt ondersteund in JDK-versies eerder dan JDK 5, dus elke combinatie van de oude constructies met de nieuwe kan onverwachte resultaten opleveren.

De compiler waarschuwt de programmeur ervoor, maar als de programmeur het al weet, kunnen ze die gevreesde waarschuwingen uitschakelen met SuppressWarnings.


Antwoord 10

Een waarschuwing waarmee de compiler aangeeft dat hij de typeveiligheid niet kan garanderen.
De term “ongecontroleerde” waarschuwing is misleidend. Het betekent niet dat de waarschuwing op enigerlei wijze is uitgeschakeld. De term “niet aangevinkt” verwijst naar het feit dat de compiler en het runtime-systeem niet genoeg type-informatie hebben om alle typecontroles uit te voeren die nodig zijn om de typeveiligheid te garanderen. In die zin zijn bepaalde bewerkingen “niet aangevinkt”.

De meest voorkomende bron van “niet-gecontroleerde” waarschuwingen is het gebruik van onbewerkte typen. “niet-gecontroleerde” waarschuwingen worden gegeven wanneer een object wordt benaderd via een onbewerkte typevariabele, omdat het onbewerkte type niet genoeg type-informatie biedt om alle noodzakelijke typecontroles uit te voeren.

Voorbeeld (van niet-aangevinkte waarschuwing in combinatie met onbewerkte typen):

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");  
                      ^

Wanneer de add-methode wordt aangeroepen, weet de compiler niet of het veilig is om een String-object aan de verzameling toe te voegen. Als de TreeSet een verzameling is die String s (of een supertype daarvan) bevat, dan zou het veilig zijn. Maar uit de type-informatie van het onbewerkte type TreeSet kan de compiler het niet vertellen. Daarom is de oproep mogelijk onveilig en wordt een “niet-aangevinkte” waarschuwing gegeven.

“niet aangevinkte” waarschuwingen worden ook gerapporteerd wanneer de compiler een cast vindt waarvan het doeltype ofwel een geparametriseerd type of een typeparameter is.

Voorbeeld (van een niet-aangevinkte waarschuwing in combinatie met een cast naar een geparametriseerd type of typevariabele):

 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;

Een cast waarvan het doeltype een (concreet of begrensd jokerteken) geparametriseerd type of een typeparameter is, is onveilig als er sprake is van een dynamische typecontrole tijdens runtime. Tijdens runtime is alleen het wissen van het type beschikbaar, niet het exacte statische type dat zichtbaar is in de broncode. Als gevolg hiervan wordt het runtime-gedeelte van de cast uitgevoerd op basis van het wissen van het type, niet op het exacte statische type.

In het voorbeeld zou de cast naar Wrapper controleren of het object dat wordt geretourneerd door super.clone een Wrapper is, niet of het een wrapper is met een bepaald type leden. Evenzo worden de casts naar de typeparameter T tijdens runtime naar het type Object gegoten en waarschijnlijk helemaal weggeoptimaliseerd. Als gevolg van het wissen van het type kan het runtime-systeem tijdens runtime geen nuttigere typecontroles uitvoeren.

In zekere zin is de broncode misleidend, omdat het suggereert dat een cast naar het respectievelijke doeltype wordt uitgevoerd, terwijl in feite het dynamische deel van de cast alleen controleert op het wissen van het type van het doeltype. De “ongecontroleerde” waarschuwing wordt gegeven om de aandacht van de programmeur te vestigen op deze discrepantie tussen het statische en dynamische aspect van de cast.

Raadpleeg: Wat is een “niet aangevinkte” waarschuwing?


Antwoord 11

@SuppressWarnings-annotatie is een van de drie ingebouwde annotaties die beschikbaar zijn in JDK en worden toegevoegd naast @Override en @Deprecated in Java 1.5.

@SuppressWarnings instrueert de compiler om de gespecificeerde compilerwaarschuwing in het geannoteerde element en alle programma-elementen binnen dat element te negeren of te onderdrukken.
Als een klasse bijvoorbeeld is geannoteerd om een bepaalde waarschuwing te onderdrukken, wordt een waarschuwing die is gegenereerd in een methode binnen die klasse ook gescheiden.

Misschien heb je @SuppressWarnings(“unchecked”) en @SuppressWarnings(“serial”) gezien, twee van de meest populaire voorbeelden van @SuppressWarnings-annotaties. Eerstgenoemde wordt gebruikt om waarschuwingen te onderdrukken die worden gegenereerd vanwege niet-gecontroleerde casten, terwijl de latere waarschuwing wordt gebruikt om te herinneren aan het toevoegen van SerialVersionUID in een Serializable-klasse.

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

Other episodes