内部类
1.成员内部类
概念:
一个类的内部出现了另一个类的定义
[所谓内部类就是在一个类内部进行其他类结构的嵌套操作]
public class Test{
public static void main(String[] args) {
A a=new A();
a.fun2();
A.B b=new A().new B();
b.fun1();
}
}
class A {
private int x=11;
static int z=300; //静态成员变量
public void fun2() {
System.out.println(x);
B b=new B();
System.out.println(b.y);
}
class B{ //1.成员内部类
private int x=300;
private int y=200;
public void fun1() {
System.out.println(A.this.x);
System.out.println(this.x);
System.out.println(y);
System.out.println(z);
}
}
}
① 成员内部类B被定义在一个 A 类的内部,与外部 A 类的属性和方法处于同一个级别,类似于一个类的成员 所以我们称其为 成员内部类;
② 成员内部类可以访问外部类的所有成员 包括私有成员;
③ 如果成员内部类和外部类之间存在同名成员
可以使用”this”和 ”外部类名.this”来区分成员的归属
④ 成员内部类和外部类的数据是可以相互访问的
在成员内部类中可以直接访问外部类数据和方法
在外部类中去放问内部类数据需要借助于内部类的对象
⑤ 关于成员内部类的创建问题:
在外部类的内部创建成员内部类对象 就像普通对象一样直接创建
如:B b=new B();
在外部类的外部创建成员内部类对象
外部类.内部类 内部类对象 = new 外部类().new 内部类();
如: 在 Test 类的 main 方法中:A.B b=new A().new B();
我们观察到:new B()之前是 new A() 说明:内部类对象创建依赖于外部类对象
即:成员内部类是依附外部类的 只有创建了外部类才能创建内部类
⑥ 成员内部类内部不允许存在任何 static 成员 [属性 | 方法]
[但可以调用外部类的静态成员]
⑦ 如果内部类被私有化 那么这个内部类在外部类的外部将不可被访问 只在当前外部类中可见
备注:成员内部类在编译完成之后会隐含的保存着一个引用 该引用是指向创建它的外部类
成员内部类持有的外部类引用 是通过其在构造器中隐式传入将外部类实现的
2.静态内部类
概念:
使用 static 修饰的内部类我们称之为静态内部类
[成员内部类上修饰有 static 关键字 即为静态内部类]
public class Test{
public static void main(String[] args) {
A a=new A();
a.fun2();
A.C c=new A.C();
}
}
class A {
private int x=11;
static int z=300; //静态成员变量
public void fun2() {
System.out.println(x);
C.fun3();
new C().fun4();
}
static class C{//2.静态内部类
static int x1=200;
int x2=400;
public static void fun3() {
System.out.println(x1);
System.out.println(new C().x2);
}
public void fun4() {
System.out.println(x1);
System.out.println(x2);
System.out.println(z);
}
}
}
① 相比于成员内部类[不能出现静态成员] 静态内部类中既可以出现静态成员 也可以出现实例成员
② 关于静态内部类的创建问题:
在外部类的内部创建静态内部类对象 就像普通对象一样直接创建 如:C b=new C();
在外部类的外部创建静态内部类对象 外部类.内部类 内部类对象 = new 外部类.内部类();
如: A.C c=new A.C();
③ 静态内部类和成员内部类之间存在一个最大的区别
成员内部类在编译完成之后会隐含的保存着一个引用 该引用是指向创建它的外部类 但是静态内部类没有
意味着:
->静态内部类的创建不需要依赖外部类可以直接创建 [A.C c=new A.C() - 可以证明]
->静态内部类不可以访问任何外部类的实例成员(属性|方法) 但可以访问自己的实例成员
3.局部[方法]内部类
概念:
定义在外部类方法中的类
public class Test{
public static void main(String[] args) {
A a=new A();
a.fun(111);
}
}
class A{
int num1=11;
static int num2=300; //静态成员变量
public void fun(final int num) { //JDK1.8 隐式将方法形参标注为final
int num3=200; //隐式final
class D{ //3.局部内部类 访问修饰符只能使用缺省的
public int num4=100;
public void fun5() {
System.out.println(num1); //所在方法所在类的实例成员
System.out.println(num2); //所在方法所在类的静态成员
System.out.println(num3); //所在方法的局部变量
System.out.println(num4); //内部类自己的成员
System.out.println(num); //所在方法的形参变量
}
}
new D().fun5(); //局部内部类的可见范围仅为当前方法中
}
}
① 对比前面的成员内部类 和 静态内部类 [可以 public protecte 缺省的 以及 private 访问修饰符]
但 局部内部类只能使用缺省的访问权限修饰符
② 局部内部类如果想要使用所在方法的形参
该形参必须使用 final 声明(考虑到生命周期的问题.防止方法的二次调用数据不一致;防止数据被释放后,还有人进行篡改)
[JDK8 形参变为隐式 final 声明]
4.匿名内部类
概念:
不带名字的局部内部类 一般而言 匿名内部类是对接口或抽象类的实现
特点和局部内部类完全一致,除此之外,还有自己的特点:
A. 匿名内部类必须继承一个抽象类或者实现一个接口
B. 匿名内部类没有类名,因此没有构造方法
interface IA{
public void fun1();
}
class A{
public void test() {
new IA() {
public void fun1() {
System.out.println("hello world...");
}
}.fun1();
}
}