CodeGym /Courses /Java Multithreading /What really happens (i.e. what the compiler generates fro...

What really happens (i.e. what the compiler generates from classes)

Java Multithreading
Level 4 , Lesson 7
Available
What really happens (i.e. what the compiler generates from classes) - 1

"Hi, Amigo! Here's some more information for you."

"I already told you that the compiler actually converts all anonymous classes into ordinary inner classes."

"Yep. I even remember that their names are numbers: 1, 2, 3, etc."

"Exactly. But there's another nuance here."

"If a class is declared inside a method and uses any of its variables, then references to those variables will be added to the generated class. See for yourself."

"We start with this:"

Before compiling:
class Car {
 public ArrayList createPoliceCars(int count) { ArrayList result = new ArrayList(); for(int i = 0; i < count; i++) { final int number = i; result.add(new Car() { public String toString() { return ""+number; } }); } return result; }
}

"And the compiler generates this:

After compiling:
class Car {
 public ArrayList createPoliceCars(int count) { ArrayList result = new ArrayList(); for(int i = 0; i < count; i++) { final int number = i; result.add(new Anonymous2 (number)); } return result; }

 class Anonymous2 { final int number; Anonymous2(int number) { this.number = number; } public String toString() { return ""+ number; } }
}

"Did you get the point? The inner class can't change the method's local variable, because by the time the inner class's code is executed, we may be exiting the method altogether."

"Now the second point. The toString() method uses a passed variable. To accomplish this, it was necessary to:"

A) save it inside the generated class

B) add it to the constructor.

"Got it. Classes declared inside methods always use copies of variables."

"Exactly!"

"Then it makes sense why variables must be final. And why they can't be changed. If you're actually working with copies rather than the originals, the user won't understand why he can't change variables' values, which means we need to just forbid him from changing them."

"Right, declaring variables as final seems a small price to pay in exchange for having the compiler generate a class for you, pass it to the method, and save all of the method's variables that you want to use."

"I agree. Anonymous local classes are still super cool."

"If I declare a local class inside a method, and I use the method's variables in it, will the compiler add them to the class too?"

"Yes, it will add them to the class and its constructor."

"That's what I thought."

Comments (7)
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION
Hoist Level 38, San Diego, United States
21 September 2025
Translation: from below -- @Niko - Level 41 1. Variables used in methods of a local class are automatically passed to the constructor by the compiler and stored as properties. 2. All variables used in a local class must be declared final. 31 March 2022, 04:33 The inner class directly stores a reference to the outer class instance. Local classes, on the other hand, can only store variable values. To prevent variables from changing their values, they must be declared final.
Vadim “迪姆哥” Level 35, Kazakhstan
12 September 2023
Why in your example class Anonymous2 does not extend Car class?
Lisa L Level 47, Nuremberg, Germany
5 May 2022
Sometimes it is necessary to get around that final limitation. If you do some calculations inside the anon class and you want to save the result in such a local variable. Making that local var final would contradict your intention. What you can do is use a instance variable or an array with one element. Right now this might seem not important but when you use lambas it may be nice to know this.

public class SaveStateOutsideAnonClass {
    private int b;
    public static void main(String[] args) {
        SaveStateOutsideAnonClass s = new SaveStateOutsideAnonClass();
        int a;
        // you can not save results from an anon class, lambda in a local variable
        // if you make the var final it of course won't work either ;)
        // IntStream.range(0, 5).forEach(i -> a = i); // does not compile

        // but you can save into fields
        IntStream.range(0, 5).forEach(i -> s.b = i);

        // of you use reference variables. You can not change the reference but the object
        int[] c = new int[1];
        IntStream.range(0, 5).forEach(i -> c[0] = i);
    }
}
If you wonder, the anon class is inside the forEach method (in form of a lambda). Here's the last example that saves into an array written with an anon class extending the IntStream interface

        IntStream.range(0, 5).forEach(new IntConsumer() {
            @Override
            public void accept(int i) {
                c[0] = i;
            }
        });
Niko Level 41, Wuhan, China
31 March 2022
1.local class用到的方法中的变量都会被编译器自动传递到构造器,并被保存为属性。 2.local class用到的变量都必须先被声明为final
Niko Level 41, Wuhan, China
31 March 2022
inner class直接存储了外部类的实例的引用。而local class只能存储变量的值。为了防止变量的值发生变化,因此必须被声明为final
Johannes Level 27, Centurion, Pretoria, South-Africa
6 May 2020
Makes a little more sense to me, now.
Andrei Level 41
9 April 2021
Yay, Johannes seems happy for once! 😆