Java常用对象API——泛型

泛型

jdk1.5出现的安全机制。

好处:
1,将运行时期的问题ClassCastException转到了编译时期。
2,避免了强制转换的麻烦。

<>:什么时候用?当操作的引用数据类型不确定的时候。就使用<>。将要操作的引用数据类型传入即可.
其实<>就是一个用于接收具体引用数据类型的参数范围。

在程序中,只要用到了带有<>的类或者接口,就要明确传入的具体引用数据类型 。

泛型技术是给编译器使用的技术,用于编译时期。确保了类型的安全。

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

public class GenericDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		
		int[] arr = new int[4];
			
		ArrayList<String> al = new ArrayList<String>();//泛型:明确传入的只能是String类型
		
		al.add("abc");//public boolean add(Object obj)
		al.add("hahah");
//		al.add(4);//al.add(new Integer(4));放不进去了
		
		Iterator<String> it = al.iterator();
		while(it.hasNext()){
			
			String str = it.next();
			System.out.println(str);
		}
	}

}

运行时,会将泛型去掉,生成的class文件中是不带泛型的,这个称为泛型的擦除
为什么擦除呢?为了兼容运行的类加载器。

泛型的补偿:在运行时,通过获取元素的类型进行转换动作。使用者不必再强制转换了。

泛型在集合中的应用

例子:

import java.util.Iterator;
import java.util.TreeSet;

import cn.itcast.p2.bean.Person;
import cn.itcast.p3.comparator.ComparatorByName;

public class GenericDemo2 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		//泛型:传入Person类
		TreeSet<Person> ts = new TreeSet<Person>(new ComparatorByName());
		ts.add(new Person("lisi8",21));
		ts.add(new Person("lisi3",23));
		ts.add(new Person("lisi",21));
		ts.add(new Person("lis0",20));
		
		Iterator<Person> it = ts.iterator();
		
		while(it.hasNext()){
			Person p = it.next();
			System.out.println(p.getName()+":"+p.getAge());
		}
	}

}
//ComparatorByName.java  这个比较器通过名称排序
import java.util.Comparator;

import cn.itcast.p2.bean.Person;

public class ComparatorByName implements Comparator<Person> {

	@Override
	public int compare(Person o1, Person o2) {
		
		int temp = o1.getName().compareTo(o2.getName());
		return temp==0? o1.getAge()-o2.getAge(): temp;
	}

}

运行结果:(对Person对象按名称排序)
在这里插入图片描述

泛型类

在jdk1.5后,使用泛型来接收类中要操作的引用数据类型。
泛型类。什么时候用?当类中的操作的引用数据类型不确定的时候,就使用泛型来表示。

public class Tool<QQ>{//泛型类
	private QQ q;

	public QQ getObject() {
		return q;
	}

	public void setObject(QQ object) {
		this.q = object;
	}
public class GenericDefineDemo3 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		
		Tool<Student> tool = new Tool<Student>();
		
	    tool.setObject(new Worker());//在编译时就报错

		Student stu = tool.getObject();

		
	}

}

泛型方法


    public class Tool<QQ>{
	private QQ q;

	public QQ getObject() {
		return q;
	}

	public void setObject(QQ object) {
		this.q = object;
	}
	
	
	/**
	 * 将泛型定义在方法上。
	 * @param str
	 */
	public <W> void show(W str){
		System.out.println("show : "+str.toString());
	}
	public void print(QQ str){
		System.out.println("print : "+str);
	}
	
	/**
	 * 当方法静态时,不能访问类中定义的泛型。
	 * 如果静态方法使用泛型,只能将泛型定义在方法上。 泛型必须写在返回值类型的前面,静态修饰符的后面
	 * @param obj
	 */
	public static <Y> void method(Y obj){
		System.out.println("method:"+obj);
	}
}

public class GenericDefineDemo4 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		
		Tool<String> tool = new Tool<String>();
		
		tool.show(new Integer(4));
		tool.show("abc");
		tool.print("hahah");

		Tool.method("haha");//调用静态方法
		Tool.method(new Integer(9));
	}
	

}

在这里插入图片描述

泛型接口

