泛型
泛型深入
泛型:jdk5新特性,可以在编译阶段约束操作的数据类型,并进行检查
泛型的格式:<数据类型>
注意:泛型只能支持引用数据类型
泛型的好处:
- 统一数据类型
- 把运行时期的问题提前到了编译期间,避免开了强制类型转换可能出现的异常,因为在编译阶段类型就能确定下来
扩展知识点:Java中的泛型是伪泛型
java文件(是有泛型的)–泛型的擦除–class文件(没有泛型,都是Object强转)
泛型的细节
- 泛型中不能写基本数据类型
- 指定泛型的具体类型后,传入数据时,可以传入该类型或者其子类类型
- 如果不写泛型,类型默认是Object
泛型可以在很多地方进行定义
类后面(泛型类)
格式:修饰符 class 类名<类型>{}
举例:public class ArrayList<E>{} 创建该类对象时,E就确定类型
此处E可以理解为变量,但不是用来记录数据的,而是记录数据类型的
可以写成:T(type) 、E(element) 、K(key) 、V(value)
使用场景:当一个类中,每个变量的数据类型不确定时,就可以定义带有泛型的类
package com.mygenerics;
import java.util.Arrays;
public class MyArrayList <E>{
Object[] obj = new Object[10];
int size;
public boolean add(E e){
obj[size] = e;
size++;
return true;
}
public E get(int index){
return (E)obj[index];
}
@Override
public String toString () {
return Arrays.toString (obj);
}
}
package com.mygenerics;
public class GenericsDemo02 {
public static void main (String[] args) {
MyArrayList<String> list = new MyArrayList<> ();
list.add ("aaa");
list.add ("bbb");
list.add ("ccc");
list.add ("ddd");
System.out.println (list);
MyArrayList<Integer> list2 = new MyArrayList<> ();
list2.add (1);
list2.add (3);
list2.add (2);
list2.add (4);
int get = list2.get (1);
System.out.println (get);
System.out.println (list2);
}
}
方法上面(泛型方法)
此时泛型写的什么类型,那么就只能传递什么类型的数据
弊端:
利用泛型方法有个小弊端,此时它可以接受任意的数据类型
接口上面(泛型接口)
泛型通配符
?表示不确定的类型
它可以进行类型的限定
?Extends E 表示可以传递E或者E 的所有的子类类型
? super E :表示可以传递E或者E所有的父类类型
应用场景:
1. 如果我们在定义类、方法、接口的时候,如果类型不确定,姐可以定义泛型类、泛型方法、泛型接口
2. 如果类型不确定,但是能知道只能传递某个继承体系中的,就可以使用泛型通配符
泛型的通配符
关键点:可以限定类的范围
package com.mygenerics;
import java.util.ArrayList;
public class GenericsDemo04 {
public static void main (String[] args) {
/*
需求:定义一个方法,形参是一个集合,但是集合中的数据类型不确定
*/
//创建集合的对象
ArrayList<Ye> list1 = new ArrayList<> ();
ArrayList<Fu> list2 = new ArrayList<> ();
ArrayList<Zi> list3 = new ArrayList<> ();
ArrayList<Student2> list4 = new ArrayList<> ();
//调用method方法
method(list1);
method(list2);
method(list3);
method (list4);
}
/**
此时泛型写的什么类型,那么就只能传递什么类型的数据
弊端:
利用泛型方法有个小弊端,此时它可以接受任意的数据类型
希望:虽然不确定类型,但是只希望他传递 Ye Fu Zi
此时我们就可以使用泛型的通配符
?表示不确定的类型
它可以进行类型的限定
?Extends E 表示可以传递E或者E 的所有的子类类型
? super E :表示可以传递E或者E所有的父类类型
应用场景:
1. 如果我们在定义类、方法、接口的时候,如果类型不确定,姐可以定义泛型类、泛型方法、泛型接口
2. 如果类型不确定,但是能知道只能传递某个继承体系中的,就可以使用泛型通配符
泛型的通配符
关键点:可以限定类的范围
*/
public static<E> void method(ArrayList<? extends Ye> list){
}
}
class Ye{
}
class Fu extends Ye { }
class Zi extends Fu {
}
class Student2{}
综合练习
package com.mygenerics.test;
import java.util.Objects;
public abstract class Animal {
private String name;
private int age;
public abstract void eat();
public Animal () {
}
public Animal (String name, int age) {
this.name = name;
this.age = age;
}
public String getName () {
return name;
}
public void setName (String name) {
this.name = name;
}
public int getAge () {
return age;
}
public void setAge (int age) {
this.age = age;
}
@Override
public String toString () {
return "Animal{" + "name='" + name + '\'' + ", age=" + age + '}';
}
@Override
public int hashCode () {
return Objects.hash (name, age);
}
}
package com.mygenerics.test;
public abstract class Cat extends Animal{
}
package com.mygenerics.test;
public class Persian extends Cat{
@Override
public void eat () {
System.out.println ("一只叫做"+getName ()+"的"+getAge ()+"岁波斯猫,正在吃小饼干");
}
}
package com.mygenerics.test;
public class Civet extends Cat{
@Override
public void eat () {
System.out.println ("一只叫做"+getName ()+"的"+getAge ()+"岁狸花猫,正在吃鱼");
}
}
package com.mygenerics.test;
public abstract class Dog extends Animal{
}
package com.mygenerics.test;
public class Teddy extends Dog {
@Override
public void eat () {
System.out.println ("一只叫做"+getName ()+"的"+getAge ()+"岁泰迪,正在吃骨头,边吃边蹭");
}
}
package com.mygenerics.test;
public class Husky extends Dog{
@Override
public void eat () {
System.out.println ("一只叫做"+getName ()+"的"+getAge ()+"岁哈士奇,正在吃骨头,边吃边拆家");
}
}
package com.mygenerics.test;
import java.util.ArrayList;
public class Test {
public static void main (String[] args) {
ArrayList<Persian> list1 = new ArrayList<> ();
ArrayList<Civet> list2 = new ArrayList<> ();
ArrayList<Husky> list3 = new ArrayList<> ();
ArrayList<Teddy> list4 = new ArrayList<> ();
keepPet (list1);
keepPet (list2);
keepPet (list3);
keepPet (list4);
}
//该方法能养所有的动物,但是不能传递其他类型
public static void keepPet(ArrayList<? extends Animal> list){
//遍历集合,调用动物的eat() 方法
}
/**
* 该方法能养所有的猫,但是不能养狗
* public static void keepPet(ArrayList<? extends Cat> list){
}*/
/**
* 该方法能养所有的狗,但是不能养猫
* public static void keepPet(ArrayList<? extends Dog> list){
}*/
}
总结