当前位置: 首页 > 面试题库 >

Java-构造函数中可重写的方法调用有什么问题?

萧飞
2023-03-14
问题内容

我有一个Wicket页面类,该类根据抽象方法的结果设置页面标题。

public abstract class BasicPage extends WebPage {

    public BasicPage() {
        add(new Label("title", getTitle()));
    }

    protected abstract String getTitle();

}

NetBeans用消息“构造函数中的可重写方法调用”警告我,但是这应该怎么办?我能想到的唯一选择是将其他方法的结果传递给子类中的超级构造函数。但这可能很难通过许多参数来读取。


问题答案:

从构造函数调用可重写方法
简而言之,这是错误的,因为它不必要地打开了许多错误的可能性。当@Override被调用时,该对象的状态可以是不一致的和/或不完整。

引用有效Java 2nd Edition,条款17:继承的设计和文档,或者禁止这样做:

类必须遵守一些其他限制以允许继承。构造函数不得直接或间接调用可重写的方法。如果违反此规则,将导致程序失败。超类构造函数在子类构造函数之前运行,因此子类中的重写方法将在子类构造函数运行之前被调用。如果重写方法依赖于子类构造函数执行的任何初始化,则该方法将无法正常工作。

这是一个示例说明:

public class ConstructorCallsOverride {
    public static void main(String[] args) {

        abstract class Base {
            Base() {
                overrideMe();
            }
            abstract void overrideMe(); 
        }

        class Child extends Base {

            final int x;

            Child(int x) {
                this.x = x;
            }

            @Override
            void overrideMe() {
                System.out.println(x);
            }
        }
        new Child(42); // prints "0"
    }
}

在此,当Base构造函数调用时overrideMeChild尚未完成对的初始化final int x,并且该方法获得了错误的值。这几乎肯定会导致错误和错误。

关于具有许多参数的对象构造
具有许多参数的构造函数可能导致较差的可读性,并且存在更好的替代方法。

这是来自Effective Java 2nd Edition,项目2的引用:面对许多构造函数参数时,请考虑一个构造器模式:

传统上,程序员使用伸缩构造函数模式,在这种模式下,你只为构造函数提供必需的参数,另一个为单个可选参数,第三个为两个可选参数,依此类推…

伸缩构造函数模式本质上是这样的:

public class Telescope {
    final String name;
    final int levels;
    final boolean isAdjustable;

    public Telescope(String name) {
        this(name, 5);
    }
    public Telescope(String name, int levels) {
        this(name, levels, false);
    }
    public Telescope(String name, int levels, boolean isAdjustable) {       
        this.name = name;
        this.levels = levels;
        this.isAdjustable = isAdjustable;
    }
}

现在,你可以执行以下任一操作:

new Telescope("X/1999");
new Telescope("X/1999", 13);
new Telescope("X/1999", 13, true);

但是,你目前不能仅设置nameisAdjustable,并保留levels默认值。你可以提供更多的构造函数重载,但是显然,数量会随着参数数量的增长而爆炸,甚至可能包含多个booleanint参数,这确实会使事情一团糟。

如你所见,这不是一个令人愉快的模式,而且使用起来也不那么令人愉快(“ true”在这里是什么意思?13是什么?)。

Bloch建议使用构建器模式,这将使你可以编写如下代码:

Telescope telly = new Telescope.Builder("X/1999").setAdjustable(true).build();

请注意,现在参数已命名,你可以按所需的任何顺序设置它们,也可以跳过要保留为默认值的参数。这肯定比伸缩构造函数好得多,尤其是当存在大量属于许多相同类型的参数时。



 类似资料:
  • 问题内容: 对不起任何较小的语法错误或其他错误,我正在使用Jitsi模块进行此操作,并且对Java不太熟悉,因此想确认正在发生的事情以及为什么以及如何对其进行修复。 使用按名称加载类方法创建类B的实例时,应用程序正在执行此操作: 在类B中调用重写的load() 初始化变量(根据调试器调用“私有字符串testString = null”),将其无效。 这是预期的Java行为吗?是什么原因造成的?它是

  • 问题内容: 我遇到的情况是,在实例化类时,我只想读取配置文件一次。 假设我有一个名为的方法,该方法读取配置并将其放入对象中。当程序需要使用配置值时,它将使用定义键读取对象。我想知道构造函数仅在生命周期中调用一次。我可以将我的方法放入构造函数中,这将使我有一次调用的好处,还是有另一种机制可以这样做? 问题答案: 更好的设计是 工厂设计模式

  • 我想覆盖类LocalDate的toString()方法。我知道如何使用像java.util.Date这样的公共构造函数覆盖类的toString()方法: 但我不能对像java这样有私有构造函数的类做同样的事情。时间LocalDate有什么办法可以解决这个问题吗?

  • 本文向大家介绍请解释Java中的概念,什么是构造函数?什么是构造函数重载?什么是复制构造函数?相关面试题,主要包含被问及请解释Java中的概念,什么是构造函数?什么是构造函数重载?什么是复制构造函数?时的应答技巧和注意事项,需要的朋友参考一下 考察点:JAVA构造函数 当新对象被创建的时候,构造函数会被调用。每一个类都有构造函数。在程序员没有给类提供构造函数的情况下,Java编译器会为这个类创建一

  • 根据我的理解,当创建了临时对象时,将调用move构造函数。这里,函数返回一个临时对象,但我的程序没有打印来自移动构造函数的消息:

  • 问题内容: 我正在处理一个扩展的类。 这不是我的代码,它在开始构造GUI之前先进行调用。我想知道为什么要这样做,因为我一直只访问超类的方法而不必调用; 问题答案: 对于具有父级的所有类(这是Java中每个用户定义的类),都有一个不带参数的隐式调用,因此通常不需要显式调用。但是,如果父级的构造函数接受参数,并且你希望指定它们,则可以使用参数调用。此外,如果父级的构造函数接受参数,并且没有默认的无参数