Java'da SuppressWarnings ("işaretlenmemiş") nedir?


Yanıtlar:


420

Bazen Java jenerikleri sadece istediğiniz şeyi yapmanıza izin vermez ve derleyiciye yaptığınız işin gerçekten yürütme zamanında yasal olacağını söylemeniz gerekir .

Genel bir arayüzle alay ederken bunu genellikle bir acı olarak görüyorum, ancak başka örnekler de var. Bu uyarıyı kaçınarak yerine onu bastırmak için bir yol bulmaya çalışıyorum genellikle değer ( Java Jenerik SSS burada yardımcı olur) ama bazen bile eğer olduğunu mümkünse, o kadar çok uyarı bastırmayı kıvrımlara olduğuna şekil dışında kodunu büker. Bu durumda her zaman açıklayıcı bir yorum ekleyin!

Aynı jenerik SSS, bu konuda "" İşaretlenmemiş "uyarı nedir?" - okumaya değer.


10
Bazı durumlarda, YourClazz.class.cast () öğesini kullanarak bundan kaçınabilirsiniz. Tek genel öğe kapları için çalışır, ancak koleksiyonlar için çalışmaz.
akarnokd

Veya tercihen joker karakter jenerikleri kullanın (YourClazz<?>)- Java asla güvenli oldukları için bu tür uyarılar konusunda uyarmaz. Ancak bu her zaman işe yaramaz (ayrıntılar için genel SSS bölümüne bakın).
Konrad Borowski

48

Yayınlar gibi denetlenmeyen jenerik işlemler (istisnalar değil) hakkında derleme uyarılarını bastırmak bir ek açıklamadır. Temel olarak programcının belirli bir kod parçasını derlerken zaten bildiği bunlardan haberdar edilmeyi istemediği anlamına gelir.

Bu özel ek açıklama hakkında daha fazla bilgiyi buradan edinebilirsiniz:

SuppressWarnings

Ayrıca, Oracle, ek açıklamaların kullanımı hakkında burada bazı öğretici belgeler sunmaktadır:

Açıklamalar

Koydukları gibi,

"Jeneriklerin ortaya çıkmasından önce (Generics başlıklı derste tartışılmıştır) yazılan eski kodla arayüz oluştururken 'kontrolsüz' uyarısı oluşabilir."


19

Ayrıca, geçerli Java türü sistem sürümünün durumunuz için yeterince iyi olmadığı anlamına da gelebilir. Bunu düzeltmek için birkaç JSR öneri / hack vardı : Tür belirteçleri, Süper Tür Belirteçleri , Class.cast ().

Bu baskıya gerçekten ihtiyacınız varsa, mümkün olduğunca daraltın (örneğin, sınıfın kendisine veya uzun bir yönteme koymayın). Bir örnek:

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

   Collections.reverse(list);
   return list;
}


8

Basitçe: Bu, derleyicinin tür güvenliğini sağlayamayacağını belirten bir uyarıdır.

JPA hizmet yöntemi örneğin:

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

Burada @SuppressWarnings ("işaretlenmemiş") anotate değil, benim ResultList dönmek istiyorum hattı ile ilgili bir sorun olurdu.

Kısayol türü güvenliği anlamına gelir: Bir program, hatalar ve uyarılar olmadan derlenirse ve çalışma zamanında beklenmedik bir ClassCastException oluşturmazsa, tür güvenli olarak kabul edilir.

I inşa http://www.angelikalanger.com/GenericsFAQ/FAQSections/Fundamentals.html


2
Bu, SuppressWarnings'i kullanmamız gereken durum için iyi bir örnektir.
Jimmy

8

Java'da, jenerikler tür silme yoluyla uygulanır. Örneğin, aşağıdaki kod.

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

Aşağıdakilere derlenir.

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

Ve List.ofolarak tanımlanır.

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

Hangi tip sonrası silme olur.

static List of(Object e1, Object e2);

