当前位置:  开发笔记 > 编程语言 > 正文

Java 8不兼容类型

如何解决《Java8不兼容类型》经验,为你挑选了1个好方法。

这是简单的代码

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class SimpleTest {

    public static void main(String[] args) {
    final ArrayList> maps = newArrayList(
        createMap("1", "a", Collections.EMPTY_MAP, Collections.EMPTY_MAP),
        createMap("2", "b", Collections.EMPTY_MAP, Collections.EMPTY_MAP),
        createMap("3", "c", Collections.EMPTY_MAP, Collections.EMPTY_MAP)
    ); 

    System.out.println(" maps = " + maps);
    }

    public static Map createMap(String value1, String value2, Map object1, Map object2) {
       Map map = new HashMap<>();
       map.put("value1", value1);
       map.put("value1", value1);
       map.put("object1", object1);
       map.put("object2", object2);
       return map;
    }    

    public static  ArrayList newArrayList(E... elements) {
    ArrayList list = new ArrayList(elements.length);
    Collections.addAll(list, elements);
    return list;
    }
}

当JAVA_HOME指向JDK 8并且我使用时,javac -source 1.7 SimpleTest.java我得到

SimpleTest.java:9: error: incompatible types: ArrayList cannot be converted to ArrayList>
        final ArrayList> maps = newArrayList(
                                                                ^

当我使用-source 1.8或不-source选择任何选项时,一切正常。现在,当JAVA_HOME指向JDK 7时,无论是否使用,代码总是会编译-source 1.7

最初,这个问题是关于一个软件,其中POM文件具有设置1.7和构建是失败的JDK 8,但也没关系的JDK 7。

现在要问的是-导致它发生的原因是什么?在我看来,这似乎是一种主要的忽视。为什么在source设置为的JDK 8上编译1.7失败?



1> Holger..:

您可以将代码简化为不需要第三方库的独立示例:

public class Test2 {
    @SafeVarargs
    static  ArrayList newArrayList(T... arg) {
        return new ArrayList(Arrays.asList(arg));
    }
    private final List> maps = newArrayList(
        createMap(null, Collections.EMPTY_MAP)
     );

    public static Map createMap(String id, Map m) {
        return null;
    }
}

这可以使用编译javac从jdk1.7,但不能与javac利用jdk1.8 -source 1.7

这里的要点是,javac与以前版本中包含的jdk1.8相比,jdk1.8仍然是不同的编译器,并且该选项-source 1.7不会告诉它模仿旧实现的行为,而是与Java 7 规范兼容。如果旧的编译器有错误,则新的编译器不必尝试重现该错误。

由于代码使用Collections.EMPTY_MAP而不是Collections.emptyMap(),原始类型Map将传递给createMap,从而使其成为具有原始结果类型的未经检查的调用Map

这是JLS§15.12.2.6要求的:

所选方法的结果类型确定如下:

如果以返回类型为void声明所选方法,则结果为void。

否则,如果要使该方法适用就必须进行未经检查的转换,则结果类型是该方法的声明的返回类型的擦除(第4.6节)。

似乎尚未在javacjdk1.7中完全实现此行为。有趣的是,添加类型参数时,它将正确执行此操作

public static  Map createMap(String id, Map m)

使其成为通用方法。然后,jdk1.7将产生相同的错误。但是引用的规则适用于所有方法调用。


相反,使用Java 8兼容性进行编译成功的事实源于具有完全不同规则的新目标类型推断。

推荐阅读
mobiledu2402851377
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有