【问题标题】:How to assign a value for inherited field in Java?如何在 Java 中为继承的字段赋值?
【发布时间】:2013-06-05 10:39:50
【问题描述】:

我有两个类,Parent 和 Child,代码如下:

public class Parent {
    public String word;
}

父类只包含一个公共字段。

public class Child extends Parent {

//super.word = "Simple field assignment.";
{
    System.out.println(word);
}
String word2 = super.word = "Field assignment.";

{
    System.out.println(word);
    super.word = "Initialization block.";
    System.out.println(word);
}

public Child(){
    super.word="Constructor.";
    System.out.println(word);
}
}

我想问的问题是为什么不允许简单的赋值'super.word = "word"',但是下面的双重赋值是可以的。有人能具体说明后者到底发生了什么吗?

还有为什么初始化块内允许赋值?

如果我运行以下主程序:

public class FieldTest {
public static void main (String[] args)
{
    Child c = new Child();
    System.out.println("1: "+c.word);
    System.out.println("2: "+c.word2);
}
}

结果是:

null
Field assignment.
Initialization block.
Constructor.
1: Constructor.
2: Field assignment.

【问题讨论】:

  • 删除super。您只需要this.wordword。该字段是继承的。
  • 删除 super 或将其替换为 this 不会改变任何内容。
  • 那是评论而不是答案。

标签: java inheritance initialization field


【解决方案1】:

声明

super.word = "Simple field assignment.";

在构造函数、初始化程序或方法之外不是有效的 Java 语法。声明时可以初始化一个字段

public class Parent {
   public String word = "Don't use mutable public fields!"
}

并在子类的构造函数或初始化器中修改它们

public class Child extends Parent {
   public Child() {
      super();
      this.word = "Don't mutate parent state like this...";
   }
}

super 关键字与字段组合仅在隐藏超类的变量时有用:

public class Child extends Parent {
    public String word = "Only for demonstration purposes - do not hide fields!";

    public Child() {
        super.word = "Mutating the hidden field.";
    }
}

正如您从代码中看到的那样,这不应该最终投入生产 - 我不记得在我的职业生涯中使用过一次super.someField。如果您不确定某些构造,请使用 CheckStyle 和 FindBugs。如果您需要任何有关解决具体继承问题的提示,请随时联系我。

附注:Hiding Fields in the Java Tutorials.

【讨论】:

    【解决方案2】:

    如果您指的是已注释掉的行

    super.word =  "Simple field assignment.";
    

    那一行是错误的,因为它是一个语句,直接在类体内“裸”出现。在那个位置,只允许声明。实例初始化器就是这样一个例子。

    另外一点,您对super 的使用完全是多余的。您可以在不影响语义的情况下删除它,或者您可以使用 this 代替,再次获得相同的结果。

    【讨论】:

      【解决方案3】:

      尝试将 child 的定义更改为以下

      public class Child extends Parent {
      {
          super.word = "Simple field assignment.";
          System.out.println(word);
      }
      String word2 = super.word = "Field assignment.";
      
      {
          System.out.println(word);
          super.word = "Initialization block.";
          System.out.println(word);
      }
      
      public Child(){
          super.word="Constructor.";
          System.out.println(word);
      }
      }
      

      即将 super.word = "Simple field assignment" 放在块内 - 所有不是声明的代码都必须放在初始化程序块内。见here

      【讨论】:

        【解决方案4】:

        第一个赋值是不允许的,因为它直接在类内部,而另一个在一个块内,所以没关系。

        要回答第二个问题,让我们看看发生了什么:

        1. Child正在被实例化,所以第一个块被执行,打印word,它还没有被初始化,所以它是null
        2. 属性word2被赋予了word的值,已经被赋予了Field assignment.的值,它们都包含这个字符串。
        3. word 打印:Field assignment.
        4. word 的值是 Initialization block.
        5. word 打印:Initialization block.
        6. Child 的构造函数被调用,word 被赋予值 Constructor. 并且正在被打印。
        7. 正在打印word 的值:Constructor.
        8. 正在打印word2 的值:Field assignment.

        【讨论】:

          【解决方案5】:
              class Check {
              //static block
              static {
                  System.out.println("hello from Static");
              }
              //object block
          
              {
                  System.out.println("This is my object block");
              }
          
              public static void main(String args[]) {
                  System.out.println("hello from main");
                  Check obj = new check();
              }
          }
          

          这是输出:

          hello from Static
          hello from main
          This is my object block
          

          每当类加载到 JVM 时,都会执行静态块。而对象块或构造器块将在您创建所述对象的实例时运行。

          更多信息请访问

          http://www.jusfortechies.com/java/core-java/static-blocks.php http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-02-06
            • 2012-08-28
            • 2013-01-09
            • 2017-09-20
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多