原文: https://www.programiz.com/java-programming/nested-inner-class

在本教程中,您将借助示例学习 Java 中的嵌套类及其类型。

在 Java 中,您可以在另一个类中定义一个类。 这种类称为nested class。 例如,

  1. class OuterClass {
  2. // ...
  3. class NestedClass {
  4. // ...
  5. }
  6. }

您可以使用 Java 创建两种类型的嵌套类。

  • 非静态嵌套类(内部类)
  • 静态嵌套类

推荐阅读

首先让我们看一下非静态嵌套类。


非静态嵌套类(内部类)

非静态嵌套类是另一个类中的一个类。 它有权访问封闭类(外部类)的成员。 通常称为inner class

由于inner class存在于外部类中,因此您必须首先实例化外部类,以便实例化内部类。

这是一个如何在 Java 中声明内部类的示例。

示例 1:内部类

  1. class CPU {
  2. double price;
  3. // nested class
  4. class Processor{
  5. // members of nested class
  6. double cores;
  7. String manufacturer;
  8. double getCache(){
  9. return 4.3;
  10. }
  11. }
  12. // nested protected class
  13. protected class RAM{
  14. // members of protected nested class
  15. double memory;
  16. String manufacturer;
  17. double getClockSpeed(){
  18. return 5.5;
  19. }
  20. }
  21. }
  22. public class Main {
  23. public static void main(String[] args) {
  24. // create object of Outer class CPU
  25. CPU cpu = new CPU();
  26. // create an object of inner class Processor using outer class
  27. CPU.Processor processor = cpu.new Processor();
  28. // create an object of inner class RAM using outer class CPU
  29. CPU.RAM ram = cpu.new RAM();
  30. System.out.println("Processor Cache = " + processor.getCache());
  31. System.out.println("Ram Clock speed = " + ram.getClockSpeed());
  32. }
  33. }

输出

  1. Processor Cache = 4.3
  2. Ram Clock speed = 5.5

在上面的程序中,有两个嵌套类:CPURAM位于外部类内部:CPU。 我们可以将内部类声明为受保护的。 因此,我们已将 RAM 类声明为受保护的。

Main类里面

  • 我们首先创建了一个名为cpu的外部类CPU的实例。

  • 然后使用外部类的实例创建内部类的对象: ```java CPU.Processor processor = cpu.new Processor;

CPU.RAM ram = cpu.new RAM();

  1. **注意**:我们使用点(`.`)运算符使用外部类创建内部类的实例。
  2. ---
  3. <a name="157bb9c6"></a>
  4. ### 访问内部类中的外部类成员
  5. 通过使用`this`关键字,我们可以访问外部类的成员。 如果您想了解`this`关键字,请访问 [Java `this`关键字](https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html)。
  6. <a name="286610f5"></a>
  7. ### 示例 2:访问成员
  8. ```java
  9. class Car {
  10. String carName;
  11. String carType;
  12. // assign values using constructor
  13. public Car(String name, String type) {
  14. this.carName = name;
  15. this.carType = type;
  16. }
  17. // private method
  18. private String getCarName() {
  19. return this.carName;
  20. }
  21. // inner class
  22. class Engine {
  23. String engineType;
  24. void setEngine() {
  25. // Accessing the carType property of Car
  26. if(Car.this.carType.equals("4WD")){
  27. // Invoking method getCarName() of Car
  28. if(Car.this.getCarName().equals("Crysler")) {
  29. this.engineType = "Smaller";
  30. } else {
  31. this.engineType = "Bigger";
  32. }
  33. }else{
  34. this.engineType = "Bigger";
  35. }
  36. }
  37. String getEngineType(){
  38. return this.engineType;
  39. }
  40. }
  41. }
  42. public class Main {
  43. public static void main(String[] args) {
  44. // create an object of the outer class Car
  45. Car car1 = new Car("Mazda", "8WD");
  46. // create an object of inner class using the outer class
  47. Car.Engine engine = car1.new Engine();
  48. engine.setEngine();
  49. System.out.println("Engine Type for 8WD= " + engine.getEngineType());
  50. Car car2 = new Car("Crysler", "4WD");
  51. Car.Engine c2engine = car2.new Engine();
  52. c2engine.setEngine();
  53. System.out.println("Engine Type for 4WD = " + c2engine.getEngineType());
  54. }
  55. }

