Java 7中的菱形操作符允许如下代码:

List list = new LinkedList<>();

然而,在Java 5/6中,我可以简单地写:

List list = new LinkedList();

我对类型擦除的理解是它们完全相同。(无论如何,泛型都会在运行时删除)。

为什么还要麻烦钻石呢?它允许什么新的功能/类型安全?如果它没有产生任何新的功能,为什么他们把它作为一个功能来提到呢?我对这个概念的理解有缺陷吗?

请注意,如果使用静态工厂方法,这不是问题,因为Java对方法调用进行类型推断。

当你禁用警告时,它实际上是无用的…:)我喜欢

它已经被回答了,但它也在Java教程(页面的中间):DOCS.Oracle、COM/JavaSe/Tube/Java/Guogys/Helip;

关于dzone的文章不错。

我的观点是,它是listlist=new linkedlist();也就是说,保持它的通用性。

问题与

List list = new LinkedList();

在左侧,您使用的是通用类型List,在右侧,您使用的是原始类型LinkedList。Java中的原始类型只与前泛型代码兼容,不应用于新代码中,除非你绝对得这么做。

现在,如果Java从一开始就有泛型,并且没有类型,比如EDCX1(6),它最初是在有泛型之前创建的,它可能是这样做的,以便泛型类型的构造函数在可能的情况下从赋值的左手边自动推断出它的类型参数。但事实并非如此,为了向后兼容,它必须对原始类型和泛型类型进行不同的处理。这使得它们需要做一个稍微不同但同样方便的方法来声明一个通用对象的新实例,而不必重复它的类型参数…钻石操作员。

对于您最初的Listlist = new LinkedList()示例,编译器会为该分配生成一个警告,因为它必须这样做。考虑一下:

List strings = ... // some list that contains some strings

// Totally legal since you used the raw type and lost all type checking!

List integers = new LinkedList(strings);

泛型的存在是为了提供编译时保护,以防做错事。在上面的示例中,使用原始类型意味着您没有得到这种保护,并且在运行时会得到一个错误。这就是为什么不应该使用原始类型的原因。

// Not legal since the right side is actually generic!

List integers = new LinkedList<>(strings);

但是,diamond运算符允许将赋值的右侧定义为一个真正的泛型实例,该实例与左侧具有相同的类型参数…不必再输入这些参数。它允许您以几乎与使用原始类型相同的努力来保持泛型的安全性。

我认为要理解的关键是原始类型(没有<>)不能被视为通用类型。当您声明一个原始类型时,您将无法获得泛型的任何好处和类型检查。你还必须记住,泛型是Java语言的通用部分。它们不仅适用于Collections的no arg构造函数!

在您的第二个代码块中,该行LinkedList raw = a;将导致未选中的警告。这与问题中建议的方法不同。

@罗曼:这两种情况下,右手边都是未加工的。原始类型和泛型类型不应该混合在一起,仅此而已。

@罗曼:我换了一个例子,更清楚地表明,即使右手边是new LinkedList,也有可能出现问题。

向后兼容性很好,但不能以牺牲复杂性为代价。为什么Java 7不能只引入EDCOX1×5编译器开关,而如果不存在,那么EDCOX1?6将禁止所有原始类型,只执行严格的泛型类型。这将使我们的代码不再那么冗长。

@Rosdi:同意,在新代码中不需要原始类型。但是,我非常希望在源文件中包含Java版本号(而不是使用命令行(MIS)),请参阅我的答案。

我并不是完全按照这个回答,我必须说有两个原因——第一,我知道没有"通用实例"这样的东西,第二,左边的信息用在右边是不正确的。采用声明对象o=New LinkedList<>();…那里没有信息,没有任何东西可以从作业的左侧"复制"到右侧。

我个人不喜欢钻石的使用,除非你在同一行定义和实例化钻石。Liststrings = new List<>()是可以的,但是如果你定义了private Listmy list;,然后在你用my_list = new List<>()实例化的页面的中间,那就不酷了!我的列表又包含什么?哦,让我四处寻找定义。突然间,钻石捷径的好处就消失了。

所以如果它是一个无参数的构造函数,那么右边使用泛型和右边使用原始类型是一样的?

