-1
import java.util.*;

class Employee {
    public void evaluateStatus(String empID, int empAge) {
        final int age = 40;
        class Rank {
            public char getRank (String empID) {
                System.out.print("\n\tGetting rank of employee: "+empID);
                if (empAge >= 40 && empAge <= 60)
                    return 'B';
                else if (empAge >= 61)
                    return 'A';
                else
                    return 'C';
            }
        }

        if (empAge >= age) {
            Rank objRank = new Rank();
            char rank = objRank.getRank(empID);
            if (rank == 'A' || rank == 'B' || rank == 'C') {
                System.out.print("\n\tEmployee rank is: "+ rank);
                System.out.print("\n\tStatus: Eligible for upgrade.");
            } else {
                System.out.print("\n\tStatus: not eligible for upgrade.");
            }
        } else {
            System.out.print("\n\tStatus: not eligible for upgrade.");
        }
    }

    public static void main(String[] args) {
        if (args.length == 2) {
            Employee objEmp1 = new Employee();
            objEmp1.evaluateStatus(args[0], Integer.parseInt(args[1]));
        } else {
            System.out.print("\n\tError!");
        }
    }
}

I get the following error:

Y:\student\Desktop\Atif>javac Employee.java

Employee.java:13: error: local variable empAge is accessed from within inner class; needs to be declared final
                                if (empAge >= 40 && empAge <= 60)
                                    ^ Employee.java:13: error: local variable empAge is accessed from within inner class; needs to be declared final
                                if (empAge >= 40 && empAge <= 60)
                                                    ^ Employee.java:15: error: local variable empAge is accessed from within inner class; needs to be declared final
                                else if (empAge >= 61)  
                                    ^ 3 errors
Bista
  • 7,869
  • 3
  • 27
  • 55
Skaper
  • 27
  • 6
  • There is a mistake in the variable used. You set `age` final but use `empAge` in the inner class. – AxelH Dec 29 '16 at 12:32
  • If I run the given example in Eclipse, it would work without any error. – fabfas Dec 29 '16 at 12:33
  • 2
    Possible duplicate of [Why are only final variables accessible in anonymous class?](http://stackoverflow.com/questions/4732544/why-are-only-final-variables-accessible-in-anonymous-class) – Tom Dec 29 '16 at 13:13
  • Or: [Local variable access to inner class needs to be declared final](//stackoverflow.com/q/27558425) // or: [Variable is accessed within inner class. Needs to be declared final](//stackoverflow.com/q/14425826) (or many other questions). – Tom Dec 29 '16 at 13:14
  • You get "error: local variable empAge is accessed from within inner class; needs to be declared final" because you made an error - you accessed a local variable, `empAge`, from within an inner class, and the variable is not final. The inner class reference to the outer variable has to have definite knowledge of the variable's value because it can't know when it will be invoked. If the variable can change, the inner code would go crazy, so the variable must be final. – Lew Bloch Dec 29 '16 at 20:38

2 Answers2

2

The answer is pretty much because JLS 8.1.3 says so:

[...]

Any local variable, formal parameter, or exception parameter used but not declared in an inner class must be declared final.

[...]

In this particular case empAge is your formal parameter. As it is used within the inner class, but was declared within the method Employee#evaluateStatus it has to be declared as final. But as you never reassign empAge declaring it as final wouldn´t do any harm.

As a sidenote:

As your class Rank basicly only consists of a single method i´d rather declare this as static char getRank() at the scope of Employee, if you are not planning to make use of the Rank class itself.

Community
  • 1
  • 1
SomeJavaGuy
  • 7,307
  • 2
  • 21
  • 33
0

Your code would not compile with version 1.7 but will compile with 1.8. The memory management for Java 1.7 is different then 1.8

Method Local variables are alloted in Stack and Class variables are alloted in heap.

Now when you want to use a method local variable in inner class you need to promote it to heap as it is getting used inside the class, and final variables are alloted in heap, that is the reason you need to declare it final

Now Why do we at all need to promote variables from stack to heap?

Reason: The scope of the stack is no more present after the execution of the method, but the scope of the method local inner class can be propagated beyond the method. I have modified your code where the scope of the method local inner class is propagated outside the method getRank()

Your Code(modified):

interface SuperRank{
     public char getRank(String empID);
}

class Employee
{
    public SuperRank getRank(String empID, final int empAge){
//      final int age = 40;
        class Rank implements SuperRank
        {
            public char getRank (String empID)
            {
                System.out.print("\n\tGetting rank of employee: "+empID);
                if (empAge >= 40 && empAge <= 60)
                    return 'B';
                else if (empAge >= 61)
                    return 'A';
                else
                    return 'C';
            }
        }
        return new Rank();

    }
    public void evaluateStatus(String empID, int empAge)
    {
        SuperRank rank = getRank(empID,empAge);
        char rankChar = rank.getRank(empID);
        if (rankChar == 'A' || rankChar == 'B' || rankChar == 'C')
        {
            System.out.print("\n\tEmployee rank is: "+ rankChar);
            System.out.print("\n\tStatus: Eligible for upgrade.");
        }
        else 
        {
            System.out.print("\n\tStatus: not eligible for upgrade.");
        }
    }

    public static void main(String[] args)
    {
        if (args.length == 2)
        {
            Employee objEmp1 = new Employee();
            objEmp1.evaluateStatus(args[0], Integer.parseInt(args[1]));
        }
        else
        {
            System.out.print("\n\tError!");
        }
    }
}
AkikG
  • 71
  • 3