>  기사  >  Java  >  Java 내부 클래스의 코드 예제 공유

Java 내부 클래스의 코드 예제 공유

黄舟
黄舟원래의
2017-09-21 09:43:451503검색

이 글은 주로 Java 내부 클래스의 세부 예제에 대한 관련 정보를 소개합니다. 이 기사를 통해 모든 사람이 Java 내부 클래스의 사용법을 이해하고 숙달할 수 있기를 바랍니다.

할 수 있습니다. 한 클래스의 정의는 다른 클래스의 정의 내부에 배치됩니다.

내부 클래스는 매우 유용한 기능이지만 이해하고 사용하기가 어렵습니다. (저는 내부 클래스를 사용해 본 적이 없으며 이에 대해 조금 알고 있습니다.)

첫번째 만남

내부 클래스는 외부에서 보면 매우 이해하기 쉽습니다. 클래스 내부에 클래스를 정의하는 것에 지나지 않습니다.

public class OuterClass {
  private String name ;
  private int age;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }

  class InnerClass{
    public InnerClass(){
      name = "chenssy";
      age = 23;
    }
  }
}

여기서 InnerClass는 초보자의 경우 Inner Class를 많이 사용하지 않습니다. (스윙 등록 이벤트에서만 사용한 것 같습니다.) 실력이 향상되면 그 매력을 깨닫고 프로그램 구조를 더욱 우아하게 디자인하는 데 사용할 수 있습니다. 내부 클래스를 사용하기 전에 내부 클래스를 사용해야 하는 이유와 내부 클래스가 우리에게 가져올 수 있는 이점이 무엇인지 이해해야 합니다.

1. 내부 클래스를 사용하는 이유

내부 클래스를 사용하는 이유는 무엇입니까? "Think in Java"에는 다음 문장이 있습니다. 내부 클래스를 사용하는 가장 매력적인 이유는 각 내부 클래스가 독립적으로 (인터페이스의) 구현을 상속할 수 있기 때문에 외부 클래스가 (인터페이스) 구현을 상속했는지 여부에 관계없이 가능하다는 것입니다. 내부 클래스에는 영향을 미치지 않습니다.

프로그래밍에는 때때로 인터페이스를 사용하여 해결하기 어려운 문제가 있습니다. 이때 내부 클래스에서 제공하는 기능을 사용하여 여러 구체적 또는 추상 클래스를 상속하여 이러한 프로그래밍 문제를 해결할 수 있습니다. 인터페이스는 문제의 일부만 해결하고 내부 클래스는 다중 상속 솔루션을 더욱 완벽하게 만든다고 말할 수 있습니다.

public interface Father {

}

public interface Mother {

}

public class Son implements Father, Mother {

}

public class Daughter implements Father{

  class Mother_ implements Mother{

  }
}

사실 이 예에서는 내부 클래스를 사용하는 것의 이점을 실제로 볼 수 없지만, Father와 Mother가 인터페이스가 아니라 추상 클래스이거나 구체적인 클래스라면 어떨까요? 현재로서는 다중 상속을 달성하기 위해 내부 클래스만 사용할 수 있습니다.

실제로 내부 클래스를 사용하면 다중 상속 문제를 아주 잘 해결할 수 있다는 것이 가장 큰 장점입니다. 하지만 다중 상속 문제를 해결할 필요가 없다면 자연스럽게 다른 코딩 방법을 사용할 수도 있지만, 내부 클래스를 사용하면 도움이 될 수도 있습니다. 다음 기능을 제공합니다("Think in Java"에서 발췌):

1. 내부 클래스는 여러 인스턴스를 사용할 수 있으며, 각 인스턴스는 자체 상태 정보를 가지며 다른 주변 객체의 정보와 독립적입니다. .

2. 단일 주변 클래스에서 여러 내부 클래스가 동일한 인터페이스를 다른 방식으로 구현하거나 동일한 클래스를 상속할 수 있습니다.

3. 내부 클래스 객체가 생성되는 시간은 외부 클래스 객체 생성에 의존하지 않습니다.

4. 내부 클래스는 혼란스러운 "is-a" 관계가 없으며 독립적인 개체입니다.

5. 내부 클래스는 더 나은 캡슐화를 제공합니다. 주변 클래스를 제외하고 다른 클래스는 액세스할 수 없습니다.


2. 내부 클래스의 기본

이번 편에서는 내부 클래스가 외부 클래스의 속성과 메소드를 어떻게 사용하는지, .this와 .new를 어떻게 사용하는지를 주로 소개합니다.

내부 클래스를 만들면 외부 클래스와 보이지 않는 연결이 있으며, 이 연결을 통해 외부 클래스의 요소에 무제한으로 액세스할 수 있습니다.

public class OuterClass {
  private String name ;
  private int age;

  /**省略getter和setter方法**/

  public class InnerClass{
    public InnerClass(){
      name = "chenssy";
      age = 23;
    }

