简单理解:静态成员属于类,非静态成员属于对象,如果要访问外部类的实例成员(非静态成员),当然要先存着外部类对象的.而静态内部类的创建是不需要外部类的对象,因此,如果访问外部类的实例成员,必须通过外部类的实例去访问.
c.在静态内部类中可以定义静态成员和实例成员.
d.测试类可以通过完整的类名直接访问静态内部类的静态成员.
//外部类 class Outter { static String name = "outter"; public Integer age = 17; // 静态内部类:使用static修饰 static class Inner { Inner() { // 静态内部类能直接访问外部类的静态成员 System.out.println(name);// 输出 outter // 访问外部类的实例成员,必须通过外部类的实例去访问. System.out.println(new Outter().age);// 输出 17 } } }
3.3局部内部类(几乎用不到)
1)定义:在方法中定义的内部类,其可见范围是当前方法,和局部变量是同一个级别,所以局部内部类只能在方法中使用.
注意,局部内部类和方法里面的局部变量一样,是不能有public、protected、private以及static修饰符的。
public class InnerDemo3 { public static void main(String[] args) { // 局部内部类 class Inner { } } }
2)特点:
a.局部内部类和实例内部类一样,不能包含静态成员.(局部内部类属于方法,而静态成员属于类)
b.局部内部类和实例内部类,可以访问外部类的所有成员.
c.局部内部类访问的局部变量必须使用final修饰,在Java8中是自动隐式加上final(语法糖).
原因:当方法被调用运行完毕之后,当前方法的栈帧被销毁,方法内部的局部变量的空间全部销毁.但内部类对象可能还在堆内存中,要直到没有被引用时才会消亡.此时就会出现一种情况:内部类要访问一个不存在的局部变量.为了避免该问题,我们使用final修饰局部变量,从而变成常量,永驻内存空间,即使方法销毁之后,该局部变量也在内存中,对象可以继续持有.
public class InnerDemo3 { public static void main(String[] args) { int age = 17; final int num = 15; // 局部内部类 class Inner { public void test() { // 报错:Cannot refer to a non-final variable age inside an inner class defined in a different method System.out.println(age); System.out.println(num);// 正确 } } } }
3.4匿名内部类(使用最频繁)
1):定义:匿名内部类是一个没有名称的局部内部类,适合于只使用一次的类.
2)创建匿名内部类:
匿名内部类本身没有构造器,但是会调用父类构造器.一般来说,匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写.
注意:匿名内部类必须继承一个父类或者实现一个接口,但最多只能一个父类或实现一个接口.
//定义一个接口
interface Person {
public void eat();
}
public class AnonymousDemo {
public static void main(String[] args) {
// 使用匿名内部类
Person p = new Person() {
public void eat() {
System.out.println("eat something");
}
};
p.eat();
}
}
4.总结