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

java泛型中的类型见证

刁远
2023-03-14

我知道什么是类型证人,因为我看到泛型跟踪在Java文档

BoxDemo.<Integer>addBox(Integer.valueOf(10), listOfIntegerBoxes);

或者,如果您省略类型见证,Java编译器会自动推断(从方法的参数)类型参数是整数:

BoxDemo.addBox(Integer.valueOf(20), listOfIntegerBoxes);

我想理解

  • 正确的方法是什么?使用类型见证还是让Java推断
  • 是否存在绝对需要使用类型见证的情况
  • 这是Java5的特性还是后来添加的

共有3个答案

戚森
2023-03-14

为了完整起见,这是在Java5中添加的。以下是JLS第三版的相关部分,涵盖Java5和6:

8.8.7.1显式构造函数调用

ExplicitConstructorInvocation:
    NonWildTypeArgumentsopt this ( ArgumentListopt ) ;
    NonWildTypeArgumentsopt super ( ArgumentListopt ) ;
    Primary. NonWildTypeArgumentsopt super ( ArgumentListopt ) ; 

NonWildTypeArguments:
    < ReferenceTypeList >

ReferenceTypeList: 
    ReferenceType
    ReferenceTypeList , ReferenceType

15.12方法调用表达式

MethodInvocation:
    MethodName ( ArgumentListopt )
    Primary . NonWildTypeArgumentsopt Identifier ( ArgumentListopt )
    super . NonWildTypeArgumentsopt Identifier ( ArgumentListopt )
    ClassName . super . NonWildTypeArgumentsopt Identifier ( ArgumentListopt )
    TypeName . NonWildTypeArguments Identifier ( ArgumentListopt )

注意,它们被称为非WildTypeArguments。术语“类型见证人”未出现在JLS中。在JLS SE 8中,调用规范被重写,以使用预先存在的类型参数的概念;而“证人”这个词仍然不见踪影。

方法名已经包含了TypeName.标识符,所以第五个方法调用定义了类型见证的显式用法,这就是为什么它没有被标记为可选的原因。)

封烈
2023-03-14

是否存在绝对需要使用类型见证的情况?

这是Java5的特性还是后来添加的?

下面的示例显示了使用类型见证的强制情况和SE 8Java改进

引自泛型追踪Java文档:

假设您想用空列表调用processStringList方法。在Java SE 7中,不编译以下语句:

processStringList(Collections.emptyList());

Java SE 7编译器会生成类似以下内容的错误消息

List<Object> cannot be converted to List<String> The compiler requires

类型参数T的值,因此它以值Object开始。因此,调用Collections.empty列表返回类型列表的值,这与方法过程StringList不兼容。因此,在JavaSE 7中,您必须指定类型参数的值如下:

processStringList(Collections.<String>emptyList());

这在JavaSE8中不再是必需的。什么是目标类型的概念已经扩展到包括方法参数,例如方法processStringList的参数。在本例中,processStringList需要类型为List的参数。方法是收集。emptyList返回一个List值,因此使用List的目标类型,编译器推断类型参数T的值为String。因此,在Java SE 8中,编译以下语句:

processStringList(Collections.emptyList());
萧嘉茂
2023-03-14

快速回答您的问题:

正确的方法是什么?使用类型见证还是让Java推断?

由于这两种方法都是有效的,因此没有技术上正确的答案。但代码可读性应该始终是质量标准。所以后者更好。此外,您可能会在以后的开发阶段更改参数的类型。使用类型推断,您不必更改该行。

是否存在绝对需要使用类型见证的情况?

对当需要从输入方法推断类型时,不能从输入方法推断类型。泛型类型可能只用于返回值,与参数的类型无关。然后你只需要指定它。

这是Java5的特性还是后来添加的?

泛型是Java5上的一种语言特性。类型推断是Java语言规范(JLS)中指定的编译器功能。在Java8JLS中,这个主题有自己的章节。每个Java版本都对该功能进行了一些增强。例如,Java7引入了菱形操作符。据我所知,Java 5中已经引入了方法的类型见证。

 类似资料:
  • 如何获取这个类的类型?对于上下文,我使用ModelMapper,我需要类类型T从S转换为T。 背景: 我已经尝试了N种方法,其中我放置了“//一些方法来获取类型”,但没有任何效果。例如: 或

  • 问题内容: 如果在Java中创建泛型类(该类具有泛型类型参数),则可以使用泛型方法(该方法带有泛型类型参数)吗? 考虑以下示例: 正如您对通用方法所期望的那样,我可以使用任何对象调用的实例: 但是,如果我尝试使用 不 指定泛型类型的实例,则无论传入什么,我都会调用返回, 奇怪的是,如果返回类型是通用类,它将编译(例如(实际上,这可以解释-参见下面的答案)): 此外,如果输入通用类,即使仅使用通配符

  • 如果在Java中创建泛型类(该类具有泛型类型参数),是否可以使用泛型方法(该方法采用泛型类型参数)? 考虑下面的例子: 正如您所期望的那样,对于任何对象,的实例,我都可以调用: 但是,如果我试图使用的实例而不指定泛型类型,那么调用将返回一个

  • 问题内容: 我有一个通用类,说: 在此类的方法内部,我想测试T的类型,例如: 我怎样才能做到这一点 ? 谢谢你的帮助 问题答案: 通常,由于类型擦除,您不能这样做。有关更多详细信息,请参见Angelika Langer的Java泛型常见问题解答 。 您 可以 做的是将a传递给构造函数,然后检查: 请注意,尽管如此,Java仍不允许将原语用于类型参数,因此实在不行。

  • 我有一个关于Java仿制药的问题。假设我有以下方法: 我如何用通配符<解释上面的类型转换?扩展U>?使用它与只使用有什么区别?

  • 问题内容: 我有一个代表文本片段的泛型类。该文本片段可能具有多种不同模式(突出显示的不同类型)中的任何一种。这些模式用枚举表示。每个项目的Enum可能不同,但是它必须实现一个接口,该接口提供了一种将其中两个结合的方法(可以突出显示并加粗显示)。所以我有一个界面: 然后我的TextFragment是文本字符串和模式的容器。但是当我尝试声明该类时: 我收到以下错误: 令牌“扩展”的语法错误,预期 根据