ninghaiywx
ninghaiywx
2017-02-08 14:42
采纳率: 44.4%
浏览 1.3k
已采纳

关于JAVA泛型的类型擦除的一些疑问

例如
public class list
{
private Object[] elements;
@SuppressWarnings("unchecked")
public E get(int n)
{
return (E)elements[n];
}
}
按照泛型的类型擦除不应该都变成Object了吗,
public E get(int n)
{
return (E)elements[n];
}应该也变成
public Object get(int n)
{
return (Object)elements[n];
}如果用的是list的get方法,为什么最后能返回String类型而不是Object类型。

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

3条回答 默认 最新

  • devmiao
    devmiao 2017-02-08 20:45
    已采纳
    点赞 评论
  • sinat_19923369
    sinat_zjflynat 2017-02-08 17:38

    我个人认为楼主把<? extends E>和弄混了,前面一个表示将持有某种具体类型的集合但是不知道是哪个,因此使用这个返回值时返回的是object类型,
    但是第二个楼主可以使用Javap -c ClassName你可以看到,会在你取出的时候进行转型,也就是说前面你进行编译的时候相当远原生类,全部擦除了,
    但是在最后会进行相应的转型,我也最近在学习这个不知道我说的对不对,如果有错误,欢迎指正

    点赞 评论
  • wojiushiwo945you
    毕小宝 2017-02-09 01:17

    首先,你这段代码定义有问题,必须指定list类的泛型类型也为E才能通过编译:

     public class list<E> {
        private Object[] elements;
    
        @SuppressWarnings("unchecked")
        public E get(int n) {
            return (E) elements[n];
        }
    
        public static void main(String[] args) {
            list<String> list = new list<String>();
            System.out.println(list == null);   
        }
    }
    
    

    其次,这段代码反编译后的内容还是原来的定义,因为你这里并不是涉及到泛型擦除,而是在定义泛型类,Java中泛型接口、泛型类和泛型方法的定义过程中,我们常见的如T、E、K、V等形式的参数常用于表示泛型形参,你这个仅仅是定义一个list类,E标识其是泛型参数。实际用法是你在使用list这个泛型类的时候必须指定泛型形参,而编译器编译时的泛型擦除会将其转换为最顶级的父类来处理,代码中完全没有泛型信息:

     public class list<E>
    {
      private Object[] elements;
    
      public E get(int n)
      {
        return this.elements[n];
      }
    
      public static void main(String[] args) {
        list list = new list();
        System.out.println(list == null);
      }
    }
    

    这才是泛型擦除的真正含义:使用泛型类的地方list list = new list();已经没有了泛型信息。

    点赞 评论

相关推荐