java 内部类

2333

为什么要将一个类定义在另一个类里面?因为内部类隐藏在外部类之内,更好的实现了信息隐藏(从定义结构类看有些类似 js 的 内部函数)

1. 成员内部类

成员内部类是最常见的内部类,也称为普通内部类

规则
  • 内部类在外部使用时,无法直接实例化,需要借由外部类信息才能完成实例化
  • 内部类的访问修饰符可以任意,但是访问范围会受到影响
  • 内部类可以直接访问外部类的成员,如出现同名属性则优先访问内部类中定义的成员
  • 可以使用 “外部类.this.成员” 的方式访问外部类中同名的信息
  • 外部类无法直接访问内部类成员信息,需要将内部类实例化
  • 内部类编译后.class文件命名: 外部类$内部类.class
public class Person { /** * 年龄 */ int age; /** * 获取内部类 * @return */ public Heart getHeart() { return new Heart(); } /** * test */ public void test() { System.out.println("外部类"); } /** * 内部类 */ class Heart { public String beat() { return "健康检查"; } public void run() { test(); Person.this.test(); } public void test() { System.out.println("内部类"); } } }
调用方式
// 1. new 外部类().new 内部类() Person.Heart myHeart = new Person().new Heart() // 2. 外部类对象.new 内部类 Person person = new Person(); Person.Heart heart = person.new Heart() // 3. 外部类对象.获取方法(方法内部有实例化内部类逻辑) Person person = new Person(); Person.Heart heart = person.getHeart();

2. 静态内部类

规则
  • 静态内部类只能访问外部类的静态成员,如果需要调用非静态成员可以通过对象实例;
  • 静态内部类对象实例化时,可以不依赖于外部类对象,如: Person.Heart myHeart = new Person.Heart();
  • 可以通过 “外部类.内部类.静态成员” 的方式访问内部类中的静态成员;
  • 当静态内部类与外部类属性同名时,默认直接调用内部类的成员,需要访问外部类中的静态属性, 可以通过 “外部类.属性” 的方式,如需要访问外部类中的非静态属性,则可以通过 “new 外部类().属性” 的方式;
public class Person { public int age = 11; void eat() { System.out.println("2333"); } /** * 静态内部类 */ static class Heart { int age = 13; int temp = 22; public String beat() { new Person().eat(); return new Person().age + "岁的跳动"; } } }

3. 方法内部类

规则
  • 定义在方法内部,作用范围也在方法内
  • 和方法内部成员使用规则一样,class 前面不可以添加 public、private、protected、static 修饰成员
  • 类中不能包含静态成员
  • 类中可以包含 final、abstract 修饰的成员
public class Pserson { public static int age; /** * 方法内部类 * @return */ public Object getHeart() { class Heart { int age = 123; int temp = 12; public void say() { System.out.println("hello"); } public String beat() { new Pserson().eat(); return Pserson.age + "岁"; } public void eat() {} } return new Heart().beat(); } public void eat() { System.out.println("人会吃东西"); } }

匿名内部类

跟js的回调函数是一个道理

规则
  • 匿名内部类没有类名称、实例对象名称
  • 编译后的文件命名: 外部类$数字.class
  • 无法使用 private、public、protected、abstract、static 修饰
  • 无法编写构造方法,但是可以添加构造代码块
  • 不能出现静态成员
  • 匿名内部类可以实现接口也可以继承父类,但是2这只能选其中一种。
public abstract class Person { private String name; public Person(){} public String getName() { return name; } public void setName(String name) { this.name = name; } public abstract void read(); }
调用
public class PersonTest { /** * 根据传入的不同的人的类型,调用对应的 read 方法 */ public void getRead(Person person) { person.read(); } public static void main(String[] args) { PersonTest test = new PersonTest(); test.getRead(new Person() { @Override public void read() { System.out.println("男生喜欢看小说11"); } }); } }