0

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?

9
  • 6
    Read the error message. It is nothing to do with your static block, but because you have a final field that your constructor doesn't initialise. Commented Jan 30, 2022 at 6:55
  • isMove is final - what means your noarg ctor is invalid. Commented Jan 30, 2022 at 6:56
  • @tgdavies I removed final keyword. Commented Jan 30, 2022 at 6:58
  • @BoristheSpider I understood removing the final keyword. This is because initialization must be preceded. Commented Jan 30, 2022 at 6:59
  • Better to initialise the final field in the no-args constructor and keep it final, if immutable behaviour is what you want -- and presumably you had a reason for making it final to start with? Commented Jan 30, 2022 at 7:01

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

I solved it by attaching static to the field.
1

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

Comments

-1

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

3 Comments

it may work, but making a field static just because it works is a (bad) workaround. It should be done so if it reflects the use case, data design, Object Oriented concepts, ... (if the field should be a class member only than it should be declared static) ((I did not understand the second paragraph at all))
All your instances now share a single isMove field.
I understood. Single tone means nothing anymore. @Boris the Spider

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.