簡體   English   中英

如何在特定情況下Java不是類型安全的?

[英]How can it be that Java is NOT type safe in a particular situation?

今天我發現了一個非常奇怪的JVM 行為 ,一個(通常是類型安全的) List<Date>確實在運行時持有List<MyObject>

我想知道怎么會發生,但在網絡上找不到任何東西。

情況就是這樣:我正在使用JRE 1.6.0_18-b07JBoss EAP 6.0 Server上使用Spring Data JPA 1.2.0

錯誤地,在Spring Data JPA Repository類中,在@Query表達式中寫入了錯誤的結果類型。 應該是:

  @Query("select distinct trunc(record.orderDateTime) from MyType record [...]" )
  public List<Date> getOrderDates(...);

但是:

  @Query("select record from MyType record [...]" )
  public List<Date> getOrderDates(...);

因此,目的是加載日期列表( java.util.Date ),如果在第一個代碼片段中正確定義了查詢,則該日期工作正常。

但是編碼錯誤導致了以下結果:在運行時,實際上返回了一個List<MyType> ,即使方法的簽名定義了List<Date> 同樣在我的模型中, List<Date>的屬性包含List<MyType> 我調試了它,無法相信我的眼睛! 我甚至可以將此列表的內容寫入JSP(我只識別這種奇怪的行為,因為嘗試從MyTypeDate鍵入匹配時出現Spring Expression Language錯誤,因此無法再顯示JSP,其中當然不得不崩潰)。

天哪,我現在應該放棄對Java類型安全性的信任嗎?

有沒有人遇到過這樣的問題?

是否存在對此的解釋?

我可以做任何事情來解決這個問題,還是一般問題? 也許是另一個版本的JRE,JBOSS,......?

我想知道怎么會發生,但在網絡上找不到任何東西。

之所以發生這種情況,是因為泛型主要是僅編譯時功能。 元數據是根據類的類型參數,字段等來維護的......但是在執行時,類型參數(大部分)都會丟失。 例如:

Object x = new ArrayList<String>();
Object y = new ArrayList<Integer>();
System.out.println(x.getClass() == y.getClass()); // True

JVM無法區分 - 這就是為什么當您嘗試強制轉換時會收到警告的原因:

// At execution time, this cast will *really* only check for List
List<String> dodgyCast = (List<String>) y;

大多數情況下,編譯器使用泛型保持“常規”代碼安全。 但是當你有像ORM這樣的東西通過反射或動態字節代碼提供值時,所有這些安全性就會消失。

可悲的是,由於類型擦除,可能會發生這種情況。 您在集合中設置的類型僅在編譯時檢查,而不是在運行時檢查。

問題是您的查詢未編譯,因此Java無法知道它將返回哪種對象。 為了避免這種行為,我總是創建我的查詢測試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM