250 泛型概述和好处
【泛型概述】
泛型是JDK5引入的特性,它提供了编译时类型安全检测机制。
该机制允许在编译时检测到非法的类型,本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
参数化类型如何理解?
——将类型由原来的类型参数化,然后在使用or调用时传入具体的类型
这种参数类型可以用在类、方法、接口中,分别被称为泛型类、泛型方法、泛型接口
-
【泛型定义格式】
- <类型>:指定1种类型的格式
- <类型1,类型2,类型3…>,指定多种类型的格式,多种类型之间用逗号隔开
- 实参的类型只能是引用数据类型
-
【代码思路】
1. 创建集合,添加元素,遍历输出。
// 在以上的操作里,如果不设置泛型,遍历输出时需要强转集合元素为某种类型(例如String)。
// 运行时报错,如果添加的元素有多种类型(例如String、int),最后报错其他类型(即int)无法强转输出为设置好的类型(即String)。
2. 创建集合时设置好泛型(String),那么添加int类型的元素时出现编译时报错
-
【泛型的好处】
好处1,限制添加的元素为指定的类型,否则抛出编译时异常
好处2,避免了遍历集合时的强转操作
-
【分析】
创建集合时设置泛型,则只能添加指定类型的元素
创建集合时不设置泛型,则可以添加任意类型的元素
输出时强转集合元素为指定类型,则必须保证集合元素全部为指定类型,否则报运行时异常
输出时不强转集合元素为指定类型,则可以直接输出所有集合元素
---------------------------------------------------------------
1 package e250;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.Iterator;
6
7 public class GenericDemo {
8 public static void main(String[] args) {
9 Collection c = new ArrayList();
10
11 c.add("250");
12 c.add("Generic");
13 c.add("two advantages");
14 c.add(100);//编译时不报错,创建集合时没有设置了泛型,则可以添加任意类型的元素
15
16 System.out.println("250.ArrayList");
17 Iterator itt = c.iterator();
18 // while(itt.hasNext()){
19 // Object ooo = itt.next();
20 // System.out.println(ooo);
21 // }
22 // System.out.println("---");
23 // 这段要注释掉,不然下面的while循环不运行
24
25 while(itt.hasNext()){
26 String sss = (String) itt.next();//运行时报错classCastException,因为100不是String类型的
27 System.out.println(sss);
28 }
29 }
30 }
--------------------------------------------------------------
1 package e250;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.Iterator;
6
7 public class GenericAdvantage {
8 public static void main(String[] args) {
9 Collection<String> c = new ArrayList<String>();
10
11 c.add("250.2");
12 c.add("Generic");
13 c.add("two advantages");
14 // c.add(100);//报错,编译时报错,创建集合时设置了泛型,则不能添加指定泛型外的元素
15
16 System.out.println("250.ArrayList");
17 Iterator<String> itt = c.iterator();
18 while(itt.hasNext()){
19 String sss = itt.next();
20 System.out.println(sss);
21 }
22 }
23 }
251 泛型类
【代码思路】
3个类,Student,Teacher,GenericDemo
Student,Teacher类里面各有一套变量、构造方法
Demo类里调用、运行
--------------------------------------------------------------
package e251;
public class Teacher {
private Integer age;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}//不写带参构造方法,则调用时只能用set方法修改对象,不能在创建时修改
//用set方法修改对象,t.setAge(70);
//在创建时修改,Teacher t = new Teacher(70);
--------------------------------------------------------------
package e251;
public class GenericDemo {
public static void main(String[] args) {
Student s = new Student("TRACY");
System.out.println(s.getName());
// Teacher t = new Teacher("44");//报错了,Teacher的参数只能Integer类型,不能其他类型
Teacher t = new Teacher(44);
System.out.println(t.getAge());
}
}
--------------------------------------------------------------
【泛型类的定义格式】
- 修饰符 class 类名<类型>{}
- 例如,public class Generic<T>{}
- - 此处的T可以是任意标志符(可以随意起名),常见的有T、E、K、V等,表示泛型
【代码总结】
由以下代码可知,如果对象类Generic不限定变量类型,则可调用时再灵活设置变量类型
--------------------------------------------------------------
package e251;
public class Generic<T> {
private T t;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
--------------------------------------------------------------
package e251;
public class GenericDemo {
public static void main(String[] args) {
Student s = new Student();
s.setName("Tracy");
System.out.println(s.getName());
// Teacher t = new Teacher("44");//报错了,Teacher的参数只能Integer类型,不能其他类型
Teacher t = new Teacher();
t.setAge(44);
System.out.println(t.getAge());
Generic<String> g1 = new Generic<>();
g1.setT("Ben");
System.out.println(g1.getT());
Generic<Integer> g2 = new Generic<>();
g2.setT(70);
System.out.println(g2.getT());
Generic<Boolean> g3 = new Generic<>();
g3.setT(true);
System.out.println(g3.getT());
}
}
252 泛型方法
【泛型方法的定义格式】
- 修饰符<类型> 返回值类型 方法名(类型 变量名){}
- 例如,public<T> void show(T t){}
--------------------------------------------------------------
【使用泛型类优化前】
package e252;
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);
}
}
-------------------------------
package e252;
public class GenericDemo {
public static void main(String[] args) {
Generic g = new Generic();
g.show("TRACY");
g.show(33);
g.show(false);
}
}
"TRACY"
33
false
--------------------------------------------------------------
//【使用泛型类改进】
package e252;
//使用泛型类改进
public class Generic <T>{
public void show(T t){
System.out.println(t);
}
}
------------------------------
package e252;
public class GenericDemo {
public static void main(String[] args) {
Generic<String> g1 = new Generic<String>();
g1.show("TOAD");
Generic<Integer> g2 = new Generic<>();
g2.show(23);
Generic<Boolean> g3 = new Generic<>();
g3.show(true);
}
}
TOAD
23
true
--------------------------------------------------------------
//【用泛型方法改进】
package e252;
//使用泛型方法改进
public class Generic {
public<T> void show(T t){
System.out.println(t);
}
}
-----------------------------
package e252;
public class GenericDemo {
public static void main(String[] args) {
Generic g = new Generic();
g.show("BADGER");
g.show(30);
g.show(true);
g.show(12.3);
}
}
-----------------------------
BADGER
30
true
12.3
253 泛型接口
【泛型接口的定义格式】
- 修饰符 interface 接口名<类型>{}
- 例如public interface Interface<T>{}
-
如何写泛型接口的实现类?
——参考ArrayList类对List接口的实现,List没有设定泛型,ArrayList类、ArrayList类的方法也都没有设定泛型
--------------------------------------------------------------
package e253;
public interface Generic <T>{
void show(T t);
}
--------------------------------------------------------------
package e253;
public class GenericImpl <T> implements Generic<T>{
@Override
public void show(T t) {
System.out.println(t);
}
}
--------------------------------------------------------------
package e253;
public class GenericDemo {
public static void main(String[] args) {
Generic<String> g1 = new GenericImpl<String>();
g1.show("TRACY");
Generic<Integer> g2 = new GenericImpl<Integer>();
g2.show(33);
}
}
//TRACY
//33