Derleyicinin çalışma zamanında genel türler hakkında hiçbir fikri yoktur, bu nedenle böyle bir şey yazarsanız.

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

Java Virtual Machine, bir programı çalıştırırken genel türlerin ne olduğu hakkında hiçbir fikre sahip değildir, bu nedenle bu, Java Virtual Machine için olduğu gibi derler ve çalışır, bu tür bir dökümdür List(doğrulayabildiği tek şey budur, bu yüzden sadece bunu doğrular).

Ama şimdi bu satırı ekleyin.

Integer hello = actualList.get(0);

JVM, ClassCastExceptionJava derleyicisi örtük bir yayın eklediğinden beklenmedik bir şey atacak .

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

Bir uncheckeduyarı, bir programcıya oyuncu kadrosunun bir programın başka bir yere istisna atmasına neden olabileceğini bildirir. Uyarının bastırılması @SuppressWarnings("unchecked")derleyiciye kodun güvenli olduğuna inandığını ve beklenmedik istisnalara neden olmayacağını söyler.

Bunu neden yapmak istiyorsun? Java türü sistem, tüm olası tür kullanım modellerini temsil edecek kadar iyi değildir. Bazen bir oyuncu kadrosunun güvenli olduğunu biliyor olabilirsiniz, ancak Java böyle bir yol göstermez - böyle uyarıları gizlemek @SupressWarnings("unchecked")için kullanılabilir, böylece bir programcı gerçek uyarılara odaklanabilir. Örneğin, Optional.empty()bir değer saklamayan boş seçeneklerin tahsis edilmesini önlemek için bir singleton döndürür.

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

Boş bir isteğe bağlı olarak depolanan değer alınamadığı için bu döküm güvenlidir, bu nedenle beklenmedik sınıf döküm istisnaları riski yoktur.


5

Derleyici uyarılarını bastırabilir ve jeneriklere yazdığınız kodun ona göre yasal olduğunu söyleyebilirsiniz.

Misal:

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

5

Bir numara, genel bir taban arayüzünü genişleten bir arayüz oluşturmaktır ...

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

Sonra dökümden önce instanceof ile kontrol edebilirsiniz ...

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;

4

Bildiğim kadarıyla şimdilik jeneriklerle ilgili uyarıları bastırmakla ilgili; jenerikler JDK 5'ten önceki JDK sürümlerinde desteklenmeyen yeni bir programlama yapısıdır, bu nedenle eski yapıların yenileriyle herhangi bir karışımı beklenmedik sonuçlar doğurabilir.

Derleyici programcıyı uyarır, ancak programcı zaten biliyorsa, bu korkunç uyarıları SuppressWarnings kullanarak kapatabilir.


1
JDK5 yeni mi? Hizmet Sonu Ömrü döneminin çoğunu tamamladı.
Tom Hawtin - tackline

JDK 5'in oldukça eski olduğunu biliyorum, demek istediğim, daha önce JDK 4'te sunulmayan Java'ya yeni özellikler getirmesi açısından yeni. Ayrıca JDK 5'i geride bırakmadan önce hala JDK 7'yi bekleyenlerin olduğunu unutmayın. JDK 6'yı kucaklamak için nedenini anlayamıyorum!
BakerTheHacker

2

Derleyicinin tür güvenliğini sağlayamayacağını belirten bir uyarı. "İşaretlenmemiş" uyarısı yanıltıcıdır. Bu, uyarının hiçbir şekilde işaretlenmediği anlamına gelmez. "İşaretlenmemiş" terimi, derleyicinin ve çalışma zamanı sisteminin, tür güvenliğini sağlamak için gerekli olabilecek tüm tür denetimlerini gerçekleştirmek için yeterli tür bilgisine sahip olmadığı anlamına gelir. Bu anlamda bazı operasyonlar "kontrol edilmez".

