JAVA学习第四十二课 — 泛型(二)—泛型接口&&通配符应用

一、泛型接口

interface Inter<T>{
	public void show(T t);
}
class InterImple implements Inter<String>{//知道是字符串类型
	public void show(String str){
		System.out.println("show "+str);
	}
}
class InterImple_2<Q> implements Inter<Q>{//不知道是什么类型,使用的时候才知道
	public void show(Q q){
		System.out.println("InterImple_2.show()+"+q);
	}
}
public class Main 
{
	public static void main(String[] args) {
		InterImple in = new InterImple();
		in.show("sf");
		
		InterImple_2<Integer> in2 = new InterImple_2<Integer>();
		in2.show(2);
	}
}

同上,在使用继承时,如果父类的泛型指定了,那么子类就可以不写泛型,如果不指定还是T,那么子类也必须指定为T


泛型与继承关系

若A是B的子类,在多态上,可以将B 向上转型为A,但是在List<A> 与 List<B> ,List<B>就不能赋给List<A>

List<Object> l1 = new ArrayList<>();
 List<String> l2 = new ArrayList<>();
 l1 = l2; 错误
此处,List<>中无论是什么泛型,两个List都是并列关系,不存在父子关系,如果需要进行如父子关系的赋值等操作,需要使用通配符

二、泛型限定 


泛型的通配符,通俗的说就是不管什么类型,都用一个符号表示T,E,X,?...
其中通配符?和通配符T区别不大

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

public class Main 
{
	public static void main(String[] args) {
		ArrayList<String> al = new ArrayList<String>();
		al.add("ads");
		al.add("sfdf");
		show(al);
		ArrayList<Integer> a3 = new ArrayList<Integer>();
		a3.add(5);
		a3.add(6);
		show(a3);
		HashSet<Integer> al2 =  new HashSet<Integer>();
		al2.add(1);
		al2.add(2);
		show(al2);
	}
	//如果单纯是打印,通配符用?即可,不能使用 增强for
	public static void show(Collection<?> al)   //此处的a1 a2  a3 就都可以 付给 al,言外之意就是 <span style="font-family: Arial, Helvetica, sans-serif;">Collection<?> al,是他们的父类,是任何泛型的父类</span>
<span style="white-space:pre">								</span>//<span style="white-space:pre">	</span>而使用  <span style="font-family: Arial, Helvetica, sans-serif;">Collection<Object> al,就不可以,只能放 List<Object></span>

	{
		Iterator<?> it = al.iterator();
		Iterator<?> it = al.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
	}
	//如果需要返回继续操作
//	public static <T> T show(Collection<T> al) {
//		Iterator<T> iterator = al.iterator();
//		T t = iterator.next();
//		return t;
//	}
}

PS:不能向声明为通配符的对象中,写入数据


关于迭代器

/*Iterator<T> it = al.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}*/
		//java5.0 以后用了更为优雅的for each循环,与iterator表示同样的循环
		for(T x : al){
			System.out.println(x);
		}

简洁明了
通配符第一种演示:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Main 
{
	public static void main(String[] args) {
		ArrayList<Worker> al = new ArrayList<Worker>();
		al.add(new Worker("abc",12));
		al.add(new Worker("dgh",11));
	
		show(al);
		ArrayList<Student> a3 = new ArrayList<Student>();
		a3.add(new Student("ASD",156));
		a3.add(new Student("AFDFD",16));

		show(a3);
	}
	//如果只想打印Man的子类
	//Collection<Man>不对,Collection<Man> = new ArrayList<Student>();左右类型不匹配
	//所以在泛型声明,就可以采用继承的方式
	public static void show(Collection<? extends Man> al)
	{//
		Iterator<? extends Man> it = al.iterator();
		while(it.hasNext()){
			Man man = it.next();
			System.out.println(man);
		}
	}//等价于
	public static <T extends Man> void  show1(Collection<T> al)
	{//
		for(T xT : al)
			System.out.println(xT);
	}
}

所以泛型存的限定有两种:
上限:?extends E,?只能就收E类型或E的子类

下限:? super E,接受E类型或E的父类