    public void display(){
      System.out.println("name:" + getName() +"  ;age:" + getAge());
    }
  }

  public static void main(String[] args) {
    OuterClass outerClass = new OuterClass();
    OuterClass.InnerClass innerClass = outerClass.new InnerClass();
    innerClass.display();
  }
}
--------------
Output:
name:chenssy  ;age:23

이 애플리케이션에서는 내부 InnerClass가 비공개적으로 수정되었음에도 불구하고 외부 클래스 OuterClass의 속성에 원활하게 액세스할 수 있음을 볼 수 있습니다. 이는 외부 클래스의 내부 클래스 개체를 생성할 때 외부 클래스 개체에 대한 참조를 확실히 캡처하기 때문입니다. 외부 클래스의 멤버에 액세스하는 한 이 참조를 사용합니다. 둘러싸는 클래스.

사실 이 애플리케이션에서는 내부 클래스를 참조하는 방법도 살펴보았습니다. 내부 클래스를 참조하려면 OuterClasName.InnerClassName이라는 개체의 유형을 지정해야 합니다. 동시에 내부 클래스 객체를 생성해야 하는 경우 외부 클래스 객체를 사용하여 .new를 통해 내부 클래스를 생성해야 합니다. OuterClass.InnerClass innerClass = externalClass.new InnerClass();.

동시에 외부 클래스 개체에 대한 참조를 생성해야 하는 경우 OuterClassName.this를 사용하면 외부 클래스에 대한 참조를 올바르게 생성할 수 있습니다. 물론 이는 컴파일 타임에 알려지며 런타임 비용은 없습니다.

/**
 * Java学习交流QQ群:589809992 我们一起学Java!
 */
public class OuterClass {
  public void display(){
    System.out.println("OuterClass...");
  }

  public class InnerClass{
    public OuterClass getOuterClass(){
      return OuterClass.this;
    }
  }

  public static void main(String[] args) {
    OuterClass outerClass = new OuterClass();
    OuterClass.InnerClass innerClass = outerClass.new InnerClass();
    innerClass.getOuterClass().display();
  }
}
-------------
Output:
OuterClass...

이 시점에서 내부 클래스는 컴파일 타임 개념이라는 점을 분명히 해야 합니다. 일단 성공적으로 컴파일되면 이 클래스와 외부 클래스는 완전히 다른 두 클래스에 속합니다(물론 두 클래스 사이에는 여전히 연결이 있습니다). 그들을). OuterClass라는 주변 클래스와 InnerClass라는 내부 클래스의 경우 성공적으로 컴파일되면 OuterClass.class 및 OuterClass$InnerClass.class라는 두 개의 클래스 파일이 나타납니다.

Java에서 내부 클래스는 크게 멤버 내부 클래스, 로컬 내부 클래스, 익명 내부 클래스, 정적 내부 클래스로 구분됩니다.

3. 멤버 내부 클래스

成员内部类也是最普通的内部类,它是外围类的一个成员,所以他是可以无限制的访问外围类的所有 成员属性和方法,尽管是private的,但是外围类要访问内部类的成员属性和方法则需要通过内部类实例来访问。

在成员内部类中要注意两点,第一:成员内部类中不能存在任何static的变量和方法;第二:成员内部类是依附于外围类的,所以只有先创建了外围类才能够创建内部类。


public class OuterClass {
  private String str;

  public void outerDisplay(){
    System.out.println("outerClass...");
  }

  public class InnerClass{
    public void innerDisplay(){
      //使用外围内的属性
      str = "chenssy...";
      System.out.println(str);
      //使用外围内的方法
      outerDisplay();
    }
  }

  /*推荐使用getxxx()来获取成员内部类,尤其是该内部类的构造函数无参数时 */
  public InnerClass getInnerClass(){
    return new InnerClass();
  }

  public static void main(String[] args) {
    OuterClass outer = new OuterClass();
    OuterClass.InnerClass inner = outer.getInnerClass();
    inner.innerDisplay();
  }
}
--------------------
chenssy...
outerClass...

推荐使用getxxx()来获取成员内部类,尤其是该内部类的构造函数无参数时 。

四、局部内部类

有这样一种内部类,它是嵌套在方法和作用于内的,对于这个类的使用主要是应用与解决比较复杂的问题,想创建一个类来辅助我们的解决方案,到那时又不希望这个类是公共可用的,所以就产生了局部内部类,局部内部类和成员内部类一样被编译,只是它的作用域发生了改变,它只能在该方法和属性中被使用,出了该方法和属性就会失效。

对于局部内部类实在是想不出什么好例子,所以就引用《Think in java》中的经典例子了。

定义在方法里:


/**
 * Java学习交流QQ群:589809992 我们一起学Java!
 */
