2009-07-15 76 views

回答

335

有時Java泛型只是沒有讓你做你想要什麼,你需要有效地告訴編譯器,你正在做的真的是是在執行時的法律。

當我嘲笑一個通用接口時,我通常會覺得這很痛苦,但也有其他例子。通常值得設法避免警告而不是壓制(Java Generics FAQ幫助這裏),但有時即使它可能是,它會使代碼變形太多以至於抑制警告更加簡潔。在這種情況下總是添加解釋性評論!

相同的仿製藥常見問題有幾個部分關於這個主題,從"What is an "unchecked" warning?"開始 - 這非常值得一讀。

+8

在某些情況下,您可以通過使用YourClazz.class.cast()來避免它。適用於單個通用元素容器,但不適用於集合。 – akarnokd 2009-07-15 07:30:34

+0

或者最好使用通配符泛型``(YourClazz )` - Java從不警告這樣的類型轉換,因爲它們是安全的。但這並不總是可行的(詳情請參閱泛型常見問題解答)。 – xfix 2018-01-21 11:33:43

39

這是一個註釋,用於禁止關於未經檢查的泛型操作(而非例外)的編譯警告,如強制轉換。它基本上意味着程序員不希望收到他在編譯特定位代碼時已經知道的這些信息。

你可以閱讀更多關於這個具體標註位置:

SuppressWarnings

此外,Oracle提供了註釋的使用這裏的一些教程文檔:

正如他們所說的那樣,

「可以與仿製藥的出現(在課題爲泛型討論)之前舊代碼交互時,會出現‘未選中’警告」。

9

SuppressWarning註釋用於抑制註釋元素的編譯器警告。具體而言,unchecked類別允許抑制由於未檢查類型轉換而生成的編譯器警告。

+0

您的SupressWarning鏈接已停用;這裏有一個替代方法:http://docs.oracle.com/javase/specs/jls/se6/html/interfaces.html#9.6.1.5 – 2015-07-29 15:57:59

3

據我所知,目前它與抑制有關泛型的警告有關;泛型是一種新的編程構造,它在JDK 5以前的JDK版本中不受支持,因此舊構造與新構造的混合可能會帶來一些意想不到的結果。

編譯器警告程序員它,但如果程序員已經知道,他們可以使用SuppressWarnings關閉這些可怕的警告。

+1

JDK5是新的?它已經完成了其大部分服務壽命終止期。 – 2009-07-15 10:43:09

17

這也可能意味着當前的Java類型系統版本不夠好,您的情況。有幾個JSR propositions/hacks來解決這個問題:類型令牌,Super Type Tokens,Class.cast()。

如果你真的需要這種抑制,儘可能縮小它(例如,不要把它放在類本身或長方法)。例如:

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

    Collections.reverse(list); 
    return list; 
} 
5

您可以禁止編譯器警告,並告訴泛型,根據它編寫的代碼是合法的。

例子:

@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

一個技巧就是創建一個擴展的通用基接口的接口...

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

然後,你可以投之前的instanceof檢查...

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

簡單地說:這是編譯器指出它不能確保類型安全的警告。例如

JPA服務方法:

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

如果我didn'n anotate的@SuppressWarnings(「未登記」)在這裏,它會與線,在這裏我想回到我的ResultList問題。

快捷鍵類型安全手段:如果程序編譯時沒有錯誤和警告,並且在運行時不會引發任何意外的ClassCastException,則認爲該程序是類型安全的。

我建立在http://www.angelikalanger.com/GenericsFAQ/FAQSections/Fundamentals.html

0

在Java中,泛型是通過類型擦除來實現。例如,下面的代碼。

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

編譯爲以下內容。

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

List.of被定義爲。

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

哪種類型的擦除變成了。

static List of(Object e1, Object e2); 

編譯器不知道什麼是運行時的泛型類型,所以如果你寫這樣的東西。

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

Java虛擬機並不知道泛型類型是什麼在運行程序時,所以這個編譯和運行,對於Java虛擬機,這是一個強制轉換爲List類型(這是它可以驗證的唯一的事情,所以它只驗證)。

但現在添加此行。

Integer hello = actualList.get(0); 

和JVM將拋出一個意外ClassCastException,如Java編譯器插入隱式轉換。

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

unchecked警告告訴鑄造可能導致程序拋出一個異常別處程序員。用@SuppressWarnings("unchecked")抑制警告告訴編譯器,程序員認爲代碼是安全的,不會引起意外的異常。

你爲什麼要這麼做? Java類型系統不足以表示所有可能的類型使用模式。有時候你可能知道演員陣容是安全的,但是Java沒有提供這樣的說法 - 爲了隱藏這樣的警告,可以使用@SupressWarnings("unchecked"),以便程序員可以專注於真實的警告。例如,Optional.empty()返回一個單例以避免分配不存儲值的空白選項。

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

這投是安全的,存儲在一個空的可選值無法恢復,所以沒有意外的類轉換異常的風險。

相關問題