自 Java5 以来初始化通用集合的方法 +钻石操作员

发布于 2024-12-13 23:41:01 字数 1382 浏览 0 评论 0原文

据我所知,泛型仅在编译时有用。

因此可以声明:

private Set set = new HashSet<String>();

然后,在这个字符串哈希集中,将狗或任何东西添加到该集合中,没有任何问题,因为在运行时没有像数组那样进行任何检查(ArrayStoreException ...)(但是您可能会遇到问题就像使用该集合时的类转换一样...

所以我想说的是,我们通常以这种方式实例化泛型集合:

Set<String> set = new HashSet<String>();

我的问题是,为什么我们要放置 HashSet 的类型,因为只有 HashSet 的引用类型变量真的很重要(我认为)

。意思是,我们可以简单地写:

Set<String> set = new HashSet();

并且它的工作原理完全相同,对吧? 那么为什么我们通常要在实例化的时候写类型呢? (这不是强制性的)


编辑

我知道用于类型推断的“钻石运算符”,但为什么我们甚至需要它!因为类型推断已经起作用了!

以下代码:

            Set<String> set = new HashSet();
            set.add("Test add a string 1");
            set.add("Test add a string 2");
            for ( String s : set ) {
                    System.out.println(s);
            }

产生输出:

测试添加字符串1 测试添加字符串2

自己测试一下 http://ideone.com/vuiCE

所以现在你谈论类型推断作为 Java7 功能,但它已经是为我工作...

使用java7,我将不得不替换我的

            Set<String> set = new HashSet();

By

            Set<String> set = new HashSet<>();

它仍然是2个额外的字符来完成完全相同的事情,不是吗? (除非泛型不仅仅是Java7的编译时?我不知道)

As far as i know, the generics are only useful at compilation time.

Thus it is possible to declare:

private Set set = new HashSet<String>();

And then, in this string hashset, to add dogs or anything to that set, without any problem since there is not any check at runtime like for arrays (ArrayStoreException...) (but you may have problems like a classcast when you use that set...

So what i want to say is, we usually instantiate generic collections that way:

Set<String> set = new HashSet<String>();

My question is, why do we put the type of the HashSet, since only the type of the reference of the variable is really important (i think).

I mean, we could simply write:

Set<String> set = new HashSet();

And it would work exactly the same right?
So why do we usually write the type during the instantiation? (it's not mandatory)


Edit

I know about the "diamond operator" for type inference but why do we even need it!!! since type inference is already working!

The following code :

            Set<String> set = new HashSet();
            set.add("Test add a string 1");
            set.add("Test add a string 2");
            for ( String s : set ) {
                    System.out.println(s);
            }

Produces the output:

Test add a string 1
Test add a string 2

Test it yourself
http://ideone.com/vuiCE

So now you talk about type inference as a Java7 feature, but it is already working for me...

With java7 i will have to replace my

            Set<String> set = new HashSet();

By

            Set<String> set = new HashSet<>();

It's still 2 extra characters for doing exactly the same thing no? (Unless generics are not only compile time with Java7? I don't know)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

耶耶耶 2024-12-20 23:41:01

它的工作原理完全一样吗?

在运行时:

在编译时:

您的代码会将包含任意对象的集合分配给存储包含字符串的集合的变量,这是不好的,并且会被类型检查员皱起眉头。

当您编写 new HashSet() 时,您正在使用 原始类型。我提到这个问题的含义以及为什么应该避免它:


一般来说,你可以这样争论:

Set<String> set = new HashSet();

HashSet tmp = new HashSet();
...
Set<String> set = tmp;

它不远,反过来又离它不远,

HashSet tmp = new HashSet();
tmp.add(7);
...
Set<String> set = tmp;

它仍然可以编译,但是是有一千个理由不好:)


Java 7 允许您编写

Set<String> set = new HashSet<>();

,这会告诉编译器推断 <...> 之间的类型。

有关“钻石运算符”的文档:

And it would work exactly the same right?

In runtime: Yes.

In compile time: No

Your code would be assigning a set containing arbitrary objects, to a variable storing a set containing strings which is bad, and will be frowned upon by the type-checker.

When you write new HashSet() you're using a raw type. I refer to this question regarding it's meaning, and why it should be avoided:


In general, you could argue like this:

Set<String> set = new HashSet();

is not far from

HashSet tmp = new HashSet();
...
Set<String> set = tmp;

which in turn is not far from

HashSet tmp = new HashSet();
tmp.add(7);
...
Set<String> set = tmp;

Which still compiles, but is bad for a thousand reasons :)


Java 7 allows you to write

Set<String> set = new HashSet<>();

though, which tells the compiler to infer the type between the <...>.

Documentation on the "diamond operator":

违心° 2024-12-20 23:41:01

您最后的建议是类型推断,并且已通过所谓的菱形运算符在 Java 7 中引入:

Set<String> set = new HashSet<>();

所以是的,这可能从一开始就存在。但这是 Java,通常需要几十年的时间才能获得新的语言功能批准(<-- 有点夸张)

Your suggestion at the end is type inference and has been introduced in Java 7 via the so-called diamond operator:

Set<String> set = new HashSet<>();

