这是一个设计问题。存储Foo对象的映射是不好的做法,其中Foo是一个超类并将查找转换为更具体的对象?即:
Map<Integer, Foo> lookup = new HashMap<>();
lookup.put(0, new Bar()); //Bar extends Foo
lookup.put(1, new Fizz()); // Fizz extends Foo
public Bar getBarById (int barId){
(Bar)lookup.get(barId);
}
上述方法有多脆弱?在Java8中是否有更好的方法或更好的设计模式可以让我做类似的事情?
答案 0 :(得分:0)
你有个好主意,但看起来你需要拆分对象。除非您要跟踪他们的密钥,否则您不会知道从地图中取出哪种类型。
因此,如果您输入一个带有键0的新Bar(),您需要将其存储在列表或其他内容中,因此当您只想调用Bar的方法时,您可以查看Bar对象ID的ArrayList。
Map<Integer, Foo> lookup = new HashMap<>();
ArrayList<Integer> listOfBar = new ArrayList<>();
ArrayList<Integer> listOfFizz = new ArrayList<>();
lookup.put(0, new Bar()); //Bar extends Foo
listOfBar.add(0);
lookup.put(1, new Fizz()); // Fizz extends Foo
listOfFizz.add(1);
//in Method to return Bars
if(listOfBar.size() != 0){
int k = listOfBar.get(0);
Bar b = lookup.get(k);
return b;
}
所以现在可以使用arraylist访问该特定对象的所有id。
答案 1 :(得分:0)
原始代码无法正常工作,因为 getBarbyId()会在您为其提供&#34; Fizz&#34;的ID时失败(在您的示例中为id#1):
// ClassCastException: System.out.println(this.getBarById(1).getClass().getSimpleName());
您可以使用ArrayList完成相同的操作,但重要的是,如果您想要自己的访问者,您应该将其设为 getFooById ,即使您没有能力改变Foo类。
示例:
import java.util.ArrayList;
public class Main {
class Foo {
// Assume defined elsewhere and we can't change it
}
class Bar extends Foo {}
class Fizz extends Foo {}
public Foo getFooById(int id) {
return fooList.get(id);
}
ArrayList<Foo> fooList = new ArrayList<>();
Main() {
fooList.add(0, new Bar()); // keys optional here, unless you are
fooList.add(1, new Fizz()); // looking for specific entries later
for (int i=0; i < fooList.size(); i++) {
System.out.println("foo: " + i + " " + getFooById(i).getClass().getSimpleName());
}
}
public static void main(String[] args) {
Main m = new Main();
}
}
<强>输出:强>
foo: 0 Bar
foo: 1 Fizz