成员内部类
将一个类定义在另一个类内部,
成员内部类可以访问其所在类的内部任何数据信息,私有变量,共有变量,静态变量,以及成员方法,静态方法,等所有属于外部类的代码
对于外部类,如果想要访问内部类的一些方法或者属性,需要先构建好一个内部类对象
public class Outer {
private double radius = 0;
public static int count = 1;
public Outer(){
}
private Inner inner;
public Inner getInnerInstance() {
System.out.println(new Inner().innerVar);
if(inner == null) {
inner = new Inner();
}
return inner;
}
protected class Inner{
private int innerVar;
public Inner() {
Outer.get();
System.out.println(count);
System.out.println(radius);
}
}
private static void get(){
System.out.println("Test");
}
}
成员内部类是完全依靠其外部类存活的,所以想要在外部类之外构建一个内部类,前提条件是,先构建好外部类对象,然后通过外部类对象构建内部类对象。
Outer.Inner inner = new Outer().new Inner();
Q:为什么成员内部类可以无条件的访问外部类?
A:我们在编译Outer.java文件时,会生成两个class文件,一个是Outer.class,还有一个是Outer$Inner.class文件,通过javap -v Outer$Inner.class 文件我们会发现,在Inner class中包含了一个指向OuterClass的引用,虽然我们创建的Innter的构造方法是无参的,但是通过编译出来的构造方法可以看到,里面传递了一个OuterClass对象的引用,这就说明了为什么局部内部类可以对外部类的一切进行访问。
静态内部类
静态内部类是维护在类内部一个类,只不过比成员内部类多了一个static修饰符,静态内部类是不需要依赖于外部类的,静态内部类只能访问外部类的静态变量,静态方法
外部类的静态代码块早于外部类的构造方法,内部类在构建时,获取到内部类对象,才会去执行内部类的静态代码块,以及内部类的构造方法
静态内部类不持有外部类的引用
public class Outer {
private double radius = 0;
public static int count = 1;
public Outer(){
System.out.println("Outer 构造方法!");
}
private Inner inner;
static {
System.out.println("outer class static");
}
public Inner getInnerInstance() {
System.out.println(new Inner().innerVar);
if(inner == null) {
inner = new Inner();
}
return inner;
}
static class Inner{
static {
System.out.println("Inner class static");
}
private int innerVar;
public Inner() {
System.out.println("Inner 构造方法!");
}
}
private static void get(){
System.out.println("Test");
}
public static void main(String[] args) {
Outer outer = new Outer();
System.out.println("====================");
Outer.Inner inner = new Outer.Inner();
}
}
局部内部类
局部内部类是定义在方法内或者说是定义在一个作用域里面,对于局部内部类的访问仅限于方法内或者说作用域内部,类似于方法的一个局部变量,因此,是不可以使用protected,private ,public这种访问修饰符来修饰内部类的
class People{
public People() {
}
}
class Man{
public Man(){
}
public People getWoman(){
class Woman extends People{ //局部内部类
int age =0;
}
return new Woman();
}
}
匿名内部类
匿名内部类在调用的时候,通常是把一个接口或者说一个抽象类的具体实现作为一个对象,放在调用出,所以匿名内部类是没有修饰符,也没有构造方法,只是对继承方法的重写
public class OuterClass {
public InnerClass getInnerClass(final int num,String str2){
return new InnerClass(){
int number = num + 3;
public int getNumber(){
return number;
}
}; /* 注意:分号不能省 */
}
public static void main(String[] args) {
OuterClass out = new OuterClass();
InnerClass inner = out.getInnerClass(2, "chenssy");
System.out.println(inner.getNumber());
}
}
interface InnerClass {
int getNumber();
}
Q:为什么局部内部类和匿名内部类只能访问局部final变量?
A: 当方法中定义的内部类访问的方法局部变量的值, 不是在编译时能确定的字面常量时, 编译器会为内部类增加一个成员变量, 在运行时, 将对外部类方法中局部变量的访问。 转换成对这个内部类成员变量的方法。 这就要求内部类中的这个新增的成员变量和外部类方法中的局部变量具有相同的值。 编译器通过为内部类的构造方法增加参数, 并在调用构造器初始化内部类对象时传入这个参数, 来初始化内部类中的这个成员变量的值。 所以, 虽然在源文件中看起来是访问的外部类方法的局部变量, 其实运行时访问的是内部类对象自己的成员变量。