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,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);
	}
	//如果单纯是打印,通配符用?即可
	public static void show(Collection<?> al)
	{
		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;
//	}
}

关于迭代器

/*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的所有子类

四、下限的体现:

通常对集合中元素进行取出动作时,可以用下限

也就是不论存什么类型(只要是当前父类的子类),都可以用父类型接收

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

时间: 2024-10-15 14:42:59

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

JAVA学习第四十八课 — IO流(二):文件的复制 &amp; 缓冲区1

一.复制文本文件 将G盘的文本文件复制到D盘上 也就是 读取G盘中文本文件的数据,写入D盘中->连读带写 而剪切呢,就是连读带写后,删除原盘的文件 <span style="font-family:KaiTi_GB2312;font-size:18px;"><strong>import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public clas

JAVA学习第四十六课 — 其他对象API(二)Date类 &amp; Calendar类(重点掌握)

Date类(重点) 开发时,会时常遇见时间显示的情况,所以必须熟练Date的应用 <span style="font-family:KaiTi_GB2312;font-size:18px;"><strong>import java.util.*; public class Main { public static void main(String[] args){ long l = System.currentTimeMillis();//14140798929

JAVA学习第四十九课 — IO流(三):缓冲区2 &amp; 装饰设计模式

一.模拟BufferedReader 自定义MyBuffereaReader 对于缓冲区而言,里面其实就是封装一个数组,对外提供方法对数组的操作,这些方法最终操作的都是数组的角标 原理:从源中取出数据存入缓冲区,再从缓冲区不断的取出数据,取完后,继续从源中继续取数据,进缓冲区,直至源中的数据取完,用-1做为结束标记 import java.io.*; class MyBufferedReader { private FileReader fr; //定义数组作为缓冲区 private char[

JAVA学习第四十五课 — 其他对象API(一)

一.System类 1. static long currentTimeMillis() 返回以毫秒为单位的当前时间. 实际上:当前时间与协调世界时 1970 年 1 月 1 日午夜之间的时间差(以毫秒为单位测量). long time = 1414069291407l;//long型 后面加l System.out.println(time); 2. static void exit(int status)终止当前正在运行的 Java 虚拟机. static void gc()运行垃圾回收器

JAVA学习第四十五课 — 其它对象API(一)System、Runtime、Math类

一.System类 1. static long currentTimeMillis() 返回以毫秒为单位的当前时间. 实际上:当前时间与协调世界时 1970 年 1 月 1 日午夜之间的时间差(以毫秒为单位測量). long time = 1414069291407l;//long型 后面加l System.out.println(time); 2. static void exit(int status)终止当前正在执行的 Java 虚拟机. static void gc()执行垃圾回收器

JAVA学习第三十六课(常用对象API)- 集合框架(四)— Set集合:HashSet集合演示

随着Java学习的深入,感觉大一时搞了一年的ACM,简直是明智之举,Java里很多数据结构.算法类的东西,理解起来就轻松多了 Set集合下有两大子类开发常用 HashSet集合 .TreeSet集合 Set集合的元素是不重复且无序 一.HashSet集合 API文档解释:此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持.它不保证 set 的迭代顺序:特别是它不保证该顺序恒久不变.此类允许使用null 元素. 此类为基本操作提供了稳定性能,注意,此实现不是同步的. 由上可

JAVA学习第四天 基础概念总结 二

五.程序控制结构 1,程序的结构设计 (1)顺序结构:按书写顺序执行的语句构成的程序段.按顺序一句一句地执行. (2)选择结构:也称为分支结构,在许多实际问题的程序设计中,根据输入数据和中间结果的不同情况需要选择不同的语句组执行,在这种情况下,必须根据某个变量或表达式的值作出判断,以决定执行那些语句和跳过那些语句不行执行. (3)循环结构:在给定条件成立时,反复执行某个程序段.   2,选择结构 (1) if语句 (2) if...else语句 (3) if...else...if...else

JAVA学习第四十四课 — 集合框架工具类(二)

Collections操控集合的工具类,Arrays操控数组的工具类 Arrays中方法大多是重载 重点掌握asList();将数组转为集合 static <T> List<T> asList(T... a) 返回一个受指定数组支持的固定大小的列表. import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { String[]

JAVA学习第四十课(常用对象API)- Map集合练习

一.LinkedHashMap集合 import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; public class Main { public static void main(String[] args) { HashMap<Integer, String> hm = new LinkedHashMap<Integer,Stri