java - 这三个参数化变量有何不同?

标签 java generics

给定 AGenericClass 声明如下:

public class AGenericClass<T> {
  T subject;
  public void setSubject(T subject) {
    this.subject = subject;
  }
}

变量abc之间有什么区别?

AGenericClass<String> a = new AGenericClass<>();
AGenericClass<?> b = new AGenericClass<String>();
AGenericClass c = new AGenericClass<String>();

a.setSubject("L"); // OK.

b.setSubject("M"); // Error: setSubject(capture<?>) cannot be
                   // applied to (java.lang.String)

c.setSubject("N"); // Warning: Unchecked call to 'setSubject(T)'
                   // as a member of raw type 'AGenericClass'

a bc 都是在 IDE 没有提示的情况下声明的,但是当 setSubject 被调用。

最佳答案

这三者之间的差异很大程度上与您在编译时获得的检查有关。鉴于泛型旨在保护用户免受运行时不安全转换的影响,因此它们之间的关键和主要差异就 Root 于此。


AGenericClass<String>声明类型为 String 的泛型类实例.使用此泛型完成的任何需要泛型参数的操作都会将该参数绑定(bind)到 String ,并将在编译时强制执行类型检查和类型安全。

也就是说,如果你有AGenericClass<String> a = new AGenericClass<>();你试着调用a.setSubject(3) , Java 将不允许应用程序编译,因为类型不匹配。

AGenericClass<?>声明具有未知 类型的泛型类的实例。正式地,?是一个通配符,它​​可以是任何类型,可以如果您想从中检索元素,但不是如果您想要从中添加元素。

原因是什么? AGenericClass<?>实际上是 AGenericClass<? extends Object> ,这很重要,因为 in and out principle .通常(虽然这不是严格保证),任何与 extends 通用的东西意味着只读操作。

正如我之前所说,从中读取很好,因为保证您的类(class)至多Object ,但是您不能写入它,因为您不知道,也不能保证,您从任何给定的调用中添加了什么样的对象。

AGenericClass 没有 类型声明是原始类型。 You can read more about them here ,但要知道它们的存在是出于遗留兼容性原因。如果您的代码使用原始类型,您将失去编译时检查并且您的代码可能最终会抛出 ClassCastException。在运行时,调试、诊断和解决要困难得多。

关于java - 这三个参数化变量有何不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36052041/

相关文章:

java - 文本在网页中出现多少次 - Selenium Webdriver

Java安全访问控制异常

java - 从 JVM 获取正在运行的字节码

c# - 为什么我的测试 "propType == typeof(ObservableCollection<string>)"失败了?

typescript - 带有泛型的 Typescript 箭头函数的语法错误

java - 如何将大量值传递到 GET 请求参数中

java - 滑行不下载图像

java - JSON查询过滤传输

java - 如何将 Scala List[String] 转换为旧版 Java List<?>

c# - 在本地窗口中更改 T 类型 int