Odpowiedzi:
Czasami ogólne elementy języka Java po prostu nie pozwalają ci robić tego, co chcesz, i musisz skutecznie powiedzieć kompilatorowi, że to, co robisz, będzie legalne w czasie wykonywania.
Zwykle odczuwam to ból, gdy kpię sobie z ogólnego interfejsu, ale są też inne przykłady. Zwykle warto spróbować znaleźć sposób na uniknięcie ostrzeżenia, zamiast go tłumić ( pomocne są tutaj często zadawane pytania dotyczące Java Generics ), ale czasami nawet jeśli jest to możliwe, wygina kod do tego stopnia, że tłumienie ostrzeżenia jest bardziej odpowiednie. W takim przypadku zawsze dodawaj wyjaśnienia!
Ten sam ogólny rodzaj FAQ zawiera kilka sekcji na ten temat, zaczynając od „Co to jest„ niezaznaczone ”ostrzeżenie?” - warto przeczytać.
(YourClazz<?>)
- Java nigdy nie ostrzega przed takimi rzutowaniami, ponieważ są one bezpieczne. Jednak nie zawsze to działa (szczegółowe informacje znajdują się w ogólnych często zadawanych pytaniach).
Jest to adnotacja, aby ukryć ostrzeżenia kompilacyjne o niesprawdzonych operacjach ogólnych (nie wyjątkach), takich jak rzutowania. Zasadniczo implikuje to, że programista nie chciał być powiadamiany o tych, o których jest już świadomy podczas kompilowania określonego fragmentu kodu.
Możesz przeczytać więcej o tej konkretnej adnotacji tutaj:
Ponadto Oracle udostępnia tutaj dokumentację instruktażową dotyczącą korzystania z adnotacji:
Jak to ujęli,
„Ostrzeżenie„ niesprawdzone ”może wystąpić podczas łączenia się ze starszym kodem napisanym przed nadejściem generics (omówione w lekcji zatytułowanej Generics).”
Może to również oznaczać, że obecna wersja systemu typu Java nie jest wystarczająca dla twojego przypadku. Naprawiono kilka propozycji / hacków JSR : tokenów Type, Super Type Tokens , Class.cast ().
Jeśli naprawdę potrzebujesz tej supresji, zawęź ją tak bardzo, jak to możliwe (np. Nie umieszczaj jej na samej klasie ani na długiej metodzie). Przykład:
public List<String> getALegacyListReversed() {
@SuppressWarnings("unchecked") List<String> list =
(List<String>)legacyLibrary.getStringList();
Collections.reverse(list);
return list;
}
SuppressWarning adnotacja jest używana do tłumienia ostrzeżeń kompilatora dla adnotacjami elementu. W szczególności unchecked
kategoria umożliwia eliminację ostrzeżeń kompilatora generowanych w wyniku rzutowania typu niezaznaczonego.
Po prostu: jest to ostrzeżenie, za pomocą którego kompilator wskazuje, że nie może zapewnić bezpieczeństwa typu.
Metoda usługi JPA na przykład:
@SuppressWarnings("unchecked")
public List<User> findAllUsers(){
Query query = entitymanager.createQuery("SELECT u FROM User u");
return (List<User>)query.getResultList();
}
Gdybym nie zanotował tutaj @SuppressWarnings („niezaznaczone”), miałby problem z linią, w której chcę zwrócić moją Listę wyników.
W skrócie bezpieczeństwo typu oznacza: Program jest uważany za bezpieczny dla typu, jeśli kompiluje się bez błędów i ostrzeżeń i nie zgłasza żadnych nieoczekiwanych wyjątków ClassCastException w czasie wykonywania.
Buduję na http://www.angelikalanger.com/GenericsFAQ/FAQSections/Fundamentals.html
W Javie, generyczne są implementowane za pomocą kasowania typu. Na przykład następujący kod.
List<String> hello = List.of("a", "b");
String example = hello.get(0);
Jest skompilowany do następujących.
List hello = List.of("a", "b");
String example = (String) hello.get(0);
I List.of
jest zdefiniowany jako.
static <E> List<E> of(E e1, E e2);
Które po usunięciu typu staje się.
static List of(Object e1, Object e2);
Kompilator nie ma pojęcia, jakie są typy ogólne w czasie wykonywania, więc jeśli napiszesz coś takiego.
Object list = List.of("a", "b");
List<Integer> actualList = (List<Integer>) list;
Wirtualna maszyna Java nie ma pojęcia, jakie są typy ogólne podczas uruchamiania programu, więc kompiluje się ona i uruchamia, podobnie jak w przypadku wirtualnej maszyny Java, jest to rzutowanie na List
typ (jest to jedyna rzecz, którą może zweryfikować, więc weryfikuje tylko to).
Ale teraz dodaj tę linię.
Integer hello = actualList.get(0);
A JVM wyrzuci nieoczekiwany ClassCastException
, ponieważ kompilator Java wstawił niejawną obsadę.
java.lang.ClassCastException: java.base/java.lang.String cannot be cast to java.base/java.lang.Integer
unchecked
Ostrzeżenie mówi programista że obsada może powodować program wyjątek gdzieś indziej. Wyłączenie ostrzeżenia za pomocą @SuppressWarnings("unchecked")
informuje kompilator, że programista uważa kod za bezpieczny i nie spowoduje nieoczekiwanych wyjątków.
Dlaczego chcesz to zrobić? System typów Java nie jest wystarczająco dobry do przedstawienia wszystkich możliwych wzorców użycia typów. Czasami możesz wiedzieć, że rzutowanie jest bezpieczne, ale Java nie pozwala na to, aby to powiedzieć - @SupressWarnings("unchecked")
można użyć takiego ukrywania ostrzeżeń , aby programista mógł skupić się na prawdziwych ostrzeżeniach. Na przykład Optional.empty()
zwraca singleton, aby uniknąć przydzielenia pustych opcji, które nie przechowują wartości.
private static final Optional<?> EMPTY = new Optional<>();
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
Ta rzutowanie jest bezpieczne, ponieważ nie można odzyskać wartości przechowywanej w pustej opcjonalnej, więc nie ma ryzyka wystąpienia nieoczekiwanych wyjątków rzutowania klas.
Możesz wyłączyć ostrzeżenia kompilatora i poinformować ogólne, że napisany przez ciebie kod jest zgodny z prawem.
Przykład:
@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;
}
Jedną sztuczką jest stworzenie interfejsu rozszerzającego ogólny interfejs podstawowy ...
public interface LoadFutures extends Map<UUID, Future<LoadResult>> {}
Następnie możesz to sprawdzić za pomocą instanceof przed obsadą ...
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;
O ile wiem, na razie ma to związek z tłumieniem ostrzeżeń dotyczących leków generycznych; generics to nowy konstrukt programistyczny nieobsługiwany w wersjach JDK wcześniejszych niż JDK 5, więc wszelkie mieszanki starych konstrukcji z nowymi mogą dawać nieoczekiwane wyniki.
Kompilator ostrzega programistę przed tym, ale jeśli programista już wie, może wyłączyć te przerażające ostrzeżenia za pomocą SuppressWarnings.
Ostrzeżenie, za pomocą którego kompilator wskazuje, że nie może zapewnić bezpieczeństwa typu. Pojęcie „niesprawdzone” ostrzeżenie wprowadza w błąd. Nie oznacza to, że ostrzeżenie nie jest w żaden sposób odznaczone. Termin „niezaznaczony” odnosi się do faktu, że kompilator i system wykonawczy nie mają wystarczających informacji o typie, aby wykonać wszystkie kontrole typu, które byłyby konieczne do zapewnienia bezpieczeństwa typu. W tym sensie niektóre operacje są „niezaznaczone”.
Najczęstszym źródłem „niesprawdzonych” ostrzeżeń jest stosowanie typów surowych. „niesprawdzone” ostrzeżenia są wydawane, gdy dostęp do obiektu uzyskuje się poprzez zmienną typu raw, ponieważ typ raw nie zapewnia wystarczającej ilości informacji o typie, aby wykonać wszystkie niezbędne sprawdzenia typu.
Przykład (niezaznaczone ostrzeżenie w połączeniu z typami surowymi):
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");
^
Po wywołaniu metody add kompilator nie wie, czy można bezpiecznie dodać obiekt String do kolekcji. Jeśli TreeSet jest kolekcją zawierającą String s (lub jego nadtyp), to byłby bezpieczny. Jednak na podstawie informacji o typie dostarczonych przez TreeSet typu surowego kompilator nie jest w stanie stwierdzić. Dlatego połączenie jest potencjalnie niebezpieczne i generowane jest ostrzeżenie „niezaznaczone”.
„niesprawdzone” ostrzeżenia są również zgłaszane, gdy kompilator znajdzie rzutowanie, którego typem docelowym jest sparametryzowany typ lub parametr typu.
Przykład (niesprawdzonego ostrzeżenia w połączeniu z rzutowaniem na sparametryzowaną zmienną typu lub typu):
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;
Rzutowanie, którego typem docelowym jest sparametryzowany (konkretny lub ograniczony symbol wieloznaczny) lub parametr typu jest niebezpieczne, jeśli w grę wchodzi dynamiczna kontrola typu w czasie wykonywania. W czasie wykonywania dostępne jest tylko usuwanie typu, a nie dokładny typ statyczny widoczny w kodzie źródłowym. W rezultacie część wykonawcza rzutowania jest wykonywana na podstawie usunięcia typu, a nie na podstawie dokładnego typu statycznego.
W tym przykładzie rzutowanie na Wrapper sprawdzałoby, czy obiekt zwrócony z super.clone jest Wrapper, a nie czy jest to wrapper z określonym typem elementów. Podobnie rzutowania na parametr typu T są rzutowane na typ Object w czasie wykonywania i prawdopodobnie całkowicie zoptymalizowane. Z powodu kasowania typu system wykonawczy nie jest w stanie wykonać bardziej przydatnych kontroli typów w czasie wykonywania.
W pewnym sensie kod źródłowy wprowadza w błąd, ponieważ sugeruje, że wykonuje się rzutowanie na odpowiedni typ docelowy, podczas gdy w rzeczywistości część dynamiczna rzutowania sprawdza tylko pod kątem usunięcia typu docelowego. Wyświetlane jest ostrzeżenie „niezaznaczone”, aby zwrócić uwagę programisty na niedopasowanie między statycznym a dynamicznym aspektem rzutowania.
Proszę odnieść się do: Co to jest „niezaznaczone” ostrzeżenie?
Adnotacja @SuppressWarnings jest jedną z trzech wbudowanych adnotacji dostępnych w JDK i dodawanych obok @Override i @Deprecated w Javie 1.5.
@SuppressWarnings instruuje kompilator, aby ignorował lub pomijał określone ostrzeżenie kompilatora w adnotowanym elemencie i wszystkich elementach programu w tym elemencie. Na przykład, jeśli klasa ma adnotację, aby ukryć określone ostrzeżenie, ostrzeżenie wygenerowane w metodzie wewnątrz tej klasy również zostanie oddzielone.
Być może widziałeś @SuppressWarnings („niezaznaczone”) i @SuppressWarnings („serial”), dwa najpopularniejsze przykłady adnotacji @SuppressWarnings. Poprzednia służy do pomijania ostrzeżeń generowanych z powodu niekontrolowanego rzutowania, natomiast późniejsze ostrzeżenie służy do przypominania o dodaniu SerialVersionUID do klasy Serializable.
Czytaj więcej: https://javarevisited.blogspot.com/2015/09/what-is-suppresswarnings-annotation-in-java-unchecked-raw-serial.html#ixzz5rqQaOLUa