泛型
一、使用泛型的好处
创建集合对象,不使用泛型
好处:集合不使用泛型,默认是Object类型,可以存储任意的数据类型
弊端:不安全,会抛出异常
创建集合对象,使用泛型
好处:避免了类型转化的麻烦,存储的是什么类型,取出的就是什么类型
将运行时期的异常提到了编译时期
弊端:泛型是什么类型,就只能存储什么类型的数据
import java.util.ArrayList;
import java.util.Iterator;
public class Demo01Generic {
public static void main(String[] args) {
show01();
System.out.println("===========");
show02();
}
private static void show02() {
//使用泛型
ArrayList<String> list = new ArrayList<String>();
list.add("123");
list.add("ABC");
// list.add(1); //只能存储字符串类型的数据
for (String str : list){
System.out.println("字符串:"+str+",长度:"+str.length());
}
}
private static void show01() {
//不使用泛型
ArrayList list = new ArrayList();
list.add("abc");
list.add(1);
//获取迭代器
Iterator it = list.iterator();
while(it.hasNext()){
Object obj = it.next();
System.out.println(obj);
//获取集合的长度,需要类型的转换
//注意:抛出异常:Integer cannot be cast to java.lang.String
/*String str = (String)obj;
System.out.println("集合的长度:"+str.length());*/
}
}
}
二、泛型的定义与使用
1.定义和使用含有泛型的类
GenericClass类
public class GenericClass<E> {
private E name;
public E getName() {
return name;
}
public void setName(E name) {
this.name = name;
}
}
Demo02GenericClass类
/*
泛型:数据类型未知
*/
public class Demo02GenericClass {
public static void main(String[] args) {
//创建字符串类型的对象
GenericClass<String> gc = new GenericClass<String>();
gc.setName("小明");
String name = gc.getName();
System.out.println("姓名1:"+name);
//创建整型对象
GenericClass<Integer> gc2 = new GenericClass<Integer>();
gc2.setName(1);
Integer name1 = gc2.getName();
System.out.println("姓名2:"+name1);
}
}
2.含有泛型的方法
使用泛型来定义方法:
注意:泛型写在访问符和返回值的类型之间
在调用方法时确定泛型的具体数据类型
GenericMethod类
public class GenericMethod {
//定义一个带有泛型的方法
public <E> void method01(E e){
System.out.println(e);
}
//定义一个带有泛型的静态方法
public static <M> void method02(M m){
System.out.println(m);
}
}
Demo03GenericMethod类
public class Demo03GenericMethod {
public static void main(String[] args) {
//普通成员方法调用
GenericMethod gm = new GenericMethod();
gm.method01("(1)你好,中国!");
gm.method01("(2)"+1314520);
gm.method01("(3)"+3.14);
System.out.println("========================");
//静态方法调用
GenericMethod.method02("(4)中国我爱你");
GenericMethod.method02("(5)"+1314520);
GenericMethod.method02("(6)"+3.14);
}
}
3.含有泛型的接口
含有泛型的接口,第一种使用方式:定义接口的实现类,实现接口,指定接口的类型
public interface Iterator<E>{
E next();
}
Scanner类实现了Iterator接口,并指定接口的泛型为String,所以重写的next方法泛型默认是String
public final class Scanner implements Iterator<String>{
public String next(){}
}
含有泛型的接口,第二种使用方式:接口使用什么类型,实现类就使用什么类型,类跟着接口走
相当于定义了一个还有泛型的类,创建对象时确定泛型的类型
public interface List<E>{
boolean add(E e);
E get(int index);
}
public class ArrayList<E> implements List<E>{
public boolean add(E e){}
public E get(int index){}
}
GenericInterface 接口
public interface GenericInterface<E>{
public void method(E e);
}
GenericInterfaceImpl1 实现类
public class GenericInterfaceImpl1 implements GenericInterface<String> {
public void method(String s) {
System.out.println(s);
}
}
GenericInterfaceImpl2 实现类
public class GenericInterfaceImpl2<I> implements GenericInterface<I> {
public void method(I i) {
System.out.println(i);
}
}
Demo04GenericInterface 测试类
public class Demo04GenericInterface {
public static void main(String[] args) {
//创建GenericInterfaceImpl1对象
GenericInterfaceImpl1 gci = new GenericInterfaceImpl1();
gci.method("你好呀!");
System.out.println("==========================");
//创建GenericInterfaceImpl2对象
GenericInterfaceImpl2<String> gci2 = new GenericInterfaceImpl2<String>();
gci.method("Hello!");
GenericInterfaceImpl2<Double> gci3 = new GenericInterfaceImpl2<Double>();
gci3.method(3.14);
}
}
三、泛型通配符
1.通配符的基本使用
泛型的通配符:
?:代表任意的数据类型
使用方式:
不能创建对象使用
只能作为方法的参数使用
import java.util.ArrayList;
import java.util.Iterator;
public class Demo05Generic {
public static void main(String[] args) {
ArrayList<Integer> list01 = new ArrayList<Integer>();
list01.add(1);
list01.add(2);
ArrayList<String> list02 = new ArrayList<String>();
list02.add("你好");
list02.add("我很好");
printArray(list01);
printArray(list02);
}
/*
定义一个方法,可以遍历所有类型的ArrayList集合
可以使用通配符
*/
public static void printArray(ArrayList<?> list){
//获取迭代器
Iterator<?> it = list.iterator();
while (it.hasNext()){
Object obj = it.next();
System.out.println(obj);
}
}
}
2.通配符的高级使用------受限泛型
泛型的高级使用
泛型的上限限定:? extends E 代表使用的泛型只能是E类型的子类或本身
泛型的下限限定:? super E 代表使用的泛型只能是E类型的父类或本身
import java.util.ArrayList;
import java.util.Collection;
public class Demo06Generic {
public static void main(String[] args) {
Collection<Integer> list1 = new ArrayList<Integer>();
Collection<String> list2 = new ArrayList<String>();
Collection<Number> list3 = new ArrayList<Number>();
Collection<Object> list4 = new ArrayList<Object>();
/*
类与类之间的继承关系
Integer extends Number extends Object
String extends Object
*/
getElement1(list1);
// getElement1(list2); //报错
getElement1(list3);
// getElement1(list4); //报错
// getElement2(list1); //报错
// getElement2(list2); //报错
getElement2(list3);
getElement2(list4);
}
//泛型的上限:此时的类型?必须是Number类型或Number类型的子类
public static void getElement1(Collection<? extends Number> coll){};
//泛型的下限:此时的类型?必须是Number类型或Number类型的父类
public static void getElement2(Collection<? super Number> coll){};
}