繁体   English   中英

构造函数中的泛型推理

[英]Generic inference in constructors

如果我有一个类Foo

public class Foo<T> {
    public Foo(T t) {
        //do something
    }

    public static <E> void bar(E e) {
         //do something
    }
}

为什么Foo.bar("String"); 推断E是一个String(因此不会抛出编译器警告)但是new Foo("String"); 不是说T是一个字符串?

因为构造函数可以被认为是一个特殊的实例方法,所以它不是类型化的 - 它从类名(带有类型参数)获取它的类型,例如Foo<String> 即构造函数未定义为:

public <T> Foo(T t) ...

也不是。 这样做会隐藏类的泛型类型(并且会收到警告)

然而,静态方法键入的。 FYI,一般推断类型的泛型参数,相当于:

Foo.<String>bar("String");

当Java实现泛型时,决定实例化没有类型参数的泛型类总是返回原始类型。 这与缺少类型参数的泛型方法不同,编译器尝试推断类型参数。 来自Java教程:

通常,Java编译器可以推断泛型方法调用的类型参数。 因此,在大多数情况下,您不必指定它们。

但当讨论转向构造者时:

请注意,要在泛型类实例化期间利用自动类型推断,必须指定菱形。 在以下示例中,编译器生成未经检查的转换警告,因为HashMap()构造函数引用HashMap原始类型,而不是Map<String, List<String>>类型:

Map<String, List<String>> myMap = new HashMap(); // unchecked conversion warning

来源: http//download.oracle.com/javase/tutorial/java/generics/gentypeinference.html

这在Java 7中保持不变,但是他们试图通过支持菱形语法来减少重复性。 例如, Foo<String> foo = new Foo<>("String") 请参阅同一篇文章的这一部分

我想你需要这样做

new Foo<String>("String");

告诉得到通过的泛型信息; 类似于Collections API。

看看这个,我想在这里猜一想。 考虑以下:

public class Foo {
    public <E> Foo(E t) {
        //do something
    }

    public static <E> void bar(E e) {
         //do something
    }
}

在上面的类中,在实例化Foo时没有得到警告,如下所示:

Foo f = new Foo("String");

这是有效的,因为这里推断出E的类型。 就像你期望它在方法案例中发生一样。 但是,您获得的错误不是因为参数类型未被推断,而是因为无法推断类的原始类型。

我认为这归结为类原始类型可以传播到方法,但方法不能使用推理设置类原始类型。

@Kublai Khan的回答是正确的; 为了向后兼容性, new Foo(s)的类型是原始Foo

Java7的构造函数菱形类型推断( new Foo<>(s) )与方法上的方法类型推断相同,并在其中定义。

http://cr.openjdk.java.net/~darcy/ProjectCoin/ProjectCoin-Documentation-v0.9375.html#diamond

如果类实例创建表达式使用“<>”来消除类类型参数,则为了重载解析和类型参数推断而定义方法列表m1 ... mk ...

...然后使用§15.12.2(确定方法签名)中描述的过程选择m1 ... mk中的一个

你的怀疑是正确的,构造函数可以像方法一样使用推理,没有本质区别。 由于向后兼容性问题,您只需添加<>

为什么用Java 6年来添加这个功能是另一回事。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM