[英]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中沒有目標類型推斷可以回退到推斷T
到Object
。
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.