我正在try 构建一个类列表,这些类实现一个名为100的特定接口:

List<Class<? extends Interface>> myList= myMap.entrySet().stream()
        .filter(entry -> entry.getValue().equals(myValue))
        .map(Map.Entry::getKey) // Stream<Interface>
        .map(Interface::getClass) // Stream<Class<capture of ? extends Interface>>
        .distinct()
        .toList();

在调用map()之后,我添加了Stream中元素的类型作为注释.

代码遍历映射中的所有条目,如果它们的值等于100,则:

  • 首先,获取类型Interfaceinstance(这是条目的键)
  • 然后,获取class接口.

100的定义为:

Map<Interface, Integer> myMap = new HashMap<>()

我得到的错误是:

Incompatible types. Found: 'java.util.List<java.lang.Class<capture<? extends application.interfaces.Interface>>>', required: 'java.util.List<java.lang.Class<? extends application.interfaces.Interface>>'

我显然忽略了泛型在Java中的工作原理,但我在这里不知所措.我想这与编译器无法正确具体化我的"?"有关.通配符.

如有任何帮助、提醒或提示,我们将不胜感激.

推荐答案

Update:

正如@Slaw在注释中指出的那样,在这种情况下,getClass()能够向编译器提供有关泛型类型的信息.

根据前documentation名:

实际的结果类型是Class<? extends |X|>,其中|X|是对其调用getclass的表达式的静态类型的擦除.

因此,在编译类型中,我们将拥有? extends Interface,并且所观察到的行为仅与Java中的type inference的特性有关.

在这种情况下,当我们在map()次操作之后链接方法时,编译器无法根据流返回的结果类型正确推断方法引用Interface::getClass的类型.

如果我们用collect(Collectors.toList())替换toList(它需要类型T的元素并产生List<T>),而collect(Collectors.toList())的收集器是Collector<? super T, A, R>类型的,编译器将能够完成它的工作(这里是proof):

List<Class<? extends Interface>> myList = myMap.entrySet().stream()
    .filter(entry -> Objects.equals(entry.getValue(), myValue))
    .map(Map.Entry::getKey)   // Stream<Interface>
    .map(Interface::getClass) // Stream<Class<capture of ? extends Interface>>
    .distinct()
    .collect(Collectors.toList());

但要使类型推断与toList()一起工作,我们需要提供泛型类型explicitly.

例如,下面的代码将进行编译,因为可以从赋值上下文推断出Interface::getClass的类型(这里map()之后没有操作,因此myStream直接说明应该是map()的返回类型):

Stream<Class<? extends Interface>> myStream = myMap.entrySet().stream()
    .filter(entry -> Objects.equals(entry.getValue(), myValue))
    .map(Map.Entry::getKey)
    .map(Interface::getClass);

List<Class<? extends Interface>> myList = myStream.distinct().toList();

一种更方便的方法是使用所谓的Type Witness:

Map<Interface, Integer> myMap = Map.of(new ClasA(), 1, new ClasB(), 1);
        
int myValue = 1;
        
List<Class<? extends Interface>> myList = myMap.entrySet().stream()
    .filter(entry -> Objects.equals(entry.getValue(), myValue))
    .map(Map.Entry::getKey)                               // Stream<Interface>
    .<Class<? extends Interface>>map(Interface::getClass) // Stream<Class<? extends Interface>>
    .distinct()
    .toList();
        
myList.forEach(c -> System.out.println(c.getSimpleName()));

Output:

ClasA
ClasB

Dummy classes:

interface Interface {}
class ClasA implements Interface {}
class ClasB implements Interface {}

Java相关问答推荐

Spring Webocket:尽管凭据设置为False,但MLhttpsify和Fetch请求之间的CORS行为存在差异

是否有一种格式模式,可以在除0之外的数字前面有正负符号?

将偶数元素移动到数组的前面,同时保持相对顺序

Saxon 9:如何从Java扩展函数中的net.sf.saxon.expr. XPathContent中获取声明的变量

Java字符串常数池困惑

ApachePOI:不带换行的新行

将数组整体转换为链接表

AssertJ Java:多条件断言

对Java中的通配符参数的混淆

通过移动一个类解决了潜在的StubbingProblem.它怎麽工作?

如何从JNI方法正确调用NSOpenPanel以在正确的线程上运行?

JDK 21-为什么线程局部随机S nextInt不直接用Super.nextInt实现?

try 判断可选参数是否为空时出现空类型安全警告

使用存储在字符串变量中的路径目录打开.pdf文件

如何在Cosmos DB(Java SDK)中增加默认响应大小

Kotlin Val是否提供了与Java最终版相同的可见性保证?

向Java进程发送`kill-11`会引发NullPointerException吗?

为什么我不能建立输入/输出流?Java ServerSocket

Oracle中从JSON中提取和插入数据

ControlsFX RangeSlider在方向垂直时滞后