Search Logic Blocks

Thursday, August 6, 2020

Java: Local Classes

We already know about inner class which is declared in another class and is accessed through outer class only. A local class is a class in a method, loop or block. And the local class can not be accessed outside from the method or the block where the class is declared. Local class is only visible to the method or block where it is declared. It is hidden from rest of the program.

When there is need to create a class which should not be reused and should be inaccessible to rest of the world, should be declared as a local class. Like in program below, I have a method rollDice(). rollDice() method has declared a local class Dice, which generates a random number between 1 and 6. Two instances of Dice class created and their numbers are added. Depending on the result, the text is printed. This is the simplest case, we can add more complex instructions. 
import java.util.Scanner;

public class DiceGame {
public static void main(String[] args) {
System.out.println("Mystery number should be between 2 and 12");
System.out.println("Guess the mystery number");
Scanner sc = new Scanner(System.in);
int number = sc.nextInt();
rollDice(number);
}

static void rollDice(int number) {
int tempNumber1;
tempNumber1 = 9;
//tempNumber1 = tempNumber1 + 3;
int tempNumber2 = tempNumber1 + 3;

class Dice {
int rand = 0;
int totDice = 0;
int mysteryNumber = 0;
int range = 6;

// Dice constructor
Dice() {
totDice++;
}

// Gets Random Number, if 0 then again gets the random number
void getRandomNumber() {
do {
rand = (int) (range * Math.random());
} while(rand == 0);
}

// Adds Dice number to another Dice number
void addDice(Dice d) {
mysteryNumber = rand + d.rand;
}

// Gets Random Value
int getRandValue() {
return rand;
}

// Checks if Mystery number equals to guessed number
void checkMysteryNumber() {
if(number >= 2 && number <= 12) {
int closeDiff = mysteryNumber - number;
if (mysteryNumber == number) {
System.out.println("Correct!!");
} else if ((closeDiff <= 3) && (closeDiff >= -3)) {
System.out.println("Close Enough!!");
} else if ((closeDiff > 3) || (closeDiff < -3)) {
System.out.println("Good try but not so close!!");
}
System.out.println("Mystery number is : " + mysteryNumber);
} else {
System.out.println("Wrong number!!");
}

}

void finalData() {
// Variables and parameters can be accessed but can't be changed
// tempNumber1++;
// number++;
System.out.println("Temporary Number 1 : - " + tempNumber1);
System.out.println("Parameter number - " + number);
}
}

Dice d1 = new Dice();
Dice d2 = new Dice();
d1.getRandomNumber();
d2.getRandomNumber();
d1.addDice(d2);
d1.checkMysteryNumber();

// Variables and parameters can't be changed in method itself -
// they are effectively final as they are accessed in the local class
// tempNumber1++;
// number++;
System.out.println("");
System.out.println("Final Data Accessed in class");
d1.finalData();
// tempNumber2 is not final as it is not accessed by the local class
tempNumber2 = tempNumber2 + 5;
System.out.println("Data Not Accessed in class, so it's not final");
System.out.println("Temporary Number 2 - " + tempNumber2);
}
}
And the output is:

Mystery number should be between 2 and 12
Guess the mystery number
9
Close Enough!!
Mystery number is : 8

Final Data Accessed in class
Temporary Number 1 : - 9
Parameter number - 9
Data Not Accessed in class, so it's not final
Temporary Number 2 - 17

Local class is a hidden class and can not be accessed from outside, so it has few restrictions - 
  • The local classes can access the parameters passed to the enclosing method but can not change the value of the parameters. The local class treats parameters to the enclosing method as final. 
  • The local classes can access the variables of the enclosing method, but can not change the value of the variables. The local class treats all the variables in the enclosing method as final.
  • Local / Inner classes can not have static variables.
  • The variables and parameters to be accessed by local class are effectively final. It doesn't matter if the variable declared final or not, if it is to be accessed by the local class, it has to be final. Even, the value of the variable can not be changed in the method itself outside the local class.
Above program asks the user to guess the mystery number. And then calls the method rollDice() with the number entered by the user as parameter. In method, a class named Dice is declared. Two instances of class Dice are created. Two numbers are randomly generated. The numbers are added and compared with the guessed number and prints the appropriate message.

In above example, pay close attention to comments -
//tempNumber1 = tempNumber1 + 3;
Above statement will give a compilation error as tempNumber1 is effectively final as it is accessed in the local class.
void finalData() {
// Variables and parameters can be accessed but can't be changed
// tempNumber1++;
// number++;
System.out.println("Temporary Number 1 : - " + tempNumber1);
System.out.println("Parameter number - " + number);
}
Above method is accessing variable declared in method and parameter passed to the method. They can't be changed as they are accessed by the local class.
// Variables and parameters can't be changed in method itself -
// they are effectively final as they are accessed in the local class
// tempNumber1++;
// number++;
System.out.println("");
System.out.println("Final Data Accessed in class");
d1.finalData();
Above statements are written after local class declaration and using class methods. Still, the program can't change the variable and parameter as they are still treated like final.
// tempNumber2 is not final as it is not accessed by the local class
tempNumber2 = tempNumber2 + 5;
System.out.println("Data Not Accessed in class, so it's not final");
System.out.println("Temporary Number 2 - " + tempNumber2);
But above statement is perfectly fine as the variable tempNumber2 is not accessed by local class.

The code can be accessed here at Github Link.

No comments: