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

为什么使用通配符捕获辅助方法?

宋典
2023-03-14

参考:通配符捕获辅助方法

它说创建一个助手方法来捕获通配符。

public void foo(List<?> i) {
    fooHelper(i);
}        
private <T> void fooHelper(List<T> l) {
    l.set(0, l.get(0));
}

仅使用下面的函数不会产生任何编译错误,并且似乎以同样的方式工作。我不明白的是:为什么你不直接使用这个,避免使用助手?

public <T> void foo(List<T> l) {
    l.set(0, l.get(0));
}

我认为这个问题真的可以归结为:通配符和泛型有什么区别?所以,我去了这个:通配符和泛型之间的区别。它说使用类型参数:

1)如果你想对不同类型的方法参数强制执行某种关系,你不能用通配符来做到这一点,你必须使用类型参数。

但是,这不正是带有帮助函数的通配符实际在做的事情吗?它没有通过设置和获取未知值来强制不同类型的方法参数之间的关系吗?

我的问题是:如果你必须定义一些需要在不同类型的方法参数上建立关系的东西,那么为什么首先使用通配符,然后使用帮助函数呢?

这似乎是一种结合通配符的黑客方式。

共有3个答案

吴镜
2023-03-14

你说得对,我们不必使用通配符版本。

这取决于哪个API看起来/感觉“更好”,这是主观的

    void foo(List<?> i) 
<T> void foo(List<T> i)

我会说第一个版本更好。

如果有界限

    void foo(List<? extends Number> i) 
<T extends Number> void foo(List<T> i)

第1个版本看起来更紧凑;类型信息都在一个位置。

在这个时候,通配符版本是惯用的方式,程序员更熟悉它。

JDK方法定义中有很多通配符,尤其是在java8引入lambda/Stream之后。诚然,它们非常丑陋,因为我们没有方差类型。但是试想一下,如果我们将所有通配符扩展到vars类型,情况会变得多么糟糕。

晏富
2023-03-14

我同意:删除helper方法并键入公共API。没有理由不这样做,也没有理由不这样做。

总结一下通配符版本对助手的需求:虽然对我们人类来说很明显,但编译器不知道从l.get(0)返回的未知类型与列表本身的未知类型相同。也就是说,它没有考虑到set()调用的参数来自与目标相同的列表对象,因此它必须是一个安全操作。它只注意到从get()返回的类型是未知的,目标列表的类型是未知的,并且两个未知不能保证是同一类型。

严阳成
2023-03-14

在这种特殊情况下,这是因为列表。set(int,E)方法要求类型与列表中的类型相同。

如果没有helper方法,编译器就不知道是否有 与列表相同

The method set(int, capture#1-of ?) in the type List<capture#1-of ?> is not applicable for the arguments (int, capture#2-of ?)

对于helper方法,您告诉编译器,类型是相同的,我只是不知道类型是什么。

那么为什么有非辅助方法呢?

泛型直到Java 5才被引入,因此有很多代码早于泛型。Java 5之前的列表现在是一个列表

 类似资料:
  • 问题内容: 引用:通配符捕获帮助器方法 它说创建一个辅助方法来捕获通配符。 仅在下面使用此函数不会产生任何编译错误,并且似乎以相同的方式工作。我不明白的是:您为什么不只使用它而避免使用帮助器? 我以为这个问题可以归结为:通配符和泛型有什么区别?所以,我去了:通配符和泛型之间的区别。它说要使用类型参数: 1)如果要对不同类型的方法参数强制执行某种关系,则不能使用通配符来实现,必须使用类型参数。 但是

  • 以下代码不能在Eclipse中编译。它说“类型Abc中的方法putHelper(List,int,E)不适用于参数(List<.capture#8-of extends E>”,int,E)“ 我不明白为什么会这样?因为下面的代码可以正常工作。

  • 问题内容: 在以下代码段中: 尽管类型似乎完全匹配,但分配是错误的。 我通过将Collection的类型指定为另一个通用参数,设计出了一种肮脏的解决方法,如下所示: 但是该参数实际上是“无关”类型,只会使API复杂化,在保持类型安全的同时,有没有什么方法可以摆脱它呢? 谢谢。 问题答案: 这样做就可以了: 您仍然可以像这样使用迭代器: 作为参考,请阅读get and put原理 (最初来自Java

  • 在这个问题中,我看到我可以使用帮助方法将通配符泛型“捕获”到类型T中以执行类型安全操作,如下所示: 但是当我尝试使用关键字执行此操作时,它不起作用: 我得到以下错误: 当使用扩展关键字时,有没有办法捕获通配符? 我的背景是,我有一个扩展给定类a的类列表,每个类都有一个不同的泛型参数T。对于每个类,我想获得对其T类的引用,我试图安全地进行类型转换。

  • 方法在类型不适用于参数

  • 问题内容: 我知道这些问题听起来很愚蠢,但是在Java中,什么是辅助类,有人怎么写一个,以及编译器如何知道某种东西是辅助类? 编辑:我问这是因为编译器正在生成有关外部库中对象的警告,我想知道原因。 编辑2: 这是针对那些想要的人的编译器警告: 问题答案: 正如Java规范descried 在这里,你可以在一个java文件指定多个类。名称与.java文件名匹配的类将成为主要类,可以将其声明为公共类,