• 定义在类内部的类 就是内部类
  • 成员内部类(实例内部类和静态内部类)字节码文件:外部类类名$内部类类名.class
  • 局部内部类的字节码文件:外部类类名$N内部类类名.class
  • 匿名内部类的字节码文件:外部类类名$N.class
  • 实例内部类
    • 实例内部类内部不允许定义任何静态内容
    • 外部类静态方法中不能直接访问实例内部类数据
    • static final 修饰的变量的值,能在编译器确定值,可以在实例内部类中定义
  • 静态内部类
    • 被static修饰的成员内部类
    • 只有内部类可以被static修饰
  • 匿名内部类
    • 匿名内部类中不能定义构造方法,但是可以定义构造块。

    • 成员内部类 静态内部类 局部内部类

      ```java package cn.java.money.innerclass.demo01;

/**

  • 内部类位置:
  • 成员位置 —- 成员内部类 静态内部类
  • 局部位置 —- 局部内部类 (方法内部类)
  • 内部类的访问特点:
  • 1.0 内部类可以直接访问外部类的成员(成员变量,成员方法),包括私有的。
  • 2.0 外部类要访问内部类的成员,必须创建对象. */ // public 和 default public class Outer { private int num = 10; private static int num2 = 10;

    public void method2() {

    1. System.out.println("我是外部类的方法 method2");

    }

    public static void method3() {

    1. System.out.println("我是外部类的静态方法 method3");

    }

    public void method4() {

    1. // 外部类中访问内部类中的成员,必须创建内部类对象
    2. // 访问成员内部类中的成员
    3. Inner inner = new Inner();
    4. inner.method();
    5. System.out.println(inner.num);
    6. // 静态内部类也要创建对象 才能使用
    7. Inner3 inner3 = new Inner3();
    8. inner3.method();

    }

    //成员内部类 //成员内部类的修饰符:public private protected default 都可以使用 public class Inner {

    1. public int num = 11;
    2. // 内部类中不能有静态成员变量声明
    3. //public static int num2 = 11;
    4. public void method() {
    5. System.out.println("我是成员内部类");
    6. //成员内部类 可以访问外部的所有变量和方法
    7. System.out.println(num);
    8. method2();
    9. //成员内部类 可以访问外部类的静态变量和静态方法
    10. System.out.println(num2);
    11. //每一个内部类对象中都隐含了一个外部类对象
    12. System.out.println(Outer.this.num2);
    13. method3();
    14. }

    }

    //静态内部类: 属于外部类本身,不属于外部类某个对象 public static class Inner3 {

    1. public void method() {
    2. System.out.println("我是静态内部类");
    3. // 编译报错, Inner3 是静态成员类,要访问外部类的非静态变量或方法 都会报错
    4. //System.out.println(num);
    5. // 编译报错
    6. // method2();
    7. //静态内部类 只能访问外部类静态成员
    8. System.out.println(num2);
    9. method3();
    10. }

    }

    public void method1() {

    1. // 局部变量:包括方法里的和 代码块里的(静态和非静态), 可以被default(默认不写), final修饰
    2. final int ii = 0;
    3. int ii2 = 0;
    4. //局部内部类
    5. //方法内部类只能在该方法内部使用,所以不能使用访问控制符(public等)和修饰符(static);
    6. //就像是局部变量,在方法外部是无法访问的。
    7. class Inner2 {
    8. public void method() {
    9. System.out.println("我是局部内部类");
    10. //局部内部类 可以访问外部的所有变量和方法
    11. System.out.println(num);
    12. method2();
    13. //局部内部类 可以访问外部类的静态变量和静态方法
    14. System.out.println(num2);
    15. method3();
    16. //可以访问被声明为final的局部变量.
    17. // 原因说明:局部变量在栈中,而局部变量new以后在堆上,方法调用完成以后局部变量就释放了,而局部内部类的对象不一定被回收。
    18. // final修饰局部变量, 局部变量变为一个常量,因此在编译的时候,局部内部类就使用这个常量。
    19. // jdk 1.8以后, 如果局部内部类使用了方法的局部变量,在编译的时候会自动加上final。
    20. System.out.println(ii);
    21. System.out.println(ii2); // jdk1.8 以前必须要显示声明为final,jdk1.8以后不用显示声明
    22. //Java 中局部内部类和匿名内部类访问的局部变量必须由 final 修饰,以保证内部类和外部类的数据一致性。
    23. // 但从 Java 8 开始,我们可以不加 final 修饰符,由系统默认添加,当然这在 Java 8 以前的版本是不允许的。
    24. // Java 将这个功能称为 Effectively final 功能。
    25. }
    26. }
    27. //局部内部类只能在局部范围使用
    28. Inner2 inner2 = new Inner2();
    29. inner2.method();

    }

}

  1. ```java
  2. package cn.java.money.innerclass.demo01;
  3. public class TestOuter {
  4. public static void main(String[] args) {
  5. //成员内部类 实例化: 外部类.内部类 obj = new 外部类().new 内部类()
  6. Outer.Inner obj = new Outer().new Inner(); // 因为 Inner 被public修饰,所以可以在外部类以外使用
  7. // 调用成员内部类的方法
  8. obj.method();
  9. System.out.println("--------------------------------------");
  10. // 调用局部内部类中方法,通过调用外部类的方法,间接的调用
  11. Outer outer = new Outer();
  12. outer.method1();
  13. System.out.println("--------------------------------------");
  14. //静态内部类 实例化
  15. Outer.Inner3 obj2 = new Outer.Inner3();
  16. obj2.method();
  17. System.out.println("--------------------------------------");
  18. outer.method4();
  19. }
  20. }

