Java 8 不兼容类型

2024-05-01

这是简单的代码

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<Map<String, Object>> 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<String, Object> createMap(String value1, String value2, Map<String, Object> object1, Map<String, Object> object2) {
       Map<String, Object> map = new HashMap<>();
       map.put("value1", value1);
       map.put("value1", value1);
       map.put("object1", object1);
       map.put("object2", object2);
       return map;
    }    

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

当 JAVA_HOME 指向 JDK 8 并且我使用javac -source 1.7 SimpleTest.java I get

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

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

最初这个问题是关于一个软件,其中 POM 文件有一个<source> and <target> set to 1.7在 JDK 8 上构建失败,但在 JDK 7 上构建正常。

现在的问题是——是什么原因导致它发生?在我看来,这似乎是某种重大的忽视。为什么在 JDK 8 上编译source set to 1.7失败?


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

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

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

这可以使用编译javac从jdk1.7开始,但不带javac从jdk1.8开始使用-source 1.7.

这里的重点是javac从jdk1.8开始仍然是一个与之前版本和选项中包含的编译器不同的编译器-source 1.7并没有告诉它模仿旧实现的行为,而是与 Java 7 兼容规格。如果旧的编译器有错误,新的编译器不必尝试重现该错误。

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

这是由JLS §15.12.2.6 https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.6:

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

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

  • 否则,如果方法需要未经检查的转换才能适用,则结果类型是方法声明的返回类型的擦除(第 4.6 节)。

似乎这种行为尚未(完全)实施javacjdk1.7的。有趣的是,当添加像这样的类型参数时,它会正确执行

public static <T> Map<String, Object> createMap(String id, Map<String,String> m)

使其成为通用方法。那么,jdk1.7就会产生同样的错误。但所引用的规则适用于all方法调用。


相比之下,使用 Java 8 合规性编译它的成功源于新的目标类型推断,它具有完全不同的规则。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 8 不兼容类型 的相关文章

随机推荐

  • 从 varchar(50) 列表中查找值包含单词的行

    我正在从 t sql 存储过程收集数据以导入到 C 程序中 我想先缩小数据范围 我的数据包含三个字段 描述了它们后面的三个值 我只需要查找描述中具有十几个关键字之一的字段 我正在使用将所有字段与值联合起来的东西 然后 AND TEXT123
  • java hashmaps 的 get() 函数

    我声明了以下哈希图 HashMap
  • 从 AppleScript 路径中提取文件扩展名

    我正在编写一个 Apple 脚本 最终将为 EyeTV 的所有 iTunes 导出标记广告 但我遇到了 AppleScript 路径的一个简单问题 EyeTV 应用程序将其返回为录制位置 这是上下文 set recordingID to 3
  • AttributeError:尝试删除字符时,“列表”对象没有属性“替换”

    我试图通过执行以下操作从字符串中删除字符 kickoff tree xpath id page div 1 div main div article div div 1 section 2 p 1 b 1 text kickoff kick
  • 在 Objective-C 中呈现另一个类的“控制器”

    如何呈现来自另一个类的 UIAlertController 我想知道如何捕获在 B 类中创建但在 A 类中呈现的 UIAlertController 中的 确定 按钮的操作 这就是我调用在 ClassA 的类 ErrorHandler 上创
  • HTML 5

    尽管开放视频标准似乎处于某种危险之中 但它是一个好主意 我看到了一些关于运动跟踪的演示 只是概念验证 但仍然很有趣 现在 我想说像这样的概念really如果能够访问用户的网络摄像头 这将是一种收获 想象一下 双手举在半空中浏览 Flickr
  • Stripe 订阅 Webhook 缺少元数据和 client_reference_id

    我在将 stripe webhook 链接到客户时遇到问题 因为我通常使用 client reference id 或元数据字段 但是订阅 webhook 似乎没有这些字段 例如事件结帐 会话 完成确实包含 client reference
  • Flask_dance:如果没有关联用户,则无法获取 OAuth 令牌

    我想将 Flask dance 与我的应用程序一起迁移 以使用户授权使用谷歌和其他社交网络 我收到此错误 Cannot get OAuth token without an associated user 在我在蓝图和 sqlalchemy
  • Dart 将客户端 Socket 升级为 WebSocket

    Since WebSocket https api dartlang org stable 2 1 0 dart io WebSocket class html在 Dart 中不允许直接设置安全上下文 https api dartlang
  • Windows 上的 npm run start 出现“DEBUG=*”问题

    name apokidsi version 0 717 contributors dependencies angular 1 5 8 angular cookies 1 5 8 angular messages 1 5 8 angular
  • 是否可以将 ServiceStack.Text.JsConfig 设置范围限制为您的库?

    我正在编写一个使用的自定义库ServiceStack Text https github com ServiceStack ServiceStack Text内部 使用我的其他库也可能使用 ServiceStack Text 我想改变一些J
  • 大熊猫群体中的百分位排名

    我不太清楚如何编写函数来完成分组百分位数 我将 1985 年至 2012 年的所有球队都放在一个数据框中 前 10 个如下所示 目前按年份排序 我想给一个百分位LgRnk分组依据Year 例如 1985 年的 23 LgRank 最差球队
  • 将 BeanFactory 注入 Bean

    我想注入一个SpringBeanFactory到由同一个创建的 BeanBeanFactory有什么办法可以这样做吗 顺便说一句 我正在开发一个网络应用程序 如果没有 我知道我可以通过以下方式获得 BeanFactoryRequestCon
  • React Native 中的 ListView 网格

    我正在 React Native 中构建一个简单的应用程序 它从远程 JSON 源获取列表并将其显示在屏幕上 到目前为止 使用优秀的example http www raywenderlich com 99473 introducing r
  • tampermonkey 脚本跨多个页面运行

    这是我想做的一个例子 每当我们位于目标网址 即 stackoverflow 时 底部就会出现一个带有按钮的粘性页脚 在搜索中输入内容的按钮之一是提交表单 之后 它等待页面加载并执行刚刚加载的页面的操作 即单击第一个链接 我发现仅在提交后单击
  • 为什么 Redshift 在加入时会自动修剪 varchar 列?

    我在使用 Redshift 时遇到了独特的问题 请参阅下面的说明性示例 drop table if exists joinTrim temp1 create table joinTrim temp1 rowIndex1 int charTo
  • 获取正在运行的程序的属性

    我想开发一个程序 其 ID 是一张牌 因为它在另一个正在运行的程序 例如扑克或红心游戏或其他程序 中播放 我首先尝试获取有关已运行的游戏程序的所需信息 但我从一开始就遇到了问题 我正在运行 MSVC 2013 并开发 MFC 应用程序 现在
  • Safari 中的日期无效

    alert new Date 2010 11 29 chrome ff 对此没有问题 但 safari 会喊 无效日期 为什么 编辑 好的 根据下面的评论 我使用了字符串解析并尝试了这个 alert new Date 11 29 2010
  • 如何使用speakhere示例中的AQRecorder

    我已经从 talkHere 示例中复制了 AQRecorder 以及所有其他所需的文件 这样做之后 由于编译错误 我将链中使用它的所有类重命名为 mm 现在似乎已解决 但是我仍然不知道如何使用 AQRecorder 类 该示例中还有另一个名
  • Java 8 不兼容类型

    这是简单的代码 import java util ArrayList import java util Collections import java util HashMap import java util Map public cla