Java 7钻石操作符和派生类的初始化

前端之家收集整理的这篇文章主要介绍了Java 7钻石操作符和派生类的初始化前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
class A {}

class B extends A {}

class Holder<T> {

    T object;

    Holder(T object) {
        this.object = object;
    }
}

有一个Holder类来保存一些使用泛型创建的对象.
在main()中,当使用菱形运算符初始化时,它不会编译(Java 7),派生类传递给Holder的构造函数(需要A /找到B):

public static void main(String[] args) {    
    Holder<A> holder = new Holder<>(new B());        
}

但是,如果在右侧部分指定了基本类型,它将编译并运行:

public static void main(String[] args) {
    Holder<A> holder = new Holder<A>(new B());
}

为什么?钻石运算符是否使用与左侧相同的类型参数定义赋值的右侧部分?

解决方法

首先观察:
Holder<B> h = new Holder<>(new B());

用Java 8和Java 7编译,并且都创建Holder< B>在那种情况下.所以使用<>使用带参数的构造函数很好.

然而:

Holder<A> h = new Holder<>(new B());

> Java 7首先评估右侧,确定它是Holder< B>.并给出编译错误,因为a Holder<B> can’t be converted into a Holder<A>.
> Java 8更进了一步,推断出新的Holder< A>(新的B())实际上可以工作并自动神奇地完成.这要归功于一项名为“目标打字”的新功能 – 请参阅the tutorial on type inference的最后一部分以获取概述.

更详细地说,Java 8的改进是由于引入了poly expressions(强调我的):

The type of a standalone expression can be determined entirely from the contents of the expression; in contrast,the type of a poly expression may be influenced by the expression’s target type (§5 (Conversions and Contexts)).

这是Java 8的一个非常强大的功能(Java 7仅提供不考虑表达式上下文的独立表达式).

泛型类实例创建是一个多义表达式,JLS #15.9解释(强调我的):

A class instance creation expression is a poly expression (§15.2) if it uses the diamond form for type arguments to the class,and it appears in an assignment context or an invocation context (§5.2,§5.3). Otherwise,it is a standalone expression.

由于新的规则,Java 8允许您使用上面的第二种形式,并自动推断新的B()应该被视为A(加宽参考转换),并且您打算创建一个Holder< A>.在这种情况下.

猜你在找的Java相关文章