文章目录
- JAVA内部类
- 静态内部类
- 成员内部类
- 约束
- 局部内部类
- 约束
- 匿名内部类
JAVA内部类
JAVA类中不仅可以定义变量和方法,还可以定义类,这样定义在类内部的类就被称为内部类。根据定义的方式不同,内部类按照一般区分,大致可分为一下四类:
- 静态内部类
- 成员内部类
- 局部内部类
- 匿名内部类
每个内部类都能独立地继承一个实现,所以无论外围类是否已经继承了某个实现,对于内部类都没有影响。内部类使得多重继承的解决方案时变得更加完整。
静态内部类
定义在类内部的静态类,相当于static修饰的成员内部类,可以用静态变量来类比,称之为“嵌套内部类”。非静态内部类在编译完成后会隐含着保存一个引用,该引用是指向创建它的外部类,但是静态内部类却没有,它的创建是不需要依赖于外部类的。
public class StaticInnerClass {
private static int a = 10;
private int b = 20;
public void test() {
// 外部类中的方法中可直接使用
InnerClass.print();
}
public static class InnerClass {
public static void print() {
System.out.println(a);
}
}
}
public class Test
{
public static void main(String[] args) {
StaticInnerClass.InnerClass innerClass = new StaticInnerClass.InnerClass();
innerClass.test();
}
}
- 静态内部类可以访问外部类所有的静态变量和方法,即使是private的也一样。
- 静态内部类和一般类一致,可以定义静态变量、方法、构造方法等。
- 其他类使用静态内部类需要使用“外部类.静态内部类“方式,如下所示:
Out.Inner inner = new Out.Inner();
inner.print(); - Java集合类HashMap内部就有一个静态内部类Entry,Entry是HashMap存放元素的抽象,HashMap内部维护Entry数组用来存放元素,但是Entry对使用者是透明的。像这种和外部类关系密切,且不依赖外部类实例的,都可以使用静态内部类。
成员内部类
定义在类内部的非静态类,可以类比为成员变量来理解。成员内部类不能定义静态方法和变量(final修饰的除外)。它是外部类的一个成员,所以他是可以无限制的访问外部类的所有成员属性和方法,尽管是private的,但是外围类药访问内部类的成员属性和方法则需要通过内部类实例来访问。
public class MemberInnerClass {
private int num = 10;
private class PrivateMemberClass {
//TODO:不允许使用static修饰任何其中的属性或方法
static int a;
static void test() { a = 10; }
}
public class PublicMemberClass {
private int num = 20;
public void printThisNum() {
System.out.println(this.num); //20
System.out.println(MemberInnerClass.this.num); //10
}
}
}
public class Test
{
public static void main(String[] args) {
//TODO:必须要利用外部类的对象通过.new来创建内部类
MemberInnerClass memberInnerClass = new MemberInnerClass();
MemberInnerClass.PublicMemberClass publicMemberClass = memberInnerClass.new PublicMemberClass();
}
}
约束
- 成员内部类的类定义没有任何约束,可以声明为public、private,甚至是abstract和interface,以及继承外部类,定义十分宽松。
- 对于内部属性和方法是有约束的,其不能使用static来修饰任何成员内部类的属性和方法,也就是说不能存在静态属性和方法。类初始化的时候先出初始化静态成员,如果允许成员内部类定义静态变量,那么成员内部类的静态变量出实话顺序是有歧义的。
- 成员内部类也存在this指针,但是这个指针指向的是自己的引用,如果想访问外部类中的属性或方法,需要使用外部类名.this来访问。
- 同时如果我们需要创建内部类对象,必须要利用外部类的对象通过.new来创建内部类
局部内部类
定义在方法中的类,如果一个类只能在某个方法中使用,则可以考虑使用局部,可类比局部变量。
public class LocalInnerClass {
public void publicMethod() {
//TODO:其类上不允许有任何修饰符,不允许声明为接口
public class InnerClass{}
interface InnerInterface{}
//TODO:但是可以使用abstract将类声明为抽象类
abstract class InnerClass {}
}
public static void publicStaticMethod() {
class InnerClass {
//TODO:不允许使用static来声明成员变量和方法
static int a;
static void print();
int b;
}
InnerClass innerClass = new InnerClass();
}
}
约束
- 其类上不允许有任何修饰符,但是可以使用abstract将类声明为抽象类
- 不允许将局部内部类声明为接口
- 不允许使用static来声明成员变量和方法
- 可以将局部内部类声明在静态方法中
- 任意两个方法中的局部内部类可以重名
匿名内部类
匿名内部类我们必须要继承一个父类或者实现一个接口,当然也仅能只继承一个父类或实现一个接口。同时它也是没有class关键字,因为匿名内部类是直接使用new来生成一个对象的引用。它与局部类很相似,不同的是它没有类名,如果某个局部类你只需要使用一次,那么你就可以使用匿名内部类。
public class AnonymousInnerClass {
public void method(int num) {
new InnerInterface() {
@Override
public void print(int num) {
System.out.println(num + 1);
}
}.print(num);
}
public static void main(String[] args) {
new AnonymousInnerClass().method(1);
}
interface InnerInterface {
public void print(int num);
}
}