0

So in C++ there is a preprocessor which replaces the pre-processor directives with values. Now my question is: JAVA Is there something like a pre-processor in Java? Now. We know that in Java the switch statement's case value must be something that is evaluated in compile-time. For example:

int month = 5;
switch(month) {
  case 1: doSth() break; 
  ... 
  case month: doSth() break; 

Now in this example I cannot use "case month:" because the value of the variable month is getting evaluated in run-time. But if I add final keyword like this:

final month = 5;

And after that if I do the same thing but with the variable that has the final keyword everything will work. Now could you explain me what is that and is this "preprocessored" code accessible for me to see?

BoSsYyY
  • 563
  • 5
  • 13
  • 4
    *JAVA Is there something like a pre-processor in Java?* **No.** There is not a Java preprocessor. The `final` keyword makes the "variable" a constant. – Elliott Frisch Nov 18 '17 at 17:14
  • often use cases like above can be modeled with `enums`. Or if you really need a dynamic case/switch statement, use some pattern library or a lambda-version of a switch statement. – Jochen Bedersdorfer Nov 18 '17 at 17:25
  • @Elliott Frisch So after compile-time in the bytecode there is no variable "month" in the memory and "5" is placed in the places where "month" was? – BoSsYyY Nov 18 '17 at 17:34
  • @BoSsYyY Yes and no. What is happening is the `final` keyword tells the compiler the variable cannot ever change, so it can be treated as a constant and used in places where a constant is required. How this happens under the covers is immaterial. – Jim Garrison Nov 18 '17 at 17:37

1 Answers1

0

So after compile-time in the bytecode there is no variable "month" in the memory and "5" is placed in the places where "month" was?

Yes and no. What is happening is the final keyword tells the compiler the variable cannot ever change, so it can be treated as a constant and used in places where a constant is required. How this happens under the covers is immaterial, but in practice the constant value will be substituted.

Now let's consider your code:

int month = 5;
switch(month) {
  case 1: doSth() break; 
  ... 
  case month: doSth() break; // compilation error

There's something not right here, because your switch variable is the same as one of your cases. The only possible path through this is the month case, so all the other cases are dead code. Maybe you meant:

int monthOfInterest = 5;
switch(month) {
  case 1: doSth() break; 
  ... 
  case monthOfInterest: doSth() break; // Still a compilation error

This looks a little better but won't compile since monthOfInterest is not a "constant expression". Here we get to your original question. Case selectors have to be either numeric literals or expressions that can be evaluated at compile time. So we change this to:

final int monthOfInterest = 5;
switch(month) {
  case 1: doSth() break; 
  ... 
  case monthOfInterest: doSth() break; // This is valid code

This "behaves" as if monthOfInterest was replaced by the constant 5. Note that this is not the same as:

final int monthOfInterest;
...
monthOfInterest = 5;
switch(month) {
  case 1: doSth() break; 
  ... 
  case monthOfInterest: doSth() break; // Oops, compilation error again

It is perfectly legal to declare a variable final and initialize it later. The compiler will ensure you set the value only once, but in this case monthOfInterest is no longer a constant expression, and this code will not compile.

One final note. consider:

final int monthOfInterest = 1;
switch(month) {
  case 1: doSth() break; 
  ... 
  case monthOfInterest: doSth() break; // Oops again, different compilation problem

This fails to compile since now you have two cases with the same value.

Jim Garrison
  • 85,615
  • 20
  • 155
  • 190