Java中泛型(5)——泛型限定(传智播客毕老师视频讲解)

个人理解:所谓泛型限定,是指一个方法在接收所传参数引用数据类型时做的限定!

1、<?>:接收指定类型

先看下面的程序

import java.util.*;
public class GenericLimit 
{
	public static void main(String[] args)
	{
		ArrayList<String> L1=new ArrayList<String>();
		L1.add("001");
		L1.add("002");
		L1.add("003");
		L1.add("004");
		L1.add("005");
		
		ArrayList<Integer> L2=new ArrayList<Integer>();
		L2.add(001);
		L2.add(002);
		L2.add(003);
		L2.add(004);
		L2.add(005);
		
		show(L1);
		//show(L2);
	}
	public static void show(ArrayList<String> L)
	{//<指定类型>
		ListIterator<String> it=L.listIterator();
		while(it.hasNext())
		{
			System.out.println(it.next().length()+"...");
		}
	}
}

在show方法里定义了ArrayList<String>泛型后,就不能再通过传入L2来调用show方法,为了解决这个问题,用<?>来解决:根据传进来的类型做决定,类似于Object多态形式。

2、“?”通配符:接收任意类型

代码如下

import java.util.*;
public class GenericLimit 
{
	public static void main(String[] args)
	{
		ArrayList<String> L1=new ArrayList<String>();
		L1.add("001");
		L1.add("002");
		L1.add("003");
		L1.add("004");
		L1.add("005");
		
		ArrayList<Integer> L2=new ArrayList<Integer>();
		L2.add(001);
		L2.add(002);
		L2.add(003);
		L2.add(004);
		L2.add(005);
		
		show(L1);
		show(L2);
	}
	public static void show(ArrayList<?> L)
	{//<?>接收任意类型
		ListIterator<?> it=L.listIterator();
		while(it.hasNext())
		{
			System.out.println(it.next()+"...");
		}
	}
}
结果如下图:


<?>与<T>与<指定类型>的区别:

区别不是很大;但是有区别:

1、<T>代表一个具体类型,传什么类型就是什么类型,<?>是占位符,不明确具体类型,<指定类型>明确规定了传入引用数据类型!

2、静态方法中不能调用类上定义的泛型,因此若用<T>,必须在static后声明<T>;而<?>、<指定类型>不需要在static后声明!

3、由于<?>不明确具体类型,所以相应的不能建立其对象;<T>与<指定类型>均能建立其相应的对象;

4、由于<T>是在接收传入的引用数据类型才明确类型,所以其只能调用Objcet类中的方法,<?>更是如此!但<指定类型>由于一开始就明确了引用数据类型,所以可以调用相应的特有方法!

如<T>代码可以这样写:

public static<T> void show(ArrayList<T> L)     //静态方法中不能调用类上定义的泛型,因此若用<T>,必须在static后声明<T>
{
	ListIterator<T> it=L.listIterator();
	while(it.hasNext())
	{
		T o=it.next();                 //T是传进来的具体类型;但<?>就不能写成? o=it.next();形式!
		System.out.println(o+"...");   //由于T是在接收L后才能确定类型,因此只能调用Object类中的方法,不能调用L中特有方法;
	}                                      //<span style="font-family: Arial, Helvetica, sans-serif;"><?>更是如此,其只表示占位符的意思,因此等L传递进来,它也不知道传递的什么类型…………</span>
}

<指定类型>

public static void show(ArrayList<String> L)  //但若是指定类型的泛型,则不必提前声明了,
{
	ListIterator<String> it=L.listIterator();
	while(it.hasNext())
	{
		System.out.println(it.next().length()+"...");  //但由于指定类型固定,所以可以调用L中特有方法
	}
}

3、泛型上限:接收本类型和本类型子类

? extends E: 可以接收E类型或者E的子类型。

代码如下:

import java.util.*;
public class Person 
{
	private String name;
	public Person(String name)
	{
		this.name=name;
	}
	public String getName()
	{
		return name;
	}
}
public class Worker extends Person
{
	public Worker(String name)
	{
		super(name);  //切记:子类构造方法第一句话必须是super();
	}
}
public class Student extends Person
{

	public Student(String name) 
	{ 	
		super(name);
	}
}

