Java中的泛型(转载/整理)

本文详细介绍了Java和C++中的泛型概念及其应用。对比两种语言泛型的不同实现方式,包括Java的擦拭法与C++的膨胀法。通过示例代码展示了泛型类的创建、使用以及不同类型参数的兼容性问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

泛型的介绍——详细出处参考http://liyanblog.cn/articles/2012/11/01/1351757228794.html

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

    Java语言引入泛型的好处是安全简单。泛型的好处是在编译的时候检查类型安全(泛类型之前没有),并且所有的强制转换都是自动和隐式的,提高代码的重用率。

    泛型在使用中还有一些规则和限制:
    1、泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。
    2、同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。
    3、泛型的类型参数可以有多个。
    4、泛型的参数类型可以使用extends语句,例如<T extends superclass>。习惯上成为“有界类型”。
    5、泛型的参数类型还可以是通配符类型。例如Class<?> classType = Class.forName(Java.lang.String);

C++泛型与Java泛型——详细出处参考http://hi.baidu.com/wolongxzg/item/e66b9bd14f5a6c362b35c7b0

  C++的泛型和Java的泛型 在泛型的实现上,C++和Java有着很大的不同, Java是擦拭法实现的 C++是膨胀法实现的 因为Java原本实现就是泛型的,现在加入型别,其实是"窄化",所以采用擦拭法,在实现上,其实是封装了原本的 ArrayList,这样的话,对于下边这些情况,Java的实现类只有一个。
  ArrayList<Integer> ...;   public class ArrayList
  ArrayList<String> ...;   --同上--
  ArrayList<Double> ...;   --同上--
  而C++采用的是膨胀法,对于上边的三种情况实际是每一种型别都对应一个实现,实现类有多个
  list<int> li;                class list; //int 版本
  list<string> ls;             class list; //string 版本
  list<double> ld;             class list; //double 版本   
  这就造成了,在序列化后,Java不能分清楚原来的ArrayList是 ArrayList<Integer>还是ArrayList

多说无益,还是看代码

class GenItems<T1, T2, T3> {
        private T1 firstObj;
        private T2 secondObj;
        private T3 thirdObj;
        
        public GenItems(T1 obj1, T2 obj2, T3 obj3){
            firstObj = obj1;
            secondObj = obj2;
            thirdObj = obj3;
        }
        
        public void setFirstObj(T1 obj1){
            firstObj = obj1;    
        }
        
        public T1 getFirstObj(){
            return firstObj;    
        }
                
        public void setSecondObj(T2 obj2){
            secondObj = obj2;    
        }
        
        public T2 getSecondObj(){
            return secondObj;    
        }
                
        public void setThirdObj(T3 obj3){
            thirdObj = obj3;    
        }
        
        public T3 getThirdObj(){
            return thirdObj;    
        }
}
class Item {
    Item(){}
    private String item_name;
    Item(String item_name){
        this.item_name = item_name;
    }    
    public String toString(){
            return item_name;
    }
}
class SubItem extends Item{
        private String sub_name;
        SubItem(String sub_name){
            this.sub_name = sub_name+"_sub";
        }
        public String toString(){
            return sub_name;
        }
}
public class GenericTest{
    public static void main(String[] args){
            GenItems<String, Integer, Double> items1 = new GenItems<String, Integer, Double>("Java", 15, 79.89);
            System.out.println(items1.getFirstObj());
            items1.setFirstObj("C++");
            System.out.println(items1.getFirstObj());
            
            Item item1 = new Item("Item1");
            Item item2 = new Item("Item2");
            SubItem sub_item1 = new SubItem("Item1");
            SubItem sub_item2 = new SubItem("Item2");
            
            GenItems<String, Item, Item> items2 = new GenItems<String, Item, Item>("Test", item1, item2);
            System.out.println();
            System.out.println(items2.getFirstObj());
            System.out.println(items2.getSecondObj());
            System.out.println(items2.getThirdObj());
            
            GenItems<?, ?, ?> items3 = new GenItems<String, Item, SubItem>("? 无界通配符", item1, sub_item1);
            System.out.println();
            System.out.println(items3.getFirstObj());
            System.out.println(items3.getSecondObj());
            System.out.println(items3.getThirdObj());
            
            GenItems<String, ? extends Item, ? extends Item> items4 = new GenItems<String, Item, SubItem>("? extends上界通配符", item2, sub_item2);
            System.out.println();
            System.out.println(items4.getFirstObj());
            System.out.println(items4.getSecondObj());
            System.out.println(items4.getThirdObj());
            
            GenItems<String, ? super SubItem, ? super SubItem> items5 = new GenItems<String, Item, SubItem>("? super下界通配符", item1, sub_item2);
            System.out.println();
            System.out.println(items5.getFirstObj());
            System.out.println(items5.getSecondObj());
            System.out.println(items5.getThirdObj());
            
            boolean why1 = items1 instanceof GenItems<?, ?, ?>;
            boolean why2 = items2 instanceof GenItems<?, ?, ?>;
            boolean why3 = items3 instanceof GenItems<?, ?, ?>;
            boolean why4 = items4 instanceof GenItems<?, ?, ?>;
            System.out.println();
            System.out.println("运行时消除erasure机制");
            System.out.println(why1);
            System.out.println(why2);
            System.out.println(why3);
            System.out.println(why4);
    }
}

在贴出结果之前,其中还有几个重要的泛类型概念要解释一下(摘自Java编程艺术——高永强著):
    无界通配符<?>,可用来表示一个参数,匹配任何类型;
    上界通配符<? extends T>,限定参数类型必须是包括T在内的子类元素,否则非法;
    下界通配符<? super T>,限定元素类型必须是包括T在内的超类元素,否则为非法;
    运行时消除erasure,Java再利用泛类型技术时使用运行司消除机制,即所有类型参数信息(包括类型参数和各种通配符)在运行时全部清除,但加入了造型机制(这个不懂,哪位高手指点下,谢谢先)。

上述代码运行结果如下:

Java
C++

Test
Item1
Item2

? 无界通配符
Item1
Item1_sub

? extends上界通配符
Item2
Item2_sub

? super下界通配符
Item1
Item2_sub

运行时消除erasure机制
true
true
true
true

 为保证类型安全,在使用JDK1.5编译没有使用泛类型创建集合、并增添元素的代码时,将产生警告信息,提示在增添操作中存在类型不安全问题。另外,在通配符的应用提供限定上、下界,并限定不允许在通配符创建的集合中使用add()增添元素等,也进一步保障了集中的类型安全性。

转载于:https://www.cnblogs.com/xhj-records/archive/2013/03/29/2980716.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值