public class Parcel5 {
  public Destionation destionation(String str){
    class PDestionation implements Destionation{
      private String label;
      private PDestionation(String whereTo){
        label = whereTo;
      }
      public String readLabel(){
        return label;
      }
    }
    return new PDestionation(str);
  }

  public static void main(String[] args) {
    Parcel5 parcel5 = new Parcel5();
    Destionation d = parcel5.destionation("chenssy");
  }
}

定义在作用域内:


public class Parcel6 {
  private void internalTracking(boolean b){
    if(b){
      class TrackingSlip{
        private String id;
        TrackingSlip(String s) {
          id = s;
        }
        String getSlip(){
          return id;
        }
      }
      TrackingSlip ts = new TrackingSlip("chenssy");
      String string = ts.getSlip();
    }
  }

  public void track(){
    internalTracking(true);
  }

  public static void main(String[] args) {
    Parcel6 parcel6 = new Parcel6();
    parcel6.track();
  }
}

五、匿名内部类

在做Swing编程中,我们经常使用这种方式来绑定事件


button2.addActionListener( 
        new ActionListener(){ 
          public void actionPerformed(ActionEvent e) { 
            System.out.println("你按了按钮二"); 
          } 
        });

我们咋一看可能觉得非常奇怪,因为这个内部类是没有名字的,在看如下这个例子:


/**
 * Java学习交流QQ群:589809992 我们一起学Java!
 */
public class OuterClass {
  public InnerClass getInnerClass(final int num,String str2){
    return new InnerClass(){
      int number = num + 3;
      public int getNumber(){
        return number;
      }
    };    /* 注意:分号不能省 */
  }

  public static void main(String[] args) {
    OuterClass out = new OuterClass();
    InnerClass inner = out.getInnerClass(2, "chenssy");
    System.out.println(inner.getNumber());
  }
}

interface InnerClass {
  int getNumber();
}

----------------
Output:

这里我们就需要看清几个地方

1、 匿名内部类是没有访问修饰符的。

2、 new 匿名内部类,这个类首先是要存在的。如果我们将那个InnerClass接口注释掉,就会出现编译出错。

3、 注意getInnerClass()方法的形参,第一个形参是用final修饰的,而第二个却没有。同时我们也发现第二个形参在匿名内部类中没有使用过,所以当所在方法的形参需要被匿名内部类使用,那么这个形参就必须为final。

4、 匿名内部类是没有构造方法的。因为它连名字都没有何来构造方法。

六、静态内部类

在java提高篇——关键字static中提到Static可以修饰成员变量、方法、代码块,其他它还可以修饰内部类,使用static修饰的内部类我们称之为静态内部类,不过我们更喜欢称之为嵌套内部类。静态内部类与非静态内部类之间存在一个最大的区别,我们知道非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围内,但是静态内部类却没有。没有这个引用就意味着:

1、 它的创建是不需要依赖于外围类的。

2、 它不能使用任何外围类的非static成员变量和方法。


/**
 * Java学习交流QQ群:589809992 我们一起学Java!
 */
public class OuterClass {
  private String sex;
  public static String name = "chenssy";

  /**
   *静态内部类
   */
  static class InnerClass1{
    /* 在静态内部类中可以存在静态成员 */
    public static String _name1 = "chenssy_static";

    public void display(){
      /* 
       * 静态内部类只能访问外围类的静态成员变量和方法
       * 不能访问外围类的非静态成员变量和方法
       */
      System.out.println("OutClass name :" + name);
    }
  }

  /**
   * 非静态内部类
   */
  class InnerClass2{
    /* 非静态内部类中不能存在静态成员 */
    public String _name2 = "chenssy_inner";
    /* 非静态内部类中可以调用外围类的任何成员,不管是静态的还是非静态的 */
    public void display(){
      System.out.println("OuterClass name:" + name);
    }
  }

  /**
   * @desc 外围类方法
   * @author chenssy
   * @data 2013-10-25
   * @return void
   */
  public void display(){
    /* 外围类访问静态内部类:内部类. */
    System.out.println(InnerClass1._name1);
    /* 静态内部类 可以直接创建实例不需要依赖于外围类 */
    new InnerClass1().display();

    /* 非静态内部的创建需要依赖于外围类 */
    OuterClass.InnerClass2 inner2 = new OuterClass().new InnerClass2();
    /* 方位非静态内部类的成员需要使用非静态内部类的实例 */
    System.out.println(inner2._name2);
    inner2.display();
  }

  public static void main(String[] args) {
    OuterClass outer = new OuterClass();
    outer.display();
  }
}
----------------
Output:
chenssy_static
OutClass name :chenssy
chenssy_inner
OuterClass name:chenssy

上面这个例子充分展现了静态内部类和非静态内部类的区别。

到这里内部类的介绍就基本结束了!对于内部类其实本人认识也只是皮毛,逼近菜鸟一枚,认知有限!我会利用这几天时间好好研究内部类!

위 내용은 Java 내부 클래스의 코드 예제 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.