代码之家  ›  专栏  ›  技术社区  ›  notnoop

Java中的无界通配符

  •  19
  • notnoop  · 技术社区  · 16 年前

    无界通配符之间有什么区别吗? <?> 一个有界通配符,其界是 Object ,例如 <? extends Object> ?

    我记得在某个地方读到过,泛型的早期草稿有所不同,但再也找不到那个来源了。

    6 回复  |  直到 10 年前
        1
  •  18
  •   Tom Hawtin - tackline    16 年前

    作为pedntry的一点,如果类/接口/构造函数/方法声明了一个绑定(而不是 extends Object )

    interface Donkey<T extends Thing> { }
    
    ...
        Donkey<? extends Object> foo; // FAIL
    
        2
  •  32
  •   mernst    10 年前

    对大多数人来说, <? extends Object> 与 <?> ,就像大家在这里建议的那样。

    然而,它们在两个非常细微和微妙的方面有所不同:

    1. JVM(Java虚拟机规范)对无界通配符具有特殊的规范,如 ClassFileFormat-Java5 指定无边界通配符编码为 * ,而将对象边界通配符编码为 +Ljava/lang/Object; . 这样的更改将泄漏到任何分析字节码的库中。编译器编写器也需要处理这个问题。从 revisions to "The class File Format"

    2. 从关系的角度来看,它们是不同的。 JLS 4.6 and 4.7 编纂 List<?> 作为一种可偿还的类型,但是 List<? extends Object> 作为删除类型。任何库编写器添加 .isReifiable() (例如) mjc lib )需要说明的是,要遵守jls术语。从 JLS 4.6和4.7 .

        3
  •  4
  •   C. K. Young    16 年前

    从实验来看,例如, List<?> 和 List<? extends Object> 两种方法都是赋值兼容的,并且使用其中一种方法的签名可以被使用另一种方法的签名重写。例如。,

    import java.util.List;
    
    class WildcardTest<T> {
        public void foo(List<? extends T> bar) {}
    }
    
    class WildcardTest2 extends WildcardTest<Object> {
        @Override
        public void foo(List<?> bar) {super.foo(bar);}
    }
    
        4
  •  2
  •   irreputable    13 年前

    很复杂…

    对于任何类型变量 T ,说明书上说 http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.4

    每个类型变量…有一个界限。如果没有为类型变量声明绑定,则假定为对象。

    人们会认为通配符也是如此,而且 ? 应该是 ? extends Object .

    然而,通过规范搜索,根本没有证据表明通配符必须有上界(或下界)。“无界的” ? 与有界通配符区别对待。

    我们可以从子类型规则中推断出 List<?> 和 List<? extends Object> 是彼此的子类型,即 基本上 同一类型。

    但规范还是分别对待它们。例如 http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.7 名单&?gt; 是一种可付费的类型,但是 名单&?扩展对象> 不是,也就是说

        // ok
        List<?>[] xx = {};
        // fail
        List<? extends Object>[] yy = {};
    
        // ok
        boolean b1 = (y instanceof List<?>);
        // fail
        boolean b2 = (y instanceof List<? extends Object>);
    

    我不明白为什么。可以说通配符必须有上界和下界,默认为 Object 和 null type .

        5
  •  -1
  •   Malfist    16 年前

    除了原语以外,Java中的所有东西都会扩展对象,所以没有,没有区别。自动装箱允许使用原语,因此可以说Java中的所有东西都是对象。

        6
  •  -1
  •   Kevin Bourrillion Gergely    16 年前

    <? extends Object> 与 <?> . 很抱歉我手头没有参考资料,但是…它是。:)

    编辑:当然,我说这话的时候只是从一个特定的角度来思考。忽略我的答案(它被正确地否决了),看看真实故事的更高评价的答案。

    推荐文章