익명의 내부 클래스 및 예 - 1

"안녕, 아미고!"

"하지만 우린 이미 인사했지, 엘리!"

"이봐, 이모랑 말다툼하지 마. 31세기에는 누군가를 30분 이상 만나지 않으면 다시 인사하는 것이 관습이야. 그러니 나에게 태도를 주지 마!"

"어쨌든, 또 다른 흥미로운 주제인 로봇 재생산을 할 시간입니다!"

"O_O."

"농담입니다. 새로운 주제는 익명의 내부 클래스 입니다 ."

"Java에서는 때때로 여러 클래스를 상속하기 위해 클래스가 필요한 상황이 있습니다. Java는 다중 상속을 지원하지 않기 때문에 내부 클래스를 사용하여 이 문제를 해결했습니다. 우리 클래스에서는 내부 클래스를 선언하고 상속에 필요한 모든 클래스를 상속합니다. 예를 들면 다음과 같습니다."

Thread 클래스를 상속받은 내부 클래스의 예
class Tiger extends Cat
{
 public void tigerRun()
 {
  .....
 }

 public void startTiger()
 {
  TigerThread thread = new TigerThread();
  thread.start();
 }

 class TigerThread extends Thread
 {
  public void run()
  {
   tigerRun();
  }
 }
}

"다른 예를 살펴보겠습니다."

실행 메서드를 재정의하려면 Thread 클래스의 하위 클래스가 필요합니다."

"그래서 Tiger 클래스에서 Thread를 상속하고 run 메서드를 재정의하는 TigerThread 내부 클래스를 선언했습니다.

"편의를 위해 Tiger 클래스에 두 가지 메서드인 tigerRun과 startTiger를 정의했습니다 (Thread의 실행 및 시작 메서드와 유사합니다.").

"tigerStart 메소드에서 TigerThread 객체를 생성 하고 start() 메소드를 호출합니다."

"JVM은 TigerThread의 실행 메소드가 호출될 때 실행을 시작할 새 스레드를 생성합니다 ."

"그런 다음 이 메서드는 우리의 실행 메서드인 tigerRun을 호출합니다 ."

"이전에 스레드로 작업한 적이 있으므로 간단해 보입니다."

"방법의 이름을 tigerRun 및 tigerStart로 지정해야 합니까?"

"아니요, 실행 및 시작이라고 부를 수 있었지만 Thread를 상속하지 않는다는 것을 보여주고 싶었습니다. 설명이 더 혼란스러울 수 있습니다."

"알겠습니다. 그럼 알겠습니다. 하지만 tigerStart가 두 번째로 호출되면 두 번째 Thread 객체를 생성하고 시작합니다. "두 개의 서로 다른 스레드에서 실행 중인 하나의 호랑이"가 있다는 의미가 아닙니까? "

"글쎄, 당신은 날카롭지 않습니까! 당신이 옳고 좋지 않습니다. 다음과 같이 코드를 다시 작성해 봅시다."

암호
class Tiger extends Cat
{
 public void tigerRun()
 {
  .....
 }

 public void startTiger()
 {
  thread.start();
 }

 private TigerThread thread = new TigerThread();

 private class TigerThread extends Thread
 {
  public void run()
  {
   tigerRun();
  }
 }
}

"완벽하지 않습니다. 여전히 그런 메서드를 두 번 호출할 수 없습니다. 하지만 이번에는 적어도 두 번째 스레드를 생성하지 않고 모든 것이 괜찮은 것처럼 보이게 할 것입니다."

"그렇습니다. Tiger가 두 번째로 시작되면 예외가 발생합니다."

"나는 이미 너보다 실수를 더 잘 찾아내고 있어, 엘리!"

"그래, 잘하고 있어. 그럼 익명의 내부 클래스로 넘어가자."

"위 코드의 여러 측면에 유의하십시오."

1) 우리는 Thread 클래스를 물려받았지만 실제로 거기에 코드를 구현하지 않았습니다. "«우리는 그것을 확장하기 위해 그것을 물려받았습니다»라기보다는 «우리는 Thread 클래스를 물려받아야 했습니다»였습니다.

2) 하나의 TigerThread 객체만 생성됩니다.

즉, 하나의 메서드를 재정의하고 하나의 객체를 생성하기 위해 코드 전체를 작성했습니다.

내가 생성자의 발명에 대해 어떻게 이야기했는지 기억하십니까?

