欢迎光临我的博客[http://poetize.cn],前端使用Vue2,聊天室使用Vue3,后台使用Spring Boot
前言
内部类是指在一个外部类的内部再定义一个类。外部类不能直接访问内部类的的成员,但可以通过内部类来访问。
内部类可以是静态static的,也可用public,default,protected和private修饰(而外部类只能使用public和缺省的包访问权限)
内部类主要有以下几类(内部类可以自由地访问外部类的成员变量(静态内部类除外),无论是否是private的):
成员内部类:需要先创建了外部类,才能创建它自己的
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
局部内部类:内部类定义在方法和作用域内
静态内部类(只能访问外部类的静态成员变量):不能声明为private
匿名内部类
内部类的好处
内部类有效地实现了"多重继承"。
每个内部类都能独立地继承自一个(接口的)实现。
静态内部类与普通内部类的区别
非静态内部类有一个很大的优点:可以自由使用外部类的所有变量和方法。
当外围类(Outer)的对象创建内部类(Inner)的对象时,
此内部类(Inner)会捕获一个隐式引用,它引用了实例化该内部对象的外围类(Outer)对象。
通过这个指针,可以访问外围类对象的全部状态。
静态内部类不持有外部类的引用,只可以访问外部类的静态方法和静态属性。
静态内部类不依赖外部类。
普通内部类与外部类之间是相互依赖的关系,内部类实例不能脱离外部类实例。
静态内部类是可以独立存在的,即使外部类消亡了,静态内部类还是可以存在的。
普通内部类不能声明static的方法和变量,注意这里说的是变量,常量(也就是final static修饰的属性)还是可以的,
而静态内部类形似外部类,没有任何限制。
为什么普通内部类不能有静态变量
非静态内部类并不随外部类一起加载,只有在实例化外部类之后才会加载。
在外部类并没有实例化,内部类还没有加载的情况下,
这时候如果调用内部类的静态成员或方法,内部类还没有加载。无法调用内部类的静态成员或方法。
内部类的加载
普通内部类在第一次用到时加载,并且每次实例化时都会执行内部成员变量的初始化,以及代码块和构造方法。
内部类也是延时加载:不论是静态内部类还是非静态内部类都是在第一次使用时才会被加载。
匿名内部类
使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口(抽象的或是一个接口)
匿名内部类的定义格式:
接口名称 对象名 = new 接口名称() {
//覆盖重写所有抽象方法
};
匿名内部类就是没有名字的内部类,是局部内部类的一种特殊形式。
1 匿名内部类不能有构造方法。
2 匿名内部类不能定义任何静态成员、方法和类。
3 匿名内部类不能是public,protected,private,static。
4 只能创建匿名内部类的一个实例。
5 一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
内部类初始化:使用构造代码块
内部类初始化
匿名内部类里的final
给匿名内部类传递参数的时候,若该形参在内部类中需要被使用,那么该形参必须要为final。
为了避免引用值发生改变,例如被外部类的方法修改等,而导致内部类得到的值不一致,于是用final来让该引用不可改变
public class Outer {
public void display(final String name,String age) {
class Inner {
void display() {
System.out.println(name);
}
}
}
}
public class OuterClass$InnerClass {
public InnerClass(String name,String age){
this.InnerClass$name = name;
this.InnerClass$age = age;
}
}
内部类并不是直接调用方法传递的参数,而是利用自身的构造器对传入的参数进行备份,
自己内部方法调用的实际上时自己的属性而不是外部方法传递进来的参数。
内部类实现多重继承
public class Son {
class MyFather extends Father{
public int strong(){
return super.strong();
}
}
class MyMother extends Mother{
public int kind(){
return super.kind();
}
}
}