--------------------------------------泛型--------------------------------------
1.当我们定义一个集合后,我们可以向集合中添加什么数据?任何的引用类型;
2.当我们取出时,尤其是需要"向下转型"时,会给我们带来很大麻烦;
3.实际上我们开发时,经常只需要一个集合中只存储一种数据类型的引用;
4.这时,Java为我们提供了一种机制:
1).在定义集合时,就强制定义了这个集合中只能存储哪种类型的数据;
2).如果代码中,试图存储其它类型的数据时,编译时,就会发生错误;
这种机制:泛型
5.示例: //定义一个只存储字符串的集合
List<String> strList = new ArrayList<String>();
或:
List<String> strList = new ArrayList<>();//(常用)
或:
List<String> strList = new ArrayList();
//存储元素
strList.add("abc");//OK的
strList.add(20);//编译错误
//遍历取出时--不需要强制转换
for(int i = 0;i < strList.size(); i++){
String str = strList.get(i);
}
6.注意:泛型只存在于"编译期",当生成class文件后,就没有泛型信息了;
public class Student { String name; int age; public Student(String name, int age) { super(); this.name = name; this.age = age; } public boolean equals(Object obj) { Student stu = (Student) obj; return this.name.equals(stu.name) && this.age == stu.age; } }
public class Demo { public static void main(String[] args) { // 不带泛型的集合,可以添加任何东西,取出时 ArrayList list = new ArrayList(); list.add("aaa"); list.add(10);// 自动装箱 list.add(true);// 自动装箱 list.add(3.14);// 自动装箱 list.add(new Student("张三", 20)); ArrayList list2 = new ArrayList(); list2.add("aaa"); list2.add("bbb"); list2.add("ccc"); list2.add(new Student("张三", 20)); /* * for(int i = 0;i < list2.size() ; i++){ * //很多时候,我们为了访问所存储对象的"特有成员",经常要向下强转为所存储的类型, * 如果没有用泛型限定,取出时需要(instanceof)先判断元素是不是此类型,不然就会转换异常 * String str =(String)list2.get(i); * } */ // 使用泛型定义只能存String类型的集合 ArrayList<String> strList = new ArrayList<>(); strList.add("aaa"); // strList.add(20);//编译错误 for (int i = 0; i < strList.size(); i++) { String str = strList.get(i); } // 定义泛型的集合,只能存指定的类型,所以取出时不需要进行转换 ArrayList<Student> stuList = new ArrayList<>(); stuList.add(new Student("张三", 20)); for (int i = 0; i < stuList.size(); i++) { Student stu = stuList.get(i); System.out.println(stu.name + "," + stu.age); } } }
--------------------------------------泛型类--------------------------------------
泛型类的定义:
1.在"类名后"使用一对<>括号;
2.里面可以定义泛型名称;
3.泛型名称:
1).可以是一个字母;也可以是多个字母;
2).可以小写,可以大写;
3).可以是一个,可以是多个;多个的话使用逗号分隔;
public class MyLinkedList<T> { private LinkedList<T> list = new LinkedList(); public void add(T obj) { this.list.addFirst(obj); } public T get(int index) { return this.list.get(index); } public int size() { return this.list.size(); } }
public class Demo { public static void main(String[] args) { MyLinkedList<String> list = new MyLinkedList<>(); list.add("abc");// OK,上面使用了String泛型定义的,所以只能存String类型的数据 // list.add(123);// 编译错误 String str = list.get(0);// OK } }
--------------------------------------泛型方法--------------------------------------
public class MyLinkedList { // 接收三个某种类型的数据 // 能返回一个具有这种类型泛型的一个集合对象; public <T> List<T> add1(T obj1, T obj2, T obj3) { // 传过来是什么类型就list就是什么类型 List<T> list = new ArrayList<>(); list.add(obj1); list.add(obj2); list.add(obj3); return list; } }
/* * 在方法上定义泛型: */ public class Demo { public static void main(String[] args) { MyLinkedList list = new MyLinkedList(); List<String> strList = list.add1("aaa", "bbb", "ccc"); } }
--------------------------------------泛型接口--------------------------------------
当子类实现了一个带泛型的接口时:
有三种可选择的操作:
1.丢弃泛型;方法内的泛型部分全部变为Object类型;
class SubA implements IA{
public void add(Object obj){
}
}
2.指定一个具体类型:
class SubA implements IA<String>{
public void add(String str){
}
}
3.继续支持泛型;(子类常见的方式)
class SubA<E> implements IA<E>{
public void add(E e){
}
}
public class SubA<E> implements IA<E> { @Override public void add(E e) { // TODO Auto-generated method stub } @Override public E get(int index) { // TODO Auto-generated method stub return null; } }
public interface IA <E>{ public void add(E e); public E get(int index); }
--------------------------------------泛型通配符--------------------------------------
泛型通配符:
1.<?> :
1).变量可以指向什么类型的对象:具有任何泛型的集合对象;
2).可以存储什么东西:由于?不确定具体类型,所以不能add()任何类型
3).取出时用什么接收:只能用Object接收;
作用:不能存入,只能获取,所以一般用作方法的返回值声明;
2.<? extends E> :
1).变量可以指向什么类型的对象:具有E泛型或者E子类泛型的集合;
2).可以存储什么东西:由于不确定是哪个E的子类,所以不能存任何东西;
3).取出时用什么接收:只能用E及E的父类类型接收;
3.<? super E> :
1).变量可以指向什么类型的对象:具有E泛型或者E父类泛型的集合;
2).可以存储什么东西:只能存储E或者E的子类对象;
3).取出时用什么接收:由于存储的可能是任何的E的子类对象,所以只能用Object接收;
class Animal{} class Cat extends Animal{}; class Dog extends Animal{}; class JMDog extends Dog{}; public class Demo { public static void main(String[] args) { //1.<?> List<?> list1 = new ArrayList<>(); List<?> list2 = new ArrayList<String>(); List<?> list3 = new ArrayList<Animal>(); // // list2.add("aa"); // list2.add(10); // list2.add(new Animal()); Object obj = list2.get(0); //2.<? extends E> // List<? extends Dog> list4 = new ArrayList<Animal>();//编译错误 List<? extends Dog> list5 = new ArrayList<Dog>(); List<? extends Dog> list6 = new ArrayList<JMDog>(); / list5.add("你好"); list5.add(10); list5.add(new Animal()); list5.add(new Dog()); list5.add(new JMDog()); / Dog d1 = list5.get(0); Animal a1 = list5.get(0); //3.<? super E> List<? super Dog> list7 = new ArrayList<Animal>(); List<? super Dog> list8 = new ArrayList<Dog>(); // List<? super Dog> list9 = new ArrayList<JMDog>(); // list7.add(new Animal()); list7.add(new Dog()); // list7.add(new Cat()); list7.add(new JMDog()); Object d = list7.get(0); } }