Java 泛型小结

泛型是“参数化类型”,也有形参和实参,其形参一般是用<T>/<E>/<K>/<V>等方式表示,实参则是在调用时传入它的引用类型,如String、Double等,注意是引用类型,不是基本类型;使用泛型的好处是能在编译阶段就防止一些错误的发生。

           【1】泛型定义

           【2】泛型类

           【3】泛型方法

           【4】泛型接口

           【5】类型擦除

           【6】类型通配符

           【7】总结

泛型定义

什么是“泛型”,其实就是“宽泛的数据类型”,就是什么类型都可以的啦

泛型类

从下面的泛型类的例子中可以看到,类的定义时后面多了<T1, T2>,这是他的类型参数,当使用时被替换成了<Integer, Interger>等,这个叫做传值参数,T表示一般意义上的数据类型,K表示键值,V表示值,E表示错误,泛型的使用方式就是Person<String, Double> p2 = new Person<String, Double>();这样的。

package Gener;
public class GenerClass {
	public static void main(String args[]){
		Person<Integer, Integer> p1 = new Person<Integer, Integer>();
		p1.setName(88);
		p1.setAge(99);
		System.out.println("姓名:"+p1.getName()+" 年龄:"+p1.getAge());
		
		Person<String, Double> p2 = new Person<String, Double>();
		p2.setName("zhangsan");
		p2.setAge(77.99D);
		System.out.println("姓名:"+p2.getName()+" 年龄:"+p2.getAge());
	}
}
class Person<T1, T2>{
	T1 name;
	T2 age;
	public void setName(T1 name){
		this.name = name;
	}
	public void setAge(T2 age){
		this.age = age;
	}
	public T1 getName(){
		return this.name;
	}
	public T2 getAge(){
		return this.age;
	}
	
}


泛型方法

泛型方法的使用和普通的方法差不多,只不过在定义的时候多了一个类型参数<T1, T2>,类型参数需要放在修饰符的后边、返回值的前边。使用泛型方法时不必指明参数的类型,直接使用即可。为了说明泛型类和泛型方法之间没有必然的联系,下面的例子中没有使用泛型类,直接调用的泛型方法。

package Gener;
public class GenerMethod {
	public static void main(String args[]){
		PersonMethod p1 = new PersonMethod();
		p1.setName("lisi");
		p1.setAge(99);
		p1.printPerson(p1.getName(), p1.getAge());
		
		PersonMethod p2 = new PersonMethod();
		p2.setName("zhangsan");
		p2.setAge(77);
		p2.printPerson(p2.getName(), p2.getAge());
	}
}
class PersonMethod{
	String name;
	int age;
	public void setName(String name){
		this.name = name;
	}
	public void setAge(int age){
		this.age = age;
	}
	public String getName(){
		return this.name;
	}
	public int getAge(){
		return this.age;
	}
    public <T1, T2> void printPerson(T1 x, T2 y){
        T1 m = x;
        T2 n = y;
        System.out.println("姓名:" + m + "年龄:" + n);
    }	
}


泛型接口

泛型接口和泛型方法是类似的,也是要在接口名字定义的后面加上<T>等类型参数,另外继承他的抽象类也要加上相同的类型参数<T>,还需要注意抽象接口的定义和使用方法。

package Gener;
public class GenerInterface {
	public static void main(String args[]){
		Human<String> h = new PersonInterface<String>();
		h.setName("zhangsan");
		System.out.println("NAME IS:"+ h.getName());
	}
}
interface Human<T>{
	public void setName(T name);
	public T getName();
}

class PersonInterface<T> implements Human<T>{
	private T name;
	public void setName(T name){
		this.name = name;
	}
	public T getName(){
		return this.name;
	}

}


类型擦除

如果在使用泛型时没有指定数据类型,那么就会擦除泛型类型。但是类型的擦除是有一定风险的,应为在打印输出的时候需要向下转型,所以很容易发生错误。请看下面的例子:

package Gener;
public class GenerEras {
	public static void main(String args[]){
		PersonEras p1 = new PersonEras();// 类型的擦除
		p1.setName(88);
		p1.setAge(99);
		System.out.println("姓名:"+(Integer)p1.getName()+" 年龄:"+(Integer)p1.getAge());
		// 上面的这句强制类型转换是,泛型的向下转型
		PersonEras p2 = new PersonEras();// 类型的擦除
		p2.setName("zhangsan");
		p2.setAge(77.99D);
		System.out.println("姓名:"+(String)p2.getName()+" 年龄:"+(Double)p2.getAge());
	}
}
class PersonEras<T1, T2>{
	T1 name;
	T2 age;
	public void setName(T1 name){
		this.name = name;
	}
	public void setAge(T2 age){
		this.age = age;
	}
	public T1 getName(){
		return this.name;
	}
	public T2 getAge(){
		return this.age;
	}	
}


类型通配符

下边例子中的PersonChar<?> 是PersonChar<String>/PersonChar<Integer>/PersonChar<Number>逻辑父类,所以我们可以定义这样的泛型方法来最终简化代码。

此外、我们还听说过类型通配符上限、类型通配符下限这样的说法,上限的表示形式为Person<? extends Number>、下限表示形式为Person<? super Number>、这两个正好相反,上限代表只能是Number类型及其子类,下限代表只能接收这个类以及其父类。

package Gener;
public class GenerChar {
	public static void main(String args[]){
		PersonChar<String> name1 = new PersonChar();
		PersonChar<Integer> name2 = new PersonChar();
		PersonChar<Number> name3 = new PersonChar();
		name1.setName("zhangsan");
		name2.setName(88);
		name3.setName(99.89D);
		getData(name1);
		getData(name2);
		getData(name3);
	}
	public static void getData(PersonChar<?> per){
		System.out.println("姓名:"+per.getName());
	} //
}
class PersonChar<T>{
	private T name;
	public void setName(T name){
		this.name = name;
	}
	public T getName(){
		return this.name;
	}
}
总结

使用泛型的思想就是在开发中可以简化开发,如果因为使用了泛型而使开发更复杂,那么不如不使用,或者说明你使用的不够熟练,看了好多博客再加上自己的理解总结了这一点,本笔记还有待补充,未完待续。。。


你可能感兴趣的:(泛型,泛型接口,泛型类)