三、上限的体现:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Main 
{
	public static void main(String[] args) {
		
	ArrayList<Man> al1 = new ArrayList<Man>();
		al1.add(new Man("ABC",12));
		al1.add(new Man("DGH",11));
		
		ArrayList<Worker> al2 = new ArrayList<Worker>();
		al2.add(new Worker("abc",12));
		al2.add(new Worker("dgh",11));
		
		ArrayList<Student> al3 = new ArrayList<Student>();
		al3.add(new Student("abc",12));
		al3.add(new Student("dgh",11));
		
		al1.addAll(al2);//一般存元素的时候,都是上限,因为这样取出都是按照上限类型来运算的,不会出现类型安全隐患 
		
		System.out.println(al1.size());
	}
}

详细看API文档,addAll方法 : addAll(? extends E),可以存储E及E的所有子类

泛型的使用规则

1.静态方法中不可以使用泛型 解释:static 在实例化之前就存在,但是泛型<T>是在实例化时才确定的

      如果要用,必须在静态方法前定义 public static<F> void mthod(F str),必须要先定义,否则报错

2.当一个泛型类是接口或抽象类时,它是不可以创建该泛型类的对象的

3.try-catch不能使用泛型 

4.从泛型类派生子类,泛型类型需要具体化


四、下限的体现:

通常对集合中元素进行取出动作时,可以用下限
也就是不论存什么类型(只要是当前父类的子类),都可以用父类型接收

import java.util.Comparator;
import java.util.TreeSet;
import java.util.Iterator;
class ComparaName implements Comparator<Man>{
//按姓名排序
	public int compare(Man o1, Man o2) {
		// TODO Auto-generated method stub
		int t = o1.getName().compareTo(o2.getName());	
		return t==0?o1.getAge()-o2.getAge():t;
	}
}
public class Main 
{
	public static void main(String[] args) {
		
	TreeSet<Man> al1 = new TreeSet<Man>(new ComparaName());
		al1.add(new Man("ABC",12));
		al1.add(new Man("DGH",11));
		
		TreeSet<Worker> al2 = new TreeSet<Worker>();
		al2.add(new Worker("abc",12));
		al2.add(new Worker("dgh",11));
		
		TreeSet<Student> al3 = new TreeSet<Student>(new ComparaName());
		al3.add(new Student("abc",12));
		al3.add(new Student("dgh",11));
		//把学生和工人都加入al1集合
		al1.addAll(al3);
		al1.addAll(al2);
		//都按照Man的排序规则排序
		Iterator<Man> it = al1.iterator();
		while(it.hasNext())
			System.out.println(it.next());
	}
}

五、通配符的体现

import java.util.Collection;
import java.util.ArrayList;
import java.util.Iterator;

public class Main 
{
	public static void main(String[] args) {
		
		ArrayList<Man> al1 = new ArrayList<Man>();
		al1.add(new Man("ABC",12));
		al1.add(new Man("DGH",11));
		
		ArrayList<Man> al2 = new ArrayList<Man>();
		al2.add(new Man("ABC",12));
		al2.add(new Man("DGH",11));
		
		boolean flag1 = al1.containsAll(al2);
		System.out.println(flag1);
		
		ArrayList<String> al3 = new ArrayList<String>();
		al3.add("qwertyi");
		al3.add("asd");
		
		boolean flag2 = al1.containsAll(al3);
		System.out.println(flag2);
	}
	//方法 : containsAll(Collection <?> c) 
	//?不论传什么都接收,就好比Object里的equals方法:"asd".equals(new Worker("asd",12)),编译和运行都是通过的
	public static void show(Collection<?> al){
		for(Iterator<?> it = al.iterator();it.hasNext();){
			System.out.println(it.next());
		}
	}
}

interface Information {

}
class PersonInfor implements Information{
	private int age;
	private String name;
}

class ContactInfor implements Information{
	private String phone;
	private String address;
}

class Person<T extends Information>{ 
	//这个person类只能是  Information 或 Information 的子类
	
	public void get(List<? extends PersonInfor> ls){
		
	}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值