做题目时经常遇到,始终没能完全搞清楚,这里总结一下
内部分类:
成员内部类
静态内部类
局部内部类
匿名内部类
成员内部类
相当于外部类的一个成员变量,可以用任意访问修饰符
定义的方法可以直接访问外部类的数据,不受访问控制符的影响,比如private
成员内部类的成员不能声明为static的
在外部类的静态成员使用内部类时,内部类要该为静态内部类
编译上述语句后产生两个.class文件:Outer.class,Outer$Inner.class{}
在内部类里默认访问自己的成员变量或方法,要访问外部类的,用外部类对象.this.name
public class Outer{
private int age = 18;
String name = "wang";
public class Inner{
String name = "wan";
//static String name = "wan";//不能使用static修饰成员变量和方法
public void method(){
System.out.println(Outer.this.name);//使用外部类成员:外部类名.this.成员
System.out.println(name);//默认使用内部类的成员
System.out.println(age);//内部类没有的话就用外部类的
}
}
public Inner getInnerClass(){
return new Inner();//外部类要先创建内部类对象才能访问内部类
}
public static void main(String[] args){
Outer outer = new Outer();
Inner in = outer.new Inner();//内部类 对象名 = 外部类对象.new 内部类()
in.method();
}
}
静态内部类
只能访问外部静态成员
属于外部类本身,不属于外部类某个对象
静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法。
class Outter {
public static void main(String[] args) {
Outter.Inner inner = new Outter.Inner();
}
static class Inner {
public Inner() {}
}
}
静态内部类实现延迟加载单例模式
静态内部类和成员内部类一样,都不会因为外部类的加载而加载,在使用时才加载。在加载静态内部类时也会加载外部类。
public class SingletonIniti {
private SingletonIniti() {}
private static class SingletonHolder {
private static final SingletonIniti INSTANCE = neSingletonIniti();
}
public static SingletonIniti getInstance() {
return SingletonHolder.INSTANCE;
}
}
局部内部类
其作用域仅限于方法内,方法外部无法访问该内部类
不能有public、protected、private 以及 static 修饰符
只能访问方法中的final的局部变量,因为方法调用完了后就没了,而局部内部类还可以存在
在内部类中的属性和外部方法的参数两者从外表上看是同一个东西,但实际上却不是,所以他们两者是可以任意变化的, 也就是说在内部类中我对属性的改变并不会影响到外部的形参,而然这从程序员的角度来看这是不可行的,毕竟站在程序的角度来看这两个根本就是同一个,如果内部类该变了,而外部方法的形参却没有改变这是难以理解和不可接受的,所以为了保持参数的一致性,就规定使用 final 来避免形参的不改变
注意:在JDK8版本之中,方法内部类中调用方法中的局部变量,可以不需要修饰为 final,匿名内部类也是一样的,主要是JDK8之后增加了 Effectively final 功能
反编译jdk8编译之后的class文件,发现内部类引用外部的局部变量都是 final 修饰的
public class Outer{
public void Show(){
final int a = 25;
int b = 13;
class Inner{
int c = 2;
public void print(){
System.out.println("访问外部类:" + a);
System.out.println("访问内部类:" + c);
}
}
Inner i = new Inner();
i.print();
}
public static void main(String[] args){
Outer o = new Outer();
o.show();
}
}
匿名内部类
new 类/接口{
//写了一堆东西;
};
只能访问局部final变量(JDK8开始可以不用final,系统默认加了)
不能有构造方法
不能定义任何静态的成员、方法
只能创建一个实例
必须且只能继承一个类或者实现一个接口
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();
}