在此示例中:
import java.util.*;
public class Example {
static void doesntCompile(Map<Integer, List<? extends Number>> map) {}
static <T extends Number> void compiles(Map<Integer, List<T>> map) {}
static void function(List<? extends Number> outer)
{
doesntCompile(new HashMap<Integer, List<Integer>>());
compiles(new HashMap<Integer, List<Integer>>());
}
}
doesntCompile()
无法编译为:
Example.java:9: error: incompatible types: HashMap<Integer,List<Integer>> cannot be converted to Map<Integer,List<? extends Number>>
doesntCompile(new HashMap<Integer, List<Integer>>());
^
而compiles()
被编译器接受。
这个答案说明唯一的区别是,与不同<? ...>
,它<T...>
允许您稍后引用类型,似乎并非如此。
是什么区别<? extends Number>
,并<T extends Number>
在这种情况下,为什么不第一编译?
通过使用以下签名定义方法:
static <T extends Number> void compiles(Map<Integer, List<T>> map) {}
并像这样调用它:
compiles(new HashMap<Integer, List<Integer>>());
在jls§8.1.2中,我们发现(有趣的部分被我加粗了):
通用类声明定义了一组参数化类型(第4.5节), 每种可能通过类型arguments调用类型参数节的类型 。所有这些参数化类型在运行时共享同一类。
换句话说,将类型T
与输入类型进行匹配并进行分配Integer
。签名将有效地变为static void compiles(Map<Integer, List<Integer>> map)
。
关于doesntCompile
方法,jls定义了子类型化规则(第4.5.1节,由我加粗):
如果在以下规则的自反和传递闭包中,证明T2表示的类型集是T1表示的类型集的子集,则类型自变量T1包含另一个类型自变量T2,写为T2 <=
T1。其中<:表示子类型(§4.10)):
?扩展T <=?如果T <:S则扩展S
?扩展T <=?
?超级T <=?如果S <:T则为超级S
?超级T <=?
?超级T <=?扩展对象
T <= T
T <=?延伸T
T <=?超级T
这意味着,? extends Number
确实包含Integer
,甚至List<? extends Number>
包含List<Integer>
,但Map<Integer, List<? extends Number>>
and
并非如此Map<Integer,List<Integer>>
。在该SO线程中可以找到有关该主题的更多信息。您仍然可以?
通过声明期望使用以下子类型来使带有通配符的版本起作用List<? extends Number>
:
public class Example {
// now it compiles
static void doesntCompile(Map<Integer, ? extends List<? extends Number>> map) {}
static <T extends Number> void compiles(Map<Integer, List<T>> map) {}
public static void main(String[] args) {
doesntCompile(new HashMap<Integer, List<Integer>>());
compiles(new HashMap<Integer, List<Integer>>());
}
}
问题内容: 今天,我按照一些说明在Linux中安装软件。有一个脚本需要首先运行。它设置一些环境变量。 指令告诉我要执行,但是我执行错误了。因此未设置环境。最后,我注意到了这一点并继续进行。 我想知道这两种调用脚本方法的区别。我对Linux完全陌生,所以请尽可能详细。 问题答案: 运行脚本,将启动一个新的运行脚本的外壳。新的外壳程序不会影响启动脚本的父外壳程序。 是的简写形式,它将在当前shell中
问题内容: 我刚开始使用Spring。我遇到了很多教程。我看到使用更多的例子比。我查看了Spring文档,但无法弄清楚使用其中一个的好处。有人可以提供一些解释吗? 问题答案: 是的便捷子类。 JavaDoc描述了一些添加的属性,这些属性在某些情况下可能有用: UrlBasedViewResolver的便利子类,它支持InternalResourceView(即Servlet和JSP)以及诸如Jst
问题内容: 我刚刚看到了包含标签的CSS代码。我看着MDN看看是什么,但我真的不明白。 有人可以解释它是如何工作的吗? 它会在我们通过CSS选择之前创建DOM元素吗? 问题答案: 根据这些文档,它们是等效的: 唯一的区别是CSS3中使用了双冒号,而单冒号是旧版本。 推理: CSS 3中引入了:: before表示法,以便在伪类和伪元素之间建立区别。浏览器还接受:在CSS 2中引入的表示法。
问题内容: 以下哪个更好? 要么 我知道的唯一区别是,当“ a”为null时,第一个返回false,而第二个抛出异常。除此之外,它们是否总是给出相同的结果? 问题答案: 使用时,你需要B在编译时知道类。使用时可以是动态的,并且可以在运行时更改。
问题内容: 根据MDN: 在许多情况下,revert关键字的工作原理与未设置的关键字完全相同。唯一的区别是属性具有由浏览器或用户创建的自定义样式表(在浏览器侧设置)设置的值。 我不了解浏览器和自定义样式表。浏览器和自定义样式表也都可以替换,对吗? 问题答案: 从MDN: 如果未设置CSS关键字从其父级继承,则将其重置为继承的属性,如果不是,则将其重置为初始值。换句话说,在第一种情况下,其行为类似于
问题内容: 从文档中,我们可以了解有关该功能的以下信息: 处理所有待处理的事件,调用事件回调,完成所有待处理的几何图形管理,根据需要重新绘制窗口小部件,并调用所有待处理的空闲任务。此方法应谨慎使用,因为如果从错误的位置(例如,从事件回调内部,或者从可以以任何方式从事件回调中调用的函数等)调用,则可能导致真正令人讨厌的竞争状况。 )。如有疑问,请改用。 另一方面,关于此功能: 调用所有待处理的空闲任