我可以通过调用类方法来初始化最终变量吗?

时间:2015-11-17 19:27:56

标签: java

我正在编写一个需要一些最终变量的java程序。 java类必须是单例对象。我无法直接初始化最终变量。这是我的代码:

 public class Car {

    private Price price = null;

    //Constructor
    public Car(Price p) {
       this.price = p;
    }

    //method to get the singleton
    private static Car instance = null;       
    public static Car getInstance(Price p) {
       if(instance == null) {
          instance = new ExcelUtil2(p);
       }
       return instance;
    }

    //declare & initialize final variable
    private final Wheel WHEEL_TYPE = getWheelType();

    //get value of the final variable
    public Wheel getWheelType() {

        Wheel wheel = Car.createWheel();

        if(price.getAmount() > 30000){
            wheel.setWheelType("Alloy");
        }else{
            wheel.setWheelType("Alluminium");
        }

        return wheel;
    }
}

我想知道我是否可以这样做:

private final Wheel WHEEL_TYPE = getWheelType();

这是我的第一个问题。

接下来就是,当我运行它时,我得到nullPointerException:

price.getAmount()

public Wheel getWheelType()方法中。

我正在使用公共构造函数初始化价格。

我在其他类中启动了这个类:

Car car = Car.getInstance(price);

在这里,我验证了price对象和price.getAmount()都不为空。

任何人都可以指导我做错了什么吗? 感谢

3 个答案:

答案 0 :(得分:5)

没有任何内在错误
private final Wheel WHEEL_TYPE = getWheelType();

一般情况下,(按照the Java tutorial中的建议),当你这样做时,你应该调用无法覆盖的方法 - final方法,static方法, private方法或final类中的方法。

但是,使用您的特定代码存在问题。在执行getWheelType()时,您正在调用price.getAmount()并在构造函数的主体中初始化price。不幸的是,对于您的设计,字段实例初始值设定项在构造函数的主体之前执行,因此在price.getAmount()初始化之前,您最终会调用price

我建议您在分配到WHEEL_TYPE后,只需将作业移至price到构造函数内部。

答案 1 :(得分:1)

  

始终允许您初始化最终变量。编译器   确保你只能做一次。

摘自答案:How final keyword works

答案 2 :(得分:1)

正如Ed所说,你的价格是一个实例变量,它在实例方法getWheelType()中使用,这是正常的。但问题是这个方法用于创建最终变量。在分配实例变量p之前分配最终变量。

如果您真的想拥有代码结构,可以考虑使用Builder模式。我的代码没有得到很好的考虑,但它会是这样的。

public class CarTwo {
   private Price price = null;
   private Builder b;
   public Builder getBuilder(){
      return b;
   }

   private final Wheel WHEEL_TYPE;

   private CarTwo(Builder b) {
      this.b = b;
      this.price = b.getPrice();
      WHEEL_TYPE = b.getWheelType();
   }

   private static CarTwo instance = null;       
   public static CarTwo getInstance(Builder builder) {
      if(instance == null) {
         instance = new ExcelUtil2(builder);
      }
      return instance;
   }

   public static class Builder{
     private Price pr;
     public Builder(Price price){
        pr = price;
     }

     public Price getPrice(){
        return pr;
     }
     public Wheel getWheelType() {
        Wheel wheel = CarTwo.createWheel();

        if(pr.getAmount() > 30000){
           wheel.setWheelType("Alloy");
        }else{
           wheel.setWheelType("Alluminium");
        }

        return wheel;
     }
  }
}

然后,您可以像这样创建CarTwo对象:

CarTwo.Builder b = new CarTwo.Builder(new Price());  
CarTwo ct = CarTwo.getInstance(b);