匿名内部类

  1. package cn.java.money.innerclass.demo01;
  2. // 接口类
  3. interface A {
  4. void method();
  5. }
  6. // 抽象类
  7. abstract class B {
  8. B(){
  9. }
  10. //有参构造
  11. B(int n){
  12. }
  13. abstract void method();
  14. }
  15. // 普通类
  16. class C{
  17. public void method (){
  18. System.out.println("我是普通类的普通方法");
  19. }
  20. }
  21. public class TestNiMingNeiBuLei {
  22. // 定义成员变量 执行匿名对象
  23. // 匿名内部类的本质:接口和抽象类的实现。
  24. A a = new A() {
  25. @Override
  26. public void method() {
  27. System.out.println("我是匿名内部类 实现接口");
  28. }
  29. };
  30. // 因为接口只有一个方法,因此可以简写为 lambda 表达式
  31. A a2 = () -> System.out.println("我是匿名内部类,实现接口");
  32. // b指向b的实现类的对象
  33. B b = new B() {
  34. @Override
  35. void method() {
  36. System.out.println("我是匿名内部类,实现抽象类");
  37. }
  38. };
  39. //可以是静态的
  40. static B b2 = new B() {
  41. @Override
  42. void method() {
  43. System.out.println("我是匿名内部类,实现抽象类");
  44. }
  45. //这个方法不能被外部 b2 访问,因为匿名内部类没有类名 也就没有类型
  46. public void ff(){
  47. System.out.println("匿名内部类自定义的方法");
  48. }
  49. };
  50. // 调用有参构造
  51. B b3 = new B(45) {
  52. @Override
  53. void method() {
  54. System.out.println("我是匿名内部类,实现抽象类");
  55. }
  56. };
  57. C c = new C() {
  58. @Override
  59. public void method (){
  60. System.out.println("我是普通类的普通方法 在匿名内部类中的重写");
  61. }
  62. };
  63. public static void main(String[] args) {
  64. TestNiMingNeiBuLei testNiMingNeiBuLei = new TestNiMingNeiBuLei();
  65. testNiMingNeiBuLei.a.method();
  66. testNiMingNeiBuLei.a2.method();
  67. testNiMingNeiBuLei.b.method();
  68. testNiMingNeiBuLei.c.method();
  69. //实现接口或抽象类 然后就调用
  70. new B(){
  71. @Override
  72. void method() {
  73. System.out.println("我是匿名内部类,实现抽象类, 实现完成立马调用");
  74. }
  75. }.method();
  76. //实现接口或抽象类 然后就调用
  77. new B(){
  78. @Override
  79. void method() {
  80. System.out.println("我是匿名内部类,实现抽象类, 实现完成立马调用");
  81. }
  82. //这个方法不能被外部访问,因为匿名内部类没有类名 也就没有类型,但是通过 匿名内部类对象自己调用
  83. public void ff(){
  84. System.out.println("匿名内部类自定义的方法");
  85. }
  86. }.ff();
  87. }
  88. }
  1. package cn.java.money.innerclass.demo01;
  2. // 接口类
  3. interface IA {
  4. void method();
  5. }
  6. // 抽象类
  7. abstract class IB {
  8. abstract void method();
  9. }
  10. public class TestNiMingNeiBuLei2 extends IB implements IA {
  11. //IB IA有同名的方法,可以统一给出一个实现
  12. @Override
  13. public void method() {
  14. System.out.println("IB IA有同名的方法,可以统一给出一个实现");
  15. }
  16. // IB IA有同名的方法,分别给出实现
  17. IA a = () -> {
  18. System.out.println("IA的实现");
  19. };
  20. IB b = new IB() {
  21. @Override
  22. void method() {
  23. System.out.println("IB的实现");
  24. }
  25. };
  26. public static void main(String[] args) {
  27. IA ia = new TestNiMingNeiBuLei2();
  28. IB ib = new TestNiMingNeiBuLei2();
  29. ia.method();
  30. ib.method();
  31. TestNiMingNeiBuLei2 testNiMingNeiBuLei2 = new TestNiMingNeiBuLei2();
  32. testNiMingNeiBuLei2.a.method();
  33. testNiMingNeiBuLei2.b.method();
  34. }
  35. }