有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为什么getItem(position)应该在泛型类(即定制ArrayAdapter<T>)中强制转换?

我试图理解Java中的泛型。我在安卓工作室工作。我有一个Word类,我有一个ArrayListWord对象

ArrayList<Word> words = new ArrayList<>();

我试着创建一个这样的泛型类

public class wordAdapter<T> extends ArrayAdapter<T> {
    public wordAdapter(Context context, ArrayList<T> object) {
        super(context, 0, object);
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // Get the data item for this position
        Word wordItem = getItem(position); 
        // This line gives an error because it needs to be casted to "Word"
        // Rest of the code
    }
}

现在,我的问题是为什么编译器会抱怨?当我使用这个类时,我将传递一个包含Word对象的ArrayList。据我所知,以下代码行:

wordAdapter<Word> adapter = new wordAdapter<>(this, words);

应将类型参数<T>转换为<Word>
我不明白为什么编译器将从getItem(position)获得的对象视为Object对象,而不是Word对象。另外,我想知道,既然它是一个泛型,编译器难道不应该忽略这些东西吗?它如何识别我将交付什么样的对象


共 (2) 个答案

  1. # 1 楼答案

    如果这样定义的话

    public class MyClass<T> extends SomeClass<T>{
    
      public T someMethod(){
         // T could be any type. Could be Word, could be String, ......
         T someObject = super.getItem();
         return someObject
      }
    
    }
    

    T是类MyClass中未定义的类型,因为它是泛型定义的。稍后,任何类型都可以传递

    MyClass<Word> instance1 = new MyClass<Word>();
    MyClass<String> instance2 = new MyClass<String>();
    
    Word value1 = instance1.someMethod();
    String value2 = instance2.someMethod();
    

    因此,在MyClass内部操作时,您不知道稍后将定义什么类型

    您需要做的是在类中定义类型,以便能够使用它。因此,不是稍后从外部传递泛型类型,而是在内部定义它

    public class WordClass extends SomeClass<Word>{
    
      public Word someMethod(){
        // since the generic type is now defined as Word, you can reference it as such
        Word wordObject = super.getItem();
        return wordObject;
      }
    
    }
    

    因为在您的情况下,类型未知,但您试图将其定义为Word,所以需要添加一个所谓的cast。换句话说,告诉java将返回的未知类型视为单词类型的对象。如果你只使用你的类来表达单词,它会起作用,但很难看,也没有必要。但是如果你以后在字符串中使用它,它会断开,因为字符串对象不能被转换成单词对象

    编辑
    我刚刚在你的一条评论中读到,你想为所有类型的数据类型创建一个通用类,它可以使用特定于类型的函数

    从技术上讲,这是可能的,通过做类型检查,然后铸造它们。但这将是非常非常丑陋的

    public class UglyAdapter<T> extends ArrayAdapter<T>{
    
      public void doTypeSpecificStuff(T obj){
        Class<T> objectClass = obj.getClass();
        if(objectClass.equals(Integer.class)){
          Integer intObj = (Integer) obj;
          // here you can call Integer-specific methods
        }else if(objectClass.equals(String.class)){
          String strObj = (String) obj;
          // here you can call String-specific methods
        }
        else if(objectClass.equals(Word.class)){
          Word wordObj = (Word) obj;
          // here you can call Word-specific methods
        }
        else{
          // object is unsupported type. Throw exception or do whatever
        }
      }
    
    }
    

    然而,进行这类工作的通常方法是为需要支持的每种类型创建一个适配器。这样做很难看,根本不应该这样做

  2. # 2 楼答案

    如果WordAdapter是包含Word元素的ArrayAdapter,则应将其定义为:

    public class WordAdapter extends ArrayAdapter<Word> {
        public WordAdapter(Context context, ArrayList<Word> object) {
            super(context, 0, object);
        }
    
        ...
    }
    

    这样getItem(position)将返回一个Word