泛型类型是一种在类型上参数化的泛型类或接口。 这让编译器能够对类或接口强制实施类型安全。
来看看下面这个非泛型的 Container 接口:
class Container {
private Object object;
public void set(Object object) { this.object = object; }
public Object get() { return object; }
}
由于它接受并返回 Object 类型,因此可用于任何非基本类型。
不过,这样做是有代价的:某段代码可能调用 get 并期望得到 Integer,而另一段代码却调用 set 加入了 String,结果会在运行时抛出异常。
泛型类和泛型接口的格式如下:
class ClassName<T1, T2, ..., Tn> { ... }
interface InterfaceName<T1, T2, ..., Tn> { ... }
类或接口名后面的类型参数部分由尖括号(<>)括起,它指定了类型参数(也叫类型变量)T1、T2、……和Tn。
它们可以在类或接口的内部使用,以获得泛型类型安全。
下面是 Container 的泛型版本:
class Container<E> {
private E object;
public void set(E object) { this.object = object; }
public E get() { return object; }
}
创建它时,我们必须声明它持有哪种类型,编译器会强制执行这一约束:
// empty <> can infer from context
Container<String> stringContainer = new Container<>();
// compiler knows this is a String, so it is allowed
stringContainer.set("Some string");
// no cast needed, compiler knows it is a String
String result = stringContainer.get();
// this causes a compiler error:
stringContainer.set(42);
列表是 Java 中的有序序列集合。
与数组不同,List的大小可以增长,以容纳任意数量的项。
一种标准实现是 ArrayList,它由一个可调整大小的数组支撑。
另一种标准实现是 LinkedList 类,它由一个双向链表支撑。
List 可以为空,也可以容纳任意数量的项(包括重复项)。
List 是一种泛型接口,它通过类型标明自己可以包含哪些类型的对象。
例如:
List<String> emptyListOfStrings = List.of();
List<Integer> singleInteger = List.of(1);
List<Boolean> threeBooleans = List.of(true, false, true);
List<Object> listWithMultipleTypes = List.of("hello", 1, true);
List 提供了各种实用的方法,用来添加、移除、获取元素,以及检查某个元素是否存在:
List<Character> vowels = new ArrayList<>(List.of('a', 'e', 'i', 'o', 'i', 'e', 'a'));
int startingSize = vowels.size(); // 7
vowels.add('u'); // vowels is now ['a', 'e', 'i', 'o', 'i', 'e', 'a', 'u']
char a = vowels.get(0); // 'a'
boolean hadI = vowels.remove('i'); // true and vowels is now ['a', 'e', 'o', 'i', 'e', 'a', 'u']
boolean hasI = vowels.contains('i'); // true (still have one more left)
Karl 想在 Exercism 网站上跟踪记录一份他要学习的语言列表。 Karl 需要能够添加新语言、移除旧语言,并检查某些语言是否在列表中。 如果 Karl 想学 Java 或 Kotlin,那就太令人兴奋了!
Karl 需要知道他这份语言列表是否有一天会变成空的,这样他就能去找更多语言来学习!
定义一个名为isEmpty的方法,如果列表中没有语言就返回true。
if (languageList.isEmpty()) {
findMoreLanguagesToLearn();
}
Karl 很期待学习 Kotlin 和 Python!
帮 Karl 开个头吧:定义一个名为addLanguage的方法,它接收他想学习的语言,并把它添加到列表中。
languageList.addLanguage("Kotlin");
languageList.addLanguage("Python");
Karl 决定他现在不想学 Scala 了。
帮 Karl 把它从列表中移除:定义一个名为removeLanguage的方法,它接收他要移除的语言,并把它从列表中删除。
languageList.removeLanguage("Scala");
Karl 想记住他添加到列表中的第一种语言(它仍在列表中)。
定义一个名为firstLanguage的方法,返回列表中的第一种语言。
String kotlin = languageList.firstLanguage(); // "Kotlin"
Karl 需要知道他打算学多少种语言。
帮 Karl 找到答案:定义一个名为count的方法,返回列表中语言的数量。
int two = languageList.count(); // 2
Karl 想回忆起他究竟是想学 Python 还是 Ruby。
定义一个名为containsLanguage的方法,它接收他询问的语言,这样 Karl 就能弄清楚了!
boolean learningPython = languageList.containsLanguage("Python"); // true
boolean learningRuby = languageList.containsLanguage("Ruby"); // false
如果 Karl 想学 Java 或 Kotlin,那就太令人兴奋了!
定义一个名为isExciting的方法,如果 Karl 想学 Java 或 Kotlin 就返回 true。
javaLanguageList.isExciting() // true
neitherKotlinNorJavaLanguageList.isExciting() // false