- 定义在类内部的类 就是内部类
- 成员内部类(实例内部类和静态内部类)字节码文件:外部类类名$内部类类名.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();
}
}
```java
package 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() {
@Override
public void method() {
System.out.println("我是匿名内部类 实现接口");
}
};
// 因为接口只有一个方法,因此可以简写为 lambda 表达式
A a2 = () -> System.out.println("我是匿名内部类,实现接口");
// b指向b的实现类的对象
B b = new B() {
@Override
void method() {
System.out.println("我是匿名内部类,实现抽象类");
}
};
//可以是静态的
static B b2 = new B() {
@Override
void method() {
System.out.println("我是匿名内部类,实现抽象类");
}
//这个方法不能被外部 b2 访问,因为匿名内部类没有类名 也就没有类型
public void ff(){
System.out.println("匿名内部类自定义的方法");
}
};
// 调用有参构造
B b3 = new B(45) {
@Override
void method() {
System.out.println("我是匿名内部类,实现抽象类");
}
};
C c = new C() {
@Override
public 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(){
@Override
void method() {
System.out.println("我是匿名内部类,实现抽象类, 实现完成立马调用");
}
}.method();
//实现接口或抽象类 然后就调用
new B(){
@Override
void 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有同名的方法,可以统一给出一个实现
@Override
public void method() {
System.out.println("IB IA有同名的方法,可以统一给出一个实现");
}
// IB IA有同名的方法,分别给出实现
IA a = () -> {
System.out.println("IA的实现");
};
IB b = new IB() {
@Override
void 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();
}
}