簡體   English   中英

Java generics 類型綁定。 為什么不編譯?

[英]Java generics type binding. Why isn't this compiling?

鑒於此通用 function:

<T> List<T> function() { return null; }

為什么會這樣編譯

List<String> l = function();

雖然這不

List<String> l = (List<String>) function();

因為當你做這樣的演員時:

(List<String>) function()

編譯器無法推斷function()調用的類型參數,而是將T綁定到Object

而在

List<String> l = function();

可以推斷T的正確類型。

請注意,如果通過顯式提供類型來規避類型推斷的工作,則可以強制轉換:

import java.util.List;

class Test {
    public static <T> List<T> function() { return null; }

    public static void main(String[] args) {
        List<String> l = (List<String>) Test.<String>function();
        //                              ^^^^^^^^^^^^^
    }
}

我不知道泛型參數的確切類型推斷規則。 但是,它們在JLS 第 15.12.2.7 節中指定。

看起來類型推斷發生在嘗試強制轉換之后(由編譯器)。

表達式的類型由表達式的左側確定,在嘗試強制轉換時尚未“解析”。 並且轉換本身失敗,因為對於尚未推斷的類型,(方法調用的)結果是List<Object>類型

JLS 的第15.12.2.7節指出類型推斷最后發生。

第一個使用類型推斷,使用分配結果的變量的類型。

在第二個中,調用的結果沒有分配給任何東西(在轉換完成之前),因此返回最通用的類型( List<Object> ),並且List<Object>不能轉換為List<String>

這是因為 javac 需要推斷 T,但 T 沒有出現在參數類型中。

static<T> T foo(){ .. }

foo(); // T=?

只有在 2 種情況下,javac 可以從上下文中推斷出 T

String s = foo(); // #1: assignment

String bar(){
    return foo(); // #2: return

在其他情況下,javac 不會,並且 T 被簡單地推斷為 Object

List<String>不擴展List<Object> 所以你不能施放它。

您可以通過以下方式指定 T

 List<String> l = this.<String>function();

那是因為編譯器無法推斷方法function()的參數化類型,因此它將T綁定到Object 您不能將List<Object>轉換為List<String>

這個問題並不准確。

List<String> m = (List<String>)function();

產生警告“類型安全:從 Object 到 List 的未經檢查的轉換”這是正確的,因為對泛型類型的所有轉換都是不安全的。

暫無
暫無

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

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