java泛型的使用

一、概述

1、概念:泛型就是参数化的类型,使用广泛的类型。

2、作用:

*安全:指定容器要持有什么类型的对象,而且由编译器来保证类型的正确

*省心:所有的类型转换都是自动的和隐式的,提高代码的重用率

二、泛型类

1、格式:< 字母列表>

class类名 <字母列表>{

修饰符 字母 属性;

修饰符 构造器 (字母){

}

修饰符 返回类型 方法名(字母){

}

字母列表中的每个字母都代表一种还未确定的引用类型(泛型是在使用时确定具体类型),可以使用任何字母表示,但为了规范使用,一般使用以下常见字

T 表示Type即类型;

K 和V 分别表示键值中的key和Value

E 表示Element

表示不确定的类型(通配符)

2、泛型类声明时使用泛型,不能将泛型字母使用在静态方法和静态属性上,因为泛型是在使用时确定具体类型,而static是在编译时确定。

3、泛型不能使用基本数据类型,必须使用引用类型,否则编译出错。

下面举一个泛型类的例子说明


public class Student<T1,T2> {
	private T1 javaScore;
	private T2 oracleScore;
	
	//泛型声明时不能使用 静态属性|静态方法上
	//private static T1 test;
	
	
	public T1 getJavaScore() {
		return javaScore;
	}

	public void setJavaScore(T1 javaScore) {
		this.javaScore = javaScore;
	}

	public T2 getOracleScore() {
		return oracleScore;
	}

	public void setOracleScore(T2 oracleScore) {
		this.oracleScore = oracleScore;
	}

	public static void main(String[] args) {
		//使用时指定类型(引用类型)
		Student<String,Integer> stu = new Student<String,Integer> ();
		//1、安全:类型检查
		stu.setJavaScore("优秀");
		//2、省心:类型转换
		int it =stu.getOracleScore(); //自动拆箱
	}

}

三、泛型接口

泛型在接口中的使用与泛型类基本一致,需要注意的是在接口中泛型字母只能使用在方法中,不能使用在全局常量中(接口中的成员变量均为全局常量)。

四、泛型方法

泛型方法就是为方法的返回类型签名,< >位于返回类型前面,泛型方法因为类型还未确定,所以只能访问对象信息,不能修改信息


五、泛型的擦除

1.擦除:

*在使用时没有指定具体类型

*子类继承|实现时没有指定具体类型

2.后果:

*擦除后不类型检查

*擦除后按Object接收,以Object对待

*存在编译警告,加上Object可以去除,但显得有些画蛇添足

/**
 * 父类为泛型类
 * 1、属性
 * 2、方法
 * 
 * 要么同时擦除,要么子类大于等于父类的类型,
 * 不能子类擦除,父类泛型
 * 1、属性类型
 *  父类中,随父类而定
 *  子类中,随子类而定
 * 2、方法重写:
 *  随父类而定
 */
public abstract class Father<T,T1> {
	T name;
	public abstract void test(T t);

}
/**
 * 子类声明时指定具体类型
 * 属性类型为具体类型
 * 方法同理
 */
class Child1 extends Father<String,Integer>{
	String t2;
	@Override
	public void test(String t) {
	}	
}
/**
 * 子类为泛型类 ,类型在使用时确定,大于等于父类的类型
 * @author Administrator
 *
 */
class Child2<T1,T,T3> extends Father<T,T1>{
	T1 t2;

	@Override
	public void test(T t) {
		
	}	
}
/**
 * 子类为泛型类,父类不指定类型 ,泛型的擦除,使用Object替换
 */
class Child3<T1,T2> extends Father{
	T1 name2;
	@Override
	public void test(Object t) {
		// TODO Auto-generated method stub		
		
	}
}
/**
 * 子类与父类同时擦除
 */
class Child4 extends Father{
	String name;	
	@Override
	public void test(Object t) {
		
	}	
}
/**
 *错误:子类擦除,父类使用泛型
class Child5 extends Father<T,T1>{
	String name;	
	@Override
	public void test(T t) {
		
	}
*/


/**
*泛型的擦除
*1、继承|实现声明 不指定类型
*2、使用时 不指定类型 
*统一Object 对待 
*1、编译器警告 消除使用Object
*2、不完全等同于Object ,编译不会类型检查
 */
public class Student<T> {
	private T javaScore;
	private T oracleScore;
	
	//泛型声明时不能使用 静态属性|静态方法上
	//private static T1 test;
	
	
	public T getJavaScore() {
		return javaScore;
	}
	public void setJavaScore(T javaScore) {
		this.javaScore = javaScore;
	}

	public T getOracleScore() {
		return oracleScore;
	}
	public void setOracleScore(T oracleScore) {
		this.oracleScore = oracleScore;
	}

	public static void main(String[] args) {
		Student stu1 = new Student(); 
		//消除警告 使用 Object
		Student<Object> stu = new Student<Object>(); 
		//stu.setJavaScore("af"); //以Object对待
		
		test(stu1); //stu1 相当于Object 但是不完全等同Object
		//擦除,不会类型检查
		//test(stu);
		test1(stu1);
		test1(stu);
	}
	
	public static  void test(Student<Integer> a){
		
	}
	public static  void test1(Student<?> a){
		
	}
}


六、泛型没有多态

public class Fruit {

}
class Apple extends Fruit{
	
}
public class App {
	public static void main(String[] args) {
		//A<Fruit> f = new A<Apple>();错误,泛型没有多态
		A<Fruit> f =new A<Fruit>();
		//test(new A<Apple>());错误
	}
	//形参使用多态
	public static void test(A<Fruit> f){
		
	}
	//返回类型使用多态
	public static A<Fruit>  test2(){
		//return (A<Fruit>)(new A<Apple>());错误
		return null;
	}
}

七、通配符?、extends和super在泛型中的使用

1.通配符的作用:虽然泛型没有多态,但通过通配符的使用,我们可以实现类似多态的功能。

2.通配符的使用:通配符使用在声明类型|方法上,不能用在声明类或使用时(使用时必须确定类型)。
3.? :表示类型不定,使用时确定类型。
4.? extends classA :表示小于等于,也称作上限,即该类型只能是classA的子类或自身
5.? super classA :表示大于等于,也称作下限,即该类型只能是classA的父类或自身
public class Student<T> {
	T score;
		
	public static void main(String[] args) {
		Student<?> stu = new Student<String>();
		test(new Student<Integer>());
		
		test2(new Student<Apple>());
		//test3(new Student<Apple>()); //泛型没有多态		
		
		//test4(new Student<Apple>()); //<
		 stu  = new Student<Fruit>();
		//test4(stu); //使用时确定类型
		test4(new Student<Object>());
		test4(new Student<Fruit>());		
	}
	
	public static void test(Student<?> stu){
		
	}
	public static void test3(Student<Fruit> stu){
		
	}
	//extends <=
	public static void test2(Student<? extends Fruit> stu){
		
	}
	//super >=
	public static void test4(Student<? super Fruit> stu){
		
	}
	
}

八、泛型的嵌套

1.声明:嵌套使用泛型
A<B<C>> = new A<B<C>>();
2.使用:从外到内,层层拆分

public class Bjsxt <T>{
 T stu ;
  
 public static void main(String[] args) {
	 //泛型的嵌套 
	 Bjsxt<Student<String>> room =new  Bjsxt<Student<String>>();
	 //从外到内拆分
	 room.stu = new Student<String>();
	 Student<String> stu = room.stu;
	 String score =stu.score;
	 System.out.println(score);
}
}

九、没有泛型数组

可以声明泛型数组,但是不能创建泛型数组。虽然如此,但是我们可以通过使用Object接收,再将其强制转换为泛型数组。

public static void main(String[] args) {
		Integer[]  arr = new Integer[4]; 
		//Student<String>[] arr2 = new Student<String>[10];
		Student<?>[] arr2 = new Student[10];
		
		MyArrayList<String> strList =new MyArrayList<String>();
		strList.add(0, "a");
		String elem =strList.getElem(0);
		System.out.println(elem);}
class MyArrayList<E>{
	//E[] cap =new E[10]; 没有泛型数组
	Object[] cap = new Object[10];
	
	public void add(int idx,E e){
		cap[idx] =e;
	}
		
	@SuppressWarnings("unchecked")
	public E[] getAll(){
		return (E[]) cap;
	}
	@SuppressWarnings("unchecked")
	public E getElem(int idx){
		return (E) cap[idx];
	}
}


十、JDK7泛型使用的新特性

JDK1.7中使用泛型,声明一次类型即可,在使用|创建时不用指定类型。

 例如List<String>  arrList2= new ArrayList<>();



终于写完了大笑第一次写博客,有写的不好的地方还望指教。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值