黑马程序员-泛型学习笔记

--------------------------------------泛型--------------------------------------

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);
		
		
	}
}

猜你喜欢

转载自shuangxi-zhu.iteye.com/blog/2249429