我在“自动”投射属性时遇到了一些麻烦。
public abstract class MyType<T> {
public abstract T getValue(String content);
}
public class MyString extends MyType<String> {
@Override
public String getValue(String content) {
return String.valueOf(content);
}
}
public class MyInteger extends MyType<Integer> {
@Override
public Integer getValue(String content) {
return Integer.valueOf(content);
}
}
public class User {
private String _name;
private int _id;
public void setName(String name) {
_name = name;
}
public String getName() {
return _name;
}
public void setId(int id) {
_id = id;
}
public int getId() {
return _id;
}
}
public class MainTest {
public static void main(String[] args) {
ArrayList<MyType> myTypes = new ArrayList<MyType>();
myTypes.add(new MyString());
myTypes.add(new MyInteger());
User user = new User();
for (MyType myType : myTypes) {
try {
user.setName((String) myType.getValue("foobar")); // getValue always returns an Object that I have to parse
user.setId((Integer) myType.getValue("42")); // getValue always returns an Object that I have to parse
} catch (Exception e) {
}
}
}
}
请记住,这只是我问题的一个抽象例子。
如何更换铸件?我需要这样的东西:
user.setName((user.getName().getClass()) myType.getValue("foobar"));
不幸的是,eclipse告诉我这是错误的The method getValue(String) is undefined for the type Class<capture#3-of ? extends String>
我不会表示明确。我会自动施加更多的暗示。
答案 0 :(得分:9)
问题是myTypes
列表被声明为List<MyType>
,它使用raw type MyType
而不是MyType
中的List<MyType<String>>
的特定参数化名单。 This is generally discouraged, warned against, bad practice, etc.
通常,您会将列表声明为List<MyType<Integer>>
或MyType<String>
。这将使您能够在不必投射的情况下获取元素。但是,这是有问题的,因为您希望能够在相同的列表中混合MyType<Integer>
和List<MyType<?>>
。同样,这通常不推荐,并且是code smell。
所以你可以声明List<MyType>
,而不是user.setName((user.getName().getClass()) object);
,但不是很多。唯一正确的结论是设计本质上存在缺陷:不要试图在集合中混合异构类型。*
MyType类只是一个抽象的例子。实际上我的问题是如何施放:
Map<Class<T>, MyType<T>>
如果对象是Object object =“foobar”;
无论如何,问题仍然是从根本上说你在列表中使用原始类型。您似乎最好使用维护类型参数化的内容,例如List<MyType>
而不是{{1}}。
请考虑在此处应用the strategy pattern。
*专家模式:除非有一个明智的常用超类型,您可以将其用作上限。
答案 1 :(得分:3)
我同意Matt Ball's answer 100%同意。一个简单,快速的解决方案,虽然可能不是理想的解决方案,但是从MyType中删除抽象性并添加将值作为特定类型获取的能力。您可以在标准库中的ResultSet中找到这种模式,以及其他地方:
public class MyType {
private String content;
MyType(String content) { this.content = content }
public String getStringValue() { return content; }
public Integer getIntValue() { return Integer.parseInt(content); }
}