【问题标题】:java generics in AndroidAndroid中的java泛型
【发布时间】:2013-01-01 16:44:06
【问题描述】:

我看不懂下面的代码:

public class EventAdapter extends ArrayAdapter<Event> 
{
    public EventAdapter(Context context, int textViewResourceId,
            List<Event> objects) 
    {
        super(context, textViewResourceId, objects);
        this.resource = textViewResourceId;
    }
}

在这两种情况下,我都对 &lt;Event&gt; 部分感到困惑。我知道它与泛型有关,但我不明白。看了http://docs.oracle.com/javase/tutorial/java/generics/,还是不明白。

我知道objectsArrayList 类型的对象Event

我不明白的部分是扩展一个类型为&lt;Event&gt; 的ArrayAdapter。这意味着什么?

【问题讨论】:

  • 那你不明白哪一部分?我认为您需要更清楚地了解人们不了解的内容来帮助您。
  • 模糊的标题,但问题也是如此。
  • 我更新了我的问题以更清楚
  • 您可能有兴趣找到我的答案的更新——我指出了一个更“假设”的问题。

标签: java android generics


【解决方案1】:

extends ArrayAdapter&lt;Event&gt;

这里的类型限制会影响类中方法的返回类型,以及方法的参数类型。

这里是一个例子,如果你有一个类:

class SomeClass<T> {
    protected T value;

    public void setValue (T value) {
        this.value = value;
    }

    public T getValue () {
        return value;
    }
}

如果你有其他课程:

class SubClass extends SomeClass {

    @Override
    public void setValue (Event value) {    // Fail! It is not overriding the super class' method.
        this.value = value;    // Warning! Unchecked types (maybe inconsistent).
    }
}

如果您删除 @Override 注释,它将运行。但是extends SomeClass 是没用的,如果你把它放在那里可能会导致问题——会有两种非常相似的方法:setValue(Event)super.setValue(T)。现在的问题是子类是否可以访问super.setValue(T) 方法?我会在最后解释,参见“A missing type parameter bounding example”。

所以,你需要在声明中指定类型:

class SubClass extends SomeClass<Event> {

    @Override
    public void setValue (Event value) {    // Correct now!
        this.value = value;
    }
}

另外,如果你声明了一个不一致的类型:

class SubClass extends SomeClass<String> {

    @Override
    public void setValue (Event value) {    // Fail! Not overriding.
        this.value = value;    // Fail! Inconsistent types.
    }
}

所以类型限制了类体的行为。



缺少类型参数边界示例:


import java.lang.reflect.*;

class Super<T> {
    public void method (T t) {
        System.out.println("Hello");
    }

    public void method2 () {

    }
}

public class Test extends Super {
    /*public void method (Object t) {
        System.out.println("world");
    }*/

    /*public <T> void method (T t) {

    }*/

    public static void main (String args[]) {
        new Test().method("");
        for (Method m : Test.class.getMethods()) {
            System.out.println(m.toGenericString());
        }
    }
}
  • 如果我在子类中注释method(),编译时会出现警告:Test.java uses unchecked or unsafe opertations。在运行结果中,它把泛型类型T变成了Objectpublic void Test.method(java.lang.Object)

  • 如果我只取消注释子类中的第一个 method(),则编译它时不会发出警告。在运行结果中,子类拥有一个public void Test.method(java.lang.Object)。但它不允许@Override 注释。

  • 如果我只取消注释子类中的第二个method()(它也有一个泛型类型边界),编译将失败并出现错误:name clash。它也不允许 @Override 注释。如果这样做,则会引发不同的错误:method does not override

  • method2() 被子类一致继承。但是你也不能写下面的代码:

    在超类中:public void method2 (Object obj) 和在子类中:public &lt;T&gt; void method2 (T obj)。它们也是模棱两可的,编译器不允许。

【讨论】:

    【解决方案2】:

    在这种情况下,这是我看待泛型的简单方法。给定定义:

    public class EventAdapter extends ArrayAdapter<Event> 
    

    我把它读作:“一个EventAdapter IS-A ArrayAdapter OF Event 对象。”

    我认为List&lt;Event&gt; objects 表示ListEvent 对象。

    集合是对象的容器,而泛型定义了它们可以包含的内容。

    【讨论】:

      【解决方案3】:

      这会为 ArrayAdapter 中的泛型参数分配一个值,从而从 EventAdapter 类的用户手中夺走控制权。

      任何覆盖此处的方法都可以将 T 替换为 Event 并且 Event 可以在没有强制转换的情况下代替 T。

      这是泛型的一般定义。

      在这种情况下允许这样做在spec 中定义。虽然该部分中没有定义确切的行为,但据我所知,我认为它与所有其他通用行为一致。

      虽然我第一次看到这里的构造,但经过一番思考,这确实没什么不寻常的。

      【讨论】:

        猜你喜欢
        • 2018-12-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-18
        • 2021-02-18
        • 1970-01-01
        相关资源
        最近更新 更多