二十二.泛型

泛型问题的引出

为什么要用泛型?

在java集合中储存数据会被当做Object类型来存储,可能有些类型会失去原本的特性,所以可以用泛型来统一集合当中的存储类型。

class Test3 {
	public static void main(String[] args) {
		List list = new ArrayList();
		list.add("1212");
		list.add(121);
		
		List<String> lists = new ArrayList<String>();
		lists.add("2121");
		//lists.add(2121);		//报错
	}
}

在我看来泛型就是一个辅助我们编译的东西,在很多复杂类型中可以使用泛型来解决。

泛型的基本定义

泛型不止可以用作集合上,还能用作在参数、方法、类等…

利用泛型还可以解决ClassCastException问题.

class CeShi4<T> {		//T属于类型标记,可以设置多个	
	//T返回的是什么数据类型,下面属性就是什么数据类型
	private T x;		//x轴坐标		
	private T y;		//y轴坐标
	
	public T getX() {
		return x;
	}
	public void setX(T x) {
		this.x = x;
	}
	public T getY() {
		return y;
	}
	public void setY(T y) {
		this.y = y;
	}
}

class Test3 {
	public static void main(String[] args) {
		//实例化CeShi4对象,设置"T"数据类型
		CeShi4<Integer> ceShi4 = new CeShi4<Integer>();	
		
		ceShi4.setX(10);
		ceShi4.setY(20);
		
		int x = ceShi4.getX();
		int y = ceShi4.getY();
		
		System.out.println("x轴坐标:"+x+",y轴坐标:"+y);
	}
}

输出结果:

x轴坐标:10,y轴坐标:20

泛型通配符

数组的协变

例子:

Number[] nums = new Integer[10]; // OK

因为Integer是Number的子类,一个Integer对象也是一个Number对象,所以一个Integer的数组也是一个Number的数组,这就是数组的协变。

java数组的协变是有一定的缺陷的,就算是把Integer[]赋给Number[],但是数组元素类型还是Integer,智能放入Integer子类或者Integer对象。如果放入Number子类或者Number对象,那么在运行的时候JVM能够知道数组元素的类型是Integer,所以会报java.lang.ArrayStoreException错误

那么我们可以使用泛型的通配符来解决这种问题
向上转型:

List<? extends Number> nums = new ArrayList<Integer>(); // OK
无边界通配符

当你不知道泛型返回的是什么类型可以用

class Test3 {
	public static void main(String[] args) {
		List<String> list1 = new ArrayList<String>();
		list1.add("121");
		list1.add("222");
		show(list1);
	}
	
	public static void show(List<?> c){	//当你不知道泛型是什么类型时用?
		for (Object object : c) {
			System.out.println(object);
		}
	}
}
121
222

List和List的区别

  • List是表示持有某种特定类型对象的List,但是不知道是哪种类型;List是表示持有Object类型对象的List。
  • List 因为不知道持有的实际类型,所以不能add任何类型的对象,但是List list因为持有的是Object类型对象,所以可以add任何类型的对象。
上边界限定的通配符

< ? extends E>:接收E类型或者E的子类型对象


class Person{
	private String name;
	private int age;
	
	public Person(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;
	}
	
}

class Student extends Person{

	public Student(String name, int age) {
		super(name, age);
	}
	
}

class Test3 {
	public static void main(String[] args) {
		List<Person> list1 = new ArrayList<Person>();
		list1.add(new Person("sss", 12));
		
		List<Student> list2 = new ArrayList<Student>();
		list2.add(new Student("ccc",13));
		
		show(list1);
		show(list2);
	}
	
	public static void show(List<? extends Person> c){	//当你不知道泛型是什么类型时用?

		Iterator<? extends Person> it = c.iterator();
		while(it.hasNext()){
			Person p = it.next();
			
			System.out.println("姓名:"+p.getName()+",年龄:"+p.getAge());
		}
	}
}

输出结果

姓名:sss,年龄:12
姓名:ccc,年龄:13
下边界限定的通配符

< ? super E >:接收E类型或者E的父类型

class Person{
	private String name;
	private int age;
	
	public Person(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;
	}
	
}

class Student extends Person{

	public Student(String name, int age) {
		super(name, age);
	}
	
}

class Test3 {
	public static void main(String[] args) {
		List<Person> list1 = new ArrayList<Person>();
		list1.add(new Person("sss", 12));
		
		List<Student> list2 = new ArrayList<Student>();
		list2.add(new Student("ccc",13));
		
		show(list1);
		show(list2);
	}
	
	public static void show(List<? super Student> c){	//当你不知道泛型是什么类型时用?

		Iterator<? super Student> it = c.iterator();
		while(it.hasNext()){
			
			System.out.println(it.next());
		}
	}
}

输出结果

main.Person@15db9742
main.Student@6d06d69c

泛型接口

例子:

//泛型接口
interface Person<T>{
	public void show(T t);
}

//子类继承泛型接口
class Student<Q> implements Person<Q>{
	@Override
	public void show(Q q) {
		// TODO Auto-generated method stub
		System.out.println("show:"+q);
	}			
}

class Test3 {
	public static void main(String[] args) {
		Person<Integer> p = new Student<Integer>();
		p.show(2222);
	}
}

输出结果

show:2222

泛型方法

例子:

class Person{
	//泛型方法
	public <T> void show(T t){
		System.out.println(t);
	}
	
	public <U,T> void show(U u,T t){
		System.out.println(u);
		System.out.println(t);
	} 
}

class Test3 {
	public static void main(String[] args) {
		Person person = new Person();
		person.show("sb");
		person.show(123, "小红");
	}
}

输出结果:

sb
123
小红
  • 泛型方法可以让不同方法操作不同类型,且类型还不确定。
  • 与泛型类不同,泛型方法的类型参数只能在它锁修饰的泛型方法中使用。

你可能感兴趣的:(Java面向对象,java,接口)