Java,Generics:Set <?> s = HashSet <String>()和Set s = HashSet <String>()之间有什么区别?

Sri*_*nth 4 java generics

我正在阅读有关仿制药中未知类型和原始类型的内容,我想到了这个问题.换句话说,是......

Set<?> s = new HashSet<String>();
Run Code Online (Sandbox Code Playgroud)

Set s = new HashSet<String>();
Run Code Online (Sandbox Code Playgroud)

......一个一样?

我试了一下,他们似乎都完成了同样的事情,但我想知道他们是否与编译器有任何不同.

Roh*_*ain 7

不,他们不一样.这是基本的区别:

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

Set s = HashSet<String>();
s.add(2);  // This is valid.
Run Code Online (Sandbox Code Playgroud)

关键是,第一个是无界参数化类型Set.编译器会在那里执行检查,因为除了null这些类型之外你不能添加任何东西,编译器会给你一个错误.

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

你可以看到那里失去类型安全的结果.添加2到集合将在编译时失败Set<?>,但对于原始类型Set,它将成功添加,但它可能会在运行时抛出异常,当您从集合中获取元素,并将其指定为say String.

除此之外,您应该避免在较新的代码中使用原始类型.您很少会找到任何可以使用它的地方.使用原始类型的几个地方是访问static该类型的字段,或获取Class该类型的对象 - 您可以这样做Set.class,但不能Set<?>.class.

  • 情况1(*无效的一个*)可以用于???的任何情况 (3认同)
  • "无效"可以在这种情况下工作:`设置<?super String> s = new HashSet <String>();`例如 (2认同)

JB *_*zet 5

第一个创建一个Set<?>,意思是:"一个未知类的通用集合".您将无法向此集添加任何内容(null除外),因为编译器不知道其泛型类型是什么.

第二个创建一个原始的非泛型集,您可以添加任何您想要的东西.它不提供任何类型安全性.

我不明白你为什么要使用它们.Set<String>应该是声明的类型.