Java的类型参数通配符究竟是什么意思? Foo和Foo之间真正的区别是什么? [英] What does Java's type parameter wildcard really mean? What's the real difference between Foo and Foo<?>?

查看:317
本文介绍了Java的类型参数通配符究竟是什么意思? Foo和Foo之间真正的区别是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于通用接口:

  public interface Foo< T> {
void f(T t);
}

两个字段之间的区别:

  public class Bar {
Foo foo1;
Foo<?> foo2的;

$ / code>

foo2 是一个泛型类型, foo 不是。由于是一个通配符(我认为这意味着任何类型),每种类型都是Object的子类型,所以我期望 Foo <? > Foo< Object> 在语义和语法上是等效的。

然而,请查看以下内容:

  public class Puzzler { 
void f(){
Integer i = null;
Foo<?> foo1 = null;
foo1.foo(i); //错误
Foo foo2 = null;
foo2.foo(i); // OKAY
Foo< Integer> foo3 = null;
foo3.foo(i); // OKAY
Foo< Object> foo4 = null;
foo4.foo(i); // OKAY
}

private interface Foo< T> {
void foo(T t);


$ / code>

因此 Foo <?> ; Foo< Object> 在语法上都是 not



这是怎么回事?我很努力去理解这一点。

解决方案

Foo <?> 在语义上与富< ;? extends Object> :它是一个具有特定类型参数的 Foo ,但关于something的唯一知识就是它是一些子类 Object (这并不是说太多,因为所有的类都是 Object 的子类)。另一方面, Foo< Object> Foo ,其类型参数具体为 Object 。虽然所有内容都与 Object 兼容,但并非所有内容都与兼容,其中 扩展对象



以下是 Foo<?> 应该会产生一个错误:

  public class StringFoo implements Foo< String> {
void foo(String t){。 。 。 }
}

现在将您的示例更改为:

  Foo<?> foo1 = new StringFoo(); 

由于 i Integer ,编译器不应允许 foo1.foo(i)进行编译。



请注意,

  Foo< Object> foo4 = new StringFoo(); 

也不会根据匹配参数化类型,因为 Object String 是明显不同的类型。


$ b

Foo 根本就是一种原始类型)应该被认为是一个编程错误。根据 Java语言规范(§4.8),但是,编译器接受这样的代码是为了不破坏非泛型的遗留代码。



由于 type erasure ,这些都不会对生成字节码产生任何影响。也就是说,它们之间的唯一区别是在编译时。


For a generic interface:

public interface Foo<T> {
    void f(T t); 
} 

The difference between the two fields:

public class Bar {
    Foo foo1; 
    Foo<?> foo2; 
}

Is that foo2 is a generic Type and foois not. Since ? is a wildcard (which I think means any type) and every type is a sub-type of Object, then I wold expect Foo<?> and Foo<Object> to semantically and syntactically equivalent.

However, check out the following:

public class Puzzler {
    void f() {
        Integer i = null; 
        Foo<?> foo1 = null;
        foo1.foo(i); // ERROR 
        Foo foo2 = null; 
        foo2.foo(i); // OKAY
        Foo<Integer> foo3 = null; 
        foo3.foo(i); // OKAY 
        Foo<Object> foo4 = null; 
        foo4.foo(i); // OKAY
    }

    private interface Foo<T> {
        void foo(T t);
    } 
}

So Foo<?> and Foo<Object> are not the same syntactically.

What's going on here? I'm pretty stuck in trying to understand this.

解决方案

Foo<?> is semantically the same as Foo<? extends Object>: it is a Foo with type parameter of something specific, but the only thing known about "something" is that it is some subclass of Object (which isn't saying too much, since all classes are subclasses of Object). Foo<Object>, on the other hand, is a Foo with type parameter specifically Object. While everything is assignment-compatible with Object, not everything will be assignment-compatible with ? where ? extends Object.

Here's an example of why Foo<?> should generate an error:

public class StringFoo implements Foo<String> {
    void foo(String t) { . . . }
}

Now change your example to this:

Foo<?> foo1 = new StringFoo();

Since i is an Integer, there's no way that the compiler should allow foo1.foo(i) to compile.

Note that

Foo<Object> foo4 = new StringFoo();

will also not compile according to the rules for matching parameterized types since Object and String are provably distinct types.

Foo (without type parameter at all—a raw type) should usually be considered a programming error. According to the Java Language Specification (§4.8), however, the compiler accepts such code in order to not break non-generic, legacy code.

Because of type erasure, none of this makes any difference to generated the byte code. That is, the only differences between these are at compile time.

这篇关于Java的类型参数通配符究竟是什么意思? Foo和Foo之间真正的区别是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