我正在尝试为继承另一个对象的对象创建构造函数,但是这个构造函数也应该阻止在某些条件下创建对象。
我有这段代码:
class Foo
{
double x;
public Foo(double init_x)
{
x = init_x;
}
}
class Bar extends Foo
{
public Bar(double init_x)
{
if(init_x < 10)
{
throw new Exception();
}
super(init_x);
}
}
以下是使用主要定义编译代码时的错误:
test2.java:13: error: constructor Foo in class Foo cannot be applied to given types;
{
^
required: double
found: no arguments
reason: actual and formal argument lists differ in length
test2.java:18: error: call to super must be first statement in constructor
super(init_x);
^
2 errors
我的问题是:即使我明确指定了Bar(double init_x)
,为什么我会得到第一个错误?如果超级调用必须是第一个语句,那么为什么我会得到第二个错误?那么我该如何解决这个问题?
答案 0 :(得分:2)
您有两种选择:
您将支票移至调用super
之后。它仍然在方法完成之前,因此调用者将看不到构造的对象 - 它至少在调用者的视图中阻止了构造:
class Bar extends Foo {
public Bar(double init_x) throws Exception {
super(init_x);
if (init_x < 10) {
throw new Exception();
}
}
}
您在另一个方法中进行检查,如果值正确则返回该值,但如果不正确则抛出异常:
class Bar extends Foo {
private static double checkInitX(double init_x) throws Exception {
if (init_x < 10) {
throw new Exception();
}
return init_x;
}
public Bar(double init_x) throws Exception {
super(checkInitX(init_x));
}
}
您可以在调用super中调用任何方法,该方法不是您正在构造的对象的实例方法。放置该方法的好地方是在类中作为静态方法。
但通常情况下,选项1是最好的。除非有一个很好的理由不使用超出范围的值调用超级(例如,超级构造函数非常慢,或者如果值超出范围则抛出另一个,令人困惑的异常),选项2是不必要。 (在提到的两个案例中,你最好重构超类构造函数)
答案 1 :(得分:0)
答案在您收到的错误消息中说明:error: call to super must be first statement in constructor
答案 2 :(得分:0)
我相信在构造函数中抛出异常不是好习惯。 原因,这只是我的观点,但我认为,制作简单的工厂方法会更好:
class Bar extends Foo
{
//hide constructor
private Bar(init_x){
super(init_x);
}
//factory method
public static Bar createBar(double init_x)
{
if(init_x >= 10)
{
return new Bar(init_x);
}else{
//you can return null, instead of throwing exception
throw new Exception();
}
}
}
当你需要bar的实例时:
public static void main(String [] args){
Bar bar = Bar.createBar(104.3);
...
}