泛型和类型安全的容器

  1. 什么是泛型

泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。

eg:

package com.sun11;
//simple container example(produces complier warnings)
/**
 *
 * 刚才声明容器时没有预先定义类型,默认为Object,因为ArrayList保存的是Object,
 * 所以可以将Apple对象和Orange对象放进容器中,当在使用ArrayList的get()方法来取出Apple对象时,得到的只是Object的引用,必须将其转型为Apple,因此,需在调用Apple的id()方法之前,强制进行转型,否则,

 就会得到编译错误。
 */

import java.util.*;
class Apple{
    private static long counter;
    private  final long id = counter++;
    public long id(){return id;}
}
class Orange{

}
public class AppleAndOrangesWithoutGenerics {
    @SuppressWarnings("unchecked")
    public static void main(String[] args){
        //定义一个ArrayList容器,不定义其类型
        ArrayList apples = new ArrayList();
        for (int i = 0; i < 3; i++)
            apples.add(new Apple());
        //not prevented from adding an orange to apples
        apples.add(new Orange());
        //此时apples容器存在4个对象,前3个是Apple类型,后一个是Orange类型
        for (int i = 0; i <apples.size(); i++)
            //get方法取值时得到的只是Object的引用,所以将其强制转化为Apple类型,否则编译错误
            //当试图将Orange转化为Apple类型时,发生类型转换异常----
            // java.lang.ClassCastException: com.sun11.Orange cannot be cast to com.sun11.Apple
            System.out.println(((Apple)apples.get(i)).id());
            //orange is detected only at run time
    }
}

2:解决办法

eg:

package com.sun11;

import java.util.ArrayList;

public class AppleAndOrangesWithGenerics {
    public  static void main(String[] args){
        ArrayList<Apple> apples = new ArrayList<Apple>();
        for (int i = 0; i < 3; i++)
            apples.add(new Apple());
            //现在编译器可以阻止你将Orange放入到apples中,因为它是compile-time error
        //apples.add(new Orange());
        for (int i = 0; i < apples.size(); i++)
            //将以安肃取出来,类型转换不再需要,因为apples知道保存的是什么类型
            System.out.println(apples.get(i).id());
        //using foreach来选中每个元素:
        for(Apple c : apples)
            System.out.println(c.id());
    }
}
//输出
/**
*0

*1

*2

*0

*1

*2
**/ 

 

3:当你指定某个类型作为泛型参数时,你并不只限于将该确切类型的对象放入到容器中,向上转型也可以像作用于其他类型一样作用于泛型:

eg:

package com.sun11;
import java.util.*;
class GrannySmith extends Apple{}
class Gala extends Apple{}
class Braebun extends Apple{}
public class GenericsAndUpcasting {
    public static void main(String[] args){
        ArrayList<Apple> apples = new ArrayList<Apple>();
        apples.add(new GrannySmith());
        apples.add(new Gala());
        apples.add(new Braebun());
        for (Apple c : apples)
            System.out.println(c);
    }
}
//output
//com.sun11.GrannySmith@49e6f7cb
//com.sun11.Gala@5a965654
//com.sun11.Braebun@43fdd342
/**
 * 可以将Apple的子类型添加到被指定为保存Apple对象的容器中
 * 程序的输出是从Object默认的toString()方法产生的,该方法将打印类名
 * 后面跟随该对象的散列码的无符号十六进制表示
 */

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值