没有getter方法,不能使用对象变量

时间:2013-08-23 13:26:50

标签: java oop inheritance

我有一个abstract类,AbstractNode,以及一个扩展它的具体类 - Node。

我正在尝试"编程到界面"通过声明AbstractClass的对象并使用新的Node()实例化它们。

当我在构造函数中初始化它们后尝试在Node中使用变量时,我得到一个Null指针。但是,如果我使用getter方法,一切正常。我错过了什么?

public abstract class AbstractNode
{    
    String str;
    public abstract String getStr();
}

public class Node extends AbstractNode
{
    String str;

    public Node()
    {
        str= new String();
    }

    public String getStr()
    {
        return str;
    }
}

主要方法如下:

public static void main(String[] args)
{
    AbstractNode n= new Node();
    String nullStr= n.str;
    String regularStr= n.getStr();
}

现在,nullStr包含null引用,regularStr包含对n.str的引用。 这里发生了什么? 我可以直接访问其他不需要初始化的原始类型字段,比如int,而不需要任何getter方法。

4 个答案:

答案 0 :(得分:7)

你正在“隐藏”变量strAbstractNode有一个名为String的{​​{1}},然后str有一个不同的Node,也称为Stringstr的构造函数将空字符串分配给Node,但Node.str仍为AbstractNode.str,因为它从未被分配过。 null会返回getStr()中的值,因为它是它看到的名为Node.str的“最近”变量。您在str中的代码正在读取main,因为编译器在编译时解析其全名,并且变量AbstractNode.str的声明类型为n。删除AbstractNode中的重复String str

答案 1 :(得分:2)

  

现在,nullStr包含一个Null引用,而regularStr包含对n.str的引用。这里发生了什么?

您有两个 str个变量 - 一个在AbstractNode中声明,另一个在Node中声明。

现在n被声明为AbstractNode,所以:

String nullStr = n.str;

获取AbstractNode中声明的变量的值,而不是:

String regularStr= n.getStr();

调用Node中声明的方法,该方法返回Node中声明的变量。

你应该学习的课程:

  • 决定一个对象应该有多少个状态,并且只声明那么多变量。每当在类层次结构中有两个具有相同名称的变量时,至少会感到不舒服。如果他们真正代表不同的国家,你应该能找到不同的名字。
  • 如果您只有私有字段,则阴影变得无关紧要,因为您无法 直接访问字段。

我建议修复str中声明AbstractNode,理想情况下使其成为最终版本,然后创建一个接受其值的protected构造函数。您可能也希望拥有AbstractNode中的访问者,尽管目前还不清楚。 str也不是变量的描述性名称 - 它是节点的值吗?节点的名称?谁知道。我的课程将是这样的:

public abstract class AbstractNode {
    private final String name;

    protected AbstractNode(String name) {
        this.name = name;
    }

    public abstract String getName() {
        return name;
    }

    // Presumably some abstract methods?
}

public final class Node extends AbstractNode {
    public Node() {
        super("Some default name");
    }
}

答案 2 :(得分:1)

问题在于,当方法可以覆盖时,字段不是。

因为您将变量的类型声明为AbstractNode,所以表达式n.str引用AbstractNode中的字段,即使实际类型为Node。这是因为字段在编译时静态绑定到类型。

另一方面,方法在运行时被解析,这就是你可以覆盖它们的原因:表达式n.getStr()是根据对象的实际类型解析的。

答案 3 :(得分:0)

public String getStr()
{
    return str;
}

String regularStr= n.getStr();

此函数被覆盖,并且在运行时选择了Node类中的相应函数,因此您可以获得适当的结果。

但是当你说

String nullStr= n.str;
提取了来自AbstractNode类的变量(它为null)。注意变量是只读的,不能被覆盖,