Java,泛型:What';Set<;之间的区别是什么&燃气轮机;s=哈希集<;字符串>;()和Set s=HashSet<;字符串>;()?

Java,泛型:What';Set<;之间的区别是什么&燃气轮机;s=哈希集<;字符串>;()和Set s=HashSet<;字符串>;()?,java,generics,Java,Generics,我在读关于泛型中未知类型和原始类型的书,我想到了这个问题。换句话说,是 Set<?> s = new HashSet<String>(); Set s=newhashset(); 及 Set s=newhashset(); 。。。一模一样 我试过了,它们似乎都完成了相同的任务,但我想知道它们是否与编译器有所不同。不,它们不一样。以下是基本区别: Set<?> s = HashSet<String>(); s.add(2); // This

我在读关于泛型中未知类型和原始类型的书,我想到了这个问题。换句话说,是

Set<?> s = new HashSet<String>();
Set s=newhashset();

Set s=newhashset();
。。。一模一样


我试过了,它们似乎都完成了相同的任务,但我想知道它们是否与编译器有所不同。

不,它们不一样。以下是基本区别:

Set<?> s = HashSet<String>();
s.add(2);  // This is invalid

Set s = HashSet<String>();
s.add(2);  // This is valid.
Set s=HashSet();
s、 加(2);//这是无效的
Set s=HashSet();
s、 加(2);//这是有效的。
重点是,第一个是一个无界参数化类型
Set
。编译器将在那里执行检查,因为您只能向此类类型添加
null
,所以编译器将给您一个错误

虽然第二个是原始类型,但编译器在向其添加任何内容时不会执行任何检查。基本上,你失去了这里的类型安全性

你可以在那里看到放松型安全的结果。对于
set
,将
2
添加到集合将在编译时失败,但对于原始类型
set
,它将被成功添加,但当您从集合中获取元素并将其指定为
String
时,它可能在运行时引发异常


除了区别之外,您应该避免在较新的代码中使用原始类型。你几乎找不到任何可以使用它的地方。使用原始类型的地方很少是访问该类型的
静态
字段,或者获取该类型的
对象-您可以执行
设置.Class
,但不能执行
设置.Class
第一个创建
,这意味着:“某个未知类的通用集”。由于编译器不知道其泛型类型,因此无法向该集合添加任何内容(null除外)

第二种方法创建一个原始的、非泛型的集合,您可以向其中添加任何需要的内容。它不提供任何类型的安全性


我不明白你为什么要用它们
Set
应该是声明的类型。

第一个使用泛型,第二个使用原始形式的
Set

第一个使用通配符作为泛型类型参数。它的意思是“某个特定但未知类型的
集合
”,因此您不会被调用使用泛型参数的方法,例如
add
,因为编译器不知道它实际上是哪种特定类型。它通过在编译时不允许这样的调用来维护类型安全

原始表单删除所有泛型,并且不提供强类型。您可以向这样的
集合
中添加任何内容,甚至是非
字符串
s,这会使以下代码的类型不安全:

Set<String> genericSet = new HashSet<String>();
Set rawSet = genericSet;
rawSet.add(1);  // That's not a String!

// Runtime error here.
for (String s : genericSet)
{
    // Do something here
}
Set
告诉编译器集合包含特定类型,但类型未知。当您试图使用泛型参数(如
add(T)
)调用方法时,编译器使用此信息提供错误

Set
告诉编译器集合是“原始”类型,其中没有给出泛型类型参数。当调用对象的泛型方法时,编译器将发出警告,而不是错误

为了在没有警告的情况下向集合中添加元素,需要指定变量的泛型类型信息。编译器可以推断构造函数的类型参数。像这样:

Set<String> s = new HashSet<>();
Set s=newhashset();

此信息允许编译器验证
集合
是否以类型安全的方式使用。如果您的代码编译时没有类型安全警告,并且您没有使用任何显式强制转换,那么可以确保在运行时不会引发
ClassCastException
。如果您使用泛型,但忽略类型安全警告,您可能会看到在源代码中没有强制转换的位置抛出一个
ClassCastException

尝试通过
Set
添加一些内容(null除外)。可能重复的请参见:对我来说,这是一个从一般到良好的问题……为什么人们会投票关闭它??:\可能更好的复制:任何案例1(无效)可以用于???“无效”的场景在这种情况下可以工作:
set通常您指定编译时安全检查的泛型。因此,在Java1.5之后,应该没有理由指定原始类型。
Set<String> s = HashSet<String>();
Set<String> s = new HashSet<>();