`
xvm03
  • 浏览: 141019 次
  • 来自: ...
社区版块
存档分类
最新评论

泛型的注意事项

阅读更多

1、不可以用一个本地类型(如int   float)来替换泛型.比如List<Integer>不能用List<int>型式

2、运行时类型检查,不同类型的泛型类是等价的(Pair<String>与Pair<Employee>是属于同一个类型 Pair),这一点要特别注意:即如果a instanceof Pair<String>==true的话,并不代表a.getFirst()的返回值是一个String类型

3、泛型类不可以继承Exception类,即泛型类不可以作为异常被抛出

4、不可以定义泛型数组

5、不可以用泛型构造对象,即T first = new T(); 是错误的

6、在static方法中不可以使用泛型,泛型变量也不可以用static关键字来修饰

7、不要在泛型类中定义equals(T x)这类方法,因为Object类中也有equals方法,当泛型类被擦除后,这两个方法会冲突

8、根据同一个泛型类衍生出来的多个类之间没有任何关系,不可以互相赋值,即Pair<Number> p1; Pair<Integer> p2;   p1=p2; 这种赋值是错误的。

9、若某个泛型类还有同名的非泛型类,不要混合使用,坚持使用泛型类
     Pair<Manager> managerBuddies = new Pair<Manager>(ceo, cfo);
     Pair rawBuddies = managerBuddies; 这里编译器不会报错,但存在着严重的运行时错误隐患

 

泛型与类型转换
Java 5.0引入泛型以后,提高了类型安全性,然而也给编程带来了新的挑战以及新的误区,类型转换就是一个很好的例子。引入泛型以后,对象的类型似乎由两个类型构成:集合类型和参数类型,例如List<Integer> list = new LinkedList<Integer>(),似乎list的类型由List和Integer共同决定。如果真是这样,那么我们如果希望对list进行类型转换,我们该怎么办?是对List转换,还是对Integer转换?要解答上面的问题很简单,编写如下的代码,运行之就可看出端倪:

  public   static   void  wrongConversion()   {
        List < Integer >  list  =   new  LinkedList < Integer > ();
        list.add( 1 );
        list.add( 2 );
        list.add( 3 );
       
         // 下面的代码无法编译通过。
         // List<Number> wrongList = list;
        
    }
   
     public   static   void  rightConversion()   {
        LinkedList < Integer >  list  =   new  LinkedList < Integer > ();
        list.add( 10 );
        list.add( 20 );
        list.add( 30 );
       
        List < Integer >  rightList  =  list;
         for ( int  number: rightList)   {
            System.out.println(number);
        }
       
    }
如果你运行上面的代码,你会发现前一个函数根本无法通过编译,而后一个函数不仅编译成功,而且能得到正确结果。这似乎给出了一个结论:对象的类型由集合类型来决定,对对象进行类型转换时也是对集合类型进行转换。事实确实如此!那么为什么会如此呢?
我们可以回忆一下以前我们对参数类型的描述:参数类型不过是一个占位符而已,在编译时,它会被具体的类型代替,同时对添加到集合对象中的数据进行参数检查;如果添加到对象中的数据类型不是指定的具体类型或其子类型,则编译出错;而且,编译以后,该占位符会被移除,运行时你是无法得到任何集合类型中数据的类型信息的。简而言之:
         List<String> strings = new LinkedList<String>( );
         List<Integer> ints = new LinkedList<Integer>( );
上面的代码在运行时和
         List strings = new LinkedList( );
         List ints = new LinkedList( );
毫无二致。了解了这一点以后,相信我们对于类型转换也会有更深的理解了。
泛型给我们带来了好处,使我们在编译时就能发现很多错误;然而任何事物都是柄双刃剑,泛型也不例外。泛型的缺点最明显之处就在于类型转换。如果你读过前面的文章,肯定看到过不带参数类型的集合对象转换为带参数类型的集合对象,其实不仅仅如此,这两者之间可以任意转换。这就意味着一点,我们不仅可以对集合类型进行转换,也可以对参数类型进行任意的转换。这似乎与前面的描述不符,因为上面的代码中的List<Number> wrongList = list;根本无法编译通过。确实如此,这行代码确实无法编译通过,不过我们中间做一步处理以后,上面的转换就可以正常编译了:
        List mediaList = list;
        List<Number> wrongList = mediaList;
由此可见,泛型在给我们带来好处的同时,也带来了无数陷阱,我们在编程时需十分注意,而Java的泛型机制也需要不断更新。
最后和以往一样,以一个拙劣的程序结束本文:
 package  com.jiang.tiger.chap1;

 import  java.util.ArrayList;
 import  java.util.LinkedList;
 import  java.util.List;

 public   class  GenericReflection   {
     private   static  List < Integer >  ints  =   new  ArrayList < Integer > ( );
   
     public   static   void  fillList(List < Integer >  list)   {
         for  (Integer i : list)   {
          ints.add(i);
        }
    }
   
     public   static   void  printList( )   {
         for  (Integer i : ints)   {
            System.out.println(i);
        }
    }
   
     public   static   void  badConversion()   {
        List < Integer >  list  =   new  LinkedList < Integer > ();
        list.add( 1 );
        list.add( 2 );
        list.add( 3 );
        fillList(list);
        printList();
        List badList  =  list;
        badList.add( " bad number " );
        badList.add( " wrong idea " );
        fillList(list);
        printList();
       
    }
   
     public   static   void  badConversion2()   {
        List list  =   new  LinkedList();
        list.add( 1 );
        list.add( 2 );
        list.add( " bad number " );
       
        List < Integer >  badList  =  list;
        badList.add( 12 );
         for  (Integer i : badList)   {
            System.out.println(i);
        }
    }
   
     public   static   void  wrongConversion()   {
        List < Integer >  list  =   new  LinkedList < Integer > ();
        list.add( 100 );
        list.add( 200 );
        list.add( 300 );
       
         // 下面的代码无法编译通过。
         // List<Number> wrongList = list;
         List mediaList  =  list;
        List < Number >  wrongList  =  mediaList;
        wrongList.add( 120.23 );
        wrongList.add( 0.1230 );
         for (Integer inter : list)   {
            System.out.println(inter);
        }
       
    }
   
     public   static   void  rightConversion()   {
        LinkedList < Integer >  list  =   new  LinkedList < Integer > ();
        list.add( 10 );
        list.add( 20 );
        list.add( 30 );
       
        List < Integer >  rightList  =  list;
         for (Integer number: rightList)   {
            System.out.println(number);
        }
       
    }
   
     public   static   void  badReflection()   {
        List < Integer >  myInts  =   new  ArrayList < Integer > ( );
       
        myInts.add( 4 );
        myInts.add( 5 );
        myInts.add( 6 );   
       
        System.out.println( " Filling list and printing in normal way " );
        fillList(myInts);
        printList( );
       
         try    {
            List list  =  (List)GenericReflection. class .getDeclaredField( " ints " ).get( null );
            list.add( " Illegal Value! " );
        }   catch  (Exception e)   {
            e.printStackTrace( );
        }
        System.out.println( " Printing with illegal values in list " );
        printList( );
    }
   
     public   static   void  main(String[] args)   {
       
        System.out.println( " rightConversion " );
        rightConversion();
         try  {
            Thread.sleep( 1000 );
            System.out.println( " badConversion " );
            badConversion();
        }   catch (Exception ce)   {
            ce.printStackTrace();
        }
          try  {
            Thread.sleep( 1000 );
            System.out.println( " badConversion2 " );
            badConversion2();
        }   catch (Exception ce)   {
            ce.printStackTrace();
        }
          try  {
            Thread.sleep( 1000 );
            System.out.println( " wrongConversion " );
            wrongConversion();
        }   catch (Exception ce)   {
            ce.printStackTrace();
        }
          try  {
            Thread.sleep( 1000 );
            System.out.println( " badReflection " );
            badReflection();
        }   catch (Exception ce)   {
            ce.printStackTrace();
        }
       
    }
}

分享到:
评论

相关推荐

    Java基础笔记之集合框架和泛型

    详细的介绍了集合框架的用法,及其语法规则,剖析了使用的使用注意事项,帮助更牢靠的掌握集合框架的知识及泛型内容。谢谢

    Java泛型类与泛型方法的定义详解

    主要介绍了Java泛型类与泛型方法的定义,结合实例形式详细分析了java泛型类与泛型方法定义、用法及相关操作注意事项,需要的朋友可以参考下

    深入解析C#中的泛型类与泛型接口

    创建您自己的泛型类时,需要特别注意以下事项: 将哪些类型通用化为类型参数。 通常,能够参数化的类型越多,代码就会变得越灵活,重用性就越好。但是,太多的通用化会使其他开发人员难以阅读或

    Java泛型定义与用法实例详解

    主要介绍了Java泛型定义与用法,结合实例形式较为详细的分析了Java中泛型的概念、原理、定义、使用方法及相关操作注意事项,需要的朋友可以参考下

    Java泛型的使用限制实例分析

    主要介绍了Java泛型的使用限制,结合实例形式分析了不能使用java泛型的情况以及泛型使用的相关注意事项,需要的朋友可以参考下

    Java定义泛型方法实例分析

    主要介绍了Java定义泛型方法,结合实例形式分析了java定义泛型的相关操作技巧与注意事项,需要的朋友可以参考下

    Java泛型定义与用法入门示例

    主要介绍了Java泛型定义与用法,结合实例形式分析了java泛型的功能、定义、应用场景及相关使用注意事项,需要的朋友可以参考下

    一篇文章快速了解Java中的泛型

    泛型类与接口2.1 基本用法2.1.1 泛型的声明2.1.2 示例2.2 注意事项3. 泛型方法4. 泛型类型的继承规则5. 通配符类型5.1 没有限制的通配符5.2有限制的通配符 1. 泛型的用处 集合容器类在设计阶段/声明阶段不能确定这...

    Java泛型详解

    本文给大家汇总介绍了下java中的泛型的相关资料,包括引入泛型机制的原因,泛型类,泛型方法,泛型的实现以及泛型的注意事项,非常的详细,有需要的小伙伴可以参考下

    Java使用反射来获取泛型信息示例

    主要介绍了Java使用反射来获取泛型信息,结合实例形式分析了java基于反射操作泛型信息的相关实现技巧与注意事项,需要的朋友可以参考下

    Java封装数组之改进为泛型数组操作详解

    主要介绍了Java封装数组之改进为泛型数组操作,结合实例形式详细分析了Java封装数组为泛型数组相关原理、操作技巧与注意事项,需要的朋友可以参考下

    C# 泛型数组学习小结

    C# 泛型数组学习中我们需要注意什么事项呢?C# 泛型数组的使用又是如何呢?那么本文就向你详细介绍这方面的内容

    SAP通用接口代码NCo3.0

    NCo3.0调用RFC,通用接口, 支持泛型和动态类型。 Sap通用接口 ...注意事项: 1. 仅对属性赋值,字段自动忽略(如果有异常,请检查) 2. 属性不能多于sap接口的参数 3. 属性名即是sap接口的Key 列如:

    新版java开发手册(华山版).zip

    比如,switch的空指针问题、浮点数的比较、无泛型限制引起的类型混乱、加锁与解锁的注意事项、YYYY的日期格式问题等; 2.修改描述112处。比如,IFNULL的判断方式、集合的toArray的数组长度、日志占位符的处理等; ...

    阿里巴巴Java开发手册1_5_0.zip

    比如,switch的空指针问题、浮点数的比较、无泛型限制引起的类型混乱、加锁与解锁的注意事项、YYYY的日期格式问题等; 2.修改描述112处。比如,IFNULL的判断方式、集合的toArray的数组长度、日志占位符的处理等; ...

    重要的Java概念::rocket:完整的Java-从A到Z║:books:Java的所有基本概念和重要概念的注释和程序-OOPS,数据结构,算法,设计模式和开发

    注意事项[有用的信息]: 程式 : | | | | | | || | | 。 [2] Java-泛型,集合和异常处理[完成] 注意事项[有用的信息]: 程式 : 。 [3] Java-文件,I / O,序列化和联网[完成] 注意事项[有用的信息]: 程式 : ...

    Java开发手册-华山

    比如,switch的空指针问题、浮点数的比较、无泛型限制引起的类型混乱、加锁与解锁的注意事项、YYYY的日期格式问题等; 2)修改描述112处。比如,IFNULL的判断方式、集合的toArray的数组长度、日志占位符的处理等; 3...

    C# ListT的用法小结

    所属命名空间:System.Collections.Generic public class List&lt;T&gt; : IList, ICollection, IEnumerable, IList, ICollection, IEnumerable List类是 ArrayList 类的泛型...性能注意事项: 在决定使用IList&lt;T&gt; 还是使

    成品网站源码网站源码后台

    源码描述: 一、源码特点 ...系统后台采用ASP.NET MVC框架三层架构MODEL开发,使用到的技术点有,泛型,Razor语法,数据库...三、注意事项 1、开发环境为Visual Studio 2013,数据库为SqlServer2008R2,使用.net 4.5开发。

    「Java学习+面试指南」一份涵盖大部分 Java 程序员所需要掌握的核心知识 准备 Java 面试,首选.zip

    Java 容器使用注意事项总结 源码分析 : ArrayList 源码+扩容机制分析 HashMap(JDK1.8)源码+底层数据结构分析 ConcurrentHashMap 源码+底层数据结构分析 IO IO 基础知识总结 IO 设计模式总结 IO 模型详解 并发 知识...

Global site tag (gtag.js) - Google Analytics