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

发布于 2024-10-23 15:10:40 字数 693 浏览 2 评论 0原文

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

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

这...

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();
    }
}

给了我类似于无法分配最终字段 AL 的错误。

那么它被视为一个作业吗?是的?

有没有一种方法可以拆分构造函数来实现我想要的?

提前致谢。

I wanted to split the constructor of my class into parts. But I have a problem...

Is it possible to initialize a final value in a method called inside constructor? It has to be initialized directly in constructor?

This...

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();
    }
}

gives me errors similar to The final field A.L cannot be assigned.

So it is treated as an assignment? Yeah?

Is there a way of splitting constructor in order to achieve what I wanted?

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

总以为 2024-10-30 15:10:40

这个怎么样。

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()};
    }
}

How about this.

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()};
    }
}
迷荒 2024-10-30 15:10:40

您不能根据 Java 语言规范< /a>:

必须在声明它的类的每个构造函数(第 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 */
    }
}

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

You cannot do this according to the Java Language Spec:

A blank final instance variable must be definitely assigned (§16.9) at the end of every constructor (§8.8) of the class in which it is declared; otherwise a compile-time error occurs.

You can do it in the constructor because the compiler can guarantee that the constructor will only be called once per instance. The code below compiles. I just verified it:

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 */
    }
}

You cannot assign the final variables in your non-constructor method because it cannot be guaranteed to be called only once per instance.

皇甫轩 2024-10-30 15:10:40

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

不,这是不可能的。

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

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

所以它被视为一个作业?是吗?

是的!

问题是该方法可以在任何时候调用:

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

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

有没有办法拆分构造函数来实现我想要的?

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

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

Is it possible to initialize a final value in a method called inside constructor?

No it is not possible.

It has to be initialized directly in constructor?

It has to be initialized by the end of each and every constructor. The initialization can be done in the declaration or an instance initializer ... that gets executed as part of all constructors.

So it is treated as an assignment? Yeah?

Yeah!

The problem is that the method could be called at any point:

  • it could be called twice by a constructor,
  • it could be called after the object has been constructed, or
  • it could throw an exception before / after assignment, leaving it unclear whether the assignment occurred. (And the constructor could catch the exception ...)

Rather than requiring the compiler to do a complicated analysis to ensure the assignment happens once and only once during construction (and not after construction), the JLS simply forbids the assignment in that context.

Is there a way of splitting constructor in order to achieve what I wanted?

You can calculate the values in a separate method, but the actual initialization of the final must be performed in the constructors, the declaration initializer or an initializer block.

(If there were subclasses in the frame, there are other tricks that could possibly be used.)

草莓味的萝莉 2024-10-30 15:10:40

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

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

final members can only be set during initialisation of the instance. So you can initialize final fields when you declare it, in an initialization block or in a constructor. Why don't you make getFirstLine a private constructor:

private A(Scanner scanner)
{
    this.L = scanner.nextInt();
    this.D = scanner.nextInt();
    this.N = scanner.nextInt();
}
菩提树下叶撕阳。 2024-10-30 15:10:40

好的,这就是我受到答案启发后所做的:

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);
    }
}

我创建了负责读取输入的私有静态类。
现在应该更符合逻辑地将其划分为单独的部分。

OK, that's what I've done after being inspired by answers:

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);
    }
}

I've made private static class that is responsible for reading input.
Now it should be more logically divided into separate parts.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文