【发布时间】:2018-03-14 15:52:09
【问题描述】:
我正在实现一个工厂模式,以在抽象中创建两个具体类,其中工厂方法重载(见下文):
public abstract class User {
...
public static User make(int id, String name) {
return new Admin(id, name);
}
public static User make(int id, int student_id, String name) {
return new Student(id, student_id, name);
}
}
这是工厂调用:
ArrayList<User> users = new ArrayList<>(
Arrays.asList(
User.make(1000, "Andy"), // makes new Admin
User.make(1001, 101001, "Bob") // makes new Student
)
);
这里是 Admin 类:
public class Admin extends User {
...
// constructor
protected Admin(int id, String name) {
super(id, name);
}
...
}
这里是学生类:
public class Student extends User {
...
// constructor
protected Student(int id, int student_id, String name) {
super(id, name);
this.student_id = student_id;
}
...
}
这些具体的每一个都被放置在一个用户数组列表中。我有一个函数(如下),它遍历列表并进行运行时推断以调用每个具体的特定方法;但是,我在 IDE 中收到 ClassCastException 错误,指出无法将 Admin 转换为 Student。
完整的异常消息是: 线程“main”java.lang.ClassCastException 中的异常:presentation_layer.Admin 无法转换为presentation_layer.Student
public class App {
...
public static void main(String[] args) {
ArrayList<User> users = new ArrayList<>(
Arrays.asList(
User.make(1000, "Andy"), // makes new Admin
User.make(1001, 101001, "Bob") // makes new Student
)
);
users.forEach((u) -> {
if (u instanceof Admin)) {
System.out.println("hello admin");
((Admin)u).anAdminFunc();
} else if (u instanceof Student)) {
System.out.println("hello student");
((Student)u).aStudentFunc();
}
});
}
...
}
当我注释掉具体的方法调用时,相应的打印语句按预期输出,没有错误;但是,当尝试在每次循环迭代之间使用这些独特的方法调用时,我得到了转换错误。您能否告诉我如何解决这个问题以及我做错了什么,无论是我的推理方法还是我的工厂模式方法?
【问题讨论】:
-
发布一个完整的最小示例来重现问题,以及异常的完整和准确的堆栈跟踪。
-
你能在导致类转换异常的行之前打印
d.getClass().getName()的结果吗?另外,当您更改为d instanceof Admin时会发生什么?会不会是Admin是与导入的包不同的包中的一个类? -
@ErnestKiwele 我添加了完整的异常消息。我正在尝试现在的实例。
-
您的代码在另一个方法声明中包含一个方法声明。它不可能编译。发布一个完整的最小示例来重现该问题。我们必须能够复制它,将其粘贴到我们的 IDE 中,编译并运行它。已经多次要求您这样做,但您不会这样做。所以投票结束。
-
@Jim22150 动态绑定是 Java 的标准功能,设计和创建多态对象是 100% 可以的。我唯一要改变的是需要在运行时检查类名。如果您按合同进行设计,那么
User上的方法应该适用于具体类型并在需要时被覆盖。因此,对用户列表的元素调用用户方法更为明智,即使每个元素的具体类型都可以覆盖或实现这些方法。
标签: java casting type-inference