将构造函数方法拆分为部分 - 最终值的问题

时间:2011-03-19 02:42:12

标签: java constructor final

我想将我班级的构造函数分成几部分。但我有一个问题......

是否可以在构造函数内部调用的方法中初始化最终值?它必须直接在构造函数中初始化?

此...

import java.util.Scanner;

public final class A
{
    private final int L;
    private final int D;
    private final int N;

    public A()
    {
        Scanner scanner = new Scanner(System.in);
        this.getFirstLine(scanner);

        /* the rest of the constructor method */
    }

    private void getFirstLine(Scanner scanner)
    {
        this.L = scanner.nextInt();
        this.D = scanner.nextInt();
        this.N = scanner.nextInt();
    }
}

给我的错误类似于The final field A.L cannot be assigned

所以它被视为一项任务?是吗?

有没有办法拆分构造函数以达到我想要的效果?

提前致谢。

5 个答案:

答案 0 :(得分:3)

根据Java Language Spec

,您无法执行此操作
  

必须在声明它的类的每个构造函数(第8.8节)的末尾明确赋值空白的最终实例变量(第16.9节);否则会发生编译时错误。

您可以在构造函数中执行此操作,因为编译器可以保证每个实例只调用一次构造函数。下面的代码编译。我刚刚验证了它:

import java.util.Scanner;

public final class A
{
    private final int L;
    private final int D;
    private final int N;

    public A()
    {
        Scanner scanner = new Scanner(System.in);
        this.L = scanner.nextInt();
        this.D = scanner.nextInt();
        this.N = scanner.nextInt();

        /* the rest of the constructor method */
    }
}

您无法在非构造函数方法中分配最终变量,因为无法保证每个实例只调用一次。

答案 1 :(得分:2)

最终成员只能在实例初始化期间设置。因此,您可以在声明它时,在初始化块或构造函数中初始化最终字段。为什么不将getFirstLine设为私有构造函数:

private A(Scanner scanner)
{
    this.L = scanner.nextInt();
    this.D = scanner.nextInt();
    this.N = scanner.nextInt();
}

答案 2 :(得分:2)

这个怎么样。

import java.util.Scanner;

public final class A {

    private final int l;
    private final int d;
    private final int n;

    public A() {
        Scanner scanner = new Scanner(System.in);
        int[] list = this.getFirstLine(scanner);
        l = list[0];
        d = list[1];
        n = list[2];

        /* the rest of the constructor method */
    }

    private int[] getFirstLine(Scanner scanner) {
        return new int[]{scanner.nextInt(), scanner.nextInt(), scanner.nextInt()};
    }
}

答案 3 :(得分:2)

  

是否可以在构造函数内部调用的方法中初始化最终值?

不,这是不可能的。

  

必须直接在构造函数中初始化?

必须在每个构造函数的末尾初始化它。初始化可以在声明或实例初始化器中完成......它将作为所有构造函数的一部分执行。

  

所以它被视为一项任务?是吗?

呀!

问题是可以随时调用方法:

  • 它可以被构造函数调用两次,
  • 可以在构造对象之后调用它,或者
  • 它可能会在分配之前/之后抛出异常,从而不清楚分配是否发生。 (并且构造函数可以捕获异常......)

而不是要求编译器进行复杂的分析以确保在构造期间(而不是在构造之后)只进行一次赋值,JLS只是禁止在该上下文中进行赋值。

  

有没有办法拆分构造函数以达到我想要的效果?

您可以在单独的方法中计算值,但final的实际初始化必须在构造函数,声明初始值设定项或初始化程序块中执行。

(如果框架中有子类,则可能会使用其他技巧。)

答案 4 :(得分:0)

好的,这就是我在得到答案后的所作所为:

import java.util.Scanner;

public final class A
{
    private static final Scanner scanner = new Scanner(System.in);

    private static class FirstLine
    {
        public static int[] get()
        {
            return new int[]
            {
                A.scanner.nextInt(), 
                A.scanner.nextInt(), 
                A.scanner.nextInt()
            };
        }
    }

    private final int L;
    private final int D;
    private final int N;

    public A()
    {
        int[] valuesScanned = FirstLine.get();
        this.L = valuesScanned[0];
        this.D = valuesScanned[1];
        this.N = valuesScanned[2];
    }

    /*JUST TO TEST*/
    public static void main(String[] args)
    {
        A test = new A();
        System.out.println(test.L);
        System.out.println(test.D);
        System.out.println(test.N);
    }
}

我制作了私有静态类,负责读取输入。 现在它应该在逻辑上划分为不同的部分。