簡體   English   中英

在java 8中鍵入不匹配錯誤

[英]Type mismatch error in java 8

我有以下類使用以下方法。

public class MyClass {

    public static <T> T getSomeThing(final int id, final java.lang.reflect.Type type, final Map<Integer, String> someThings) {
        final String aThing = someThings.get(id);
        if (aThing == null || aThing.isEmpty()) {
            return null;
        }
        return GsonHelper.GSON.fromJson(aThing, type);
    }

}

GsonHelper為我提供了一些com.google.gson.GsonBuilder

public class GsonHelper {

    public static final com.google.gson.Gson GSON = getGsonBuilder().create();

    public static GsonBuilder getGsonBuilder() {
        return new GsonBuilder().setPrettyPrinting()
                .enableComplexMapKeySerialization()
                .registerTypeAdapter(new com.google.gson.reflect.TypeToken.TypeToken<byte[]>() {
                    // no body
                }.getType(), new Base64TypeAdapter())
                .registerTypeHierarchyAdapter(Date.class, new DateTypeAdapter())
                .registerTypeHierarchyAdapter(Pattern.class, new PatternTypeAdapter())
                .registerTypeAdapterFactory(new ListTypeAdapterFactory())
                .registerTypeAdapterFactory(new MapTypeAdapterFactory())
                .registerTypeAdapterFactory(new SetTypeAdapterFactory());
    }
}

在Java 7之前,我使用的方法如下:

Map<Integer, String> allThings = new HashMap<>();
//FILL allThings with values

if(MyClass.getSomeThing(7, java.lang.Boolean.class, allThings)){
    //do something
}

這很好。 因為該方法將返回一個布爾值,我可以在“if”里面使用它。 但是當我改為Java 8時,這是不可能的。 編譯器抱怨:

類型不匹配:無法從Object轉換為boolean

 //while this is working but would throw a JsonSyntaxException
final String myString = "myInvalidJsonString";
if(GsonHelper.GSON.fromJson(myString, java.lang.Boolean.class)){
    //do something
}

我知道java.lang.Boolean可以為null。 我可以用以下方法解決這個問題:

final Boolean b = MyClass.getSomeThing(7, java.lang.Boolean.class, allThings);
if(b){
    //do something
}

但我很好奇為什么這適用於Java 7而不是Java 8。 (未回答)
他們改變了什么? (無解答)
更改為Java 8時,此編譯器錯誤的原因是什么? (回答)

您的方法public static <T> T getSomeThing(final int id, final java.lang.reflect.Type t, final Map<Integer, String> someThings)不保證返回Boolean 它返回由調用者定義的T ,可以是任何東西,也就是Object

if語句無法知道T將具有哪種類型,因此無法保證將其轉換為布爾值。

為什么不將簽名更改為布爾值?

public static boolean getSomeThing(final int id,
                                   final java.lang.reflect.Type t,
                                   final Map<Integer, String> someThings)

或者你在尋找這個?

public static <T> T getSomeThing(final int id,
                                 final Class<T> clazz,
                                 final Map<Integer, String> someThings)

比這段代碼編譯和工作:

public static void main(String[] args) {
    if (getSomeThing(7, Boolean.class, emptyMap())) {
        System.out.println("It works!");
    }
}

public static <T> T getSomeThing(final int id,
                                 final Class<T> clazz,
                                 final Map<Integer, String> someThings) {
    ...
}

可以根據JLS 8推斷將getSomeThing()的結果分配給Boolean變量的最后一個版本,因為在賦值上下文中 ,目標類型Boolean確實將T推斷為Boolean 這里所有編譯器都同意。

關於原始情況,JLS 8不將if語句的條件分類為賦值上下文 在賦值或調用上下文之外,調用不被視為多表達式,而是作為獨立表達式( JLS 15.12 1st bullet )。 獨立表達式沒有目標類型。 在Java 8中沒有目標類型推斷可以回退到推斷TObject

Eclipse團隊甚至在Java 8 GA之前就要求澄清這方面的內容 不幸的是, 由此產生的問題直到今天仍未得到解決。

Ergo:JLS和觀察到的javac行為似乎並不一致。 可能,JLS是應該修復的實體。

更新: JLS不會更改(通過私人電子郵件確認),因此接受該程序是javac的錯誤。

編輯: Javac版本12將通過切換表達式傳播此錯誤:

public class X {
    @SuppressWarnings("preview")
    public void foo(int i) {
        if (switch(i) { default -> magic(); })
            System.out.println("true");
    }
    <T> T magic() { return null; }
}

由於目標類型為Boolean類型推斷,javac接受此操作,但在此位置執行類型推斷對於每個JLS是非法的。

暫無
暫無

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

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