실제로 일어나는 일(예: 컴파일러가 클래스에서 생성하는 일) - 1

"안녕하세요, 아미고! 여기 당신을 위한 추가 정보가 있습니다."

"컴파일러가 실제로 모든 익명 클래스를 일반 내부 클래스로 변환한다고 이미 말씀드렸습니다."

"네. 그들의 이름이 1, 2, 3 등의 숫자라는 것도 기억합니다."

"그렇습니다. 하지만 여기에는 또 다른 뉘앙스가 있습니다."

"클래스가 메소드 내에서 선언되고 해당 변수를 사용하는 경우 해당 변수에 대한 참조가 생성된 클래스에 추가됩니다. 직접 확인하십시오."

"우리는 이것으로 시작합니다:"

컴파일하기 전에:
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;
 }
}

"그리고 컴파일러는 다음을 생성합니다.

컴파일 후:
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;
  }
 }
}

"요점을 이해하셨습니까? 내부 클래스의 코드가 실행될 때쯤이면 내부 클래스는 메서드의 로컬 변수를 변경할 수 없습니다. 우리는 메서드를 모두 종료할 수 있습니다."

"이제 두 번째 요점입니다. toString() 메서드는 전달된 변수를 사용합니다. 이를 수행하려면 다음이 필요했습니다."

A) 생성된 클래스 안에 저장

B) 생성자에 추가하십시오.

"알겠습니다. 메소드 내부에 선언된 클래스는 항상 변수의 복사본을 사용합니다."

"정확히!"

"그러면 변수가 최종 변수여야 하는 이유가 이해가 됩니다. 그리고 변수가 변경될 수 없는 이유는 무엇입니까? 실제로 원본이 아닌 복사본으로 작업하는 경우 사용자는 변수의 값을 변경할 수 없는 이유를 이해하지 못할 것입니다. 그가 그것들을 바꾸는 것을 금지해야 한다는 것을 의미합니다."

"그렇습니다. 변수를 최종으로 선언하는 것은 컴파일러가 클래스를 생성하고 메서드에 전달하고 사용하려는 메서드의 모든 변수를 저장하는 대가로 지불해야 하는 작은 대가인 것 같습니다."

"동의합니다. 익명의 로컬 클래스는 여전히 매우 멋집니다."

"메소드 내에서 로컬 클래스를 선언하고 그 안에 있는 메소드의 변수를 사용하면 컴파일러가 클래스에도 추가합니까?"

"예, 클래스와 해당 생성자에 추가합니다."

"그것이 내가 생각했던 거죠."