输出

  1. Engine Type for 8WD= Bigger
  2. Engine Type for 4WD = Smaller

在上面的程序中,我们在外部类Car内有一个名为Engine的内部类。 在这里,请注意这行,

  1. if(Car.this.carType.equals("4WD")) {...}

我们正在使用this关键字来访问外部类的carType变量。 您可能已经注意到,我们使用Car.this.carType代替了this.carType

这是因为,如果我们没有提到外部类Car的名称,那么this关键字将代表内部类内部的成员。

同样,我们也从内部类访问外部类的方法。

  1. if (Car.this.getCarName().equals("Crysler") {...}

重要的是要注意,尽管getCarName()private方法,但我们仍可以从内部类访问它。


静态嵌套类

在 Java 中,我们还可以在另一个类中定义一个static类。 此类称为static nested class。 静态嵌套类不称为静态内部类。

与内部类不同,静态嵌套类无法访问外部类的成员变量。 这是因为静态嵌套类不需要您创建外部类的实例。

  1. OuterClass.NestedClass obj = new OuterClass.NestedClass();

在这里,我们仅通过使用外部类的类名来创建静态嵌套类的对象。 因此,无法使用OuterClass.this引用外部类。

示例 3:静态内部类

  1. class MotherBoard {
  2. // static nested class
  3. static class USB{
  4. int usb2 = 2;
  5. int usb3 = 1;
  6. int getTotalPorts(){
  7. return usb2 + usb3;
  8. }
  9. }
  10. }
  11. public class Main {
  12. public static void main(String[] args) {
  13. // create an object of the static nested class
  14. // using the name of the outer class
  15. MotherBoard.USB usb = new MotherBoard.USB();
  16. System.out.println("Total Ports = " + usb.getTotalPorts());
  17. }
  18. }

输出

  1. Total Ports = 3

在上面的程序中,我们在类MotherBoard中创建了一个名为USB的静态类。 注意这一行,

  1. MotherBoard.USB usb = new MotherBoard.USB();

在这里,我们使用外部类的名称创建USB的对象。

现在,让我们看看如果尝试访问外部类的成员会发生什么:


示例 4:在静态内部类内部访问外部类的成员

  1. class MotherBoard {
  2. String model;
  3. public MotherBoard(String model) {
  4. this.model = model;
  5. }
  6. // static nested class
  7. static class USB{
  8. int usb2 = 2;
  9. int usb3 = 1;
  10. int getTotalPorts(){
  11. // accessing the variable model of the outer classs
  12. if(MotherBoard.this.model.equals("MSI")) {
  13. return 4;
  14. }
  15. else {
  16. return usb2 + usb3;
  17. }
  18. }
  19. }
  20. }
  21. public class Main {
  22. public static void main(String[] args) {
  23. // create an object of the static nested class
  24. MotherBoard.USB usb = new MotherBoard.USB();
  25. System.out.println("Total Ports = " + usb.getTotalPorts());
  26. }
  27. }

当我们尝试运行该程序时,将出现错误:

  1. error: non-static variable this cannot be referenced from a static context

这是因为我们没有使用外部类的对象来创建内部类的对象。 因此,没有引用存储在Motherboard.this中的外部类Motherboard


要记住的要点

  • Java 将内部类视为类的常规成员。 它们就像在类中声明的方法和变量一样。
  • 由于内部类是外部类的成员,因此您可以将privateprotected之类的任何访问修饰符应用于内部类,这在普通类中是不可能的。
  • 由于嵌套类是其封闭的外部类的成员,因此可以使用点(.)表示法来访问嵌套类及其成员。
  • 使用嵌套的类将使您的代码更具可读性,并提供更好的封装。
  • 非静态嵌套类(内部类)可以访问外部/封闭类的其他成员,即使它们被声明为私有的也是如此。