为什么getItem(position)应该在一个泛型类(即Custom ArrayAdapter)中输入 )?

问题描述 投票:0回答:2

我正在尝试理解Java中的泛型。我在Android工作室工作。我有一个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
    }
}

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

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

应该将类型参数<T>转换为<Word>。 我不明白为什么编译器将从getItem(position)获得的对象视为Object对象而不是Word对象。另外我想知道因为它是通用的,编译器是否应该忽略这些东西?它如何识别我将提供什么样的物体?

java android generics android-arrayadapter
2个回答
0
投票

如果这样定义

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,你需要添加一个所谓的强制转换。换句话说,告诉java将返回的未知类型看作单词类型的对象。如果你只使用你的类用于Word它会工作,但是很丑陋和不必要。但是如果你以后再使用它,那就说Strings它会破坏,因为String对象不能被转换为word对象

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

从技术上讲,这可以通过类型检查然后投射它们来实现。但这会非常难看。

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
    }
  }

}

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


3
投票

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

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

    ...
}

这样getItem(position)将返回Word

© www.soinside.com 2019 - 2024. All rights reserved.