Java学习笔记-泛型

JDK1.5以后出现的机制,用以解决安全性问题

泛型出现的原因

泛型的特点

  • 提高了程序的安全性
  • 将运行期遇到的问题转移到了编译期
  • 省去了类型强转的麻烦
  • 泛型类的出现优化了程序设计

泛型出现的好处

  • 将运行时期出现问题ClassCastException,转移到了编译时期,方便于程序员解决问题。让运行时问题减少,提高了安全性
  • 避免了强制转换麻烦

泛型的书写格式

泛型格式:
通过<>来定义要操作的引用数据类型
e.g.
ArrayList<String> al = new ArrayList<String>();
Iterator<String> it = al.iterator();

import java.util.*;
/*
按照字符串长度排序
*/
class Test {
	public static void main(String[] args) {
		TreeSet<String> ts = new TreeSet<String>(new LenComparator());
		ts.add("abcd");
		ts.add("cc");
		ts.add("cba");
		ts.add("aaa");
		ts.add("z");
		Iterator<String> it = ts.iterator();
		while(it.hasNext()) {
            String s = it.next();
			System.out.println(it.next());
		}
	}
}

class LenComparator implements Comparator<String> {
	public int compare(String o1,String o2) {
		int num = new Integer(o1.length()).compareTo(new Integer(o2.length()));
		if(num == 0)
			return o1.compareTo(o2);
		return num;
	}
}

自定义泛型类

早期定义Object来完成扩展
泛型前做法:定义类的时候使用Object,使用的时候强转
这样的这发存在问题:在使用的时候,类型转换异常在编译时后不会报错,在运行时候报错

class Student{}.
class Worker{}
class Tool {
	private Object obj;
	public void setObject(Object obj) {
		this.obj = obj;
	}
	public Object getObject() {
		return obj;
	}
}

class Test {
	public static void main(String[] args) {
		Tool t = new Tool();
		t.setObject(new Student());
		Worker w = (Worker)t.getObject(); //运行时报类型转换异常
	}
}

现在定义泛型来完成扩展
当类中要操作的引用数据类型不确定的时候,使用泛型
此时如果出现类型转换异常,就会在编译时候报错

class Student{}.
class Worker{}
class Utils<T> {
	private T t;
	public void setT(T t) {
		this.t = t;
	}
	public T getT() {
		return t;
	}
}

class Test {
	public static void main(String[] args) {
		Utils<Worker> u = new Utils<Worker>();
		u.setObject(new Student());
		Worker w = u.getObject(); //编译时报类型转换异常
	}
}

自定义泛型方法

  • 泛型类定义的泛型,在整个类中有效。如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了
  • 为了让不同方法可以操作不同类型,而且类型还不确定,那么可以将泛型定义在方法上
  • 静态方法不可以访问类上定义的泛型,如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上
  • 方法上的泛型说明放在返回值修饰符前面

类上定义泛型:相同符号代表相同类型

class Demo<T> {
	public void show(T t){
		System.out.println("show:"+t);
	}
}

方法中定义泛型

class Demo<T> {
	public <T> void show(T t) {
		System.out.println("show:" + t);
	}
    public <Q> void print(Q q) {
		System.out.println("print:" + q);
	}
}

类和方法中可以同时定义

class Demo<T> {
	public void show(T t) {
		System.out.println("show:" + t);
	}
	public <T> void print(T t)
	{
		System.out.println("print:" + t);
	}
}

静态方法定义泛型

class Demo<T> {
	public void show(T t) {
		System.out.println("show:" + t);
	}
	public <Q> void print(Q q) {
		System.out.println("print:" + q);
	}
	public  static <W> void method(W w) {
		System.out.println("method:" + w);
	}
}

自定义泛型接口

可以在接口子类中指明类型,也可以不指明

interface Inter<T> {
	void show(T t);
}

class InterImpl1 implements Inter<String> {
	public void show(String t) {
		System.out.println("show :" + t);
	}
}


class InterImpl2<T> implements Inter<T> {
	public void show(T t) {
		System.out.println("show :" + t);
	}
}
class Test {
	public static void main(String[] args) {
        InterImpl1 i1 = new InterImpl1();
		i1.show("test");
		InterImpl2<Integer> i2 = new InterImpl2<Integer>();
		i2.show(0);
	}
}

通配符(?)

在泛型的使用中,有可能存在多种类型的使用,此时可以用<?>占位,代表接受任意类型
使用<?>无法接收参数

public static void printColl(ArrayList<?> al){
	Iterator<?> it = al.iterator();
    while(it.hasNext()){
		System.out.println(it.next());
	}
}

使用<T>可以接收参数

public static <T> void printColl(ArrayList<T> al){
	Iterator<T> it = al.iterator();
    while(it.hasNext()){
        T t = it.next();
		System.out.println(t);
	}
}

泛型的限定:
? extends E: 可以接收E类型或者E的子类型。上限
? super E: 可以接收E类型或者E的父类型。下限

import java.util.*;
class Person {
	private String name;
	Person(String name) {
		this.name = name;
	}
	public String getName() {
		return name;
	}
}

class Student extends Person {
	Student(String name) {
		super(name);
	}
}

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

        ArrayList<Person> al = new ArrayList<Person>();
		al.add(new Person("abc1"));
		al.add(new Person("abc2"));
		al.add(new Person("abc3"));
		printColl(al);

		ArrayList<Student> al1 = new ArrayList<Student>();
		al1.add(new Student("abc--1"));
		al1.add(new Student("abc--2"));
		al1.add(new Student("abc--3"));
		printColl(al1);
    }

    public static void printColl(Collection<? extends Person> al){ //接收Person及其子类
    	Iterator<? extends Person> it = al.iterator();
    	while(it.hasNext()) {
    		System.out.println(it.next().getName());
    	}
    }
}
原文地址:https://www.cnblogs.com/cj5785/p/10664839.html