1

I'm learning Java and I have encountered a behaviour that I don't understand. All similar topics I have found here provided walkaround with initialization with default values (which I happily used) but no one has explained why the following approach generates errors.

To understand Java better, I have written the code below just to isolate the problematic part, so please focus on the error I'm asking about - I know this code does not make much sense.

public class Test {

public static void main(String[] args) {
    int value;
    ValueContainer valueContainer;
    boolean isInputLegal = false;

    while (!isInputLegal) {
        Scanner scanner = new Scanner(System.in);
        try {
            System.out.print("Set value ");
            value = scanner.nextInt();
            isInputLegal = true;
        } catch (NumberFormatException | InputMismatchException e) {
            scanner.nextLine();
            isInputLegal = false;
        }

        if (isInputLegal) {
            valueContainer = new ValueContainer(value);
        }
    }
    valueContainer.printValue();
}
}

class ValueContainer {

int value;

public ValueContainer(int value) {
    this.value = value;
}

public void printValue() {
    System.out.println(value);
}
}

The error appears in line valueContainer = new ValueContainer(value); and in line valueContainer.printValue();

Things I have tried:

  1. I thought maybe there is some kind of exception I am missing, so I replaced catch (NumberFormatException | InputMismatchException e) with catch (Exception e). Didn't help.

  2. I thought maybe the compiler thinks the loop can go infinite and still not provide initialization, so I added a counter to the loop, which stops it after 1000 iterations and inserts some default values. Didn't help.

I understand that this error shows up usually when the programmer makes a mistake and leaves a path that leads to usage of initialized value, but I am 90% percent positive this is not the case here.

Matjag
  • 91
  • 7
  • 1
    Java sees that `value` was initialized only in try section, which means there is a risk that in case of exception being thrown its initialization may not occur. Also Java doesn't pay attention to what `if` conditions are and what state they represent, so despite the fact that `if(isInputLegal)` makes sense for human be sure that `value` was initialized properly, for compiler it is seen as `if(someConditionWhichIDon'tReallyCare)`. – Pshemo Nov 04 '18 at 10:04
  • In other words compiler is not that smart yet to pay attention to what conditions are (well, maybe except part which handles constants values are known at compilation time) – Pshemo Nov 04 '18 at 10:04

1 Answers1

-1

Try initialising your value, so instead of writing:int value; write: int value = 0, also try and initialise your ValueContainer with the default constructor, and set it's value with a setter

public static void main(String[] args) {
  int value = 0;
  ValueContainer valueContainer = new ValueContainer();
  boolean isInputLegal = false;

  while (!isInputLegal) {
    Scanner scanner = new Scanner(System.in);
    try {
        System.out.print("Set value ");
        value = scanner.nextInt();
        isInputLegal = true;
    } catch (NumberFormatException | InputMismatchException e) {
        scanner.nextLine();
        isInputLegal = false;
    }

    if (isInputLegal) {
        valueContainer.setValue(value);
    }
  }
  valueContainer.printValue();
}

This should work (with adding a setter method in your ValueContainer class)

Stan Fieuws
  • 162
  • 1
  • 2
  • 13