public class GenericDefineDemo5 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		InterImpl in = new InterImpl();
		in.show("abc");
		
		InterImpl2<Integer> in2 = new InterImpl2<Integer>();//实现子类对象的时候才知道具体的类型
		in2.show(5);
	}
}

//泛型接口,将泛型定义在接口上。 
interface Inter<T>{
	public void show(T t);
}


class InterImpl2<Q> implements Inter<Q>{ //实现接口的时候继续定义泛型
	public void show(Q q){
		System.out.println("show :"+q);
	}
}




class InterImpl implements Inter<String>{//实现接口,明确参数类型
	public void show(String str){
		System.out.println("show :"+str);
	}
}

泛型限定

泛型的通配符:? 用来代表未知类型。

演示1:?通配符

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

public class GenericAdvanceDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		ArrayList<String> al = new ArrayList<String>();
		
		al.add("abc");
		al.add("hehe");
		
		ArrayList<Integer> al2 = new ArrayList<Integer>();
		
		al2.add(5);
		al2.add(67);
		
		printCollection(al);
		printCollection(al2);
	}

	/**
	 * 迭代并打印集合中元素。
	 * @param al
	 */
	public static void printCollection(Collection<?> al) {	//通配符的使用
	
		Iterator<?> it = al.iterator();
		
		while(it.hasNext()){

			System.out.println(it.next().toString());
		}
		
	}

}

运行结果:
在这里插入图片描述

演示2:? extends E (上限)

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

import cn.itcast.p2.bean.Person;
import cn.itcast.p2.bean.Student;
import cn.itcast.p2.bean.Worker;

public class GenericAdvanceDemo2 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		//创建3个ArrayList,分别存Worker,Student,String
		ArrayList<Worker> al = new ArrayList<Worker>();
		
		al.add(new Worker("Work",30));
		al.add(new Worker("Work",34));
		
		ArrayList<Student> al2 = new ArrayList<Student>();
		
		al2.add(new Student("stu1",11));
		al2.add(new Student("stu2",22));
		ArrayList<String> al3 = new ArrayList<String>();
		
		al3.add("stu3331");
		al3.add("stu33332");
		
		printCollection(al2);
		printCollection(al);
		//printCollection(al3);编译不通过 因为String不是Person的子类
	}

	/**
	 * 迭代并打印集合中元素。
	 * 
	 * 可以对类型进行限定:
	 * ? extends E:接收E类型或者E的子类型对象。上限!
	 * 
	 * ? super E :接收E类型或者E的父类型。下限!
	 * @param al
	 */
	public static void printCollection(Collection<? extends Person> al) {//泛型的限定 只接收Person的子类
		Iterator<? extends Person> it = al.iterator();
		
		while(it.hasNext()){

			Person p = it.next();
			
			System.out.println(p.getName()+":"+p.getAge());
		}	
	}	
}

运行结果:
在这里插入图片描述

演示3:? super E(下限)

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

import cn.itcast.p2.bean.Person;
import cn.itcast.p2.bean.Student;


public class GenericAdvanceDemo2 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		ArrayList<Person> al = new ArrayList<Person>();
		
		al.add(new Person("Person",30));
		al.add(new Person("Person",34));
		
		ArrayList<Student> al2 = new ArrayList<Student>();
		
		al2.add(new Student("stu1",11));
		al2.add(new Student("stu2",22));
		ArrayList<String> al3 = new ArrayList<String>();
		
		al3.add("stu3331");
		al3.add("stu33332");
		
		printCollection(al2);
		printCollection(al);
		//printCollection(al3);编译不通过 
	}
	//? super E :接收E类型或者E的父类型。下限!
	public static void printCollection(Collection<? super Student> al){
		Iterator<? super Student> it = al.iterator();
		
		while(it.hasNext()){
			
			System.out.println(it.next());
		}
	}

}

运行结果:
在这里插入图片描述

上限的体现

一般在存储元素的时候都是用上限,因为这样取出都是按照上限类型来运算的。不会出现类型安全隐患。
比如TreeSet的addAll方法:
在这里插入图片描述

下限的体现

什么时候用下限呢?通常对集合中的元素进行取出操作时,可以使用下限。
例如:

class TreeSet<Worker>
 {
  		Tree(Comparator<? super Worker> comp);
  }

猜你喜欢

转载自blog.csdn.net/z714405489/article/details/83545250