泛型
1. 概述
- JDK 5 中引入的特性,提供了编译时类型俺去那检测机制,该机制允许在编译时检测到非法的类型
- 本质是参数化类型,即将类型原来的具体的类型参数化,然后在使用/调用时传入具体的类型
- 这种参数类型可以用在类、方法、接口中,分别被称为:泛型类、泛型方法、泛型接口
2. 定义格式
- <类型> :指定一种类型的格式:这里的格式可以看成是形参
- <类型1,类型2>:指定多种类型的格式,多种类型之间用逗号隔开
- 将具体调用时给定的类型可以看作是实参,并且实参的类型只能是引用数据类型
3. 使用泛型的好处
3.1 好处
- 把运行时期的问题提前到了编译时期
- 避免了强制类型转换
3.2 代码示例
3.2.1 使用泛型前
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Demo01 {
public static void main(String[] args) {
//创建集合对象
Collection c = new ArrayList<>();
c.add("hello");
c.add("world");
c.add("java");
// c.add(100); //Integer 类型 自动封装
//遍历集合
Iterator it = c.iterator();
while (it.hasNext()){
/* Object obj = it.next();
System.out.println(obj);*/
/*因为我们输入的都是String类型,这里我不想把元素当成Object类使用,所以向下转型成String类型
由于这里转型成String类型,所以在添加元素的时候我添加了个Integer类型的数据,导致运行时异常*/
String s = (String)it.next(); //ClassCastException:表示代码尝试将对象转换为不属于实例的子类
System.out.println(s);
}
}
}
3.2.2 使用泛型后
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/*
使用泛型的好处: 1.把运行时期的问题提前到了编译时期
2.避免了强制类型转换
*/
public class Demo01 {
public static void main(String[] args) {
//创建集合对象
Collection<String> c = new ArrayList<String>();// 1.在创建的时候我们添加了泛型的类型<String>
c.add("hello");
c.add("world");
c.add("java");
// c.add(100); //Integer 类型
/*
4.并且在这里,如果我想要添加Integer类型的元素,就会导致编译时异常
这也就是把运行时期的问题提前到了编译时期
*/
//遍历集合
Iterator<String> it = c.iterator(); // 2.迭代器这里也要添加<String>类型
while (it.hasNext()){
/* Object obj = it.next();
System.out.println(obj);*/
String s = it.next(); // 3.这里就避免了强制转换
System.out.println(s);
}
}
}
4. 泛型类
4.1 定义格式
格式:修饰符 class 类名<类型> { }
范例:public class Generic<T>{}
- :此处T可以随便写为任意标识,常见的如T、E、K、V等形式参数常用于表示泛型
4.2 代码示例
- 泛型类
public class Generic<T> {
private T t;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
- 测试类
public class Test01 {
public static void main(String[] args) {
Generic<String> g1 = new Generic<String>();
g1.setT("哈哈哈");
System.out.println(g1.getT());
Generic<Integer> g2 = new Generic<Integer>();
g2.setT(30);
System.out.println(g2.getT());
}
}
5. 泛型方法
5.1 定义格式
格式:修饰符 <类型> 返回值类型 方法名(类型 变量名) { }
范例:public <T> void show(T t) { }
5.2 代码示例
- 方法类
/*public class Generic {
//方法重载
public void show(String s){
System.out.println(s);
}
public void show(Integer i){
System.out.println(i);
}
public void show(Boolean b){
System.out.println(b);
}
}*/
/*//利用泛型类简化
public class Generic<T> {
public void show(T t){
System.out.println(t);
}
}*/
//泛型方法
public class Generic {
public<T> void show(T t){
System.out.println(t);
}
}
- 测试类
public class GenericDemo {
public static void main(String[] args) {
Generic g = new Generic();
g.show("哈哈哈");
g.show(20);
g.show(true);
}
}
6. 泛型接口
6.1 定义格式
格式:修饰符 interface 接口名<类型> { }
范例:public interface Generic<T> { }
6.2 代码示例
- 接口
public interface Generic<T> {
void show(T t);
}
- 接口实现类
public class GenericImpl<T> implements Generic<T> {
@Override
public void show(T t) {
System.out.println(t);
}
}
- 测试类
public class Demo {
public static void main(String[] args) {
GenericImpl<String> g1 = new GenericImpl<>();
g1.show("哈哈哈");
GenericImpl<Integer> g2 = new GenericImpl<>();
g2.show(30);
}
}
7. 类型通配符
7.1 概述
-
为了表示各种泛型List的父类,可以使用类型通配符:<?>
-
List<?>:表示元素类型未知的List,它的元素可以匹配任何的类型
-
这种带通配符的List仅表示它是各种泛型List的父类,并不能把元素添加到其中
-
类型通配符上限:<? extends 类型>
- List<? extends Number>:它表示的类型是Number或者其子类型
-
l类型通配符下限:<? super 类型>
- List<? super Number>:它表示的类型是Number或者其父类型
7.2 代码示例
import java.util.ArrayList;
import java.util.List;
public class Demo {
public static void main(String[] args) {
List<?> list1 = new ArrayList<Object>();
List<?> list2 = new ArrayList<Number>();
List<?> list3 = new ArrayList<Integer>();
System.out.println("---------------");
//上限
//通过extend Number我们定义了上限是Number,所以定义Object就会出现异常
//List<? extends Number> list4 = new ArrayList<Object>(); //报错
List<? extends Number> list4 = new ArrayList<Number>();
List<? extends Number> list5 = new ArrayList<Integer>();
System.out.println("----------------");
//下限 通过super Number我们定义了下限是Number,所以定义Integer就会出现异常
// List<? super Number> list6 = new ArrayList<Integer>(); //报错
List<? super Number> list7 = new ArrayList<Object>();
List<? super Number> list8 = new ArrayList<Number>();
}
}