【问题标题】:Use constructor reference with generics将构造函数引用与泛型一起使用
【发布时间】:2021-05-07 02:12:56
【问题描述】:

我对使用泛型使用构造函数引用有疑问。 为什么l = ArrayList<>::new; 有错误?
但是如果我使用 lambda 表达式,l = ()-> new ArrayList<>();,就可以了。为什么?

public  static void main(String... args){
        Supplier<ArrayList> 

        l = ()-> new ArrayList();  // good
        l = ()-> new ArrayList<>();     // good
        l = ()-> new ArrayList<Integer>();  // good
        l = ArrayList<Integer>::new;    // good
        l = ArrayList::new;  // good
        l = ArrayList<>::new;  // Error, why?
    }                               
}

【问题讨论】:

  • // Error, why? - 因为根本就没有这样的语法?

标签: java generics lambda


【解决方案1】:

section 15.13.1 中的 Java 语言规范类型的 cmets:

为方便起见,当泛型类型的名称用于引用实例方法(其中接收者成为第一个参数)时,目标类型用于确定类型参数。这有助于使用Pair::first 代替Pair&lt;String,Integer&gt;::first。类似地,像Pair::new 这样的方法引用被视为“钻石”实例创建(new Pair&lt;&gt;())。因为“钻石”是隐含的,所以这种形式不会实例化原始类型;事实上,没有办法表达对原始类型构造函数的引用。

对于构造函数调用,有三种变体:

Specifying the generic type explicitly Inferring the generic type Raw Type
new Something&lt;T&gt;() new Something&lt;&gt;() new Something()

但是如果用方法引用来引用构造函数,只有两种方式:

Specifying the generic type explicitly Inferring the generic type Raw Type
Something&lt;T&gt;::new Something::new You can't!

注意new Something&lt;&gt;()(带菱形)如何“对应”Something::new(不带菱形)。

还要注意shouldn't use raw types anyway,所以理想的情况是:

Specifying the generic type explicitly Inferring the generic type Raw Type
new Something&lt;T&gt;() new Something() You can't
Something&lt;T&gt;::new Something::new You can't!

理想情况下,根本不会有任何原始类型,因为它们不安全。但出于历史原因。

最初根本没有泛型类型。然后他们决定让一些现有的类型(例如Vector)通用(而不是只添加通用的新类型)。而且他们还想添加类型推断,这样您在调用构造函数时就不必指定泛型参数。请注意,此时仍有很多旧代码写着new Vector()

如果new Vector() 是推断泛型类型的语法,很多旧代码会因为很多原因而中断:可能没有足够的上下文来推断泛型类型,例如,因为代码不是写的时候考虑到遗传学!他们不想破坏旧代码,因此他们引入了一种用于推断泛型类型的新语法 - .

几年后,他们开始在语言中引入方法引用。这一次,用于推断类型的语法 Vector::new 不会破坏任何旧代码,因为没有旧代码使用过方法引用!与调用构造函数不同,方法引用本身是新的!

【讨论】:

  • 您好清扫车,感谢您的信息!根据您上面的解释,您提到的“理想场景”的表格。在“推断泛型类型”下,您有 new Something() to Something::new。那不应该是新的Something() to Something::new吗?
  • 因此,假设我有供应商 s = Something::new。赋值左侧的东西是原始类型。在右边,Something::new 等价于 new Something()。而这个“new Something()”实际上是从原始类型 Something 的左侧推断出泛型类型。
  • @CoolJetdi Something 被声明为通用的吗?如果Something 不是通用的,那么这与问题无关。如果是,那么是的,左边的Something 是一个原始类型,但是不,Something::new 不对应于new Something()(那将是理想的情况,其中new Something() 是推断泛型的语法类型)。它对应于new Something&lt;&gt;()。同样不,推断的泛型类型是Object(并不重要,因为 LHS 是原始类型)。我们不是试图推断Supplier 的类型参数。我们试图推断Something的类型参数。
  • 我明白了。我明白你的意思了。我误解了您对“理想情况”的含义。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-01
  • 1970-01-01
  • 2013-10-02
  • 1970-01-01
  • 2022-01-22
相关资源
最近更新 更多