簡體   English   中英

未經檢查的轉換行為,包括和不包含變量

[英]Unchecked cast behavior with and without assignment to variable

為什么main中的第一行不會拋出ClassCastException,而第二行呢?

import java.util.function.Function;

class Scratch {

    static <T> T getSomething(Function<Integer, T> fun) {
        return (T) fun;
    }

    public static void main(String[] args) {
        Scratch.<String>getSomething(x -> "hello");
        String something = Scratch.<String>getSomething(x -> "hello");
    }
}

不同之處在於,您不會在第一種情況下使用方法的結果,而是在第二種情況下使用方法的結果。

強制轉換是一個表達式 ,但它不是StatementExpression 這意味着你不能這樣寫:

(String) somethingReturningAString();

但你可以寫:

String aString = (String) somethingReturningAString();

在編譯時,編譯器會在需要的地方插入checkcast指令,以及它可以在何處:

  • 它無法為第一種情況插入演員表,因此不會進行任何檢查。
  • 它可以(並且必須)在第二種情況下插入一個強制轉換,以確保它將一個實際上是String東西分配給一個String變量。 因此,它會檢查強制轉換,但失敗了。

值得一提的,有一些可能是意料之外的情況下,強制轉換不是絕對必要 ,但插入。 例如:

Scratch.<String>getSomething(x -> "hello").toString();

將失敗的ClassCastException ,因為它將轉換為:

((String) Scratch.getSomething(x -> "hello")).toString();

即使Object有一個toString()方法,所以它可以在沒有強制轉換的情況下調用它。

泛型只是一個編譯時檢查(讀取類型擦除 )。 所以在運行時你的getSomething()方法看起來類似於:

static Object getSomething(Function fun) {
    return fun;
}

現在你清楚地看到第一行永遠不會拋出異常

Scratch.getSomething(x -> "hello");

因為Function 一個Object ,因此可以毫無問題地返回。

然而,第二行拋出一個,因為這將類似於此:

String something = (String) Scratch.getSomething(x -> "hello");

Function仍然是一個Object因此它可以從方法返回,但它不是String ,因此,您得到ClassCastException

代碼編譯得很好,因為你指示編譯器你知道你在做什么。 您將在此行中收到Unchecked cast警告:

 return (T) fun;

此警告應該是編譯器向您(程序員)指示它(編譯器)無法確定該轉換是否成功的指示。

暫無
暫無

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

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