关于泛型

  • 转自:http://my.oschina.net/u/1386903/blog/173726

  • 1:Java的泛型是类型擦除的。
  • 2:不能初始化泛型参数和数组
  • 3:不同场景使用不同的泛型通配符
  • 4:建议使用顺序:List,List,List
  • 4:只有上限由多重限定&,下限没有
  • 5:不能在静态域或方法中引用类型变量

    1:Java的泛型是类型擦除的。

        java的泛型在编译期有效,但是在运行期所有的类型参数都会被删除。

    1 class example{
    2     public void arrayMethod(String[] strArray){}
    3     public void arraymethod(Integer[] intArray){}
    4     public void listMethod(List<String> strList){}
    5     public void listMethod(List<Integer> intList){}
    6 }
    这个例子编译会出错:Method listMethod(List<String>) has the same erasure listMethod(List<E>) as another method in type example


    JAVA泛型在编译期,所有泛型类型都会转换,编译后的字节码是没有任何泛型信息的,也就是说:一个泛型类和一个普通类在编译后指向同一个字节码。这样做的原因:

    1:泛型只存在编译期,而不在运行期,避免了JVM的大换血

    2:版本兼容,在1.5以上的版本中,List这样的 原生类型也可以正常编译通过,只是会出现警告而已。

    因为泛型是类型擦除的,所以:

    1:泛型的class对象是相同的,每个类都有class属性,泛型化不会改变其返回值


    1 class example2 {
    2     public void test() {
    3         List<String> list1 = new ArrayList<String>();
    4         List<Integer> list2 = new ArrayList<Integer>();
    5         System.out.println(list1.getClass() == list2.getClass());
    6     }
    7 }
     2:泛型数组初始化时不能声明泛型类型



    1 //  List<String>[] strList;
    2     List<String>[] strList =new List<String>[];
    以上代码编译通不过,因为类型擦除。


    3:instanceof不允许存在泛型参数


    2:不能初始化泛型参数和数组

    3:不同场景使用不同的泛型通配符

    1:泛型结构只参与”读“的操作,则限定上限(extends关键字)

    1 public static <E> void read(List<? extends E> list){
    2         for (E e : list) {
    3             //业务操作
    4         }
    5     }


    可以推断出List中取出的是E类型的,具体类型在运行时才能确定,但是一定是一个确定的类型。

    2:泛型结构只参与”写“的操作,则限定下限(super 关键字)


    1 public static void write(List<? super Number> list){
    2         list.add(23);
    3         list.add(12.34);
    4     }
    不用管是23这种Integer还是12.34这种Double类型,都可以加入到list中 ,因为他们都是Number类型的。


    JDK中的一个例子Collections.copy方法来说明上限跟下限,它实现了把源列表中的所有元素拷贝到目标列表中对应的索引处。 

    01 public static <T> void copy(List<? super T> dest, List<? extends T> src) {
    02         int srcSize = src.size();
    03         if (srcSize > dest.size())
    04             throw new IndexOutOfBoundsException("Source does not fit in dest");
    05  
    06         if (srcSize < COPY_THRESHOLD ||
    07             (src instanceof RandomAccess && dest instanceof RandomAccess)) {
    08             for (int i=0; i<srcSize; i++)
    09                 dest.set(i, src.get(i));
    10         else {
    11             ListIterator<? super T> di=dest.listIterator();
    12             ListIterator<? extends T> si=src.listIterator();
    13             for (int i=0; i<srcSize; i++) {
    14                 di.next();
    15                 di.set(si.next());
    16             }
    17         }
    18     }


    源列表是用来提供数据的,所以src要用extends,目标列表是用来写入数据的,所以dest需要用super

    如果既要读又要写,那么只需要用确定的泛型类型即可,如List<E>.



    4:建议使用顺序:List<T>,List<?>,List<Object>

    1:List<T>是一个确定的类型,只不过是在运行期确定而已

    2:List<T>可以进行读写操作, add,remove等操作,因为固定类型为T,所以不需要转型。List<?>只读类型,因为我不能确定你到底是什么类型 ,这样就不安全了,List<?>取出的是Object类型,需要主动转型

    4:只有上限由多重限定&,下限没有

    5:不能在静态域或方法中引用类型变量

    1 <strong>class example3<T>{
    2     private static T s;
    3     public static void method(T t){
    4         // do method
    5     }
    6 }</strong>
    出现编译错误 Cannot make a static reference to the non-static type T

     总而言之:

    1:虚拟机中没有泛型,只有普通的类和方法。

    2:所有的类型参数都用他们的限定类型替换

    3:桥方法被合成来保持多态

    4:为保持类型安全,必要时插入强制类型转换。 



    一个泛型的实例

    001 package generic;
    002  
    003 import java.util.Date;
    004 import java.util.GregorianCalendar;
    005  
    006 public class PairTest3 {
    007     public static void main(String[] args) {
    008         Manager ceo = new Manager("Gus Greedy"8000020031215);
    009         Manager cfo = new Manager("Sid sneaky"6000020031215);
    010         Pair<Manager> buddies = new Pair<Manager>(ceo, cfo);
    011         printBuddies(buddies);
    012  
    013         ceo.setBonus(100000);
    014         cfo.setBonus(50000);
    015         Manager[] managers = { ceo, cfo };
    016         Pair<Employee> result = new Pair<Employee>();
    017         minmax(managers, result);
    018         System.out.println(result.getFirst().getName()
    019                 + result.getSecond().getName());
    020         maxminBonus(managers, result);
    021         System.out.println(result.getFirst().getName()
    022                 + result.getSecond().getName());
    023     }
    024  
    025     public static void printBuddies(Pair<? extends Employee> p) {
    026         Employee first = p.getFirst();
    027         Employee secend = p.getSecond();
    028         System.out.println(first.getName() + secend.getName());
    029     }
    030  
    031     public static void minmax(Manager[] a, Pair<? super Manager> result) {
    032         if (a == null || a.length == 0)
    033             return;
    034         Manager min = a[0];
    035         Manager max = a[0];
    036         for (int i = 0; i < a.length; i++) {
    037             if (min.getBonus() > a[i].getBonus())
    038                 min = a[i];
    039             if (max.getBonus() < a[i].getBonus())
    040                 max = a[i];
    041         }
    042         result.setFirst(min);
    043         result.setSecond(max);
    044     }
    045  
    046     public static void maxminBonus(Manager[] a, Pair<? super Manager> result) {
    047         minmax(a, result);
    048         PairAlg.swapHelper(result);
    049     }
    050 }
    051  
    052 class PairAlg {
    053     public static boolean hasNulls(Pair<?> p) {
    054         return p.getFirst() == null || p.getSecond() == null;
    055     }
    056  
    057     public static void swap(Pair<?> p) {
    058         swapHelper(p);
    059     }
    060  
    061     public static <T> void swapHelper(Pair<T> p) {
    062         T t = p.getFirst();
    063         p.setFirst(p.getSecond());
    064         p.setSecond(t);
    065     }
    066 }
    067  
    068 class Employee {
    069     private String name;
    070     private double salary;
    071     private Date hireDay;
    072  
    073     public Employee(String n, double s, int year, int month, int day) {
    074         name = n;
    075         salary = s;
    076         GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day);
    077         hireDay = calendar.getTime();
    078     }
    079  
    080     public void raiseSalary(double byPercent) {
    081         double raise = salary * byPercent;
    082         salary += raise;
    083  
    084     }
    085  
    086     public String getName() {
    087         return name;
    088     }
    089  
    090     public double getSalary() {
    091         return salary;
    092     }
    093  
    094     public Date getHirDay() {
    095         return hireDay;
    096     }
    097 }
    098  
    099 class Manager extends Employee {
    100     private double bonus;
    101  
    102     public Manager(String n, double s, int year, int month, int day) {
    103         super(n, s, year, month, day);
    104         bonus = 0;
    105     }
    106  
    107     public double getBonus() {
    108         return bonus;
    109     }
    110  
    111     public void setBonus(double bonus) {
    112         this.bonus = bonus;
    113     }
    114  
    115     public double getSalary() {
    116         double baseSalary = super.getSalary();
    117         return baseSalary + bonus;
    118     }
    119  
    120 }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值