【Java笔记】内部类

【Java笔记】内部类

总结

定义

一个定义在另一个类中的类,叫作内部类。

成员内部类

最普通的内部类,定义在另一个类的内部,可以无条件访问外部类的所有成员属性和成员方法(包括private成员和static成员)。因为编译器会默认为成员内部类添加一个指向外部类对象的引用

class A {
  private int i;
  public static int j = 1;
  
  public void test() {
    System.out.print("A test");
  }
  
  class B {
    public method() {
      test();
      System.out.println(i);
      System.out.println(j);
    }
  }
  
}

当成员内部类和外部类有同名的成员变量或者方法时,默认情况下访问的是成员内部类的成员。

如果要访问外部类的同名成员,需要使用:

外部类.this.成员变量
外部类.this.成员方法
class A {
  private String name = "A"; 
  
  class B {
    private String name = "B";
		
    public method() {
      String name = "C"
      System.out.println(name); // 打印 C
      System.out.println(this.name); // 打印 B
      System.out.println(A.this.name); // 打印 A
    }
  }
  
}

外部类想要访问成员内部类的成员,必须先创建一个成员内部类的对象。这一点,其实和普通的类一样,先实例化,再使用

class A {
  
  public void func() {
    B b = new B(); 
    System.out.println(b.i);
  }
  
  class B {
    private int i = 1;
  }
  
}

创建成员内部类,在外部类中创建可以直接使用内部类的类名,在其他类中必须要指定外部类的类名

class A {
  
  class B {}
  
  public B getBInstance() {
    return new B();
  }
  
  public static void main(String[] args) {
    A a = new A();
    // 在外部类内部时,可以不指定外部类的类名
    // 第一种方式 
    B b = new B();
    // 第二种方式
    B b2 = a.getBInstatnce();
  }
  
}

// 重点记忆:注意在其他类中创建B时的方式
class Test {
  public static void main(String[] args) {
    A a = new A();
    
    // 在其他类中,必须指定外部类名
    // 第一种方式
    A.B b = a.new B();
    // 第二种方式
    A.B b2 = a.getBInstance();
    	
  }
}

首先,外部类只能用public或包访问权限修饰。内部类可以用public、protected、private以及包访问权限修饰

访问修饰符

  • 默认访问修饰符为对于同一个包中的其他类相当于public,对于不是同一个包中的其他类相当于private
  • protected对子类相当于public,对不是同一个包中的没有父子关系的类相当于private

成员内部类中不能有静态变量和方法,可以有常量

class A {
  class B {
    static int i; // 不能有静态变量,编译报错
    static final int j = 1; // 可以有常量
  }
}

局部内部类

定义在一个方法或者一个作用域里面的类,和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内

局部内部类不能有public、protected、private以及static修饰符,因为它不是外部类的一部分。它就像是方法的一个局部变量。

class Animal{}

class Person {
 
 public Animal getDog() {
   class Dog extends Animal {
     String color = "black";
   }
   return new Dog();
 }
 
}

匿名内部类

假如只创建这个类的一个对象,就不必命名了。这种类被称为匿名内部类。不能用访问修饰符和static修饰符

class Super {
  public void func() {
    System.out.println("super")
  }
}

public class A {
  
  public void method() {
    return new Super() { // 创建一个实现父类或者接口的类的对象,重写需要实现的方法
      @Override
      public void func() {
        System.out.println("override super");
      }
    };
  }
  
}

由于构造器的名字必须与类名相同,匿名类没有类名。所以,匿名内部类是唯一一个没有构造器的类

静态内部类

如果不需要内部类引用外部类对象,可以将内部类声明为static,这种类叫静态内部类(嵌套类)。

  1. 要创建静态内部类的对象,并不需要其外部类的对象。
  2. 不能从静态内部类的对象中访问非静态的外部类对象。
class A {
    private static int i = 10;
  
    static class B {
        public void print() {
            System.out.println(i);
        }
    }

    public static void main(String[] args) {
        A.B b = new A.B();
        b.print();
    }
}

静态内部类可以有静态域和静态方法。与成员内部类不同的是,静态内部类没有一个指向外部类对象的引用。

接口内部的类

声明在接口中的内部类自动成为staticpublic类。

问题

为什么局部内部类和匿名内部类访问局部变量必须加final修饰符?

为了保证数据一致性,必须加final修饰符

在Java 8之前,必须把局部变量声明为final,不然无法编译通过。Java 8 以后,编译器会自动加上final

# java 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×