蒙面博士
2017-08-20 09:22
采纳率: 100%
浏览 1.2k
已采纳

怎样理解java泛型中的擦除

class GenericBase {
private T element;
public void set(T arg) { arg = element; }
public T get() { return element; }
}

class Derived1 extends GenericBase {}

class Derived2 extends GenericBase {} //这里去除了T,为什么编译时没有问题?

// class Derived3 extends GenericBase<?> {}
// 上面的GenericBase<?>会出现编译错误,这又是为什么?

public class ErasureAndInheritance {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
Derived2 d2 = new Derived2();
Object obj = d2.get();
d2.set(obj); // 如果上面没有@SuppressWarnings修饰的话,这里会出现一个编 译警告,为什么偏偏在set()方法这里出现一个编译警告?
}
}

  • 写回答
  • 好问题 提建议
  • 关注问题
  • 收藏
  • 邀请回答

6条回答 默认 最新

  • 鼠小 2017-08-21 01:21
    已采纳

    【1】class Derived2 extends GenericBase {} //这里去除了T,为什么编译时没有问题?
    经过测试这种继承方法,是不继承父类泛型效果的,,可能就是题主所说的对父类的泛型擦除

    还可以这样继承,给子类设置泛型,class Derived2 extends GenericBase {},,,和上面一样,父类的泛型效果未被继承

    【2】 class Derived3 extends GenericBase<?> {} 上面的GenericBase<?>会出现编译错误,这又是为什么?
    父类设置了泛型,子类没有泛型,,创建自类时如何给父类设置泛型??所以系统报错“找不到泛型”
    必须给子类和父类设置泛型(且名字相同,测试了一下同时设置 ? 是不行的),
    class Derived2 extends GenericBase(名字随意,但要一样)

    【3】d2.set(obj); // 如果上面没有@SuppressWarnings修饰的话,这里会出现一个编 译警告,为什么偏偏在set()方法这里出现一个编译警告?
    泛型默认是 Object 类型的,,get到一个object不会有问题吧,,,
    set不同,,set需要把你的对象赋值给泛型的对象,,这是有危险的,需要设置泛型才可以取出警告。
    编译器报错,给了个map的例子,大概意思是说“没有指定泛型的地方,赋值都会出现警告。”,,下面有个List的例子:

            List list = new ArrayList();
            list.add("sss");//有警告
    
    

    我也是根据测试结果总结的,欢迎交流,,,,有问题还可以追问
    我的测试代码如下:

     public class TestT {
        //    @SuppressWarnings("unchecked")
        public static void main(String[] args) {
            Derived2<String> d2 = new Derived2<String>();
            Object obj = "aaa";
            d2.set((String) obj);
            System.out.println(d2.get());
    
            List list = new ArrayList();
            list.add("sss");//有警告
    
            GenericBase<String> genericBase = new GenericBase<>();
            genericBase.set("sss");//没警告
        }
    }
    
    class GenericBase<T> {
        private T element;
    
        public void set(T arg) {
            element = arg;
        }
    
        public T get() {
            return element;
        }
    }
    
    class Derived1 extends GenericBase {
    }
    
    class Derived2<S> extends GenericBase<S> {
    }
    
    已采纳该答案
    评论
    解决 无用
    打赏 举报
  • 蒙面博士 2017-08-20 09:26

    class GenericBase {
    private T element;
    public void set(T arg) { arg = element; }
    public T get() { return element; }
    }
    class Derived1 extends GenericBase {}
    前面一部分是这样的

    评论
    解决 无用
    打赏 举报
  • 蒙面博士 2017-08-20 09:39

    class GenericBase《T》 {
    private T element;
    public void set(T arg) { arg = element; }
    public T get() { return element; }
    }
    class Derived1《T》 extends GenericBase《T》 {}
    前面一部分是这样的

    评论
    解决 无用
    打赏 举报
  • cloudyzhao 2017-08-21 01:11

    通配符 并不适用于函数声明

    评论
    解决 无用
    打赏 举报
  • xhl_2017 2017-08-21 01:52

    public void set(T arg) { arg = element; }这句写错了--不能把一个未初始化的值传给参数,应该是public void set(T arg) { this.element = arg; }

    评论
    解决 无用
    打赏 举报
  • SevAS 2017-08-23 12:37

    泛型只是一种自检手段,以便在编译前纠错,编译的时候会补偿去掉

    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题