头图
本文参与了思否技术征文,欢迎正在阅读的你也加入。

内部类

基本概述


  • 当一个类的定义放在另一个类的实体时,则该类叫做内部类,该类所在的类叫做外部类
  • 在一个类体中可以出现的内容:成员变量、成员方法、构造方法、构造块、静态语句块、静态变量、方法、内部类
  • 嵌套类

    • 内部类(成员内部类、局部内部类、匿名内部类)
    • 静态嵌套类

语法格式

class 外部类类名{
    class 内部类类名{
        内部类类体;
    }
}

成员内部类


  • 成员内部类定义在另一个类或接口中的内部类
  • 注意事项

    • 必须先创建外部类对象才能创建成员内部类对象
    • 不能含有静态变量、静态代码块、静态方法(除了静态常量)
    • 外部类可以通过成员内部类的对象调用内部类私有成员
    • 成员内部类是一个独立的类,编译成独立的.class文件
  • 作用

    • 成员内部类既可以访问外部类信息,又可以访问父类信息,从而使得多继承的解决方案变得完整
  • 案例

    • Outer.java

      // 成员内部类的使用
      public class Outer { // 外部类
      
      private String str = "Outer类的str1";
      private String str2 = "Outer类的str2";
      
      /*
       * 第一:内部类的名称不能与外部类重名
       * 第二:可以使用final、访问修饰符修饰
       */
      public class Inner{ // 内部类
      
          private String str = "Inner类的str1";
          private String str2 = "Inner类的str2";
          
          public void show() {
              // 内部类的成员优先于外部类成员
              System.out.println(str);
              System.out.println(str2);
              
              // 使用"外部类.this.成员"访问外部类的成员
              System.out.println(Outer.this.str2);
              System.out.println(Outer.this.str);
          }
          
      }
      
      }
    • TestOuter.java

      import Inner.demo1.Outer.Inner;
      
      public class TestOuter {
      
      public static void main(String[] args) {
          // 如果要创建内部类,那么在此之前需要先创建外部类对象
          
          // 创建外部类对象
          Outer o = new Outer();
      
          // 创建内部类
          Inner inner = o.new Inner();
          inner.show();
          
      }
      }

      Inner类的str1
      Inner类的str2
      Outer类的str2
      Outer类的str1

局部内部类


  • 局部内部类是定义在方法h或代码块里的内部类
  • 注意事项:

    • 不能含有静态变量,静态代码块、静态方法
    • 只能在定义该类的方法或代码块中使用,必须在使用前定义
    • 访问它所有方法的局部变量的时候,j局部变量必须是有效的常量
    • 是一个独立的类,编译成独立的.class文件
    • 只能使用abstract、final修饰
    • 定义静态块或方法时候,只能访问外部类的静态成员
  • 案例

    • Outer.java

      // 局部内部类
      public class Outer { // 外部类
      
      private String str1 = "Outer类中的str1";
      private String str2 = "Outer类中的str2";
      
      // 定义一个外部类的方法
      public void print() {
          System.out.println("Outer类中的print方法");
      }
      
      static {
          class Inner{}  // 局部内部类
      }
      
      public void method() {
          
          // 必须在使用之前定义 
          class Inner{
              private String str1 = "Inner类中的str1";
              
              // 内部类成员优先于外部类成员
              public void visitOuter() {
                  System.out.println(str1);
                  System.out.println(str2);
                  print();  // 直接跳到外部类方法
              }
          }
          
          // 局部内部类只能在定义它的方法或代码块中使用
          // 只能使用abstract/final修饰,不能与外部类重名
          Inner in = new Inner();
          in.visitOuter();
      }
      }
    • TestOuter.java

      public class TestOuter {
      
      public static void main(String[] args) {
          
          Outer o = new Outer();
          o.method();
      }
      }

      Inner类中的str1
      Outer类中的str2
      Outer类中的print方法

匿名内部类


  • 匿名内部类是直接使用接口或父类实例化时创建没有名字的内部类
  • 语法格式

    • 接口/父类类型 引用名 = new 接口/父类类型(){
      进行方法的重写;
      }
  • 注意事项

    • 必须且仅能继承一个父类或实现一个接口
    • 没有class关键字、没有类名
    • 是特殊的局部内部类
    • 仅能使用一次
    • 不能定义构造方法
    • 匿名类不能是抽象类
  • 优点以及作用

    • 匿名内部类可以使代码更加紧凑、简洁
    • 封装性比较好
    • 匿名内部类可以灵活的创建
    • 匿名内部类使得多继承的解决方案比较完整
  • 案例

    • InterDemo.java

      public interface InterDemo {
      
      public abstract void print();
      }
    • Outer.java

      public class Outer { // 外部类
      
      private String str1 = "Outer类中str1";
      private String str2 = "Outer类中str2";
      
      // 匿名内部类
      InterDemo id = new InterDemo() {
          
          private String str1 = "匿名内部类str1";
          
          @Override
          public void print() {
          
              System.out.println(str1);
              System.out.println(str2);
              
              // 如果想要调用外部类的变量 ,  外部类.this.变量
              System.out.println(Outer.this.str1);
          }
      };
      
      public void show() {
          id.print();
      }
      }
    • TestOuter.java

      public class TestOuter {
      
      public static void main(String[] args) {
          
          Outer o = new Outer();
          o.show();
      }
      }

      匿名内部类str1
      Outer类中str2
      Outer类中str1

静态嵌套类


  • 静态嵌套类定义在另一个类、接口 、使用static关键字修饰的嵌套类
  • 注意事项

    • 不需要生成外部类对象来生成静态嵌套类对象
    • 只能直接访问外部类的静态成员
    • 外部类可以通过静态嵌套类的对象调用内部类的成员
    • 可以定义静态成员变量或静态成员方法
  • 案例

    • Outer.java

      public class Outer { // 外部类 
      
      // 创建两个成员变量   一个静态,一个非静态
      private String str1 = "外部类的str1";
      private static String str2 = "外部类的str2";
      
      // 成员方法,静态
       public static void show1() {
          System.out.println("外部类的show方法");
      }
      
      // 静态嵌套类
      // 只能定义在类的成员位置,不能定义在方法或代码块中
      public static class Inner{
          
          private String str1 = "嵌套类的str1";
          // private static String str2 = "嵌套类的str2";
          
          public void show() {
              System.out.println(str2);
              System.out.println(str1);
              
              // 不能直接访问外部类的非静态成员
              // 但是可以直接访问外部类的静态成员
              show1();
          }
      
      }
      
      }
    • TestOuter.java

      import Inner.demo4.Outer.Inner;
      
      public class TestOuter {
      public static void main(String[] args) {
          
          // 如何创建内部类或者静态嵌套类对象
          // 首先创建外部类的对象
          Inner Inner = new Outer.Inner();
          Inner.show();
      }
      
      }

      外部类的str2
      嵌套类的str1
      外部类的show方法

静态嵌套类和非静态嵌套类的区别

名称内部类(非静态嵌套类)静态嵌套类
定义位置上成员位置、方法、代码块只能在外部类的成员位置
组成实例成员、静态常量、构造方法实例成员、静态成员、静态代码块、构造方法
对象创建必须先有外部类的对象不依赖于外部类实例,可以直接实例化
访问外部类可以直接访问外部类所有成员只能直接访问外部类的静态成员

若尘
54 声望10 粉丝