Intellij 无法识别错误的返回类型

Ale*_*Tbk 4 java intellij-idea

我有这个方法:

public <T extends CacheResult> T get(Object key, CacheDefinition cacheDefinition) {
    return load(key, cacheDefinition.name(), cacheDefinition.getTypeReference());
}
Run Code Online (Sandbox Code Playgroud)

现在我的 IDE 抱怨这一行(正如预期的那样,这是正确的),因为返回类型应该是CacheResult

User user = spxCacheManager.get(username, CacheDefinition.USERS_BY_USERNAME);
Run Code Online (Sandbox Code Playgroud)

我目前不明白的是,IDE(IntelliJ)并没有抱怨这一点:

List<User> usersFromCache = spxCacheManager.get(username, CacheDefinition.USERS_BY_USERNAME);
Run Code Online (Sandbox Code Playgroud)

这实际上是错误的。我在这里缺少什么?

Swe*_*per 5

这是有效的,因为T被推断为交集类型 - List<User> & CacheResult & Object。毕竟,为什么一个类不能同时实现List<User> 实现/扩展CacheResult呢?这样的类型当然是可能的!

您可以通过编写一个玩具程序并使用以下--debug=verboseResolution=all选项来看到这种情况的发生:

import java.util.List;

public class Main {

  public static void main(String[] args) {
    List<User> u = new Main().get();
  }

  public <T extends CacheResult> T get() {
    return null;
  }
}

interface CacheResult {}
class User implements CacheResult {}
Run Code Online (Sandbox Code Playgroud)

javacverboseResolution=all输出:

  instantiated signature: ()INT#1
  target-type: List<User>
  where T is a type-variable:
    T extends CacheResult declared in method <T>get()
  where INT#1 is an intersection type:
    INT#1 extends Object,List<User>,CacheResult
Run Code Online (Sandbox Code Playgroud)

您还可以了解Java 如何进行类型推断的过程。最终(在“分辨率”中的某个位置),您将到达需要找到 和 的最大下界(“glb”)的点ObjectList<User>并且CacheResult该类型正是它们的交集类型,如此处定义

另一方面,如果您的代码CacheResult是一个类,并且您将方法结果分配给的类型是一个不相关的类,则您的代码将无法编译,因为没有任何类可以从两个不相关的类继承。