@Rmirabelle和:my_list = getTheList()有什么不同?有几种更好的方法来处理这种问题:1。使用一个显示鼠标悬停时变量类型的IDE。2。使用更有意义的变量名,如private Liststrings3。除非确实需要,否则不要拆分变量的声明和初始化。

@rmirabelle,netbeans允许您按住ctrl键并单击变量以跳转到定义(使用back按钮返回),因此,如果您使用一个好的IDE,这应该很少出现问题。

这个答案对Java 8仍然有效吗?当我将原始类型变量分配给泛型类型变量时,不会收到任何警告。

@ Morfidon:是的,它仍然适用于Java 8。我很确定你应该得到警告。

@Rosdi向后兼容性不仅适用于源代码,还适用于编译的字节码。

你的理解有点缺陷。钻石接线员是一个很好的功能,因为你不必重复你自己。在声明类型时定义一次类型是有意义的,但是在右侧再次定义类型却没有意义。干燥原理。

现在来解释一下关于定义类型的所有模糊性。在运行时删除该类型是正确的,但如果希望从具有类型定义的列表中检索某个内容,则在声明该列表时会将其恢复为所定义的类型,否则它将丢失所有特定功能,并且只有对象功能,除非将检索到的对象强制转换为其原始类型,否则它可以有时很棘手,会导致类异常。

使用Listlist = new LinkedList()将获得RAWTYPE警告。

Listlist = new LinkedList()是正确的代码。你知道,我也知道。问题(如我所理解的):为什么只有Java编译器不理解这个代码是相当安全的?

@罗曼:Listlist = new LinkedList()不是正确的代码。当然,如果是的话那就太好了!如果Java从一开始就有泛型,并且不需要处理非通用的泛型类型的向后兼容性,但它确实可以。

@ CaldJavaJava不必处理每一行的向后兼容性。在使用泛型的任何Java源文件中,应该禁止旧的非泛型类型(如果使用到遗留代码,则总是可以使用EDCOX1 2),而不可用的菱形操作符不应该存在。

此行导致[未选中]警告:

List list = new LinkedList();

因此,问题转换为:为什么[未选中]警告不会仅在创建新集合时自动取消?

我认为,这比添加<>特性要困难得多。

厄普:我还认为,如果法律上只为一些事情使用原始类型,那将是一团糟。

理论上,Diamond运算符允许您通过保存重复的类型参数来编写更紧凑(和可读)的代码。实际上,只不过是两个让人困惑的字符而已。为什么?

没有理智的程序员在新代码中使用原始类型。所以编译器可以简单地假设,通过不编写类型参数,您希望它推断它们。

Diamond运算符不提供类型信息,它只是说编译器"会很好的"。所以省略它,你就不会有任何伤害。在菱形运算符合法的任何地方,编译器都可以"推断"它。

IMHO,有一个清晰而简单的方法来标记一个源作为Java 7将比发明这些奇怪的东西更有用。在如此标记的代码中,可以禁止原始类型,而不会丢失任何内容。

顺便说一句,我不认为应该使用编译开关来完成。程序文件的Java版本是文件的属性,根本没有选择。使用一些像

package 7 com.example;

可以说清楚(你可能更喜欢复杂的东西,包括一个或多个花哨的关键词)。它甚至可以编译为不同Java版本编写的源,而不会出现任何问题。它允许引入新的关键字(例如,"module")或删除一些过时的特性(单个文件中的多个非公共非嵌套类或其他类),而不会失去任何兼容性。

你考虑过new ArrayList(anotherList)和new ArrayList<>(anotherList)之间的区别吗(特别是当它被分配给List和anotherList是List时)?

@保罗·贝洛拉:没有。让我惊讶的是,这两个都是编译的。戴钻石的人甚至没有警告。不过,我看不出这有什么意义,你能详细解释一下吗?

对不起,我解释得不太好。请看这两个例子的区别:ideone.com/uyhagh和ideone.com/ankg3t。我只是指出,使用diamond运算符而不是原始类型很重要,至少在传入具有泛型边界的参数时。

实际上,我没有花时间去读科林德的答案——他引用了几乎相同的话。

