Quack
Quack

Reputation: 740

How to initialize a value when creating an object in a static block

When creating the Racing class in ApplicationTest, I want to hand over the FixNumberBehavior class to the argument.

As shown below, to pass the argument to initialize FixNumberBehavior, but cannot pass the class field value to the static block.

The error message is as follows.

Variable 'isMove' might not have been initialized

FixNumberBehavior.java

public class FixNumberBehavior implements CarMoveBehavior {

  private final boolean isMove;
  private static FixNumberBehavior fixNumberBehavior;

  static {
      fixNumberBehavior = new FixNumberBehavior(); //error
  }

  public FixNumberBehavior(final boolean isMove) {
      this.isMove = isMove;
  }

  @Override
  public boolean moveBehavior() {
     return isMove;
  }
}

Racing.java

public class Racing {

private List<Car> cars;
private CarMoveBehavior carMoveBehavior;

public Racing(List<Car> cars, final CarMoveBehavior carMoveBehavior) {
    this.cars = cars;
    this.carMoveBehavior = carMoveBehavior;
}

public List<Car> getCars() {
    return cars;
}

public void drive() {
    cars.stream()
        .forEach(car -> racingCondition(car));
}

private void racingCondition(Car car) {
    if (carMoveBehavior.moveBehavior()) {
        car.moveForward();
     }
  }
}

ApplicationTest

 @ParameterizedTest
    @CsvSource({"a,aa,aaa"})
    void fixRandomNumberTest(String one, String two, String three) {
        final List<Car> cars = Arrays.asList(new Car(one), new Car(two), new Car(three));
        Racing racing = new Racing(cars, new FixNumberBehavior(true));
        racing.drive();
        racing.drive();
        assertAll(
            () -> assertThat(cars.get(0).getStep()).isEqualTo(2),
            () -> assertThat(cars.get(1).getStep()).isEqualTo(2),
            () -> assertThat(cars.get(2).getStep()).isEqualTo(2)
        );
    }

How can I initialize an object in the static block?

Upvotes: 0

Views: 112

Answers (3)

Pshemo
Pshemo

Reputation: 124275

I am not sure why you want to overcomplicate things by

  • providing no-argument constructor when you already have constructor in which you let client decide if created instance of FixNumberBehavior will set isMove to true or false.
  • changing (in your answer) isMove from being final to being static. Those two keywords have different purpose:
    • final prevents reassigning new value to it
    • static makes this field a class field, not instance field, so even if you create two instances of FixNumberBehavior there will be only one isMove variable which they both will use (so you can't preserve in one instance state like isMove=true and in other state isMove=false).

What you are looking for is probably simply

public class FixNumberBehavior implements CarMoveBehavior {

    private final boolean isMove;

    private static FixNumberBehavior fixNumberBehavior = new FixNumberBehavior(true);
                                                     //set value you want here ^^^^

    public FixNumberBehavior(final boolean isMove) {
        this.isMove = isMove;
    }

    @Override
    public boolean moveBehavior() {
        return isMove;
    }
}

Upvotes: 1

Quack
Quack

Reputation: 740

I solved it by attaching static to the field.

Objects created in the static block are not identified when compiling. Therefore, the argument value to be transferred to the object you create in the static block must also be processed statistically.

package racingcar.model.domain;

public class FixNumberBehavior implements CarMoveBehavior {

    private static boolean isMove;
    private static FixNumberBehavior fixNumberBehavior;

    static {
        fixNumberBehavior = new FixNumberBehavior(isMove);
    }

    private FixNumberBehavior() {

    }

    public static FixNumberBehavior getInstance(){
        return fixNumberBehavior;
    }

    public FixNumberBehavior(final boolean isMove) {
        this.isMove = isMove;
    }

    @Override
    public boolean moveBehavior() {
        return isMove;
    }
}

Upvotes: -1

ash
ash

Reputation: 5165

The problem is FixNumberBehavior has a final field that must be set in the constructor, or in an assignment on the field definition line.

While there is a constructor that takes a value for that field, the static block is not using that constructor, but instead a no-arg constructor.

Pass the value for that final field (isMove) in the new statement.

Upvotes: 1

Related Questions