- 定义在类内部的类 就是内部类
- 成员内部类(实例内部类和静态内部类)字节码文件:外部类类名$内部类类名.class
- 局部内部类的字节码文件:外部类类名$N内部类类名.class
- 匿名内部类的字节码文件:外部类类名$N.class
- 实例内部类
- 实例内部类内部不允许定义任何静态内容
- 外部类静态方法中不能直接访问实例内部类数据
- static final 修饰的变量的值,能在编译器确定值,可以在实例内部类中定义
- 静态内部类
- 被static修饰的成员内部类
- 只有内部类可以被static修饰
- 匿名内部类
/**
- 内部类位置:
- 成员位置 —- 成员内部类 静态内部类
- 局部位置 —- 局部内部类 (方法内部类)
- 内部类的访问特点:
- 1.0 内部类可以直接访问外部类的成员(成员变量,成员方法),包括私有的。
2.0 外部类要访问内部类的成员,必须创建对象. */ // public 和 default public class Outer { private int num = 10; private static int num2 = 10;
public void method2() {
System.out.println("我是外部类的方法 method2");
}
public static void method3() {
System.out.println("我是外部类的静态方法 method3");
}
public void method4() {
// 外部类中访问内部类中的成员,必须创建内部类对象// 访问成员内部类中的成员Inner inner = new Inner();inner.method();System.out.println(inner.num);// 静态内部类也要创建对象 才能使用Inner3 inner3 = new Inner3();inner3.method();
}
//成员内部类 //成员内部类的修饰符:public private protected default 都可以使用 public class Inner {
public int num = 11;// 内部类中不能有静态成员变量声明//public static int num2 = 11;public void method() {System.out.println("我是成员内部类");//成员内部类 可以访问外部的所有变量和方法System.out.println(num);method2();//成员内部类 可以访问外部类的静态变量和静态方法System.out.println(num2);//每一个内部类对象中都隐含了一个外部类对象System.out.println(Outer.this.num2);method3();}
}
//静态内部类: 属于外部类本身,不属于外部类某个对象 public static class Inner3 {
public void method() {System.out.println("我是静态内部类");// 编译报错, Inner3 是静态成员类,要访问外部类的非静态变量或方法 都会报错//System.out.println(num);// 编译报错// method2();//静态内部类 只能访问外部类静态成员System.out.println(num2);method3();}
}
public void method1() {
// 局部变量:包括方法里的和 代码块里的(静态和非静态), 可以被default(默认不写), final修饰final int ii = 0;int ii2 = 0;//局部内部类//方法内部类只能在该方法内部使用,所以不能使用访问控制符(public等)和修饰符(static);//就像是局部变量,在方法外部是无法访问的。class Inner2 {public void method() {System.out.println("我是局部内部类");//局部内部类 可以访问外部的所有变量和方法System.out.println(num);method2();//局部内部类 可以访问外部类的静态变量和静态方法System.out.println(num2);method3();//可以访问被声明为final的局部变量.// 原因说明:局部变量在栈中,而局部变量new以后在堆上,方法调用完成以后局部变量就释放了,而局部内部类的对象不一定被回收。// final修饰局部变量, 局部变量变为一个常量,因此在编译的时候,局部内部类就使用这个常量。// jdk 1.8以后, 如果局部内部类使用了方法的局部变量,在编译的时候会自动加上final。System.out.println(ii);System.out.println(ii2); // jdk1.8 以前必须要显示声明为final,jdk1.8以后不用显示声明//Java 中局部内部类和匿名内部类访问的局部变量必须由 final 修饰,以保证内部类和外部类的数据一致性。// 但从 Java 8 开始,我们可以不加 final 修饰符,由系统默认添加,当然这在 Java 8 以前的版本是不允许的。// Java 将这个功能称为 Effectively final 功能。}}//局部内部类只能在局部范围使用Inner2 inner2 = new Inner2();inner2.method();
}
}
```javapackage cn.java.money.innerclass.demo01;public class TestOuter {public static void main(String[] args) {//成员内部类 实例化: 外部类.内部类 obj = new 外部类().new 内部类()Outer.Inner obj = new Outer().new Inner(); // 因为 Inner 被public修饰,所以可以在外部类以外使用// 调用成员内部类的方法obj.method();System.out.println("--------------------------------------");// 调用局部内部类中方法,通过调用外部类的方法,间接的调用Outer outer = new Outer();outer.method1();System.out.println("--------------------------------------");//静态内部类 实例化Outer.Inner3 obj2 = new Outer.Inner3();obj2.method();System.out.println("--------------------------------------");outer.method4();}}
匿名内部类
package cn.java.money.innerclass.demo01;// 接口类interface A {void method();}// 抽象类abstract class B {B(){}//有参构造B(int n){}abstract void method();}// 普通类class C{public void method (){System.out.println("我是普通类的普通方法");}}public class TestNiMingNeiBuLei {// 定义成员变量 执行匿名对象// 匿名内部类的本质:接口和抽象类的实现。A a = new A() {@Overridepublic void method() {System.out.println("我是匿名内部类 实现接口");}};// 因为接口只有一个方法,因此可以简写为 lambda 表达式A a2 = () -> System.out.println("我是匿名内部类,实现接口");// b指向b的实现类的对象B b = new B() {@Overridevoid method() {System.out.println("我是匿名内部类,实现抽象类");}};//可以是静态的static B b2 = new B() {@Overridevoid method() {System.out.println("我是匿名内部类,实现抽象类");}//这个方法不能被外部 b2 访问,因为匿名内部类没有类名 也就没有类型public void ff(){System.out.println("匿名内部类自定义的方法");}};// 调用有参构造B b3 = new B(45) {@Overridevoid method() {System.out.println("我是匿名内部类,实现抽象类");}};C c = new C() {@Overridepublic void method (){System.out.println("我是普通类的普通方法 在匿名内部类中的重写");}};public static void main(String[] args) {TestNiMingNeiBuLei testNiMingNeiBuLei = new TestNiMingNeiBuLei();testNiMingNeiBuLei.a.method();testNiMingNeiBuLei.a2.method();testNiMingNeiBuLei.b.method();testNiMingNeiBuLei.c.method();//实现接口或抽象类 然后就调用new B(){@Overridevoid method() {System.out.println("我是匿名内部类,实现抽象类, 实现完成立马调用");}}.method();//实现接口或抽象类 然后就调用new B(){@Overridevoid method() {System.out.println("我是匿名内部类,实现抽象类, 实现完成立马调用");}//这个方法不能被外部访问,因为匿名内部类没有类名 也就没有类型,但是通过 匿名内部类对象自己调用public void ff(){System.out.println("匿名内部类自定义的方法");}}.ff();}}
package cn.java.money.innerclass.demo01;// 接口类interface IA {void method();}// 抽象类abstract class IB {abstract void method();}public class TestNiMingNeiBuLei2 extends IB implements IA {//IB IA有同名的方法,可以统一给出一个实现@Overridepublic void method() {System.out.println("IB IA有同名的方法,可以统一给出一个实现");}// IB IA有同名的方法,分别给出实现IA a = () -> {System.out.println("IA的实现");};IB b = new IB() {@Overridevoid method() {System.out.println("IB的实现");}};public static void main(String[] args) {IA ia = new TestNiMingNeiBuLei2();IB ib = new TestNiMingNeiBuLei2();ia.method();ib.method();TestNiMingNeiBuLei2 testNiMingNeiBuLei2 = new TestNiMingNeiBuLei2();testNiMingNeiBuLei2.a.method();testNiMingNeiBuLei2.b.method();}}