我在博客中做了一个评论,被过滤掉,很难理解其中的含义。我想说的是,如果我写的是像Listlist=new ArrayList();这样的行,那么编译器就没有理智的理由认为我需要一个原始类型,一个存在于支持前泛型代码的工件,而变量的List类型清楚地表明这不是前泛型代码(并且明确地说我不希望像其他人一样使用原始类型)。我写了一封信。

@霍尔格是的,这是有道理的。使用f(new List())可能会变得更复杂,但我想可以假设您实际上不需要行类型,除非您明确要求(例如使用List list=)。我不确定所有的边缘案件,但我和你在一起。+++尽管如此,假设需要一个特殊的语法,并且是我为一个原始类型的构造函数发明了一个语法,我还是使用new List<>()。D

那么,Java 8会从EDCOX1的8个参数类型推断出它的类型,它可能是通用的,而调用方可能是遗留的,但是很难想象,强制类型推断如何在这里产生问题,除非类型真的是不兼容的。另一方面,当从前通用代码迁移到通用代码而不是使用原始类型时,f(Arrays.asList(new UnmatchingType[num]))也会失败。这也是一个古老的问题,为什么泛型对待构造函数的方式与方法不同。

所以,如果我们要为原始类型引入一种新的语法,对于少数真正需要它的地方,为什么不使用像new @RawType List()这样的语法呢?这已经是有效的Java 8语法和类型注释允许在需要的每个地方使用它,例如EDCOX1(11)。考虑到原始类型当前会创建一个编译器警告,除非放置了适当的@SuppressWarnings,@RawType将是一个合理的替换,不需要更精细的语法。

当您编写Listlist = new LinkedList();时,编译器会生成一个"unchecked"警告。您可以忽略它,但是如果您曾经忽略这些警告,您也可能会错过一个通知您实际类型安全问题的警告。

因此,最好编写一个不会产生额外警告的代码,Diamond操作符允许您以方便的方式执行,而不需要重复。

其他响应中所说的都是有效的,但是用例不是完全有效的imho。如果您检查了guava,特别是与集合相关的内容,那么静态方法也会这样做。例如,lists.newarraylist(),它允许您编写

List names = Lists.newArrayList();

或静态导入

import static com.google.common.collect.Lists.*;

...

List names = newArrayList();

List names = newArrayList("one","two","three");

番石榴还有其他非常强大的功能,像这样,我真的想不出它有什么用途。

如果将菱形运算符行为设为默认行为,即从表达式的左侧推断类型,或者从右侧推断左侧的类型,则会更有用。后者是发生在斯卡拉。

Diamond运算符的要点只是在声明泛型类型时减少代码类型。它对运行时没有任何影响。

如果在Java 5和6中指定了唯一的区别,

List list = new ArrayList();

必须将@SuppressWarnings("unchecked")指定为list(否则将收到未选中的强制转换警告)。我的理解是钻石运营商正在努力使开发变得更容易。它与泛型的运行时执行完全无关。

你甚至不必使用那个注释。至少在Eclipse中,您可以告诉编译器不要对此发出警告,这样就可以了…

最好有注释。并非所有开发人员都在这里使用Eclipse。

