草庐IT

java - Java 7/8 泛型中嵌套通配符的可分配性差异

coder 2024-03-11 原文

以下代码在 JDK8 中编译得很好,但在 JDK7 中会出现类型不兼容错误。

List<List<? extends Number>> xs = Arrays.asList(Arrays.asList(0));

根据 this answer , List<List<? extends Number>>List<List<Integer>> 没有父类(super class)型关系.

在 Java 8 中有什么改变使这个任务有效?我也很难理解为什么它不能在 Java 7 中工作。


这两个语句使用 JDK7 编译时没有类型错误:

List<? extends Number> xs = Arrays.asList(0);
List<? extends List<? extends Number>> ys = Arrays.asList(Arrays.asList(0));

我觉得这两个在 JDK7 中都可以工作,但上面的原始示例却不能。当然,所有这些都可以在 JDK8 中工作。我认为要真正理解这里发生的事情,我需要理解为什么这些示例在 Java 7 中是合法的,但原始示例不是。

最佳答案

我相信这与 invocation contexts 有关和 widening reference conversion .

基本上,在该调用上下文中,参数的类型 0Arrays.asList(0)可以装箱到Integer然后扩大到Number .发生这种情况时,Arrays.asList(0)返回类型为 List<Number> .通过相同的过程,List<Number>可以转换为List<? extends Number>在用作外部 Arrays.asList(..) 的参数之前.

这等同于在 Java 7 中使用显式类型参数

List<List<? extends Number>> xs = Arrays.<List<? extends Number>>asList(Arrays.<Number>asList(0));

在 Java 7 中,表达式的类型是相同的,无论它在哪里使用,无论是独立表达式还是用于赋值表达式。

引入 Java 8 poly-expressions其中表达式的类型可能会受到表达式目标类型的影响。

例如,在下面的赋值表达式中

List<Number> numbers = Arrays.asList(1);

表达式的类型 Arrays.asList(1)是被调用方法的返回类型,它完全取决于泛型类型参数。在这种情况下,该类型参数将被推断为 Integer因为值 1可以转换为Integer通过装箱转换(基元不能与泛型一起使用)。所以表达式的类型是List<Integer> .

在 Java 7 中,这个赋值表达式不会编译,因为 List<Integer>不能分配给 List<Number> .这可以通过在调用 asList 时提供显式类型参数来解决。

List<Number> numbers = Arrays.<Number>asList(1);

在这种情况下,方法调用需要一个 Number第一个参数的参数和值 1满足那个。

在 Java 8 中,赋值表达式是一个 poly expression

A method invocation expression is a poly expression if all of the following are true:

  • The invocation appears in an assignment context or an invocation context (§5.2, §5.3).

  • If the invocation is qualified (that is, any form of MethodInvocation except for the first), then the invocation elides TypeArguments to the left of the Identifier.

  • The method to be invoked, as determined by the following subsections, is generic (§8.4.4) and has a return type that mentions at least one of the method's type parameters.

作为一个多边形表达式,它会受到分配给它的变量类型的影响。这就是发生的事情。泛型 Number影响在调用 Arrays.asList(1) 时推断的类型参数.

请注意它在下面的例子中是如何不起作用的

List<Number> numbers = ...;
List<Integer> integers = ...; // integers is not a poly expression
numbers = integers; // nope

所以它不是协方差,但我们在某些地方得到了它的一些好处。

关于java - Java 7/8 泛型中嵌套通配符的可分配性差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24188824/

有关java - Java 7/8 泛型中嵌套通配符的可分配性差异的更多相关文章

  1. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  2. ruby-on-rails - Rails 编辑表单不显示嵌套项 - 2

    我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib

  3. ruby - 将散列转换为嵌套散列 - 2

    这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[

  4. Ruby Koans about_array_assignment - 非平行与平行分配歧视 - 2

    通过ruby​​koans.com,我在about_array_assignment.rb中遇到了这两段代码你怎么知道第一个是非并行赋值,第二个是一个变量的并行赋值?在我看来,除了命名差异之外,代码几乎完全相同。4deftest_non_parallel_assignment5names=["John","Smith"]6assert_equal["John","Smith"],names7end45deftest_parallel_assignment_with_one_variable46first_name,=["John","Smith"]47assert_equal'John

  5. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  6. Ruby——嵌套类和子类是一回事吗? - 2

    下面例子中的Nested和Child有什么区别?是否只是同一事物的不同语法?classParentclassNested...endendclassChild 最佳答案 不,它们是不同的。嵌套:Computer之外的“Processor”类只能作为Computer::Processor访问。嵌套为内部类(namespace)提供上下文。对于ruby​​解释器Computer和Computer::Processor只是两个独立的类。classComputerclassProcessor#Tocreateanobjectforthisc

  7. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  8. ruby - 在 Ruby 中重新分配常量时抛出异常? - 2

    我早就知道Ruby中的“常量”(即大写的变量名)不是真正常量。与其他编程语言一样,对对象的引用是唯一存储在变量/常量中的东西。(侧边栏:Ruby确实具有“卡住”引用对象不被修改的功能,据我所知,许多其他语言都没有提供这种功能。)所以这是我的问题:当您将一个值重新分配给常量时,您会收到如下警告:>>FOO='bar'=>"bar">>FOO='baz'(irb):2:warning:alreadyinitializedconstantFOO=>"baz"有没有办法强制Ruby抛出异常而不是打印警告?很难弄清楚为什么有时会发生重新分配。 最佳答案

  9. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  10. ruby-on-rails - 使用回形针的嵌套形式 - 2

    我有一个名为posts的模型,它有很多附件。附件模型使用回形针。我制作了一个用于创建附件的独立模型,效果很好,这是此处说明的View(https://github.com/thoughtbot/paperclip):@attachment,:html=>{:multipart=>true}do|form|%>posts中的嵌套表单如下所示:prohibitedthispostfrombeingsaved:@attachment,:html=>{:multipart=>true}do|at_form|%>附件记录已创建,但它是空的。文件未上传。同时,帖子已成功创建...有什么想法吗?

随机推荐