1、什么是泛型?
泛型(Generics)是把类型参数化,运用于类、接口、方法中,在调用时传入具体的类型。
泛型就是参数化类型
- 适用于多种数据类型执行相同的代码
- 泛型的类型在使用时指定
- 泛型归根到底就是“模板”
优点:使用泛型时,在实际使用之前类型就已经确定了,不需要强制类型转换。
操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
2、泛型的使用场景
2.1 用于集合
/**
* 运用于集合中
*/
public class Demo01 {
//不使用泛型,直接存取数据
public static void test01() {
List list = new ArrayList();
list.add("001");
list.add(100);
Object o1 = list.get(1);
if(o1 instanceof Integer) {
//如果不判断类型,直接强转Integer,则运行时可能直接抛出异常
o1 = (Integer)o1;
}
System.out.println(o1);
}
public static void test02() {
List<Integer> list = new ArrayList<Integer>();
//list.add("001"); 放数据时进行安全检查,"001"不是Integer类型,编译不通过
list.add(100);
System.out.println(list.get(0));
}
public static void main(String[] args) {
test01();
test02();
}
}
2.2 自定义泛型
泛型字母
- 形式类型参数(formal type parameters)即泛型字母
- 命名泛型字母可以随意指定,尽量使用大写字母(多个参数时,在字母后加数字,例T1,T2)
- 常见字母:T(Type),K V (Key Value),E(Element)
泛型类
- 只能用在成员变量上,只能使用引用类型
泛型接口
- 只能用在抽象方法上
泛型方法
- 返回值前加<T>
自定义泛型类
/**
* 自定义泛型类
* @param <T>
*/
class Student<T> {
private T prop;
public T getProp() {
return prop;
}
public void setProp(T prop) {
this.prop = prop;
}
@Override
public String toString() {
return "Student [prop=" + prop + "]";
}
}
public class Demo02 {
public static void main(String[] args) {
//Student<int> s = new Student<int>(); 不能为基本类型,会编译报错
Student<Integer> student = new Student<Integer>();
student.setProp(18);
//输出:Student [prop=18]
System.out.println(student);
}
}
自定义泛型接口
/**
* 自定义泛型接口
* 接口中泛型字母只能使用在方法中,不能使用在全局常量中
* @param <T>
*/
public interface Comparator<T1, T2> {
//public static T1 param; 静态类型不能引用非静态的参数,会编译报错
void compare(T1 t1);
T2 compare();
public abstract T1 compare2(T2 t2);
}
非泛型类里定义泛型方法
/**
* 非泛型类里定义泛型方法
*/
public class Demo03 {
public static<T> void test01(T t) {
System.out.println(t);
}
public static<T extends List> void test02(T t) {
t.add("sdfs");
System.out.println(t);
}
public static <T extends Object> void test03(T ...l) {
for(T t:l) {
System.out.println(t);
}
}
public static void main(String[] args) {
//泛型参数
test01("01");
//泛型的继承
test02(new ArrayList<Integer>());
//可变参数
test03(new ArrayList<Integer>(), new ArrayList<String>());
}
}
泛型类的继承
abstract class Father<T1, T2> {
T1 age;
public abstract void makeFriend(T2 t);
}
/**
* 父类泛型完全保留
*/
class Child1<T1, T2> extends Father<T1, T2> {
@Override
public void makeFriend(T2 t) {
System.out.println("My attr: "+age+" &T2="+t);
System.out.println("I am "+getClass().getName()+", let`s be friend.");
}
}
/**
* 父类泛型部分保留
*/
class Child2<T1> extends Father<T1, Integer> {
@Override
public void makeFriend(Integer t) {
System.out.println("My attr: "+age+" &T2="+t);
System.out.println("I am "+getClass().getName()+", let`s be friend.");
}
}
/**
* 父类泛型不保留,子类按需实现
*/
class Child3 extends Father<Integer, String> {
@Override
public void makeFriend(String t) {
System.out.println("My attr: "+age+" &T2="+t);
System.out.println("I am "+getClass().getName()+", let`s be friend.");
}
}
/**
* 没有具体类型
* 泛型擦除,继承父类的子类,没有指定类型,默认为Object
*/
@SuppressWarnings("rawtypes")
class Child4 extends Father {
@Override
public void makeFriend(Object t) {
System.out.println("My attr: "+age+" &T2="+t);
System.out.println("I am "+getClass().getName()+", let`s be friend.");
}
}
public class Demo03 {
public static void main(String[] args) {
new Child1().makeFriend("1");
new Child2().makeFriend(1);
new Child3().makeFriend("1");
new Child4().makeFriend("1");
}
}
/**
* 类型擦除
*/
public class Demo03 {
public static void test01(Student<Integer> student) {
student.setProp(18);
System.out.println(student);
}
public static void main(String[] args) {
Student student = new Student();
//输出:Student [prop=18]
test01(student);
Student<String> s2 = new Student<String>();
//编译报错,参数不匹配
//test01(s2);
}
}
通配符
通配符(Wildcards)
- T、K、V、E 等泛型字母为有类型,类型参数赋予具体的值
- ?未知类型 类型参数赋予不确定值,任意类型
- 只能用在声明类型、方法参数上,不能用在定义泛型类上
/**
* 泛型的通配符,类型不确定,用于变量声明或者形参上面
* 不能用在类上或者对象创建上
*/
public class Demo03 {
public static<T> void test01(Student<T> student) {
//编译报错:不能转换 Student<Integer> 为 Student<T>
//student = new Student<Integer>();
//student = new Student<String>();
//student = new Student<BigDecimal>();
System.out.println(student);
}
public static void test02(Student<?> student) {
//?号代表类型参数不确定,下面代码可以执行
student = new Student<Integer>();
student = new Student<String>();
student = new Student<BigDecimal>();
System.out.println(student);
}
public static void main(String[] args) {
Student student = new Student();
//输出:Student [prop=null]
test02(student);
}
}
extends/super
上限(extends)
指定的类必须是继承某个类,或者实现了某个接口(不是implements),即<=
- ? extends List
下限(super)
即父类或本身
- ? super List
/**
* extends:泛型的上限 <= 一般用于限制操作 不能使用在添加数据上,一般都是用于数据的读取
* supper:泛型的上限 >= 即父类或自身。一般用于下限操作
*/
public class Demo03<T extends Fruit> {
public static void test01() {
Demo03<Fruit> t1 = new Demo03<Fruit>();
Demo03<Apple> t2 = new Demo03<Apple>();
//编译报错:类型转换失败
//Demo03<Fruit> t3 = new Demo03<Apple>();
}
public static void test02(List<? extends Fruit> list) {
//编译报错
//list.add(new Fruit());
//list.add(new Object());
}
public static void test03(List<? super Apple> list) {
//可以编译通过
list.add(new Apple());
list.add(new RedApple());
//编译报错
//list.add(new Fruit());
}
}
泛型嵌套
/**
* 泛型嵌套
*
*/
public class Demo05 {
public static void main(String[] args) {
Student2<String> student = new Student2<String>();
student.setScore("优秀");
System.out.println(student.getScore());
//泛型嵌套
School<Student2<String>> school = new School<Student2<String>>();
school.setStu(student);
String s = school.getStu().getScore(); //从外向里取
System.out.println(s);
// hashmap 使用了泛型的嵌套
Map<String, String> map = new HashMap<String,String>();
map.put("a", "张三");
map.put("b", "李四");
Set<Entry<String, String>> set = map.entrySet();
for (Entry<String, String> entry : set) {
System.out.println(entry.getKey()+":"+entry.getValue());
}
}
}
public class School<T> {
private T stu;
public T getStu() {
return stu;
}
public void setStu(T stu) {
this.stu = stu;
}
}
public class Student2<T> {
T score;
public T getScore() {
return score;
}
public void setScore(T score) {
this.score = score;
}
}
其他(数组)
import java.util.ArrayList;
import java.util.List;
/**
* 泛型没有多态
* 泛型没有数组
* JDK1.7对泛型的简化
* @author Administrator
*
*/
public class Demo06 {
public static void main(String[] args) {
Fruit fruit = new Apple(); // 多态,父类的引用指向子类的对象
//List<Fruit> list = new ArrayList<Apple>(); //泛型没有多态
List<? extends Fruit> list = new ArrayList<Apple>();
//泛型没有数组
//Fruit<String>[] fruits = new Fruit<String>[10];
//ArrayList底层是一个Object[],它放数据的时候直接放,取数据的时候强制类型转化为泛型类型
/*public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}*/
/*E elementData(int index) {
return (E) elementData[index];
}*/
//JDK1.7泛型的简化,1.6编译通不过
List<Fruit> list2 = new ArrayList<>();
}
}
参考:
https://segmentfault.com/a/1190000014824002?utm_source=tag-newest
http://www.importnew.com/tag/%E6%B3%9B%E5%9E%8B