Java中构造函数内的声明

时间:2015-05-24 10:19:26

标签: java constructor

Java中接受以下内容吗? 我知道它编译,但它是否在Java中被接受,或者我应该将代码更改为其他内容?

谢谢!

public class Line extends Shape {

    public Line(int x1, int x2, int y1, int y2, Color myColor) {
        super(x1, x2, y1, y2, myColor);

        Point p1 = new Point(this.getX1(),this.getY1());
        Point p2 = new Point(this.getX2(),this.getY2());
    }

2 个答案:

答案 0 :(得分:4)

如果要在构造函数外使用变量p1p2,则必须将其声明为类级别变量,如此

Point p1;
Point p2;
public Line(int x1, int x2, int y1, int y2, Color myColor) {
    super(x1, x2, y1, y2, myColor);

    p1 = new Point(this.getX1(),this.getY1());
    p2 = new Point(this.getX2(),this.getY2());
}

否则罚款。

答案 1 :(得分:3)

  

p1,p2 - 表示线点......问题是我想在某些对象的方法中使用这些点。

然后你必须在构造函数之外声明它们;如果你在构造函数中声明它们 ,那么它们就是局部变量。与任何函数中的局部变量一样,它们不在函数外的范围内。 ("功能" ="构造函数或方法")

你可以在构造函数中初始化它们,但你必须在外面声明它们:

public class Line extends Shape {
    private Point p1; // You may or may not want the `private`, it...
    private Point p2; // ...depends what you're going to do with them

    public Line(int x1, int x2, int y1, int y2, Color myColor) {
        super(x1, x2, y1, y2, myColor);

        this.p1 = new Point(this.getX1(),this.getY1());
        this.p2 = new Point(this.getX2(),this.getY2());
    }

    // ...
}

注意:访问上述实例字段可以使用或不使用前面的this.来完成。 (例如,this.p1 = new ...p1 = new...都有效。)我总是使用this.,以便在查看代码时很容易辨别,我是否正在使用实例字段或局部变量;我的IDE还可以通过自动完成帮助我。不过,我想我可能是那里的少数人。

关于是否在构造函数外部或内部进行初始化的问题,让我们讨论在构造函数外部编写的初始化何时实际完成,这可能是不明显的:

class A { 
    int x;
    int y;

    public A(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return this.x;
    }

    public int getY() {
        return this.y;
    }
}
class B extends A {
    private ImmutablePoint p = new ImmutablePoint(this.getX(), this.getY());

    public B(int x, int y) {
        super(x, y);
        System.out.println("Hello from B");
    }

    public Point getP() {
        return this.p;
    }
}

看起来像初始化发生在构造函数被调用之前(无论如何)。那不是发生了什么。编译器为类B生成的字节代码如下所示:

// Reconstituted version of the bytecode for our B above
class B extends A {
    private ImmutablePoint p;

    public B(int x, int y) {
        super(x, y);
        this.p = new ImmutablePoint(this.getX(), this.getY()); // <== Inserted
        System.out.println("Hello from B");
    }

    public Point getP() {
        return this.p;
    }
}

注意它如何插入初始化逻辑到构造函数中。

以下是在构造函数中编写初始化的一些原因,而不是声明的一部分:

  1. 如果你需要使用构造函数中唯一可用的信息(一个不会成为对象状态一部分的参数),你别无选择,你必须在构造函数中进行初始化。例如,除A参数外,x无法初始化其x字段。

  2. 如果您需要在不同的构造函数中进行不同的初始化。同样,你别无选择,只能在构造函数中进行初始化,而不是使用声明。

  3. (这是主观。)清晰度。由于初始化代码是在调用super之后以及构造函数中的任何其他内容之前运行的,因此在源代码中将其写入有助于清晰。

  4. 有一个参数,用于在构造函数外部编写初始化,声明:

    1. 如果你有多个构造函数并且初始化逻辑对于所有构造函数都是相同的,那么使用声明编写它只允许你只编写一次并重用它。 (你也可以通过在你的构造函数中调用一个方法来做到这一点,但是有些人对此不以为然。)但是,我可以选择这样做,我将在下面标记。
    2. 让我们在B

      的背景下看一下
      class B extends A {
          private ImmutablePoint p = new ImmutablePoint(this.getX(), this.getY());
      
          public B(int x, int y) {
              super(x, y);
              System.err.println("Hello from B");
          }
      
          public B(int x, int y, String msg) {
              super(x, y);
              System.out.println(msg);
          }
      
          public Point getP() {
              return this.p;
          }
      }
      

      现在我们有两个构造函数,它们使用一个参数或使用默认消息执行稍微不同的事情(System.errSystem.out。)编译器生成的字节码实际上是这样做的:

      // Reconstituted version of the bytecode for our B above
      class B extends A {
          private ImmutablePoint p;
      
          public B(int x, int y) {
              super(x, y);
              this.p = new ImmutablePoint(this.getX(), this.getY()); // <== Inserted
              System.err.println("Hello from B");
          }
      
          public B(int x, int y, String msg) {
              super(x, y);
              this.p = new ImmutablePoint(this.getX(), this.getY()); // <== Inserted
              System.out.println(msg);
          }
      
          public Point getP() {
              return this.p;
          }
      }
      

      因此,在宣言中将初始化写入一个地方可能是有益的。

      这是一种风格选择;另一种方法是使用公分母构造函数

      class B extends A {
          private ImmutablePoint p;
      
          private B(int x, int y) {
              super(x, y);
              this.p = new ImmutablePoint(this.getX(), this.getY());
          }
      
          public B(int x, int y) {
              this(x, y);
              System.err.println("Hello from B");
          }
      
          public B(int x, int y, String msg) {
              this(x, y);
              System.out.println(msg);
          }
      
          public Point getP() {
              return this.p;
          }
      }
      

      最后:Java还有初始化块,它们是在任何构造函数之外编写的初始化代码,但是以类似方法的方式:

      class B extends A {
          private ImmutablePoint p;
      
          // Instance initializer block:
          {
              this.p = new ImmutablePoint(this.getX(), this.getY());
          }
      
          public B(int x, int y) {
              super(x, y);
              System.err.println("Hello from B");
          }
      
          public B(int x, int y, String msg) {
              super(x, y);
              System.out.println(msg);
          }
      
          public Point getP() {
              return this.p;
          }
      }
      

      初始化程序块中的逻辑可能有限。

      所以你有各种各样的选择。除了 在构造函数(我之前的列表中为#1或#2)中进行初始化之外,它还是一种样式选择。