简体   繁体   中英

Initializing final fields in Java

I have a class with lots of final members which can be instantiated using one of two constructors. The constructors share some code, which is stored in a third constructor.

// SubTypeOne and SubTypeTwo both extend SuperType

public class MyClass {
    private final SomeType one;
    private final SuperType two;


    private MyClass(SomeType commonArg) {
        one = commonArg;
    }

    public MyClass(SomeType commonArg, int intIn) {
        this(commonArg);

        two = new SubTypeOne(intIn);
    }

    public MyClass(SomeType commonArg, String stringIn) {
        this(commonArg);

        two = new SubTypeTwo(stringIn);
    }

The problem is that this code doesn't compile: Variable 'two' might not have been initialized. Someone could possibly call the first constructor from inside MyClass, and then the new object would have no "two" field set.

So what is the preferred way to share code between constructors in this case? Normally I would use a helper method, but the shared code has to be able to set final variables, which can only be done from a constructor.

How about this? (Updated for changed question)

public class MyClass {

    private final SomeType one;
    private final SuperType two;

    public MyClass (SomeType commonArg, int intIn) {
        this(commonArg, new SubTypeOne(intIn));
    }

    public MyClass (SomeType commonArg, String stringIn) {
        this(commonArg, new SubTypeTwo(stringIn));
    }

    private MyClass (SomeType commonArg, SuperType twoIn) {
        one = commonArg;
        two = twoIn;
    }
}

You need to make sure that in every constructor you are initializing all final variables. What I would do is have one constructor that initializes all the variables and have all the other constructor call that, passing in null or some default value if there is a field that they are not given a value for.

Example:

public class MyClass {
    private final SomeType one;
    private final SuperType two;

    //constructor that initializes all variables
    public MyClas(SomeType _one, SuperType _two) {
        one = _one;
        two = _two;
    }

    private MyClass(SomeType _one) {
        this(_one, null);
    }

    public MyClass(SomeType _one, SubTypeOne _two) {
        this(_one, _two);
    }

    public MyClass(SomeType _one, SubTypeTwo _two) {
        this(_one, _two);
    }
}

All you need to do is ensure that "two" gets initialized. In the first constructor, just add:

two = null;

unless there's some other value you'd like to give it in the event that only the first constructor is called.

您收到此错误,因为如果您调用了MyClass(SomeType oneIn) ,则two未初始化。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM