当前位置: 首页 > 面试题库 >

Java:泛型语法

费和惬
2023-03-14
问题内容

这可以返回一个整数列表:

public List<Integer> GetIListImpl() {
    return new ArrayList<Integer>();
}

但是,如果我想让调用者指定通用类型怎么办?像这样的东西,尽管在语法上我不确定如何去做:

public List<T> GetIListImpl<T>() {
    return new ArrayList<T>();
}

用法是:

    List<String> = GetIListImpl<String>();

问题答案:

关于static参数化类型的通用工厂方法

看来您想编写方便的工厂方法来实例化通用集合。

您可以编写如下通用方法:

public static <T> List<T> newArrayList() {
    return new ArrayList<T>();
}
public static <K,V> Map<K,V> newHashMap() {
    return new HashMap<K,V>();
}

然后,您可以简单地编写:

// absolutely type-safe!!! no compilation warnings at all!!!

List<String> names = newArrayList();

List<Integer> nums = newArrayList();

Map<String, List<String>> map = newHashMap();

请注意,在某些情况下,上述方法不必须static的,你可以选择离开了实施class的名字出来的方法和只使用interface名称(例如newListnewMap)。

有效Java 2nd Edition 的认可 __

这种通用的类型推断static工厂方法实际上已被 有效Java 2nd Edition所 认可 ;它具有作为书中讨论的 第一 项的独特特权。

以下是 第1项static_的相关引号 :考虑使用_ 工厂方法而不是构造函数

一个 第四 的优点static工厂方法是它们减少了创建参数化类型实例的详细程度。

不幸的是,当调用参数化类的构造函数时,即使它们从上下文中是显而易见的,也必须指定类型参数。这通常需要您连续两次提供类型参数:

    Map<String,List<String>> m =
        new HashMap<String,List<String>>();

随着类型参数的长度和复杂性的增加,这种冗余规范很快变得很痛苦。static但是,对于工厂,编译器可以为您确定类型参数。这称为 类型推断 。例如,
假设HashMap提供该static工厂:

    public static <K,V> HashMap<K,V> newInstance() {
        return new HashMap<K,V>();
    }

然后,您可以使用简洁的替代方法替换上面的冗长声明:

    Map<String,List<String>> m = HashMap.newInstance();

不幸的是,诸如1.6之类的标准集合实现从版本1.6开始HashMap就没有static工厂方法,但是您可以将这些方法放在自己的实用程序类中。更重要的是,您可以static在自己的参数化类中提供此类工厂。

该项目还规定了这些static工厂方法的通用命名约定:

  • getInstance -返回由参数[…]描述的实例
  • newInstance-类似getInstance,除了它保证返回的每个实例都与其他实例不同。
  • new Type -像newInstance,但是在工厂方法位于其他类中时使用。 Type
    指示工厂方法返回的对象的类型。


关于显式类型参数

在大多数情况下,您不必显式提供类型参数,因为Java泛型类型推断系统通常可以确定您需要什么。

不过,为了提供显式类型参数,语法是将其放在方法名称 之前 (而不是 之后 )。这是使用显式参数<T> List<T> emptyList()从中调用泛型方法的示例java.util.Collections

Collections.<String>emptyList();
// Collections.emptyList<String>(); // DOES NOT COMPILE

请注意,泛型方法调用的显式类型参数化的语法要求是,您 必须 限定类型(if
static)或要在其上调用方法的对象,即使它们不是显式参数化也可以省略。

参考文献

  • Angelika Langer的Java泛型常见问题解答
    • 什么是通用方法?
    • 什么是类型参数推断?
    • 什么是显式类型参数规范?
  • JLS 8.4.4通用方法

附录:番石榴中的收集工厂方法

应该注意的是,Guava实际上已经为Java Collections
Framework中static的类型提供了工厂方法:

从主要方面package com.google.common.collect

  • Lists.newArrayList()newLinkedList(),…
  • Sets.newHashSet()newTreeSet()newEnumSet(…),…
  • Maps.newHashMap()newTreeMap()newEnumMap(…),…

实际上,按照 Effective Java 2nd Edition
建议的精神,Guava自己的集合不提供public构造函数,而是提供static create()工厂方法:

  • HashMultiSet.create(),一个Multiset实现
  • TreeMultimap.create(),一个Multimap实现

该库的其余部分还提供了许多非常有用的功能。



 类似资料:
  • 问题内容: 我是java泛型的新手,我的问题是: 在上面的语句中,当函数的返回类型为void时,为什么我们以前使用过?为什么此语法有效? 根据理论,方法本身可以是返回类型吗? 我的参考程序是 问题答案: 在这里没有什么做的返回类型; 这意味着这是一个通用函数,可以采用各种类型的数组。为了更容易理解,代码可能是这样的: 所以它告诉函数 “有一个通用类型,您接受的数组,因此,例如,如果我用您接受的通用

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

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

  • 主要内容:泛型集合,泛型类,泛型方法,泛型的高级用法前面我们提到 Java 集合有个缺点,就是把一个对象“丢进”集合里之后,集合就会“忘记”这个对象的数据类型,当再次取出该对象时,该对象的编译类型就变成了 Object 类型(其运行时类型没变)。 Java 集合之所以被设计成这样,是因为集合的设计者不知道我们会用集合来保存什么类型的对象,所以他们把集合设计成能保存任何类型的对象,只要求具有很好的通用性,但这样做带来如下两个问题: 集合对元素类型没有

  • 本小节我们将学习 Java5 以后出现的一个特性:泛型(Generics)。通过本小节的学习,你将了解到什么是泛型,为什么需要泛型,如何使用泛型,如何自定义泛型,类型通配符等知识。 1. 什么是泛型 泛型不只是 Java 语言所特有的特性,泛型是程序设计语言的一种特性。允许程序员在强类型的程序设计语言中编写代码时定义一些可变部分,那些部分在使用前必须做出声明。 我们在上一小节已经了解到,Java

  • Pair泛型的实际参数类型是 Interger , 为什么不能赋值给 Number