一、内部类
内部类(Inner Class)是定义在另一个类(外部类)内部的类。内部类可以访问外部类的成员(包括私有成员),因为它们位于同一个类中。内部类可以是静态的,也可以是非静态的。非静态内部类(也称为实例内部类)隐式地持有对外部类实例的引用,而静态内部类则不会持有外部类的实例引用。
内部类可以分为以下四种类型:
- 成员内部类:在外部类的成员位置定义的类,可以被任意访问修饰符修饰。成员内部类可以访问外部类的所有成员。
- 静态内部类:在外部类的成员位置定义的用static修饰的类。静态内部类不能访问外部类的非静态成员,但可以访问外部类的静态成员。
- 局部内部类:在外部类的方法体内定义的类。局部内部类只能访问外部类的成员以及方法内的final局部变量。
- 匿名内部类:没有名称的内部类,通常用于实现接口或继承类的简化版本。匿名内部类可以访问外部类的成员以及方法内的final局部变量。
类的五大成员指的是一个类的五种基本组成部分:
- 属性(Field):类的属性是用于描述类的状态或特征的变量。属性可以被赋予不同的访问修饰符(如public、private、protected),限制其访问范围。
- 方法(Method):类的方法是用于实现类的行为或操作的函数。方法可以被赋予不同的访问修饰符,限制其访问范围。方法可以是实例方法(需要对象调用)或静态方法(可以直接通过类名调用)。
- 构造方法(Constructor):类的构造方法是用于初始化类的实例的特殊方法。构造方法的名称与类名相同,没有返回类型。一个类可以有多个构造方法,以支持不同方式的初始化。
- 内部类(Inner Class):如前所述,内部类是定义在另一个类内部的类。内部类可以访问外部类的成员,也可以有自己的成员。
- 代码块(Block):代码块是一组在类中定义的语句。代码块可以是普通的代码块、静态代码块或实例代码块。静态代码块在类被加载时执行,实例代码块在创建类的实例时执行。
五种成员共同构成了类的基本结构,它们分别表示类的状态(属性)、行为(方法)、初始化过程(构造方法)、嵌套结构(内部类)以及执行逻辑(代码块)。这些成员相互协作,使得类能够实现其预定功能,满足应用程序的需求。
通过定义不同的属性、方法、构造方法、内部类和代码块,开发者可以设计出具有特定功能和行为的类。这些类可以相互交互,形成一个完整的应用程序。在面向对象编程中,类是基本的组织单元,五种成员使得类具有丰富的表现力和灵活性。
内部类(Inner Class)在某些特定场景下可以提供更好的封装和组织代码的能力。以下是一些内部类的应用场景和原因:
-
当一个类只在另一个类中有用时,可以将其定义为内部类,以避免不必要的外部访问。这有助于减少代码的耦合度,提高类的内聚性。
-
内部类可以访问外部类的成员(包括私有成员),这使得内部类可以与外部类更紧密地协作,实现某些特定功能。
-
内部类可以用于实现某些设计模式,例如工厂模式、装饰器模式、观察者模式等。在这些情况下,内部类可以提供更清晰、简洁的代码结构。
-
当需要实现一个接口,但不希望创建一个完整的类时,可以使用匿名内部类。这种方法常用于创建回调函数、事件处理器等。
定义内部类的时机主要取决于其使用场景。如果你觉得定义一个内部类能够提高代码的可读性、可维护性,或者更好地实现某种设计模式,那么就可以考虑定义一个内部类。
内部类的访问特点如下:
-
内部类可以访问外部类的所有成员(包括私有成员)。
-
静态内部类不能访问外部类的非静态成员,但可以访问外部类的静态成员。
-
非静态内部类(实例内部类)隐式地持有一个对外部类实例的引用。因此,在创建非静态内部类的实例时,需要先创建外部类的实例。例如:OuterClass.InnerClass inner = outerInstance.new InnerClass();
-
外部类可以访问内部类的成员,但需要通过内部类的实例来访问。对于静态内部类,可以直接通过类名访问其静态成员。
-
内部类可以使用任意访问修饰符,如public、private、protected。访问修饰符可以限制内部类在其他类中的可见性。
二、成员内部类
成员内部类是定义在外部类中的非静态内部类。在编写成员内部类时,需要注意以下几点:
-
成员内部类可以访问外部类的所有成员(包括私有成员),因为它们处于同一个外部类中。然而,外部类不能直接访问内部类的成员,需要通过内部类的实例来访问。
-
成员内部类不能定义任何静态成员(除非它们是编译时常量),因为成员内部类与外部类的实例关联。
-
当成员内部类和外部类具有相同名称的成员时,可以使用外部类名.this.成员名来引用外部类的成员。
-
在成员内部类中,不能定义与外部类中的成员同名的局部变量。
要获取成员内部类的实例,有以下几种方式:
- 在外部类的方法中创建成员内部类的实例:
public class Outer {
public class Inner {
// ...
}
public void createInner() {
Inner inner = new Inner();
}
}
- 在外部类的外部创建成员内部类的实例。由于成员内部类与外部类的实例关联,因此需要先创建外部类的实例,然后使用外部类实例.new 内部类名()的语法创建内部类实例:
public class Main {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
}
}
- 如果内部类与外部类需要相互访问对方的成员,可以将外部类的实例传递给内部类的构造函数,然后在内部类中保存一个对外部类的引用。这样,内部类可以通过引用访问外部类的成员:
public class Outer {
private String name;
public class Inner