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

Java 我可以通过调用类方法初始化最终变量吗?,java,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 insta

我正在编写一个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方法中

我正在使用公共构造函数初始化price

我正在其他类中初始化该类,如下所示:

Car car = Car.getInstance(price);
在这里,我验证了price对象和price.getAmount都不是null

谁能告诉我我做错了什么? 谢谢

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


这里的答案摘录如下:

没有什么内在的问题

private final Wheel WHEEL_TYPE = getWheelType();
但是,一般来说,正如中所建议的,当您这样做时,应该调用不能被重写的方法—final方法、静态方法、私有方法或final类中的方法

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


我建议您在分配给price之后,只需将分配给WHEEL_TYPE移动到构造函数内部。

如Ed所述,您的price是一个实例变量,它在实例方法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);    

那么,当您尝试它时,会发生什么呢?您可能需要考虑何时执行字段初始值设定项,而何时this.price=p;构造函数体中的语句被称为…WHEEL\u TYPE=getWheelType;'应该有用。您也不能在声明中初始化“wheel”,请参阅并在构造函数中进行初始化。您可以这样做:private final wheel\u TYPE=getWheelType@resueman请查看我的编辑如果我将赋值移动到构造函数内部,那么我无法使变量成为final,对吗?@TheGuest-当然可以。最终字段可以在构造函数中分配一次。如果有多个构造函数,每个构造函数都必须确保字段只分配一次,要么在构造函数体中,要么调用另一个构造函数。我想知道这是一个糟糕的设计,还是可以遵循。因为我的项目是纯独立的java项目,没有spring,没有ejb,没有struts,没有jdbc等等;只有java@TheGuest-将复杂的初始化逻辑从构造函数中移到类似的辅助方法中是非常常见的,也是非常精细的设计。唯一的问题是编译器不会跟踪这些调用,以确保最终的方法只被指定一次;赋值必须在编译器期望的地方完成:在构造函数、实例内初始值设定项或实例内初始值设定项块中。