• java中泛型擦除和多态的冲突及解决


    泛型擦除

    java的泛型是一种伪泛型,编译器会去除泛型信息,字节码不会包含泛型信息。

    public class Client {
    
      public static void main(String[] args) {
        List<String> nameList = new ArrayList<>();
        List<Integer> ageList = new ArrayList<>();
        //编译后都会变成 List  
        System.out.println(nameList.getClass() == ageList.getClass());// true
      }
    
    }
    

    JVM看到的都是List,所以结果为 true.

    和多态的冲突

    public class Client2 {
    
      public static void main(String[] args) {
        DateHolder dateHolder = new DateHolder();
        dateHolder.setValue(new Date());
        Date value = dateHolder.getValue();
        System.out.println(value);
      }
    
      interface Holder<T> {
    
        T getValue();
    
        void setValue(T value);
      }
    
      static class DateHolder implements Holder<Date> {
    
        private Date value;
    
        @Override
        public Date getValue() {
          return this.value;
        }
    
        @Override
        public void setValue(Date value) {
          this.value = value;
        }
      }
    }
    

    定义一个泛型接口,定义一个子类实现泛型接口,泛型接口经过编译器擦除后会变成

    static interface Holder {
    
        public abstract Object getValue();
    
        public abstract void setValue(Object obj);
    }
    

    但是子类重写的方法明明参数和返回值都是 Date 类型啊,这是怎么回事呢?
    我们的本意是想将泛型接口变成

    static interface Holder {
    
        public abstract Date getValue();
    
        public abstract void setValue(Date obj);
    }
    

    但编译器没有办法将泛型变成 Date ,只能变成 Object。但编译器使用桥方法实现了这一功能。反编译结果为

    static class DateHolder implements Holder {
    
            public Date getValue() {
                return value;
            }
    
            public void setValue(Date value) {
                this.value = value;
            }
    
            public volatile void setValue(Object obj) {
                setValue((Date)obj);
            }
    
            public volatile Object getValue() {
                return getValue();
            }
    
            private Date value;
    
            DateHolder() {
            }
    }
    

    编译器通过桥方法解决了泛型擦除和多态之间的冲突。可以看到子类实现中

    public Date getValue() {
         return value;
    }
    
    public volatile Object getValue() {
        return getValue();
    }
    

    我们自己的编码中这样写是不能通过编译器检查的,但编译器自己是可以这样的,因为虚拟机是通过返回值和参数列表来区分方法的。

  • 相关阅读:
    sql server该账户当前被锁定,所以用户'sa'登录失败。系统管理员无法将该账户解锁。(Microsoft SQL Server,错误:18486)
    windows server常用操作
    sql server2005直接会话运行成功,但在作业执行报错
    sql server xp_readerrorlog引起的CPU爆满100%
    sql server错误日志
    (13)python网络编程,python Socket
    tcp/ip
    (12)python异常处理,python中的 try except
    典型分布式系统分析:Dynamo
    c++ set与unordered set的区别
  • 原文地址:https://www.cnblogs.com/strongmore/p/13945540.html
Copyright © 2020-2023  润新知