1.成员内部类
成员内部类是最普通的内部类,它定义于另一个类的内部,形式如下
public class Outer {
private int x;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
class inner{
public void say() {
System.out.println("内部类已加载");
}
}
}
成员内部类可以无条件访问外部类的成员属性和成员方法(包括private和静态)
当外部类和内部类存在同一个变量,在访问内部类时,默认访问的是最近的(内部类)。如果想要访问外部类的成员,使用关键字this.
外部类.this.成员变量
外部类.this.成员方法
2.局部内部类
局部内部类是定义在一个方法或一个作用于内的类,它区分于成员内部类的访问权限。
局部内部类就如同方法里的一个局部变量,是不能权限修饰符修饰的。(public、protected、private以及static)
适用场景:当方法需要传入一个接口类型的参数,可是不知道创建一个什么样的具体对象,那么此时需要创建一个实现类
public class Test {
public static void main(String[] args) {
Outer o=new Outer();
class Inner implements Person{
@Override
public void say() {
// TODO Auto-generated method stub
System.out.println("局部内部类");
}
}
Inner i=new Inner();
say(i);
}
public static void say(Person p) {
System.out.println("haha");
}
}
3.匿名内部类
由于匿名内部类没有名字,所以创建后不便于调用,创建格式如下
new 父类构造器(参数列表)implement 实现接口(){
//匿名内部类
};
public class Test {
public static void main(String[] args) {
Person p=new Person(){
public void say() {
System.out.println("匿名内部类");
}
};
p.say();
}
public static void say(Person p) {
System.out.println("haha");
}
}
打印结果:
适用场景:临时使用/使用一次
注意事项:
- 使用匿名内部类时,匿名内部类必须继承或实现一个接口,同时只能实现其中一个。
- 匿名内部类中不能定义构造函数。
- 匿名内部类中不能存在任何静态成员变量和静态方法。
- 匿名内部类与成员内部类具有相似性,所以成员内部类的限制对匿名内部类同样有效,例如权限修饰符。
- 匿名内部类是不可以被修饰为抽象的,它的存在必须要继承或是实现接口中的所有抽象方法。
- 只能访问final修饰的局部变量。(java将源码编译成class文件后,同样,内部类也会被编译成一个单独的class文件,同时会将匿名内部类中用到的局部变量进行备份,如果局部变量发生更改,就会出现逻辑错误。所以在java中,为了保证数据的一致性,想要被内部类访问的局部变量,必须用final修饰)
4.静态内部类
静态内部类也是定义在一个类中的,只不过静态内部类前多了一个static关键字。
静态内部类是不依赖于外部类的对象的,这点和类的静态成员属性和方法有相似之处,由于静态属性和静态方法会在类加载前就创建,所以它不能使用外部类的非static关键词修饰的成员变量或方法。
public class Test {
public static void main(String[] args) {
Outter.Inner inner = new Outter.Inner();
}
}
class Outter {
public Outter() {
}
static class Inner {
public Inner() {
}
}
}