目录
什么是内部类
Java 编程语言允许将一个类的定义放在另一个类的定义内部,这个类就是称之为内部类。内部类是一种非常有用的特性,因为它允许你吧一些逻辑相关的类组织在一起,并控制位于内部的类的可视性。内部类如果被static修饰就称之为静态内部类,否则就是非静态内部类;非静态内部类又可以分为成员内部类、方法内部类和匿名内部类。语法格式如下:
类OuterClass {
...
类 InnerClass {
...
}
}
static关键字
static 关键字的作用就是方便在没有创建对象的时候进行方法调用(方法,属性),也就是说static 修饰的方法是没有this的,它不依赖于任何对象仅依赖于类。static不能修饰局部变量,这个是JAVA的语法规范要求,同时局部变量和static语法含义存在冲突。
static 方法就是没有 this 的方法。在 static 方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用 static 方法。这实际上正是 static 方法的主要用途。
静态内部类
被static修饰的内部类称之为静态内部类,静态内部类对象独立于外部类对象,可以通过 new 外部类.静态内部类() 创建静态内部对象;
静态内部类特点
-
静态内部类只能访问外部类静态成员变量,而不能访问普通成员变量;如果需要访问外部类普通成员变量可以通过外部类实例去访问
-
静态内部类可以定义普通成员变量也可以定义静态成员变量,可以通过外部类.内部类.静态成员变量 访问内部类的静态成员变量
-
静态内部类可以定义静态方法
-
静态内部类可以有构造方法
静态内部类可以定义静态属性也可以定义静态方法以及构造方法;
public class OuterClass {
String outerField = "Outer field";
static String staticOuterField = "Static Outer field";
static class StaticNestedClass {
private static String n = "Static Field";
private String a;
StaticNestedClass(String a) {
this.a = a;
}
void accessMemebers(OuterClass outerClass) {
//编译错误,无法访问外部类的非静态成员变量
// System.out.println(outerField);
//可以直接访问外部类静态成员变量,如果内部类有同名静态成员变量则优先访问内部类成员变量,外部类成员变量则需要使用 OuterClass.staticOuterField
System.out.println(staticOuterField);
//只能通过外部类实例去访问外部类普通成员变量
System.out.println(outerClass.outerField);
}
static void print() {
System.out.println("test static Method");
}
}
代码执行结果:
static nested class:
-------------------------
Static Field
Static Outer field
Outer field
test static Method
成员内部类
成员内部类就是最普通的内部类,也可以称之为普通内部类;内部类对象不能独立于外部类实例,可以通过外部类实例.new 内部类() 创建内部类实例。
成员内部类特点
- 内部类拥有外部类所有成员不管是普通成员还是静态成员的访问权限,如果出现同名成员优先访问内部类,可以通过 外部类.this.成员 去访问外部类成员变量或方法
- 内部类不能定义静态成员变量也不能定义静态方法
- 外部类不能直接访问内部类成员变量必须通过内部类实例去访问
- 可以是抽象内部类,即可以有抽象方法
代码示例
public class OuterClass {
String outerField = "Outer field";
static String staticOuterField = "Static Outer field";
public static void main(String[] args) {
System.out.println("Inner class :");
System.out.println("-------------");
OuterClass outerObject = new OuterClass();
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
innerObject.accessMembers();
}
class InnerClass {
//编译错误,内部类不能声明静态成员变量
//private static a="test";
public String fieldB;
void accessMembers() {
System.out.println(outerField);
System.out.println(staticOuterField);
}
//普通内部类不能定义静态方法
// public static void printA(){
//
// }
}
}
执行结果:
Inner class :
-------------
Outer field
Static Outer field
方法内部类
方法内部类顾名思义就是定义在方法内的内部类,它的作用域就在方法内;也称之为局部内部类。
方法内部类的特点
- 方法内部类不能有访问权限修饰符
public class OuterClass {
String outerField = "Outer field";
static String staticOuterField = "Static Outer field";
public void outerMethod() {
String test = "a";
class InnerClass {
//编译错误,内部类不能声明静态成员变量
//private static a="test";
public String fieldB;
void accessMembers() {
System.out.println(outerField);
System.out.println(staticOuterField);
}
//普通内部类不能定义静态方法
// public static void printA(){
//
// }
}
InnerClass innerObject = new InnerClass();
innerObject.accessMembers();
}
public static void main(String[] args) {
System.out.println("Inner class :");
System.out.println("-------------");
new OuterClass().outerMethod();
}
}
匿名内部类
匿名内部类顾名思义这个内部类没有名字;在有些场景下针对需要继承抽象类或接口的内部类只需要进行一次实例化,此时我们就可以创建一个匿名内部类。
匿名内部类特点
- 无法添加构造方法,注意 这里不是没有构造方法,它有默认构造方法,有些书籍上说它没有构造方法是完全错误的。
- 匿名内部类可以实现接口,也可以继承抽象类,鱼与熊掌不可兼得,不能既继承抽象类又实现接口
- 不能有静态成员也不能有抽象方法
public class OuterClass {
public static void main(String[] args) {
Arrays.asList(5, 1, 10).sort(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
});
}
}
为什么需要内部类
- 可以使用内部类进行逻辑分组
- 通过内部类控制访问权限,增加封装性
- 提升代码可读性以及可维护性
- 可以通过内部类解决多继承问题
- 可以使用多个内部类以不同方式实现同一个接口或继承自同一个类