1

我有两个类,父类和子类,代码如下:

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.
4

5 回答 5

2

该声明

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。如果您需要任何有关解决具体继承问题的提示,请随时通知我。

PS:Java 教程中的隐藏字段

于 2013-06-05T11:05:13.480 回答
0

如果您指的是注释掉的行

super.word =  "Simple field assignment.";

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

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

于 2013-06-05T10:44:39.743 回答
0

尝试将孩子的定义更改为以下

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" - 所有不是声明的代码都必须放在初始化块内。见这里

于 2013-06-05T10:49:10.047 回答
0

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

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

  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.
于 2013-06-05T10:56:56.447 回答
0
    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

于 2013-06-05T11:07:05.187 回答