我想创建一个通用方法来从参数对象中获取List。
问题是因为我有一个声明的对象,其他类的实例扩展了声明的类。
我不想使用instanceof
解决方案,因为扩展LimitedValue的类数量可能很大。
我认为使用反射作为解决方案,但我不知道如何在对象的这一部分中使用对象实例:
Class cls = Class.forName(limitedValue.getClass().getName());
Object obj = cls.newInstance();
//This is wrong, I don't want a new instance.
Method[] methods = cls.getDeclaredMethods();
for(int x= 0; x < methods.length; x++) {
Method method = methods[x];
if ("java.util.List".equals(method.getReturnType().getName())) {
//How to get the value of this method from limitedValue instance ?
}
}
这是我的完整代码:
public class CalculatorLimitedValue {
public static void main(String[] args) throws Exception {
StoreItem storeItem = new StoreItem(1L, "Name of StoreItem", 50L);
List listOfStoreItems = new ArrayList();
listOfStoreItems.add(storeItem);
LimitedValue limitedValue0 = new Store(listOfStoreItems);
List firstList = calculator(limitedValue0);
//do something with the list
SupermarketItem supermarketItem = new SupermarketItem(1L, "Name of SupermarketItem", 21L);
List listOfSupermarketItems = new ArrayList();
listOfSupermarketItems.add(supermarketItem);
LimitedValue limitedValue1 = new Supermarket(listOfSupermarketItems);
List secondList = calculator(limitedValue1);
//do something with the list
}
/** This is the method that I'd like to make generic to return a List */
private static List calculator(LimitedValue limitedValue) throws Exception{
Class cls = Class.forName(limitedValue.getClass().getName());
Object obj = cls.newInstance();
//This is wrong, I don't want a new instance.
Method[] methods = cls.getDeclaredMethods();
for(int x= 0; x < methods.length; x++) {
Method method = methods[x];
if ("java.util.List".equals(method.getReturnType().getName())) {
//How to get the value of this method from limitedValue instance ?
}
}
/* I don't want to use this one way, because my classes that extends LimitedValue
can be big. I would like to made a generic way to get de list of classes. */
if (limitedValue instanceof Store) {
System.out.println("This is a store");
return ((Store) limitedValue).getStoreItems();
} else if (limitedValue instanceof Supermarket) {
System.out.println("This is a supermarket");
return ((Supermarket) limitedValue).getSupermarketItems();
}
return null;
}
}
如果有帮助,这些是我的其他课程:
LimitedValue.class
public class LimitedValue { }
StoreItem.class
public class StoreItem {
private Long id;
private String nameOfStoreItem;
private Long valueOfStoreItem;
public StoreItem(Long id, String nameOfStoreItem, Long valueOfStoreItem){
this.id = id;
this.nameOfStoreItem = nameOfStoreItem;
this.valueOfStoreItem = valueOfStoreItem;
}
//getters and setters...
}
SupermarketItem.class
public class SupermarketItem {
private Long id;
private String nameOfSupermarketItem;
private Long valueOfSupermarketItem;
public SupermarketItem() {
}
public SupermarketItem(Long id, String nameOfSupermarketItem, Long valueOfSupermarketItem) {
this.id = id;
this.nameOfSupermarketItem = nameOfSupermarketItem;
this.valueOfSupermarketItem = valueOfSupermarketItem;
}
//getters and setters...
}
Store.class
public class Store extends LimitedValue {
private List<StoreItem> storeItems;
public Store(List<StoreItem> storeItems) {
this.storeItems = storeItems;
}
//getters and setters
}
Supermarket.class
public class Supermarket extends LimitedValue {
private List<SupermarketItem> supermarketItems;
public Supermarket(List<SupermarketItem> supermarketItems) {
this.supermarketItems = supermarketItems;
}
//getters and setters
}
答案 0 :(得分:2)
要获取List
值,请使用Method#invoke
:
List list = method.invoke(limitedValue);
您不需要Object obj = cls.newInstance();
- 您在该方法中根本不使用它。
无论如何,你自己很难做到这一点。您还可以定义一个接口
public interface HasList<E> {
List<E> getList();
}
并让所有类实现此目的。
答案 1 :(得分:2)
您可以尝试在此处使用反射来尝试实现您想要的效果,但最好重新考虑您的整体设计,并尝试使用更好的面向对象的设计来解决手头的问题。
特别是,假设我们考虑将一个名为getItems的方法添加到LimitedValue
类中,该类返回一个项目列表,可以是SupermarketItem
或可能是StoreItem
。如果它的结构正确,你就不需要知道实际的类型,因为代码将以多态方式被抽象化。
public abstract class LimitedValue {
List<? extends Item> getItems();
}
我们现在已经在LimitedValue
上定义了一种新方法,但我们还必须考虑到我们已经引入了这个新项目的东西。我注意到SupermarketItem
和StoreItem
都分享了类似的属性,name
,id
和value
,因此似乎可以使用单个属性类来代表他们所有人。
public abstract class Item {
final Long id;
final String name;
final Long value;
public Item(final Long id, final Long name, final Long value) {
this.id = id;
this.name = name;
this.value = value;
}
String getName() {
return name;
}
// other getters and setters
}
public class SupermarketItem extends Item {
public SupermarketItem(final Long id, final Long name, final Long value) {
super(id, name, value);
}
}
public class StoreItem extends Item {
public StoreItem(final Long id, final Long name, final Long value) {
super(id, name, value);
}
}
现在我们在访问这些对象时完全抽象出了任何反射的需要 - 您可以简单地调用item.getValue(),因为您将知道列表中的每个项目都是Item类型。
当然,您还需要重构Store和SuperMarket类,例如:
public class Supermarket extends LimitedValue {
private List<SupermarketItem> supermarketItems;
public Supermarket(List<SupermarketItem> supermarketItems) {
this.supermarketItems = supermarketItems;
}
public List<? extends Item> getItems() {
return supermarketItems;
}
}
并且因为您只返回List<Item>
,所以您始终知道其中包含的内容,并且您可以更改主代码以使用此代码。
这是一个更清洁的长期解决方案。