JAVA泛型详解与使用技巧

1:为什么要使用Java泛型

看看下面程序例子(不使用泛型):

public static void main(String[] args) {
		
		List list = new ArrayList();
		list.add("zhangsan");
		list.add("lisi");
		list.add(102);//没有使用泛型,代码出现黄色警告
		
		for(int i= 0; i < list.size();i++){
			//list装载默认是Object类型,由于第三项装载Integer类型,所以在取对象时强制转换报错。
			String name = (String) list.get(i);
			System.out.println(name);
		}
	}

出现如下错误:

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
    at com.java.test.genericity.GenericityMain.main(GenericityMain.java:40)

由于list没有使用泛型,代码出现黄色警告,list装载默认是Object类型,由于第三项装载Integer类型,所以在取对象时强制转换报错。

List使用泛型带有String形参:

public static void main(String[] args) {
		
		List<String> list = new ArrayList<String>();
		list.add("zhangsan");
		list.add("lisi");
//		list.add(102); 类型已经限定编译直接报错通不过,默认是String类型
		
		for(int i= 0; i < list.size();i++){
			String name = list.get(i);
			System.out.println(name);
		}
	}

此时list添加第三项数据直接编译报错,类型已经限定编译直接报错通不过,默认是String类型

2:Java泛型的作用

1:通过结合代码继承封装,减少Java代码重复冗余,使得代码的结构和架构更合理。
2:消除了强制类型转换 使得代码可读性好,减少了很多出错的机会。
3:Java语言引入泛型的好处是安全简单。泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,这样编译器就可以在一个高的程度上验证这个类型。

3:泛型几种使用类型和继承关系

  1. 自定义泛型类
  2. 自定义泛型接口
  3. 自定义泛型方法
  4. 了解泛型参数继承关系
  1. 自定义泛型类
    /***
     * @ClassName Car
     * @Description 定义泛型类
     * 
     * ***/
    public class Car<M> {
    	
    	private M m;
    	
    	public void openCar(M m){
    		System.out.println("开车");
    	};
    	
    	
    	public M endCar(){
    		System.out.println("关车");
    		return m;
    	}
    }

    这里的M表示泛型形参,由于接收来自外部使用时候传入的类型实参。那么对于不同传入的类型实参,生成的相应对象实例的类型是不是一样的呢?看如下例子:

Car<Person> pCar = new Car<Person>();
		Car<Animal> aCar = new Car<Animal>();
		
		System.out.println(pCar.getClass());//class com.java.test.genericity.Car
		System.out.println(aCar.getClass());//class com.java.test.genericity.Car
		System.out.println(aCar.getClass()== pCar.getClass());//true

看了以上例子,我们可以发现,在使用泛型类时,虽然传入了不同的泛型实参,但并没有真正意义上生成不同的类型,传入不同泛型实参的泛型类在内存上只有一个,即还是原来的最基本的类型(本实例中为Car),当然,在逻辑上我们可以理解成多个不同的泛型类型,在于Java中的泛型这一概念提出的目的,导致其只是作用于代码编译阶段,在编译过程中,对于正确检验泛型结果后,会将泛型的相关信息擦出,也就是说,成功编译过后的class文件中是不包含任何泛型信息的。泛型信息不会进入到运行时阶段。

2:泛型接口,泛型接口和泛型类的使用差不多,其中T表示泛型参数:

public interface Map<T> {

	public void load(T t);
	
}

实现泛型接口类的写法,传参形式如下:(在实现类实现泛型接口时,如已将泛型类型传入实参类型,则所有使用泛型的地方都要替换成传入的实参类型)

public class BaiduMap implements Map<String>{

	@Override
	public void load(String t) {
		// TODO Auto-generated method stub
		
	}

}

实现泛型接口类,不传形参写法如下:(不传形参,与泛型类的定义相同,在声明类的同时,需要将泛型的形参也一起加进去)

public class BaiduMap<T> implements Map<T>{

	@Override
	public void load(T t) {
		// TODO Auto-generated method stub
		
	}

}

3:泛型方法使用:(如果当前方法所在的Java类中没有定义T泛型参数,则在方法的前面声明泛型形参<T>)

public class BaiduMap implements Map<String>{

	
	@Override
	public void load(String t) {
		
	}
	
	
	//如果当前方法所在的Java类中没有定义T泛型参数,则在方法的前面声明泛型形参<T>
	public  <T> T getMethod(Class<T> czz) throws InstantiationException, IllegalAccessException{
		T t = czz.newInstance();
		return t;
	}
	
	
	
}

区别泛型方法和泛型类方法:

	//我们在当前类中已经定义了T类型,下面load含有泛型参数,所以泛型T不是泛型方法
	@Override
	public void load(T t) {
		
	}
	
	
	//我们在当前方法中getMethod已经定义了M类型,下面getMethod含有泛型参数,所有getMethod是泛型方法
	public  <M> M getMethod(Class<M> czz) throws InstantiationException, IllegalAccessException{
		M m = czz.newInstance();
		return m;
	}

4:了解泛型的继承关系以及泛型参数的上下行边界:

//当前定义了一个类Car 约定了M形参继承Person类。
public class Car<M extends Person> {
	
	private M m;
	
	public void openCar(M m){
		System.out.println("开车");
	};
	
	
	public M endCar(){
		System.out.println("关车");
		return m;
	}
}



public class Person {

	private String name;
	private String age;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAge() {
		return age;
	}

	public void setAge(String age) {
		this.age = age;
	}

}


public class Man extends Person{
	
	
}


public class Sedan extends Car<Man>{

	@Override
	public void openCar(Man m) {
		// TODO Auto-generated method stub
		super.openCar(m);
	}

	@Override
	public Man endCar() {
		// TODO Auto-generated method stub
		return super.endCar();
	}
	
	

}

我定义了一个Car类,约束当前的形参M继承Person,此时我定义一个Man的类作为形参,继承了Person,Sedan类继承Car在Sedan类中我传递形参Man,正因为形参Man,重写方法openCar,endCar的参数才会显示Man参数,这样就约定了泛型的边界,使得子类传递的参数必须是泛型约定的参数。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值