Java类型推断:引用在Java 8中是不明确的,但不是Java 7 [英] Java type inference: reference is ambiguous in Java 8, but not Java 7

查看:1246
本文介绍了Java类型推断:引用在Java 8中是不明确的,但不是Java 7的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们有2个类。一个空类 Base ,以及此类的子类 Derived

Lets say we have 2 classes. An empty class Base, and a subclass of this class Derived.

public class Base {}

public class Derived extends Base {}

然后我们在另一个类中有几个方法:

Then we have a few methods in another class:

import java.util.Collection

public class Consumer {

    public void test() {
        set(new Derived(), new Consumer().get());
    }

    public <T extends Base> T get() {
        return (T) new Derived();
    }

    public void set(Base i, Derived b) {
        System.out.println("base");
    }

    public void set(Derived d, Collection<? extends Consumer> o) {
        System.out.println("object");
    }

}

7,但不是在Java 8中编译。错误:

This compiles and runs successfully in Java 7, but does not compile in Java 8. The error:

Error:(8, 9) java: reference to set is ambiguous
  both method set(Base,Derived) in Consumer and 
  method set(Derived,java.util.Collection) in Consumer match

为什么在Java 7而不是Java 8中工作?如何< T extends Base> 匹配集合

Why does work in Java 7, but not Java 8? How could <T extends Base> ever match Collection?

推荐答案

问题是类型推理已改进 。您有类似

The problem is that the type inference has been improved. You have a method like

public <T extends Base> T get() {
    return (T) new Derived();
}

基本上说,调用者可以决定 Base 我返回,这是明显的废话。每个编译器应该给你一个未经检查的警告你的类型(T)这里。

which basically says, "the caller can decide what subclass of Base I return", which is obvious nonsense. Every compiler should give you an unchecked warning about your type cast (T) here.

调用:

set(new Derived(), new Consumer().get());

回想一下你的方法 Consumer.get()说呼叫者可以决定我的回报。因此,假设可以有一个类型扩展 Base 并同时实现 Collection 是完全正确的。所以编译器说我不知道是否调用 set(Base i,Derived b) set(Derived d,Collection< ;? extends

Recall that your method Consumer.get() says "the caller can decide what I return". So it’s perfectly correct to assume that there could be a type which extends Base and implement Collection at the same time. So the compiler says "I don’t know whether to call set(Base i, Derived b) or set(Derived d, Collection<? extends Consumer> o)".

您可以通过调用 set(new Derived(),new Consumer()。< Derived> get()); 但是为了说明你的方法的疯狂,注意你也可以更改为

You can "fix" it by calling set(new Derived(), new Consumer().<Derived>get()); but to illustrate the madness of your method, note that you can also change it to

public <X extends Base&Collection<Consumer>> void test() {
    set(new Derived(), new Consumer().<X>get());
}

现在将调用 set(Derived d,Collection< ;?extends Consumer> o),没有任何编译器警告。在 get 方法中发生了实际的不安全操作。

which will now call set(Derived d, Collection<? extends Consumer> o) without any compiler warning. The actual unsafe operation happened inside the get method.

因此,正确的修复方法是删除类型参数 get 方法并声明它真的返回 Derived

So the correct fix would be to remove the type parameter from the get method and declare what it really returns, Derived.

顺便说一句,令我恼火的是,你声称这个代码可以在Java 7下编译。它的嵌套方法调用的有限类型推理导致在嵌套调用上下文中处理 get 方法,如返回 Base ,无法传递到期望的方法a 派生。因此,尝试使用合格的Java 7编译器编译此代码也会失败,但是出于不同的原因。

By the way, what irritates me, is your claim that this code could be compiled under Java 7. Its limited type inference with nested method calls leads to treating the get method in a nested invocation context like returning Base which can’t be passed to a method expecting a Derived. As a consequence, trying to compile this code using a conforming Java 7 compiler will fail as well, but for different reasons.

这篇关于Java类型推断:引用在Java 8中是不明确的,但不是Java 7的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