为什么 getItem(position) 应该在通用 class(即自定义 ArrayAdapter<T>)中进行转换?
Why getItem(position) should be casted inside a generic class (i.e. Custom ArrayAdapter<T>)?
我正在尝试理解 Java 中的泛型。我在 Android 工作室工作。我有一个 Word
class 和 ArrayList
个 Word
个对象。
ArrayList<Word> words = new ArrayList<>();
我试着做一个像这样的通用 class
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
}
}
现在,我的问题是为什么编译器会报错?当我使用此 class 时,我将传递一个包含 Word
对象的 ArrayList
。因此,据我所知,以下代码行:
wordAdapter<Word> adapter = new wordAdapter<>(this, words);
应该将类型参数 <T>
转换为 <Word>
.
我不明白为什么编译器将从 getItem(position)
获得的对象视为 Object
对象而不是 Word
对象。另外我想知道既然它是通用的,编译器不应该忽略这些东西吗?它如何识别我将交付什么样的对象?
如果 WordAdapter
是包含 Word
个元素的 ArrayAdapter
,则应定义为:
public class WordAdapter extends ArrayAdapter<Word> {
public WordAdapter(Context context, ArrayList<Word> object) {
super(context, 0, object);
}
...
}
这样 getItem(position)
会 return 一个 Word
。
如果这样定义
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 是 class MyClass
中的未定义类型,因为它是定义的泛型。稍后可以传递任何类型。
MyClass<Word> instance1 = new MyClass<Word>();
MyClass<String> instance2 = new MyClass<String>();
Word value1 = instance1.someMethod();
String value2 = instance2.someMethod();
所以在MyClass
里面操作的时候不知道后面会定义什么类型
您需要做的是在 class 中定义类型以便能够使用它。因此,不是稍后从外部传递通用类型,而是已经在内部定义了它
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 将返回的未知类型视为单词类型的对象。如果您只将 class 用于 Word,它可以工作,但丑陋且不必要。但是,如果您稍后将它用于让我们说字符串,它会中断,因为无法将字符串对象转换为单词对象
编辑:
我刚刚在您的一条评论中读到,您想为所有类型的数据类型创建一个通用的 class,它可以使用 type-specific 函数。
从技术上讲,这可以通过 type-checks 然后投射来实现。但是这样会非常非常难看。
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
}
}
}
然而,处理此类问题的通常方法是为您需要支持的每种类型创建一个适配器。这样做非常丑陋,根本不应该这样做。
我正在尝试理解 Java 中的泛型。我在 Android 工作室工作。我有一个 Word
class 和 ArrayList
个 Word
个对象。
ArrayList<Word> words = new ArrayList<>();
我试着做一个像这样的通用 class
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
}
}
现在,我的问题是为什么编译器会报错?当我使用此 class 时,我将传递一个包含 Word
对象的 ArrayList
。因此,据我所知,以下代码行:
wordAdapter<Word> adapter = new wordAdapter<>(this, words);
应该将类型参数 <T>
转换为 <Word>
.
我不明白为什么编译器将从 getItem(position)
获得的对象视为 Object
对象而不是 Word
对象。另外我想知道既然它是通用的,编译器不应该忽略这些东西吗?它如何识别我将交付什么样的对象?
如果 WordAdapter
是包含 Word
个元素的 ArrayAdapter
,则应定义为:
public class WordAdapter extends ArrayAdapter<Word> {
public WordAdapter(Context context, ArrayList<Word> object) {
super(context, 0, object);
}
...
}
这样 getItem(position)
会 return 一个 Word
。
如果这样定义
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 是 class MyClass
中的未定义类型,因为它是定义的泛型。稍后可以传递任何类型。
MyClass<Word> instance1 = new MyClass<Word>();
MyClass<String> instance2 = new MyClass<String>();
Word value1 = instance1.someMethod();
String value2 = instance2.someMethod();
所以在MyClass
里面操作的时候不知道后面会定义什么类型
您需要做的是在 class 中定义类型以便能够使用它。因此,不是稍后从外部传递通用类型,而是已经在内部定义了它
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 将返回的未知类型视为单词类型的对象。如果您只将 class 用于 Word,它可以工作,但丑陋且不必要。但是,如果您稍后将它用于让我们说字符串,它会中断,因为无法将字符串对象转换为单词对象
编辑:
我刚刚在您的一条评论中读到,您想为所有类型的数据类型创建一个通用的 class,它可以使用 type-specific 函数。
从技术上讲,这可以通过 type-checks 然后投射来实现。但是这样会非常非常难看。
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
}
}
}
然而,处理此类问题的通常方法是为您需要支持的每种类型创建一个适配器。这样做非常丑陋,根本不应该这样做。