类的五大成员
属性、方法、构造器、代码块、内部类
底层源码包含大量的内部类
基本语法
class Outer {
class Inner {
}
}
即在类的内部定义一个类
内部类分类
在外部类的局部位置上
局部内部类(有类名)
比如在方法中定义
public class Main {
Outer outer02 = new Outer;
outer02.ma();
}
class Outer {
private int n1 = 100;
private void m2(){}
public void m1() {//方法
class Inner{//局部内部类,有类名
//1.可以访问外部类的所有成员、包含私有
//2.不能用除final以外的修饰符(不能被继承)
//3.作用域仅在方法或代码块内
public void f1() {
//4.局部内部类可以直接访问外部类的成员
//7.若外部类成员与内部类成员重名时,默认就近,若想访问外部类成员
// 使用“外部类名.this.成员”访问
private int n1 = 7;
System.out.println(n1);//这时由于就近会输出7
m2();
//Outer.this其实就是一个对象,调用m1方法的对象,这里就是outer02
System.out.println(Outer.this.n1);//输出100
}
}
//4.外部类可以创建内部类的实例,调用方法即可
Inner inner1 = new Inner();
inner1.f1();//可以用于反射后调用方法
}
}
- 定义在方法或代码块中
- 作用域在方法体或代码块中
- 本质仍然是个类
匿名内部类(没有类名,重点!!!)
- 本质还是类
- 它是一个内部类
- 它是匿名的
- 该类没有名字(系统帮你取名,系统分配)
- 同时它还是一个对象
- 在局部位置上
基本语法
new 类或接口(参数列表) {
类体
};
基于接口
- 实例
public class AnonymousInnerClass {
public static void main(String[] args) {
outer o1 = new outer();
o1.m1();
}
}
class outer {
private int n1 = 10;
public void m1() {
//基于接口的匿名内部类
/**
* 1.需求使用接口IA,并创建对象
* 传统方法:创建一个类继承接口,创建类的实例对象并使用该方法
* 有一种情况,这个方法只使用一次,去定义类很麻烦,此时使用匿名内部类简化开发
*/
//tiger编译类型:IA
//tiger的运行类型:匿名内部类
/**
* 底层
* class xxxx implements IA {
* @Override
public void cry() {
System.out.println("growling...");
}
* }
* xxxx=外部类名$1,可用tiger.getClass()查看,看到$就知道是匿名内部类
*/
//以下这个new就是创建xxxx$x实例,并把地址(堆里的对象)返回给tiger
//匿名内部类只能用一次,但是tiger这个对象可以反复使用
IA tiger = new IA() {
@Override
public void cry() {
System.out.println("growling...");
}
};
tiger.cry();
tiger.cry();
tiger.cry();
}
}
interface IA {
public void cry();
}
基于类
public class AnonymousInnerClass {
public static void main(String[] args) {
outer o1 = new outer();
o1.m1();
}
}
class outer {
private int n1 = 10;
public void m1() {
Father father = new Father("jack") {
//编译类型:Father
//运行类型:outer$2(不带大括号就是Father)
/**
* class Outer$2 extends Father {
* }
*/
@Override
public void test() {
//动态绑定
System.out.println("重写");
}
};
}
}
class Father{
public Father(String name) {
}
public void test() {
}
}
也可以
new Father("jack") {
@Override
public void test() {
System.out.println("重写");
}
}.test();
还可以super.方法名()这样会调用父类方法
定义在外部类成员位置上
成员内部类(没有static修饰)
外部类对象名.内部类名 对象 = 外部类对象名.new 内部类名();或者在外部类编写相应的内部类访问方法
静态内部类(使用static修饰)
只能直接访问外部类的静态成员