对于初学者而言,感觉内部类是多余的,但是随着对内部类的逐渐了解,就会发现他有独到的用处,学会使用内部类,是掌握Java高级编程的一部分,他能够让程序变得更优雅。
顶层类只能处于public和默认访问级别,而成员内部类可以处于public,protected,默认,private访问级别。
在外部类中可以直接使用内部类。 内部类的完整类名为: OuterClass.InnerClass
成员内部类分为 实例内部类和静态内部类,后者被static修饰。
实例内部类
1,在创建实例内部类的时候,外部类的实例必须存在。
2,实例内部类的实例自动持有外部类的实例引用。在内部类中可以自动引用外部类的成员变量和成员方法。在实例内部类中之所以能够直接引用外部类的成员变量和成员方法,是因为实例化内部类的使用,外部类已经实力化类。
3,外部类不能直接访问内部类的成员,必须通过内部类的实例来访问。
4,实例内部类中不能定义静态成员。
5,内部类和外部了有同名的成员时,在内部类中通过this.v访问内部类的成员变量,在内部类中通过 Outer.this.v访问外部类的成员。
静态内部类
1,静态内部类不会自动持有外部类特定实例的引用,在创建内部类的实例时,不必创建外部类的实例。
2,静态内部类可以直接访问外部类的静态成员,如果访问外部类的实例成员,则需要通过外部类的对象。
3,在静态内部类中可以定义静态变量和实例变量。
4,客户类可以通过完整的类名直接访问静态内部类的静态成员。
局部内部类
局部内部类是一个在方法中定义的内部类,它的范围是当前方法。和局部变量一样,局部内部类不用用访问控制符修饰,也不能用static修饰。
1,局部内部类只能在当前方法中使用。
2,局部内部类和实例内部类一样,不能包含静态成员。
3,可以访问外部类的所有成员。
4,局部内部类可以访问所在方法的符合一下方法的参数。
4.1,用final修饰的变量。
4.2,实际上的最终变量和参数:虽然没有用final修饰,但是程序不会修改变量的值。
子父类中的内部类同名
1,内部类不存在覆盖,如果子类和父类存在同名的内部类,那么这两个内部类有不同的命名空间,不会发生冲突。
匿名类
匿名类是一种特殊的内部类,这种类没有名字。
public class A {
A(int v) { System.out.println("another constructor");}
A() { System.out.println("default constructor");}
void method(){ System.out.println("from A"); }
public static void main(String[] args) {
new A().method();//打印结果:from A
A a=new A(){
void method(){ System.out.println("from 匿名类"); }
};
a.method();//打印结果:from 匿名类
}
}
1,匿名类没有构造方法,但是他会调用父类的构造方法。
2,匿名类虽然没有构造方法,但是可以在匿名类中提供一段实例初始化代码使用 { } 包围的代码快,JVM会在调用父类构造方法的时候执行这段代码。
3,除了可以在外部类的方法内定义匿名类,还可以在声明一个成员变量的时候定义匿名类。
4,匿名类除了可以继承类,还可以实现接口。
5,匿名类和局部类一样,可以访问外部类的所有成员,如果匿名类位于一个方法中,还可以访问所在方法的最终变量和参数,或者实际上的最终变量和参数。
6,局部内部类的名字在方法外是不可见的,隐藏匿名类也一样,能够起到封装类型名字的作用,局部内部类盒匿名类有一下区别:
6.1:匿名类程序代码比较简短。
6.2:一个局部内部类可以有多个重构方法,并且客户类可以多次创建局部内部类的实例。而匿名类没有重载构造方法,并且只能创建一次实例。
内部类的用途
1,封装类型:
面向对象的核心之一是封装:把所有不希望对外公开的细节封装起来。
2,直接访问外部类的成员:
3,回调:
回调实际上是指一个类尽管实际上实现了某种方法,但是没有直接提供相应的接口,客户类可以通过这个类的内部类的接口来获取这个功能,而这个内部类本身没有提供真实的实现,仅仅调用外部的实现。可见,回调充分发挥了内部类具有访问外部类的实现细节的优势。
回调实例:
public interface Adjustable {
/** 调节温度 */
public void adjust(int temperature);
}
public class Base {
private int speed;
/** 条件速度*/
public void adjust(int speed){
System.out.println("调节速度");
this.speed=speed;
}
}
public class Sub extends Base {
private int temperature;
private void adjustTemperature(int temperature) {
this.temperature = temperature;
}
private class Closure implements Adjustable {
@Override
public void adjust(int temperature) {
System.out.println("调节温度");
adjustTemperature(temperature);
}
}
public Adjustable getCallBackReference() {
return new Closure();
}
}
public class Running {
public static void main(String[] args) {
Sub sub = new Sub();
Adjustable callBackReference = sub.getCallBackReference();
callBackReference.adjust(15);
sub.adjust(14);
}
}