So yes, that could've just been there from the beginning. But this is Java and it usually takes several decades to get a new language feature approved (<-- slight exaggeration)

心房敞 2024-12-20 23:41:01

尽管 Java 目前删除了泛型类型信息,但他们在设计语言和库时非常小心,以便将来可以添加回完整的泛型类型信息(所谓的具体化)。任何正确编写的通用代码(即没有任何 javac 警告)都将在这种语言更改中幸存下来。在您的示例中,钻石版本是面向未来的;原始版本不是 - 当然它仍然必须编译,但它会在运行时抛出类型转换异常。

然而,这种未来兼容性完全是一种幻想。擦除将永远伴随着我们。如果引入完全具体化,可以肯定地说几乎所有重要的通用代码都会崩溃,因为每个人都在编写不正确通用代码。

这不是我们的错。 Java 迫使我们这样做。它让我们消除了废话,我们别无选择,只能绕过它来实现一些东西。我们的代码充满了对擦除细节知识的依赖。

JDK是最罪孽深重的一个。 JDK API 经过精心设计,可以在具体化中生存;然而,实现取决于擦除。如果Java增加了具体化,这些JDK代码就必须重写。如果 Java 团队指责我们编写了不正确代码,而他们自己却必须做同样的事情,那就太虚伪了。

考虑到大量代码如果不重写就无法在具体化中生存,我们可以有把握地说,只要 Java 保持向后兼容性的承诺,它就永远不会添加具体化。

在这种情况下,是的,无论如何。 Set并没有什么真正可怕的地方。 set = new HashSet()。就我个人而言,我总是添加 <> 以避免警告。 (实际上,只要有可能,我都会尝试使我的代码具有具体化证明,正如我所说,这是一种妄想行为)

在您的示例中,推理是微不足道的。可能存在更复杂的情况,其中 <> 推理并不是那么简单,它的类型检查可能会有所帮助,而原始版本则缺乏这一点。

class Foo<T>
{
    Foo(Class<T> clazz){}
}

Foo<String> foo1 = new Foo(Integer.class);    // compiles (wrongly) 

Foo<String> foo2 = new Foo<>(Integer.class);  // does not compile

Although Java currently erases generic type info, they have been extremely careful to design the language and libraries so that it is possible in future to add back full generic type info (so called reification). Any correctly written generic code (i.e. without any javac warning) will survive such language change. In your example, the diamond version is future proof; the raw version is not - it still must compile of course, but it will throw type cast exception at runtime.

Yet, this future-compatibility is a completely delusional. Erasure will stay with us forever. If full reification is introduced, it is safe to say almost all non trivial generic code will break, because everybody is writing incorrect generic code.

It is not our fault. Java forces us to. It gives us the bullshit erasure, and we have no choice but to hack around it to implement stuff. Our code is full of dependencies on detail knowledge of erasure.

JDK is the most guilty one. JDK APIs are carefully designed to survive reification; however the implementations depend on erasure. If Java adds reification, these JDK codes must be rewritten. Java team will be extremely hypocritical if they blame us for writing incorrect code while they must do the same thing themselves.

Given the amount of code that cannot survive reification without rewrite, we can safely say Java is never going to add reification, as long as it keeps the commitment on backward compatibility.

In that case, yeah, whatever. Nothing really terrible about Set<String> set = new HashSet(). Personally I always add <> to avoid the warning. (Actually whenever possible I'll try to make my code reification-proof, which is, as I said, a delusional act)

In your example, inference is trivial. There can be more complex case where <> inference is not so trivial, its type checking can be helpful, which the raw version lacks.

class Foo<T>
{
    Foo(Class<T> clazz){}
}

Foo<String> foo1 = new Foo(Integer.class);    // compiles (wrongly) 

Foo<String> foo2 = new Foo<>(Integer.class);  // does not compile
倾其所爱 2024-12-20 23:41:01

Java 7 解决了添加有限类型推断的问题
类实例创建表达式。在需要显式声明参数化类型的情况下
构造函数,以及完整的参数化类型 < T1、T2、...Tn>的
该构造函数从上下文中显而易见,然后参数化
构造函数的类型可以替换为空类型集
参数:<>。 <>构造时使用构造是合法的
对象并将其分配给变量,或者将其传递为
一个参数。

详细信息:点击此处

Java 7 addresses the addition of limited type inference for
class instance creation expressions. In cases where parametrized types need to be explicitly declared for a
constructor, and the full parametrized type < T1 , T2 , ...Tn > of
that constructor is obvious from the context, then the parameterized
type of the constructor can be replaced with an empty set of type
parameters: <>. The <> construct is legal to use when constructing an
ob ject and either assigning it to a variable, or when passing it as
a parameter.

For details : click here

儭儭莪哋寶赑 2024-12-20 23:41:01

其实并不需要。
如果您键入

Set<String> s = new HashSet();

代码进行编译,我们会收到一条警告,我们可以使用 Xlint 检查该警告。

Note: filetest.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

然后,如果我们尝试添加一个整数值,例如我们会收到编译错误。

Actually it is not required.
If you type

Set<String> s = new HashSet();

the code compiles and we get a warning which we can check with Xlint.

Note: filetest.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

Then if we try to add an integer value for example we get a compile error.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文