java lt t gt 是什么意思_关于泛型:Java 7中的菱形运算符(&lt;&gt;)有什么意义?...相关推荐

  1. java与数据类型相关的十个关键字_乐字节Java变量与数据类型之一:Java编程规范,关键字与标识符...

    大家好,这次要给大家带来的是Java变量与数据类型.本文是第一集:Java编程规范,关键字与标识符. 一.编程规范 任何地方的名字都需要见名知意: 代码适当缩进 书写过程成对编程 对代码进行合理注释 ...

  2. java捕获定时器抛出的异常_详细了解Java中定时器Timer的使用及缺陷分析

    在需要定时并且周期执行任务时,在最初的JAVA工具类库中,Timer可以实现任务的定时周期执行的需求,不过有一定的缺陷,比如,Timer是基于绝对时间而非相对时间,因此Timer对系统时钟比较敏感,本 ...

  3. Java show两个整数加减_怎么样用java编写界面实现两个数的加法运算

    展开全部 import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; ...

  4. 用java和mysql开发网站怎么实现_如何用java开发一个网站?

    java语言和类库:java语言是支持整个java技术的底层基础,java类库是随java语言 Java 运行系统:主要指java虚拟机,负责将java与平台无关的中间代码翻译成本机的 Java ap ...

  5. java内存模型按照线程隔离性_深入理解Java多线程与并发框(第③篇)——Java内存模型与原子性、可见性、有序性...

    一.Java内存模型 Java Memory Modle,简称 JMM,中文名称 Java内存模型,它是一个抽象的概念,用来描述或者规范访问内存变量的方式.因为各中计算机的操作系统和硬件不同,方式机制 ...

  6. java JLabel改变大小后如何刷新_到底一行java代码是如何在计算机上执行的

    不知道你是否思考过,每次我们在IDEA中右键Run Application启动主方法,假如程序运行正常,控制台也打印出了你所要打印的信息,在这个过程中你知道这台计算机上那些硬件及其软件都是以什么样的方 ...

  7. java 删除已画出的线_如何删除java中的绘制线?

    问题是如何删除旧行?我的意思是,只在屏幕上显示当前的x和y行,使两行之间的交点"跟随"鼠标指针. 这是更新的代码: import javax.swing.*; import jav ...

  8. java输出两个整数的积_如何检查Java中的两个数字相乘是否会导致溢出?

    如何检查Java中的两个数字相乘是否会导致溢出? 我想处理两个数字相乘导致溢出的特殊情况. 代码看起来像这样: int a = 20; long b = 30; // if a or b are bi ...

  9. java安装了为什么运行不了_如何安装java(安装了java为什么不能使用)

    如何安装java 1.双击下载的程序包,它将如图所示. 2.单击下一步:在这里,我将路径更改为(D驱动器下的jdk1.8) 3.继续下一步,将出现一个弹出框,单击"确定". 4.单 ...

  10. java程序实现可移植性依靠的是_什么是JAVA的可移植性

    JAVA的可移植性: 1.JAVA作为一种编程语言:源代码可移植性 作为一种编程语言,JAVA提供了一种最简单同时也是人们最熟悉的可移植性–源代码移植.这意味着任意一个JAVA程序,不论它运行在何种C ...

最新文章

  1. 拆分工作簿为多个文件_掌握这几行代码,快速拆分Excel工作簿(内含源码)
  2. 一些常用的WebService.
  3. 使用SignalR从服务端主动推送警报日志到各种终端(桌面、移动、网页)
  4. 四位共阳极数码管显示函数_数码管模块.doc
  5. MTK 驱动开发(31)---Sensor 移植及调试1
  6. 英特尔发布至强E-2300服务器处理器,比上一代性能提高17%
  7. Android colorPrimary、colorPrimaryDark、colorAccent详解
  8. 关注Ionic底部导航按钮tabs在android情况下浮在上面的处理
  9. Oracle数据库常用操作sql语句
  10. linux终端下的网页浏览器w3m
  11. 图像处理五:python读取图片的几种方式
  12. 汉若塔c语言源码,汉诺塔C语言.doc
  13. dw1510_超低温种子储存柜
  14. 初探Watir --- Ruby 自动化测试框架
  15. Unity MeshAnimator 2.0.16 ShaderMode
  16. 利用会员积分系统提升会员复购率的要点
  17. 用c语言屏蔽鼠标键盘,用VBS屏蔽键盘和鼠标
  18. ChatGpt替代医生可能性分析
  19. 共享办公室,丰富运营体系
  20. HTTPS原理、单向和双向认证

热门文章

  1. Android操作系统的发展史
  2. Python 微信送她99朵玫瑰花
  3. 什么是HTML 实体?
  4. 工业自动化应用智能制造技术有哪些作用?
  5. Liunx awk命令详解
  6. 【Windows】 Win10下报错:该文件没有与之关联的应用来执行该操作。请安装应用,若已经安装应用,请在“默认应用设置”页面中创建关联
  7. 图文印刷行业公共服务网络平台路在何方
  8. 盒子性能测试软件,平板、盒子视频性能检测工具 - 安兔兔视频测试
  9. 关于框架Spring------学习的第三天(AOP开发)
  10. Qt5开发从入门到精通——第三篇三节(窗口篇——停靠窗口)