当前位置: 首页 > 知识库问答 >
问题:

本地类型推理与实例

谢清野
2023-03-14

我试图扫描JEP-286关于局部类型推断的信息。我看到这只适用于局部变量-理解。因此,这确实有效:

public class TestClass {
    public static void main(String [] args){
        var list = new ArrayList<>();
        list.add("1");
        System.out.println(list.get(0)); // 1
    }  
}

另一方面,我确实看到这并不能编译:

public class TestClass {
    public var list = new ArrayList<>();
    public static void main(String [] args){

    }
}

很明显,事实并非如此,因为JEP是这么说的。现在我的问题是:

声明为var的公共/受保护成员失败是完全合理的,至少IMO是如此。但是,为什么即使它是私有,它也不能编译呢?我只能假设您仍然可以通过反射来获取该变量(我无法获取这样的局部字段)……而获取该变量需要进行转换,很可能是非常混乱的转换。

共有3个答案

翟冯浩
2023-03-14

这并不是完全不可能将这些变量转换为可以通过反射进行检查的字段。E、 你可以做到

var l = new ArrayList<String>();
l.add("text");
System.out.println(l);
System.out.println(
  new Object(){ { var x = l; } }.getClass().getDeclaredFields()[0].getGenericType()
);

在当前版本中,它只打印 ArrayList,因此实际的泛型类型尚未存储在匿名内部类的类文件中,并且不太可能更改,因为支持此自省不是实际目标。这也只是一个特例,该类型像 ArrayList 一样表示

var acs = true? new StringBuilder(): CharBuffer.allocate(10);
acs.append("text");
acs.subSequence(1, 2);
System.out.println(
  new Object(){ { var x = acs; } }.getClass().getDeclaredFields()[0].getGenericType()
);

<code>acs</code>的类型是<code>Appendable</code>和<code>CharSequence</code>的交集类型,如通过调用其中任一接口的方法所示,但由于未指定编译器是否推断<code>#1扩展了Appendable

我不认为这是合成字段的问题,但对于显式声明的字段,它可能是问题。

然而,我怀疑专家组是否详细考虑了这些影响。相反,从一开始就决定不支持字段声明(从而跳过对含义的冗长思考),因为局部变量始终是该特性的目标。局部变量的数量远高于字段声明的数量,因此减少局部变量声明的样板会产生最大的影响。

皇甫文乐
2023-03-14

各种原因:

>

  • 可见性和类型是正交的-一个不应该影响另一个。如果可以使用var初始化私有变量,那么在使它们受保护或公开时必须更改它。

    由于 var 使用右侧来推断类型,因此此类私有字段始终需要立即初始化。如果将初始化移动到构造函数中,则必须使类型显式。

    使用< code>var,编译器可以推断出当前无法用Java表达的类型(例如,< code>Comparable

  • 能烨华
    2023-03-14

    禁止字段和方法返回的类型推断的动机是API应该是稳定的;字段访问和方法调用在运行时通过描述符进行链接,因此,如果对实现的更改导致推断类型发生更改(模擦除),那么对推断类型进行细微更改的事情可能会导致现有编译客户端以可怕的方式中断。因此,将此用于实现,而不是用于API,是一个明智的指导原则。

    有理由问“那么,私人领域和方法如何?”事实上,我们完全可以选择这样做。与所有设计决策一样,这是一种权衡;这将使推理能够在更多的地方使用,以换取用户模型中的更复杂。(我不太关心规范或编译器的复杂性;这是我们的问题。)比起添加各种周转考虑因素,比如“但是,如果字段和方法是私有的,那么它们是可以的”,更容易推理“对局部变量的推断是肯定的,字段和方法不是”。画出我们所做的这条线还意味着,将字段或方法从私有更改为非私有的兼容性结果不会与推断发生意外交互。

    所以简短的回答是,这样做使语言更简单,而不会使特性的有用性大大降低。

     类似资料:
    • 问题内容: 我尝试扫描有关本地类型推断的JEP-286。我看到这仅适用于局部变量- 了解。因此这确实有效: 我确实看到,另一方面,它无法编译: 很明显,事实并非如此,因为JEP是这样说的。现在我的问题是: 对于宣布失败的 公共/受保护 成员,至少是IMO,这是完全合理的。但是,为什么即使编译也不编译呢?我只能假设您仍然可以通过反射保留该变量(而我无法获得这样的局部字段)…而且获取该变量可能需要强制

    • 问题内容: 从JEP 286中,我们可以在JDK 10(18.3)中使用局部类型推断()。JEP指出,可以进行以下编译: 我很想知道如果尝试以下操作会发生什么: 我在第二个片段中提出的内容是否可以编译?如果是这样(我对此表示怀疑),将accept 作为其通用类型吗? 我会自己尝试,但是我无法使用可以安装早期发行版的任何计算机。 谢谢! 问题答案: 是的,钻石操作员可以组合在一起。编译器将推断最特定

    • 当然,如果我给IntelliJ添加更多上下文,比如: 这是正确的,但在Java10 var推断类型上下文中,这是错误的: 我理解编译器不能推断的输入类型。如果我写: 编译器的错误更加不可读(但包含更多关于推理失败原因的提示),如下所示:

    • 从JEP 286中,我们可以在JDK 10(18.3)中利用本地类型推断()。JEP声明将进行以下编译,这是预期的: 谢谢!

    • 我正在尝试运行以下代码,由于类型推断,它在JDK8下编译得很好: 但是,运行此命令会抛出ClassCastException:CB无法强制转换为[Ljava.lang.Object,但CB b=convert(a)可以正常工作。 知道为什么吗?

    • 本文向大家介绍Java基本数据类型与类型转换实例分析,包括了Java基本数据类型与类型转换实例分析的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Java基本数据类型与类型转换。分享给大家供大家参考,具体如下: 基本数据类型 整型 浮点型 字符型 布尔型 数据类型转换 数组 首发时间:2017-06-22 21:18 修改时间: 2018-03-16 15:40  :修改了一下文字布局和样