"Kontrolsüz" uyarıların en yaygın kaynağı ham türlerin kullanılmasıdır. Ham tür gerekli tüm denetimleri gerçekleştirmek için yeterli tür bilgisi sağlamadığından, bir nesneye ham tür değişkeni üzerinden erişildiğinde "denetlenmeyen" uyarılar verilir.

Örnek (ham tiplerle bağlantılı olarak kontrol edilmemiş uyarı):

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

Add yöntemi çağrıldığında derleyici, koleksiyona bir String nesnesi eklemenin güvenli olup olmadığını bilmez. TreeSet, String s (veya bir süpertipi) içeren bir koleksiyonsa, güvenli olacaktır. Ancak ham tür TreeSet tarafından sağlanan tür bilgisinden derleyici söyleyemez. Bu nedenle çağrı potansiyel olarak güvensizdir ve "kontrol edilmez" uyarısı verilir.

Derleyici, hedef türü parametreleştirilmiş tür veya tür parametresi olan bir döküm bulduğunda "denetlenmemiş" uyarılar da bildirilir.

Örnek (parametreleştirilmiş tip veya tip değişkenine bir döküm ile birlikte kontrol edilmeyen bir uyarı):

  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;

Çalışma zamanında bir dinamik tür denetimi söz konusuysa, hedef türü (somut veya sınırlı joker karakter) parametreli bir tür veya bir tür parametresi güvenli olmayan bir döküm. Çalışma zamanında, kaynak kodda görünen tam statik türü değil, yalnızca tür silme kullanılabilir. Sonuç olarak, dökümün çalışma zamanı kısmı, tam statik türe değil, tür silme işlemine göre gerçekleştirilir.

Örnekte, Wrapper öğesine yayın, super.clone öğesinden döndürülen nesnenin belirli bir türde üyeye sahip bir sarıcı olup olmadığını değil, bir Wrapper olup olmadığını kontrol eder. Benzer şekilde, T tipi parametresine ilişkin yayınlar, çalışma zamanında Object türüne dökülür ve muhtemelen tamamen optimize edilir. Tür silme nedeniyle, çalışma zamanı sistemi çalışma zamanında daha kullanışlı tür denetimleri gerçekleştiremez.

Bir şekilde, kaynak kodu yanıltıcıdır, çünkü ilgili hedef tipe bir kadronun gerçekleştirildiğini gösterirken, aslında kadronun dinamik kısmı sadece hedef türün tip silinmesine karşı kontrol eder. "İşaretlenmemiş" uyarısı, programcının dikkatini, yayınlamanın statik ve dinamik yönü arasındaki bu uyumsuzluğa çekmek için verilir.

Lütfen bakınız: "Kontrol edilmemiş" uyarı nedir?


2

@SuppressWarnings ek açıklaması, JDK'da bulunan üç yerleşik ek açıklamadan biridir ve Java 1.5'te @Override ve @Deprecated ile birlikte eklenmiştir.

@SuppressWarnings, derleyiciye açıklamalı öğede belirtilen derleyici uyarısını ve o öğenin içindeki tüm program öğelerini yoksaymasını veya bastırmasını bildirir. Örneğin, belirli bir uyarıyı bastırmak için bir sınıfa açıklama eklenirse, o sınıfın içindeki bir yöntemde oluşturulan bir uyarı da ayrılır.

@SuppressWarnings ek açıklamasına en popüler örneklerden biri olan @SuppressWarnings ("unchecked") ve @SuppressWarnings ("serial") ifadelerini görmüş olabilirsiniz. Eski, denetlenmeyen döküm nedeniyle oluşturulan uyarıyı bastırmak için kullanılırken, sonraki uyarı SerialVersionUID'yi Serializable sınıfına eklemeyi hatırlatmak için kullanılır.

Daha fazla bilgi için: https://javarevisited.blogspot.com/2015/09/what-is-suppresswarnings-annotation-in-java-unchecked-raw-serial.html#ixzz5rqQaOLUa

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.