1.内部类
内部类有三种,成员内部类,静态内部类,方法内部类。还有就是匿名内部类。
<span style="font-size:14px;">public class Outter {
class inner1 {
}
static class inner2 {
}
public void show() {
int j = 10;
final int i = 5;
class inner3 {
public void out() {
System.out.println(i);
// System.out.println(j);
}
}
inner3 inner = new inner3();
}
}</span>
这里可以看出 inner1,是成员内部类,inner2是静态内部类,inner3是方法内部类。
实现方式如下:
public static void main(String[] args) {
Outter out = new Outter();
//非静态内部类的实现
Outter.inner1 inner1= out.new inner1();
//静态内部类的实现
Outter.inner2 inner2= new Outter.inner2();
}
仔细分析一下,其实成员内部类和成员变量是一样的,我们只用成员变量的方法来实力调用。静态内部类,和静态变量是一样的,我们可以通过类直接对其进行调用,同时你可以(注意一点new要放在调用的前面)。这样就实现了内部类。至于方法内部类,是不能在外部调用的,你的方法中的变量什么时候在外部调用了。还有一点方法内部类要写在调用的前面因为,方法内部是逐句执行的。
内部类的实现,你已经明白了。但是你会发现我在方法内注掉了一行输出j。因为,内部类内部不能访问外部非final的变量。为什么呢?下面解释一下。
这是一个内存图,(很lower)。因为你的方法是在方法栈中,我们的方法执行完以后就会弹栈。但是此时你的内部类的方法不一定会执行完, 如runnable。这时候,外部方法中的变量已经消失,你对消失的变量进行修改是没有意义的。而制定位final我们可以认为内部类中的方法只是用这个值,会在内部类中创建这个变量的复制品(可以反编译看class源码)。
这是你有肯能问我引用类型是可以改内部属性的,这是因为我们的内部复制,指定是原来的空间(也就是浅复制),这样gc不会回收对中的对象(就是final修饰的变量)。这就是java为什么内部类访问外部用final修饰了。
匿名内部类
public class Test2 {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
}
}).start();
}
}
就是方法内部类的一种简写,调用和实例一体。