一、为什么需要泛型
- 了解泛型之前,我们首先看一段代码:
List list = new ArrayList();
list.add("John");
list.add("Mary");
list.add("Lily");
list.add(10000);
Collections.sort(list);
for(Object obj:list){
String name = (String) obj;
System.out.println(name.toUpperCase());
}
你觉得上述代码有什么问题吗?
1、集合对元素类型没有任何的限制,可能不小心存入了你并不期望的数据类型是数据,导致程序运行时报错;
2、在对象存入集合后,集合丢失了对象的类型信息,统一当作Object处理,经常需要强制类型转换。
二.什么是泛型?
1、从Java 5 开始,Java引入了“参数化类型”的概念(后面举例来说明),这种参数化类型被称为泛型;
2、泛型允许在创建集合时指定集合元素的类型,则集合中只能保存这种类型的对象。
// Java 5
List<String> list = new ArrayList<String>();
Map<String,Double> map = new HashMap<String,Double>();
// Java 7 优化
List<String> list = new ArrayList<>(); //菱形语法
Map<String,Double> map = new HashMap<>(); //菱形语法
泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
package com.nefu;
import java.util.ArrayList;
import java.util.List;
/** 泛型 */
public class GenericDemo01 {
public static void main(String[] args) {
List<String> lists = new ArrayList<>();
lists.add("John");
lists.add("Mary");
lists.add("Lily");
// list.add(10000);
for(String list:lists){
System.out.println(list.toUpperCase());
}
}
}
运行结果:
"C:\Program Files\Java\jdk1.8.0\bin\java.exe" "-javaagent:C:\Program
JOHN
MARY
LILY
虽然 Java 5 版本的写法也可以使用,但是优化后的写法更加方便。
三、集合中的泛型定义
public interface List<E> extends Collection<E> {
boolean add(E e);
Iterator<E> iterator();
}
public interface Map<K,V> {
V put(K key,V value);
Set<Map.Entry<K,V>> entrySet();
}
我们可以看到,在List接口中采用泛型化定义之后,中的E表示类型形参,可以接收具体的类型实参,并且此接口定义中,凡是出现E的地方均表示相同的接受自外部的类型实参。
此时里面的E 可以理解为占位符,需要什么类型数据的时候直接替换就可以使用。Map集合里面的K,V参数也是同理。
自定义泛型类(接口)
package com.nefu;
/** 自定义泛型 */
public class GenericDemo02 {
public static void main(String[] args) {
// 使用泛型类
Foo<String> f1 = new Foo<>("World");
System.out.println(f1.getData().toUpperCase());
Foo<Integer> f2 = new Foo<>(100);
System.out.println(f2.getData().doubleValue());
//使用泛型子类
Alpha alpha = new Alpha("China");
System.out.println(alpha.getData().toUpperCase());
}
}
// 自定义泛型类(接口)
class Foo<T> {
private T data;
public Foo() {}
public Foo(T data) {
this.data = data;
}
public T getData() {
return data;
}
}
// 定义泛型类下子类(接口)
class Alpha extends Foo<String> {
public Alpha() {}
public Alpha(String data) {
super(data);
}
@Override
public String getData() {
return super.getData();
}
}
运行结果:
"C:\Program Files\Java\jdk1.8.0\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA
WORLD
100.0
CHINA