Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 构造函数中的泛型推理_Java_Generics - Fatal编程技术网

Java 构造函数中的泛型推理

Java 构造函数中的泛型推理,java,generics,Java,Generics,如果我有一个类Foo: public class Foo<T> { public Foo(T t) { //do something } public static <E> void bar(E e) { //do something } } 公共类Foo{ 公共食物(T){ //做点什么 } 公共静态空栏(E){ //做点什么 } } 为什么Foo.bar(“字符串”)推断E是一个字符串(因此不会抛

如果我有一个类
Foo

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

    public static <E> void bar(E e) {
         //do something
    }
}
公共类Foo{
公共食物(T){
//做点什么
}
公共静态空栏(E){
//做点什么
}
}

为什么
Foo.bar(“字符串”)
推断
E
是一个字符串(因此不会抛出编译器警告),但
newfoo(“字符串”)
不能推断
T
是字符串吗?

我想你需要这样做

new Foo<String>("String");
newfoo(“字符串”);

告诉我们如何传递泛型信息;与Collections API类似。

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

public <T> Foo(T t) ...
publicfoo(T)。。。
也不可能。这样做会隐藏类的泛型类型(并且会得到警告)

然而,静态方法是类型化的。仅供参考,一旦推断出类型,泛型无参数调用相当于:

Foo.<String>bar("String");
Foo.bar(“字符串”);

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

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

    public static <E> void bar(E e) {
         //do something
    }
}
这是因为这里正在推断
E
的类型。正如您在方法案例中所期望的那样。但是,您得到的错误不是因为没有推断参数类型,而是因为无法推断类的原始类型


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

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

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

但当讨论转向施工人员时:

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

Map myMap=newhashmap();//未经检查
转换警告

资料来源:


这在Java7中保持不变,但是他们试图通过支持菱形语法来减少重复性。例如,
Foo-Foo=new-Foo(“字符串”)
。见。

@忽必烈汗的回答是正确的;
newfoo
的类型为原始
Foo
,用于向后兼容

Java7的构造函数菱形类型推断(
newfoo)
)与方法上的方法类型推断相同,并根据方法类型推断定义

如果类实例创建表达式使用“”来省略类类型参数,则会定义方法m1…mk的列表,以用于重载解析和类型参数推断

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

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


为什么Java花了6年时间才添加此功能是另一回事。

您看到的确切错误是什么?@linuxuser27您在
newfoo(“字符串”)上收到原始类型警告这是正确的。OP不是问“需要做什么”,而是问“为什么”,因为在静态方法调用的事实上,这是不需要的字符串
传递给构造函数时,code>似乎是重复的。我认为在Java 7中重复性会降低。在Java 7中,您可以这样做:
ArrayList list=new ArrayList()。类型是自动推断的。+1。非常有趣,但是我仍然不明白为什么在这个例子中,它不能通过类似的机制从参数列表中推断出来。你注意到了吗:如果你像这样声明你的类:
class TestClass
和你的构造函数
public TestClass(tt)
你不会得到警告,但是如果您这样做:
classtestclass
和您的构造函数
publictestclass(tt)
您会收到一条编译器警告,声明“类型参数T正在隐藏类型T”@Varun-Achar您可以声明,如果您在构造函数上重新声明,您确实在隐藏该类”。我相信Boehmian想说的是,因为我没有创建泛型构造函数,它是从类继承它的类型,而不是相反。但它仍然留下一个问题,为什么类不能从构造函数推断类型参数。我相信这就是Bohemian的意思。因为您没有声明类的类型参数,所以构造函数没有被赋予类型。@Jeffrey-我同意。这是一个很好的问题。谢谢
Foo f = new Foo("String");