1. 泛型
(1) 泛型:定义类、接口、方法时,同事声明了一个或多个类型变量(如<E>),称为泛型类、泛型接口、泛型方法、它们统称为泛型。可以在编译阶段约束要操作的数据类型
public static void main(String[] args) {
//没加泛型 可以放任何类型的数据
ArrayList list = new ArrayList();
list.add("卡莎");
list.add(123);
list.add('c');
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
//加泛型 只能放String类型
ArrayList<String> list1 = new ArrayList<>();//从JDK1.7开始,后面的泛型<>可以不声明
list1.add("卡莎");
list1.add("艾卡西亚");
//list1.add(123);
for (int i = 0; i < list1.size(); i++) {
String str = list1.get(i);
System.out.println(str);
}
}
(2) 作用:泛型提供了在编译阶段约束所能操作的数据类型,并自动进行检查的能力,这样可以避免强制类型转换及其可能出现的异常。
(3) 泛型的本质就是把具体的数据类型作为参数传递给类型变量
2. 泛型类
(1) 格式:修饰符 class 类名<类型变量, 类型变量,.....>{ ..........}
类型变量建议使用大写的英文字母,常用的有E、T、K、V等
//泛型类
public class MyArray<E> {
Object[] array = new Object[10];
private int size = 0;//记录当前位置
public boolean add(E e) {
array[size++] = e;
return true;
}
public E get(int index) {
return (E)array[index];
}
}
//多个泛型 类
public class MyArray2<E,D> {
public void put(E e, D d) {
}
}
//动物类
public class Animal {
}
//狗继承动物类
public class Dog extends Animal{
}
//继承泛型类
public class MyArray3<E extends Animal> {
}
//测试
public static void main(String[] args) {
//泛型类
//单个泛型限定String
MyArray<String> array = new MyArray();
array.add("卡莎");
array.add("艾卡西亚");
String a = array.get(0);//卡莎
System.out.println(a);
//多个泛型限定 String,String
MyArray2<String,String> array2 = new MyArray2<>();
array2.put("卡莎","艾卡西亚");
array2.put("泰坦","勾");
//泛型限定必须为Animal的继承者 Dog继承Animal
MyArray3<Dog> array3 = new MyArray3<>();
}
3. 泛型接口
(1) 格式:修饰符 interface 接口名<类型变量,类型变量,......> { ......}
类型变量建议使用大写的英文字母,常用的有E、T、K、V等
泛型接口中泛型也可为<E extends Animal> 此时的泛型必须为Animal的继承者
//泛型接口
public interface Data<E> {
void add(E e);
ArrayList<E> get(String name);
}
//泛型继承接口
public interface Data1<E extends Animal> {
void add(E e);
ArrayList<E> get(String name);
}
//老师实体类
public class Teacher {
}
//学生实体类
public class Student {
}
//老师实现Data接口 泛型为老师实体类
public class TeacherData implements Data<Teacher>{
@Override
public void add(Teacher teacher) {
}
@Override
public ArrayList<Teacher> get(String name) {
return null;
}
}
//学生实现Data接口 泛型为学生实体类
public class StudentData implements Data<Student>{
@Override
public void add(Student student) {
}
@Override
public ArrayList<Student> get(String name) {
return null;
}
}
4. 泛型方法、泛型通配符、上下限
(1) 泛型方法格式: 修饰符<类型变量,类型变量,.....> 返回值类型 方法名(形参列表){...}
(2) 通配符
就是 ?,可以在"使用泛型"的时候代表一切类型;E T K V是在定义泛型的时候使用
(3) 泛型的上下限
泛型上限: ? extends Animal : ?能接收的必须是Animal或者他的子类
泛型下限:? super Animal:?能接收的必须是Animal或者他的父类
public class Test3 {
public static void main(String[] args) {
//泛型方法
String s = show("java");
Integer i = show(123);
char c = show('c');
Boolean falg = show(false);
Dog dog = show(new Dog());
}
//泛型方法
public static <T> T show(T t){
return t;
}
//泛型继承方法
public static <T extends Animal> T show(T t){
return t;
}
// ? 通配符 在使用泛型的时候可以代表一切类型
public static void run(ArrayList<?> list){
}
// ? 通配符继承 在使用泛型的时候可以代表一切类型 Animal(上限)的子类
public static void run1(ArrayList<? extends Animal> list){
}
//super Animal(下限) Animal的父类
public static void run3(ArrayList<? super Animal> list){
}
}
5. 泛型擦除问题、基本数据类型问题
(1)泛型是工作在编译阶段的,一旦程序编译成class文件,class文件中就不存在泛型了,这就是泛型擦除
(2)泛型不支持基本数据类型,只能支持对象类型(引用数据类型),可以使用基本数据类型的包装类
public static void main(String[] args) {
//泛型擦除问题、基本数据类型问题
//1.泛型是工作在编译阶段的,一旦程序编译成class文件,class文件中就不存在泛型了,这就是泛型擦除
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
Integer i = list.get(0);
System.out.println(i);
//2.泛型不支持基本数据类型,只能支持对象类型(引用数据类型)
//ArrayList<int> list2 = new ArrayList<int>();
}
编译之后的问文件:
基本数据类型的包装类:
基本类型 |
包装类(引用类型,包装类都位于java.Lang包下) |
byte |
Byte |
short |
Short |
int |
Integer 【特殊】 |
long |
Long |
float |
Float |
double |
Double |
char |
Character 【特殊】 |
boolean |
Boolean |