Java 中的无界通配符

发布于 2024-08-16 16:23:36 字数 145 浏览 6 评论 0原文

无界通配符(例如)和边界为Object(例如<)的有界通配符之间是否有区别?扩展对象>

我记得在某处读到仿制药的早期草案存在差异,但现在找不到该来源了。

Is there ever a difference between an unbounded wildcard e.g. <?> and a bounded wildcard whose bound is Object, e.g. <? extends Object>?

I recall reading somewhere that there was a difference in the early drafts of generics, but cannot find that source anymore.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

老旧海报 2024-08-23 16:23:36

从实际角度来说,对于大多数人来说, 相同,就像每个人都在这里建议的那样。

然而,它们在两个非常微小和微妙的点上有所不同:

  1. JVMS(Java 虚拟机规范)对无界通配符有一个特殊规范,因为 ClassFileFormat-Java5 指定无界通配符被编码为*,而将对象边界通配符编码为+Ljava/lang/Object;。这种更改会通过任何分析字节码的库泄漏。编译器编写者也需要处理这个问题。来自对“类文件格式”的修订

  2. 从可靠性的角度来看,这些是不同的。 JLS 4.6 和 4.7 编纂List 作为可具体化类型,但 List 扩展为擦除类型。任何添加 .isReABLE() 的库编写者(例如 mjc lib) 需要考虑到这一点,以遵守 JLS 术语。来自 JLS 4.6 和 4.7 .

From a practical point to most people, <? extends Object> is the same as <?>, like everyone have suggested here.

However, they differ in two very minor and subtle points:

  1. The JVMS (Java Virtual Machine Specification) has a special specification for the unbounded wildcards, as ClassFileFormat-Java5 specifies that unbounded wildcard gets encoded as *, while encodes a Object-bounded wildcard as +Ljava/lang/Object;. Such change would leak through any library that analyzes the bytecode. Compiler writers would need to deal with this issue too. From revisions to "The class File Format"

  2. From reifiablity standpoint, those are different. JLS 4.6 and 4.7 codify List<?> as a reifiable type, but List<? extends Object> as a erasured type. Any library writer adding .isReifiable() (e.g. mjc lib) needs to account for that, to adhere to the JLS terminology. From JLS 4.6 and 4.7.

一个人练习一个人 2024-08-23 16:23:36

作为 pedntry 的一个点,如果类/接口/构造函数/方法声明了一个边界(extends Object 除外),则存在差异。

interface Donkey<T extends Thing> { }

...
    Donkey<? extends Object> foo; // FAIL

As a point of pedntry, there is a difference if the class/interface/constructor/method declares a bound (other than extends Object).

interface Donkey<T extends Thing> { }

...
    Donkey<? extends Object> foo; // FAIL
酒几许 2024-08-23 16:23:36

从实验来看,例如, ListList 两种方式都是赋值兼容的,并且具有使用其中一种方式的签名的方法可以被使用另一种方式的签名覆盖。例如,

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);}
}

From experimentation it seems that, for example, List<?> and List<? extends Object> are assignment-compatible both ways, and a method that has a signature using one of them can be overridden with a signature using the other. e.g.,

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);}
}
笑红尘 2024-08-23 16:23:36

它很复杂......

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

每个类型变量...都有一个界限。如果没有为类型变量声明界限,则假定为 Object。

人们可能会认为通配符也是如此,并且 ? 应该只是 ? 的简写形式。扩展对象。

然而,通过搜索规范,根本没有证据表明通配符必须有上限(或下限)。 “无界”? 的处理方式与有界通配符一致。

我们可以从子类型规则中推断出 ListList 是彼此的子类型,即它们基本上是相同的类型。

但规范仍然将它们分开对待。例如 http://docs.oracle .com/javase/specs/jls/se7/html/jls-4.html#jls-4.7 List 是可具体化的类型,但 List 不是,这意味着

    // ok
    List<?>[] xx = {};
    // fail
    List<? extends Object>[] yy = {};

    // ok
    boolean b1 = (y instanceof List<?>);
    // fail
    boolean b2 = (y instanceof List<? extends Object>);

我不明白为什么。通配符必须有上限和下限似乎完全没问题,默认为 Objectnull 类型

It is complicated...

For any type variable T, the spec says http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.4

Every type variable ... has a bound. If no bound is declared for a type variable, Object is assumed.

One would think that it's true for wildcard too, and ? should just be a shorthand for ? extends Object.

Yet searching through the spec, there is no evidence at all that a wildcard must have an upper bound (or lower bound). The "unbounded" ? is treated consistently distinctly from bounded wildcards.

We could deduce from subtyping rules, that List<?> and List<? extends Object> are subtypes of each other, i.e., they are basically the same type.

But the spec treats them separately nevertheless. For example http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.7 List<?> is a reifiable type, but List<? extends Object> is not, which means

    // ok
    List<?>[] xx = {};
    // fail
    List<? extends Object>[] yy = {};

    // ok
    boolean b1 = (y instanceof List<?>);
    // fail
    boolean b2 = (y instanceof List<? extends Object>);

I don't understand why though. It seems perfectly fine to say a wildcard must have an upper bound and a lower bound, default to Object and null type.

莫相离 2024-08-23 16:23:36

java中除了基元之外的所有东西都扩展了Object,所以不,不会有什么区别。自动装箱允许使用原语,因此可以说 java 中的一切都是对象。

Everything in java with the exception of primitives extend Object, so no, there would be no difference. Autoboxing allows the use of primitives so it could be said everything in java is an object.

憧憬巴黎街头的黎明 2024-08-23 16:23:36

<代码> 与 完全相同。很抱歉我手头没有参考资料,但是……确实如此。 :)

编辑:当然,当我这么说时,我只是从特定的角度思考。忽略我的答案(非常正确地被否决)并查看真实故事的更高评价的答案。

<? extends Object> is EXACTLY the same as <?>. I'm sorry I don't have a reference handy, but ... it is. :)

EDIT: of course, I was only thinking from a particular perspective when I said that. Ignore my answer (which was quite correctly downvoted) and see the higher-rated answers for the real story.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文