Java SE 11 - Java 语言规范中类型转换的新案例

2022-09-04 04:47:55

Java SE 11 的 JLS §5.2 包含一些 Java 8 的 JLS 没有的新类型转换案例,请参阅列表中的第 4 项和第 5 项:

分配上下文允许使用以下方法之一:

  1. 身份转换
  2. 加宽基元转换
  3. 加宽参考转换
  4. 加宽参考转换,然后进行拆箱转换
  5. 加宽参考转换,然后进行取消装箱转换,然后进行加宽基元转换
  6. 拳击转换
  7. 装箱转换后进行加宽参考转换
  8. 拆箱转换
  9. 取消装箱转换,然后进行加宽基元转换

我不明白列表中的情况4情况5。任何人都可以给我一些例子的解释吗?如果可能的话,请同时解释其实际用法。


更新:

正如@Naman所评论的那样,这是更改JLS - JDK-8166326的建议:5.2:允许在拆箱之前加宽,这是自Java-9以来生效的。在报告中,它提到:

此行为对于与捕获的互操作性尤其重要各种现有程序都希望能够将 的元素视为 ints。List<? extends Integer>

List<? extends Integer> li = null;
int i = li.get(0);

这可能意味着这种JLS更改确实具有实际必要性。但我仍然不明白为什么<?扩展 Integer>很重要。与捕获的互操作性意味着什么,为什么它很重要?这些现有的程序是什么样子的?它们是java代码吗(我知道其他一些语言也适用于JVM,并且可能与Java代码有交互)?


答案 1

TL;DR

...拳击的问题在于它是[临时的]和昂贵的;为解决这两个问题,已经进行了广泛的工作“ - Brian Goetz,瓦尔哈拉州,2020年3月

这让我怀疑,对你所引用的规范的那些更改正在为上面链接中讨论的L-World计划中的“代码像类一样工作,像int一样工作”功能准备语言。


...任何人都可以用例子给我一些解释?...

注释中链接到的 2016 错误报告中的示例(以及链接到的 2013 错误报告)给出了列表中 #4 的最佳示例。基于这些,以下是列表中#5的示例...

< I extends Integer > void soAns0( I intRef ) {

   int intPrim;

   long longPrim = /* (3) a widening primitive conversion */
   intPrim =       /* (2) an unboxing conversion */
   intRef;         /* (1) a widening reference */
}

...如果可能的话,请同时解释其实际用法......”

自然数通常被称为“整数”。Java语言教程展示了将自然数限制为仅整数类型的一种实际用法。

public class NaturalNumber<T extends Integer> {

    private T n;

    public NaturalNumber(T n)  { this.n = n; }

    public boolean isEven() {
        return n.intValue() % 2 == 0;
    }

    // …
}

RowFilter<M,I>的API文档中也有此示例。

…
  public boolean include(Entry<? extends PersonModel, ? extends Integer> entry) {
    …
    Person person = personModel.getPerson(entry.getIdentifier());
    …
  }
…

T 扩展 Integer 的另一个用例可能是合适的,如果你想要显式禁止你的类被任何其他类型的 Number 参数化,并显式禁止 Integer 添加到该参数化类型中 — 通过利用 Get/Put 原则

假设您有一些代码,给定一些数字,将创建该数量的对象。如果你想通过用Long.MAX_VALUE的DOS尝试次数来禁止不良行为者压倒你的系统,那么边界<T扩展了短>可能是限制在任何一个方法调用中创建的对象数量的一种方法。

...这些现有的程序是什么样子的?它们是java代码吗?...

在github上搜索T扩展Integed会发现有八万次点击

...与捕获的互操作性意味着什么?...

我将捕获转换的明确解释推迟到JLS本身

...为什么它很重要?...

捕获转换很重要,因为它与类型推断有联系。

符号 ‹Integer <: α›JLS 关于类型推断的部分或多或少是表示 Integer 扩展 Integer 的一种形式方式(T 扩展 Integer 实际上意味着什么)...

...

Arrays.asList(1, 2.0) 中,我们有约束公式 ‹1 → α›‹2.0 → > α›。通过约简,这些公式将成为约束公式 ‹int → α›‹双→ α›,然后 ‹整数<:α›‹双<:α›

...

鉴于此,JDK使用<T扩展整数也就不足为奇了>JDK本身的泛型/类型推理相关测试中有很多

这是我绝对最喜欢的<T扩展了Integer>在野外的使用

不过,大多数情况下,我敢打赌,那些与开箱/加宽相关的规范更改与Valhalla有很大关系。


答案 2