0

I have a constructor with size as a parameter. Eclipse forces me to declare Integer size as final. Why ?

   public LRUCache(final Integer size) {
        lhm = Collections.synchronizedMap(new LinkedHashMap<String, Integer>() {
            @Override
            public boolean removeEldestEntry(Map.Entry eldest) {
                return size() > size;
            }
        });
    }
BenMorel
  • 34,448
  • 50
  • 182
  • 322
JavaDeveloper
  • 5,320
  • 16
  • 79
  • 132

2 Answers2

3

Eclipse isn't forcing anything. Java requires that local variables be declared final if they're used in anonymous inner classes. These classes make copies of any local variable used, and if the variable is not final, the original and the copy may be referring to a different value.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • Nit: It's not a general requirement per-se (wrt the "may be referring to a different value") that this occurs; it is how the Java specifications defines it. Many languages with closures allow modifications of the bound bindings - anon inner classes are just a "poor man's substitute", and this one of the restrictions. – user2864740 Oct 12 '13 at 03:35
  • @user2864740: it is currently a *Java Requirement*, and you are correct, that this is how Java is defined. This may change with Java 8. – Hovercraft Full Of Eels Oct 12 '13 at 03:36
  • I didn't mean to imply it's not a Java requirement. I've reworked the language on my initial comment. – user2864740 Oct 12 '13 at 03:36
  • Exploring how Java currently "rewrites" the anon inner classes in context of local-final variables would provide some insight as to why these semantics are as they are - which might be covered in similar answers. – user2864740 Oct 12 '13 at 03:40
1

size is a reference to an Integer object. When you do

size() > size

you are dereferencing size to get its int value. Because removeEldestEntry happens at in a different context, at a different time, there needs to be some guarantee that the reference you are using is the same you are declaring. Therefore you need final, ie. so the reference cannot change.

In the Java Language Specification

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

and

Each local variable (§14.4) and every blank final field (§4.12.4, §8.3.1.2) must have a definitely assigned value when any access of its value occurs.

and

V is definitely assigned before an anonymous class declaration (§15.9.5) that is declared within the scope of V iff V is definitely assigned after the class instance creation expression that declares the anonymous class.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • Sorry, but while your references are right, but your explanation is off. You make no mention of the anonymous class having to make a copy of the local variable which is the whole crux of the problem here. I'm not sure why this answer was accepted. – Hovercraft Full Of Eels Oct 12 '13 at 03:52
  • @HovercraftFullOfEels I believe that's what I meant with _there needs to be some guarantee that the reference you are using is the same you are declaring_ – Sotirios Delimanolis Oct 12 '13 at 03:56