假设我们有以下代码:
public class Main {
public static void main(String[] args) {
}
private static <K, V extends Comparable<V>> Map<K, V> sorted(Map<K, V> map) {
return map.entrySet()
.stream()
.sorted(Comparator.comparing(Entry::getValue))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
}
}
一个相当简单的片段——我们获取一个地图,并返回另一个代表相同地图但根据其值排序的地图。
让我们稍微改变一下功能——与其基于参数返回一些内容,不如介绍一个static
对象:
public class Main {
public static void main(String[] args) {
}
private static Map<Integer, String> map = new HashMap<>();
private static <K, V extends Comparable<V>> Map<K, V> sorted() {
return map.entrySet()
.stream()
.sorted(Comparator.comparing(Entry::getValue))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
}
}
请注意,我们唯一改变的是去掉参数,取而代之的是使用静态
字段。有人可能想知道为什么要引入泛型K
和V
——毕竟它们总是分别是整数
和字符串
。但是这难道不意味着Java可以很容易地推断出这些参数吗?为什么它会失败,错误为:
Error:(16, 25) java: incompatible types: inference variable K has incompatible bounds
equality constraints: K,K
lower bounds: java.lang.Integer
我看到了一些关于类似错误消息的问题,但我无法从中获得任何信息。这到底为什么会失败?也许值得一提的是,当编译器产生上述错误时,当使用IntelliJ IDEA时,Entry::getKey
和Entry::getValue
方法引用以红色高亮显示,当鼠标悬停在上方时,会显示以下消息:
Non-static method cannot be referenced from a static context.
这很奇怪,因为我在javac
的实际错误消息中看不到类似的东西。
具体类型参数在调用站点确定。
例如,其中任何一个都是合法通话:
Map<Void, Integer> mapA = Main.sorted();
Map<String, String> mapB = Main.sorted();
Map<Integer, GregorianCalendar> mapC = Main.sorted();
...但是,给定方法定义,它们都将返回相同的值;由于它们的类型不同,至少有两种mapA。。C
的类型不正确(事实上,这三种类型都不正确)。
泛型的唯一目的是允许您省略显式类型转换;这是有利的,因为编译器能够比您更好地推理一个强制转换(或者,更确切地说,整个代码中的所有强制转换)是否安全。
所以,如果你写了一个方法,它会返回一个映射
到目前为止,我只讨论了具体的类型参数:
Void、整数、字符串、格里高利日历
。但是编译器没有区分这些类型参数和类型变量。因此,如果你说一个方法返回一个Map
这里重要的一点是,这必须适用于任何
K
和任何V
,因为正如问题的第一行所述,K
和V
的具体值是在通话地点确定的。
只有少数
K
可以安全地将整数
转换为(整数
,数字
,对象
,可序列化
);null
整数可以转换为任何其他类型,但编译器不知道Integer
s是否为null
。所以编译器只是说“我不能确定这些强制转换是否安全,所以我将不允许它们”。
(类似的情况适用于
V
)。
当
K
和V
分别是整数
和String
时,您的方法只返回一个安全值,因为map
是一个Map
private static Map<Integer, String> sorted() {
return map.entrySet()
.stream()
.sorted(Comparator.comparing(Entry::getValue))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
}
(也可以是
地图。)
为什么需要泛型 前言 泛型程序最早出现1970年代的CLU和Ada语言中, 后来被许多机遇对象和面向对象的语言锁采用 1993年C++在3.0版本中引入的模板技术就属于泛型编程 1994年7月ANSI/ISO C++标准委员会通过的STL更是泛型编程的集大成者, 它已被纳入1998年9月C++标准之中. 2004年9月Java在J2SE 5.0(JDK 1.5)中开始使用泛型技术; 2005年11
问题内容: 在下面的示例中,为什么编译器能够为in中的第一次调用推断出通用参数,而在第二次调用中却无法推断出通用参数?我正在使用Java 6。 (编译错误为 Nonsense.Bar类型的func(Nonsense.Foo)方法不适用于参数(Nonsense.Foo) )。 注意:我了解编译器错误可以通过test()中的第三行来解决-我很好奇是否存在阻止编译器推断类型的特定限制。这 似乎 对我有足
问题内容: 我正在尝试在我的角度应用程序中编写一个小型服务,这将使我能够选择在全局Javascript对象中指定的配置参数。除非文档准备好,否则我不想尝试访问全局配置对象(因为我不能保证脚本元素在HTML中的插入顺序)。 但是,我不明白为什么我需要调用才能使分辨率实际传播到回调。 问题答案: 在AngularJS中,resolve()的结果在$digest周期内异步传播,而不是立即传播。这意味着仅
本文向大家介绍为什么我们需要一个数据库,包括了为什么我们需要一个数据库的使用技巧和注意事项,需要的朋友参考一下 数据库是数据的集合,通常以电子形式存储。数据库的设计通常是为了使其易于存储和访问信息。 好的数据库对任何公司或组织都至关重要。这是因为数据库存储了有关公司的所有相关详细信息,例如员工记录,交易记录,工资详细信息等。 数据库重要的各种原因是- 管理大量数据 数据库每天存储和管理大量数据。使
我试图理解为什么我们需要通配符——Java泛型中的问号,为什么我们不能使用普通的单字符t或E等作为类型?请看以下示例: 结果是一样的,尽管通配符版本更简洁。这是唯一的好处吗?
问题内容: 我可以将数据发送到服务器,但是只有在使用FromBody-Attribute时才可以。 为什么无法使用Post从主体自动读取json数据? 后端Web API 前端angularjs 问题答案: 仅因为某事是POST请求,所以没有明确的规则如何传递参数。POST请求仍可以包含URL中编码的查询参数。方法参数应该是“简单”类型(字符串,整数等)的查询参数。 通常,复杂类型应该是POST表