01. 泛型概述
- 概念
- 好处
- 语法
- 类名<泛型确定类型> 对象名 = new 类名<泛型确定类型>();
- 类名<泛型确定类型> 对象名 = new 类名<>();//jdk1.7,菱形泛型
02. 泛型由来
1 2 3 4 5 6 7 8 9 10 11 12
| public class MyTool {
private Object obj;
public Object getObj() { return obj; }
public void setObj(Object obj) { this.obj = obj; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class Demo02 {
public static void main(String[] args) { MyTool1 myTool = new MyTool1(); myTool.setObj(new Person("张三"));
Pig pig = (Pig) myTool.getObj(); pig.sleepLongTime();
}
}
|
存在的问题
- 可能会导致ClassCastException异常
- 需要进行强制类型转换
使用泛型
1 2 3 4 5 6 7 8 9 10 11 12
| public class MyTool<T> {
private T obj;
public T getObj() { return obj; }
public void setObj(T obj) { this.obj = obj; } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| public class Demo03 {
public static void main(String[] args) { MyTool<Person> myTool = new MyTool<Person>(); Person person = new Person("张三"); myTool.setObj(person);
Person p1 = myTool.getObj(); } }
|
03. 泛型的书写格式
- 格式
- 常用的格式
T
:Type
E
:Element
K
:Key
V
:Value
04. 自定义泛型类
1 2 3 4 5 6
| public class 类名<A,B,C>{ private A a; private B b; private C c; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class MyGenericClass01<T,E,K> { private T t; private E e; private K k; public void setT(T t) { this.t = t; } public void setE(E e) { this.e = e; } public void setK(K k) { this.k = k; } public T getT() { return t; } public E getE() { return e; } public K getK() { return k; } }
|
1 2 3 4 5
| MyGenericClass01<Integer,String,Boolean> class01 = new MyGenericClass01<>(); class01.setT(1); class01.setE("a"); class01.setK(true);
|
1 2
| public class SonGenericeClass01 extends MyGenericClass01<Integer,String,Boolean> { }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| new MyGenericClass01<Integer,String,Boolean>(){
@Override public void setT(Integer integer) { }
@Override public void setE(String s) {
}
@Override public void setK(Boolean aBoolean) {
} };
|
05. 自定义泛型方法
1 2 3
| 权限修饰符<A,B,C> 返回值类型 方法名(A a,B b,C c){ 方法体; }
|
1 2 3 4 5 6 7 8 9
| public class MyGenericClass02<T> {
public<T,E> T show1(T t){ System.out.println("秀秀秀" + t); return t; }
}
|
方法泛型确定
注意事项
- 当泛型类和泛型方法上都有同一个自定义泛型,根据就近原则来决定数据类型由哪个泛型确定!
06. 自定义静态泛型方法
1 2 3
| public static<A,B,C> 返回值类型 方法名(A a,B b,C c){ 方法体; }
|
1 2 3 4 5 6 7 8
| public class MyGenericClass03<E> {
public static<T> T show1(T t ){ System.out.println("咻咻咻" + t); return t; } }
|
注意事项
- 普通方法可以使用泛型类上的泛型
- 静态方法不可以使用泛型类上的泛型
07. 自定义泛型接口
1 2 3 4 5
| public interface 接口名<A,B>{ 方法; }
|
1 2 3 4 5
| public interface MyGenericInterface01<T,E> {
void show(T t,E e);
}
|
1 2 3 4 5 6
| public class MyGenericInterface01Impl implements MyGenericInterface01<Integer,String> { @Override public void show(Integer num, String s) { System.out.println("num : " + num + " , s : " + s); } }
|
1 2 3 4 5 6
| new MyGenericInterface01<Integer,String>(){ @Override public void show(Integer num, String s) { System.out.println("num : " + num + " , s : " + s); } }.show(1,"abc");
|
08. 泛型通配符
作用
分类
<?>
<? extends E>
<? super E>
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public static void main(String[] args) { MyTool<GrandFather> tool1 = new MyTool<>(); tool1.setObj(new GrandFather()); show(tool1); MyTool<Father> tool2 = new MyTool<>(); tool2.setObj(new Father()); show(tool2); MyTool<Son> tool3 = new MyTool<>(); tool3.setObj(new Son()); show(tool3); }
public static void show(MyTool<?> tool){ Object obj = tool.getObj(); System.out.println(obj); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public static void main(String[] args) { MyTool<Father> tool1 = new MyTool<>(); tool1.setObj(new Father()); show(tool1);
MyTool<Son> tool2 = new MyTool<>(); tool2.setObj(new Son()); show(tool2);
}
public static void show(MyTool<? extends Father> tool){ Object obj = tool.getObj(); System.out.println(obj); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public static void main(String[] args) {
MyTool<Father> tool1 = new MyTool<>(); tool1.setObj(new Father()); show(tool1);
MyTool<GrandFather> tool3 = new MyTool<>(); tool3.setObj(new GrandFather()); show(tool3);
MyTool<Son> tool2 = new MyTool<>(); tool2.setObj(new Son()); show(tool2); }
public static void show(MyTool<? super Father> tool){ Object obj = tool.getObj(); System.out.println(obj); }
|
常用的泛型含义:
T
- Type(类型)
R
- Result(结果)
K
- Key(键)
V
- Value(值)
E
- Element (元素)
N
- Number(数字)
?
- 不确定类型
【泛型】提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
比如要写一个排序方法,能够对整型数组、字符串数组甚至其他**任何类型
的数组进行排序**,就可以使用 Java 泛型。
09. 泛型集合
概念:参数化类型、类型安全的集合,强制集合元素的类型必须一致。
特点:
- 编译时即可检查,而非运行时抛出异常;
- 访问时,不必类型转换(拆箱);
- 不同泛型之间引用不能相互赋值,泛型不存在多态。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| import java.util.ArrayList; import java.util.LinkedList; import java.util.List; public class TestBasicGeneric { public static void main(String[] args) { List<Student> list = new ArrayList<Student>(); list.add(new Student("tom", 20)); list.add(new Student("jack", 21)); Student s = null; for (int i = 0; i < list.size(); i++) { s = list.get(i); System.out.println(s.name + " " + s.age); } List<Integer> ll = new LinkedList<>(); ll.add(100); ll.add(200); System.out.println(ll.toString()); } } class Student { String name; int age; public Student() {} public Student(String name, int age) { super(); this.name = name; this.age = age; } }
|
10. 泛型深入复杂用法
——需要时间、经验的积累。
概念:约束-规范类型
10.1 普通泛型
- 类:创建对象时,为类所定义的泛型,进行参数化赋值
- 接口:实现接口时,为接口所定义的泛型,进行参数化赋值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public class TestInstanceGeneric { public static void main(String[] args) { MyClass<Integer> mc1 = new MyClass<Integer>(); MyClass<String> mc2 = new MyClass<String>(); mc1.m1(10); mc2.m1("Hello"); } }
class MyClass<E>{ public void m1(E e) {} public void m2(Object o) {} }
interface MyInterface<T> { public T method(T a); }
class MyImplClass implements MyInterface<Dog> { @Override public Dog method(Dog a) { return a; } } class Dog{}
|
10.2 < T > 的含义
- <T> 代表某种通配类型
- <T extends Object> 约定类型T为Object的子类
- <T extends MyClass> 约定类型T只能为MyClass类的子类
- <T extends MyClass & MyInterFace> 约定类型T为MyClass子类同时实现了MyInterFace接口,父类必须写在最前面且可&上多个接口
- <T extends MyInterFace> 约定类型T只要实现了MyInterface接口
- <T extends MyInterFace> 约定类型T要实现了MyInterface接口(且必须为T泛型的接口)
10.3 < ? > 的含义
- > 代表任意通配泛型
- extends FatherClass> 泛型类型?必须是FatherClass的子类
- extends MyInterface> 泛型类型?必须是MyInterface的实现类
- super SubClass> 泛型类型?必须是SubClass类或SubClass的父类
- extends MyInterface extends T>> 泛型类型?必须是MyInterface的实现类,且接口又指定了泛型(必须T类型的子类)
- <T extends MyInterface<? super T>> 要求T所代表的类型必须实现MyInterface接口,同时,接口泛型必须是T类型或T的父类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| import java.util.ArrayList; import java.util.List; public class TestStaticGeneric { public static void main(String[] args) { List<Dog> list1 = new ArrayList<Dog>(); List<Bus> list2 = new ArrayList<Bus>(); List<Animal> list3 = new ArrayList<Animal>(); m1(list1); m2(list2); m3(list1); m3(list3); }
public static void m1(List<? extends Animal> list) {} public static void m2(List<? extends MyInterface<? extends Vehicle>> list2) {} public static void m3(List<? super Dog> list) {} } interface MyInterface<T>{} class Animal{} class Dog extends Animal{} class Vehicle{} class Bus extends Vehicle implements MyInterface<Bus>{}
|
10.4 静态泛型
1)定义在方法的返回值类型前面:<T>
、<T extends Object>
、<T extends Comparable<T>>
、<T extends Comparable<? super T>>
,可使用&多个接口
场景:形参列表、返回值两种场景,不单单可以规范泛型,还可以语义化泛型。
2)定义在方法的形参列表当中:<?>
、<? extends Object>
、<? super SubClass>
,不可使用&
场景:只能应用在形参列表上,规范泛型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import java.util.ArrayList; import java.util.List; public class TestStaticGeneric3 { public static void main(String[] args) { m( new ArrayList<Integer>() ); m( new ArrayList<Double>() ); m( new ArrayList<String>() ); } public static <T> void m(List<T> list) { }
public static <T extends Comparable<? super T>> void sort(List<T> list) { } }
|