不应该Java禁止在构造函数中使用抽象方法吗?

时间:2017-02-11 03:38:18

标签: java oop

我刚遇到一个微妙的陷阱。考虑接下来的两个类:

/**
 * Innocent-looking example that causes trouble. See {@link B}.
 *
 */
public abstract class A  {

    abstract String someStringLeftForExtensionsToSpecify();

    public A() {
        super();
        processString(someStringLeftForExtensionsToSpecify());
    }

    void processString(String string) {
        // do complicated things with string that are shared by all extensions
        // so this could should be here.
    }
}

/**
 * Looks innocent enough, but abstract method is used in {@link A}'s constructor before
 * property is set, even though it uses property.
 */
public class B extends A {

    private int property;

    public B(int property) {
        this.property = property;
    }

    public String someStringLeftForExtensionsToSpecify() {
        if (property == 13) {
            return "Unlucky";
        }
        return "Lucky";
    }
}

似乎在构造函数中使用抽象方法应该是OOP中的禁忌。不应该Java禁止这样做,就像它禁止使用"这个"或非静态方法作为" super"的参数?我想知道这是否是一个众所周知的事情。

1 个答案:

答案 0 :(得分:0)

  

似乎在构造函数中使用抽象方法应该是   OOP中的禁忌。不应该禁止Java,就像禁止它一样   使用"这个"或非静态方法作为" super"的参数?一世   想知道这是否是一个众所周知的事情。

  

问题是Java是否应该禁止它(这是编译   在Eclipse中很好)

this作为客户端方法的参数存在问题的原因是客户端接收对尚未完全构造的对象的引用存在重大风险,即当它处于不一致状态时状态和/或其不变量不完整。编译器警告this处于无效状态。

但谁说从构造函数中调用非final方法是危险的?如果您未将this传递给该方法,则它不会接收对处于无效状态的对象的引用。

这可能有危险吗?这取决于。如果恶意客户端可以拦截对可变或安全对象的引用,那么当然。但这与整个应用程序的设计中的安全性考虑有关,而不仅仅是构造函数。

在某些情况下,构造函数甚至可能需要调用可重写的非final方法...因为多态在面向对象编程中不是禁忌。

您正在解决的真正问题是可访问性。工程师不得将任何他不希望客户有权访问的方法(包括最终或非最终方法)导出到API中。