public class GenericLimit 
{
	public static void main(String[] args)
	{
		ArrayList<Student> L1=new ArrayList<Student>();
		L1.add(new Student("001"));
		L1.add(new Student("002"));
		L1.add(new Student("003"));
		
		ArrayList<Worker> L2=new ArrayList<Worker>();
		L2.add(new Worker("101"));
		L2.add(new Worker("102"));
		L2.add(new Worker("103"));
		
		show(L1);
		show(L2);
	}
	public static void show(ArrayList<? extends Person> L) //可以接收Person类及Person的子类,即一个方法所能接收传入数据引用数据类型的限定!
	{
		ListIterator<? extends Person> it=L.listIterator();
		while(it.hasNext())
		{
			System.out.println(( it.next()).getName()+"...");
		}
	}
}
结果如下:


可见Student类与Worker类均被允许并传递进来!,但是只能调用父类的方法,不能调用子类特有方法!

应用比如:ArrayList中的方法:


即可以接收E即E的子类元素,其中E是在类上定义的泛型。

4、泛型下限:接收本类型和本类型父类

? super E: 可以接收E类型或者E的父类型。

如:


可以传入当前类型父类的比较器,调用父类比较器的方法进行比较!

当多个子类对象的比较方法均和父类方法一致时,将比较器类型定义为父类比较器,通过泛型下限,将父类比较器传入子类对象中,实现比较功能,这样实现了多个子类对象公用一个比较器,而且不允许其体系外的对象使用此比较器!

(1)实现Comparable接口代码:

import java.util.*;
public class Person  implements Comparable<Person>//子类将继承父类比较方法
{
	private String name;
	public Person(String name)
	{
		this.name=name;
	}
	public String getName()
	{
		return name;
	}
	public int compareTo(Person obj)           //父类比较方法    
	{
		Person it=(Person )obj;
		return this.name.compareTo(it.name);     //按照字符串自然顺序自然排序,
	}
}
public class Student extends Person 
{

	public Student(String name) 
	{ 	
		super(name);
	}
	public void show()
	{
		System.out.println("Student");
	}
}
public class Worker extends Person 
{
	public Worker(String name)
	{
		super(name);
	}
}

public class GenericLimit 
{
	public static void main(String[] args)
	{

		TreeSet<Student> L1=new TreeSet<Student>();
		L1.add(new Student("student--003"));
		L1.add(new Student("student--002"));
		L1.add(new Student("student--001"));
		L1.add(new Student("student--0010"));
		
		TreeSet<Worker> L2=new TreeSet<Worker>();
		L2.add(new Worker("worker--101"));
		L2.add(new Worker("worker--102"));
		L2.add(new Worker("worker--103"));
		L2.add(new Worker("worker--1012"));
		
		show(L1);
		show(L2);
	}
	public static void show(TreeSet<? extends Person> L)
	{
		Iterator<? extends Person> it=L.iterator();
		
		while(it.hasNext())
		{
			System.out.println(it.next().getName()+"...");
		}
	}
}
结果如下:


(2)用比较器Comparator建立比较器,传入比较器对象给TreeSet集合,

import java.util.*;
public class NautureComp implements Comparator<Person>
{
	public int compare(Person obj1,Person obj2)
	{
		return (obj2).getName().compareTo((obj1).getName());
	}
}
public class Person  implements Comparable<Person>//子类将继承父类比较方法
{
	private String name;
	public Person(String name)
	{
		this.name=name;
	}
	public String getName()
	{
		return name;
	}
	public int compareTo(Person obj)           //父类比较方法    
	{
		Person it=(Person )obj;
		return this.name.compareTo(it.name);     //按照字符串自然顺序自然排序,
	}
}
public class Student extends Person 
{

	public Student(String name) 
	{ 	
		super(name);
	}
	public void show()
	{
		System.out.println("Student");
	}
}
public class Worker extends Person 
{
	public Worker(String name)
	{
		super(name);
	}
}

public class GenericLimit 
{
	public static void main(String[] args)
	{

		TreeSet<Student> L1=new TreeSet<Student>(new NautureComp()); //传入的为父类比较器,即 ? super E 
		L1.add(new Student("student--003"));
		L1.add(new Student("student--002"));
		L1.add(new Student("student--001"));
		L1.add(new Student("student--0010"));
		
		TreeSet<Worker> L2=new TreeSet<Worker>(new NautureComp());
		L2.add(new Worker("worker--101"));
		L2.add(new Worker("worker--102"));
		L2.add(new Worker("worker--103"));
		L2.add(new Worker("worker--1012"));
		
		show(L1);
		show(L2);
	}
	public static void show(TreeSet<? extends Person> L)
	{
		Iterator<? extends Person> it=L.iterator();
		
		while(it.hasNext())
		{
			System.out.println(it.next().getName()+"...");
		}
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值