생성자 이전 생성자 이후
TigerThread thread = new TigerThread();

private class TigerThread extends Thread
{
 public void run()
 {
  tigerRun();
 }
}
Thread thread = new Thread()
{
 public void run()
 {
  tigerRun();
 }
};

"코드가 더 간결해진 것을 볼 수 있지만 무슨 일이 일어나고 있는지 잘 모르겠습니다."

"네 가지를 하나로 결합할 수 있습니다."

1) 파생 클래스 선언

2) 메서드 재정의

3) 변수 선언

4) 파생 클래스의 인스턴스 생성.

"사실 우리가 하고 있는 일은 파생 클래스를 선언하고 해당 클래스의 인스턴스를 생성하는 두 가지 작업을 결합하는 것입니다."

익명 클래스 없이 익명 수업으로
Cat tiger = new Tiger();

class Tiger extends Cat
{
}
Cat tiger = new Cat()
{
};

"구문을 다시 살펴보겠습니다."

스레드 변수 선언
Thread thread = new Thread();
유형이 «Thread를 상속하는 익명 클래스»인 변수 선언
Thread thread = new Thread()
{

};

"단순히 새 클래스를 정의하는 것이 아닙니다. 변수를 만드는 것입니다. 끝에 세미콜론이 있습니다!"

"그리고 run 메서드를 재정의하려면 다음과 같이 작성해야 합니다."

스레드 변수 선언
Thread thread = new Thread()
{
 public void run()
  {
   System.out.println("new run-method");
  }
};

"당신은 빨리 따라 잡습니다. 잘 했어!"

"고맙습니다. Thread 클래스의 일부가 아닌 다른 메서드가 필요하면 어떻게 합니까?"

"당신은 그들을 쓸 수 있습니다."

"비록 익명이지만 본격적인 내부 클래스입니다."

자바 코드 설명
Thread thread = new Thread()
{
  public void run()
  {
   printHi();
  }

  public void printHi()
  {
   System.out.println("Hi!");
  }
};
빨간색: 변수를 생성하기 위한 코드입니다.

녹색: 개체를 생성하기 위한 코드입니다.

파란색: 익명 파생 클래스에 대한 코드입니다.

"본격적인 이너 클래스?"

"그러면 외부 클래스의 변수를 사용할 수 있습니까?"

"전적으로."

"그리고 생성자에게 무언가를 전달할 수 있습니까?"

"예, 하지만 슈퍼클래스의 생성자에 대한 인수만:"

수업 익명 내부 클래스의 인스턴스
class Cat
{
 int x, y;
 Cat(int x, int y)
 {
  this.x = x;
  thix.y = y;
 }
}
Cat cat = new Cat(3,4)
{
  public void print()
  {
   System.out.println(x+" "+y);
  }
};

"우리는 다른 사람의 생성자에 우리 자신의 매개변수를 추가할 수 없습니다. 하지만 외부 클래스의 변수를 사용할 수 있어 이 단점을 훌륭하게 보완합니다."

"아직도 생성자에 다른 매개변수를 추가해야 하는 경우에는 어떻게 해야 합니까?"

"그런 다음 일반(비익명) 내부 클래스를 선언하고 사용합니다."

"맞아, 거의 잊고 있었어."

"정적 변수를 선언하면 어떻게 될까요? 익명 클래스가 내부 클래스가 아닌 정적 중첩 클래스가 될까요? 즉, 외부 클래스에 대한 참조가 부족할까요?"

"아니요. 익명의 내부 클래스가 될 것입니다. 이 예를 보십시오."

익명 수업으로 익명 클래스 없이
Thread thread = new Thread()
{
  public void run()
  {
   tigerRun();
  }
};
TigerThread thread = new TigerThread();

private class TigerThread extends Thread
{
 public void run()
 {
  tigerRun();
 }
}
static Thread thread = new Thread()
{
  public void run()
  {
   tigerRun();
  }
};
static TigerThread thread = new TigerThread();

private class TigerThread extends Thread
{
 public void run()
 {
  tigerRun();
 }
}

"그렇군요. 클래스가 아니라 정적 변수만 정적이겠죠."

"네."

"실제로 컴파일러는 모든 익명의 내부 클래스에 대한 내부 클래스를 생성합니다. 이러한 클래스의 이름은 일반적으로 «1», «2», «3» 등으로 지정됩니다."