0

在 Java 中工作。

我有一个抽象类:

public abstract class Foo {
    protected Logger log = null;

    // other stuff

    public boolean isLoggerSet() {
        return (this.log != null) ? true : false;
    }
}

现在我像这样扩展这个类:

public class Bar extends Foo {
    public Bar() {
        this.log = Logger.getLogger(Bar.class);
    }

    public void someMethod(String[] args) {
        Bar b = new Bar();
        if(b.isLoggerSet()) {
            // do some stuff
        }
    }
}

The question:我的 Bar.class 实际上是指super.log即使我打电话this.log,因为 Bar 没有它自己的局部变量调用log?或者实现该isLoggerSet()方法的正确方法是使其抽象并强制 Bar.class 在它的本地副本上实现它,log因为它已被扩展?

基本上我不得不this.log在我的 Foo 类中说,因为它指的是它自己。但是在 Bar 类中我希望能够进行空检查log,我应该改为super.log =在 Bar.class 中使用吗?

4

5 回答 5

3

您尚未将 Logger 设置为static,而是设置为protected。在这种情况下,无论您使用super还是this,它们都指向完全相同的变量。

于 2013-05-21T19:13:31.337 回答
2

如果在类层次结构中只有一个属性被调用log,那么无论你说this.logor super.log,它都会引用同一个属性——唯一的一个!

于 2013-05-21T19:13:03.567 回答
2

this.log是一样的super.loglog因为继承自 Foo,所以只有一个变量。唯一需要更改的是:this.isLoggerSet()应替换为b.isLoggerSet() You cannot call non static method inside static method

于 2013-05-21T19:17:32.117 回答
2

类是制作对象的蓝图。在您的情况下,“Bar”的蓝图添加到“Foo”中定义的蓝图(它添加到“Object”中定义的蓝图)。

不要让基类混淆:从概念上讲,这里编译器将所有基类拉到一个顶级组合类中(忽略“对象”基类):

public class Bar {

    protected Logger log = null;

    public boolean isLoggerSet() {
        return (log != null) ? true : false;
    }

    public Bar() {
        log = Logger.getLogger(Bar.class);
    }

    public void someMethod(String [] args) {
        Bar b = new Bar();
        if(b.isLoggerSet()) {
            // do some stuff
        }
    }

}

你会像这样练习你的代码:

Bar x = new Bar();
x.isLoggerSet(); // Returns true since Bar() constructor just set it
x.someMethod(args);

第一行在内存中创建了一个类型为“Bar”的新对象。该对象有一个指向“Logger”对象的单个指针,该对象在第一行的 Bar 构造函数中使用“new Bar()”进行设置。

下一行检查“isLoggerSet”。假设“getLogger”返回一个活动对象,那么“isLoggerSet”将始终返回 true。

最后一行调用“x.someMethod(args)”。此方法创建一个新的“Bar”对象(其构造函数设置其“log”指针)。因此“b.isLoggerSet()”也会通过这里。

于 2013-05-21T21:15:04.297 回答
1

这是一个稍作修改的示例:

public abstract class Foo {
    protected String name;

    public Foo() {
        name = "Mr. Foo";
    }
}

public class Bar extends Foo {
    protected String name;

    public Bar() {
        name = "Mr. Bar";
    }

    public void someMethod() {
        System.out.println("this.name=" + this.name);
        System.out.println("super.name=" + super.name);
    }

    public static void main(String[] args) {
        Bar bar = new Bar();
        bar.someMethod();
    }
}

输出:

this.name=Mr. Bar
super.name=Mr. Foo

因此,有两个变量称为“名称”,每个类中都有一个。要从子类中访问超类中的那个,您需要使用“super.name”。

创建 Bar() 时,Java 检查对超类的构造函数的 super(...) 调用作为构造函数的第一行。如果它不存在(如上),则 'super();' 作为构造函数的第一行被无形地插入。所以我可以写:

....
    public Bar() {
        super();
        name = "Mr. Bar";
    }
....

结果相同。但是,这不是必需的,如果您自己不调用超级构造函数,Java 会为您插入对默认构造函数的超级调用。以这种方式强制执行构造函数链接。

如果您想自己调用超级构造函数,也可以调用非默认构造函数,例如:

    public abstract class Foo {
        protected String name;

        public Foo() {
            name = "Mr. Foo";
        }

        public Foo(String name) {
            this.name = name;
        }
    }

    public class Bar extends Foo {

        public Bar() {
            super("Mr. Bar");
        }

        public void someMethod() {
            System.out.println("this.name=" + this.name);
            System.out.println("super.name=" + super.name);
        }

        public static void main(String[] args) {
            Bar bar = new Bar();
            bar.someMethod();
        }
    }

输出:

this.name=Mr. Bar // refers to 'name' inherited from Foo
super.name=Mr. Bar // refers to 'name' in superclass, set by the String constructor
// so these both refer to the same variable in this example

请注意,在最后一个示例中没有调用 Foo 的默认构造函数。

于 2013-05-21T20:00:57.987 回答