# Java 嵌套和内部类

> 原文： [https://www.programiz.com/java-programming/nested-inner-class](https://www.programiz.com/java-programming/nested-inner-class)

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

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

```java
class OuterClass {
    // ...
    class NestedClass {
        // ...
    }
}
```

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

*   非静态嵌套类（内部类）
*   静态嵌套类

**推荐读物**：

*   [Java 访问修饰符](/java-programming/access-modifiers "Java Access Modifiers")
*   [Java 静态关键字](/java-programming/static-keyword "Java Static Keyword")

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

* * *

## 非静态嵌套类（内部类）

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

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

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

### 示例 1：内部类

```java
class CPU {
    double price;
    // nested class
    class Processor{

        // members of nested class
        double cores;
        String manufacturer;

        double getCache(){
            return 4.3;
        }
    }

    // nested protected class
    protected class RAM{

        // members of protected nested class
        double memory;
        String manufacturer;

        double getClockSpeed(){
            return 5.5;
        }
    }
}

public class Main {
    public static void main(String[] args) {

        // create object of Outer class CPU
        CPU cpu = new CPU();

       // create an object of inner class Processor using outer class
        CPU.Processor processor = cpu.new Processor();

        // create an object of inner class RAM using outer class CPU
        CPU.RAM ram = cpu.new RAM();
        System.out.println("Processor Cache = " + processor.getCache());
        System.out.println("Ram Clock speed = " + ram.getClockSpeed());
    }
}
```

**输出**：

```java
Processor Cache = 4.3
Ram Clock speed = 5.5
```

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

在主班里面

*   我们首先创建了一个名为`cpu`的外部类`CPU`的实例。
*   然后使用外部类的实例创建内部类的对象：

    ```java
    CPU.Processor processor = cpu.new Processor;

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

**注意**：我们使用点（`.`）运算符使用外部类创建内部类的实例。

* * *

### 访问内部类中的外部类成员

通过使用`this`关键字，我们可以访问外部类的成员。 如果您想了解`this`关键字，请访问 [Java `this`关键字](https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html)。

### 示例 2：访问成员

```java
class Car {
    String carName;
    String carType;

    // assign values using constructor
    public Car(String name, String type) {
        this.carName = name;
        this.carType = type;
    }

    // private method
    private String getCarName() {
        return this.carName;
    }

// inner class
    class Engine {
        String engineType;
        void setEngine() {

           // Accessing the carType property of Car
            if(Car.this.carType.equals("4WD")){

                // Invoking method getCarName() of Car
                if(Car.this.getCarName().equals("Crysler")) {
                    this.engineType = "Smaller";
                } else {
                    this.engineType = "Bigger";
                }

            }else{
                this.engineType = "Bigger";
            }
        }
        String getEngineType(){
            return this.engineType;
        }
    }
}

public class Main {
    public static void main(String[] args) {

// create an object of the outer class Car
        Car car1 = new Car("Mazda", "8WD");

        // create an object of inner class using the outer class
        Car.Engine engine = car1.new Engine();
        engine.setEngine();
        System.out.println("Engine Type for 8WD= " + engine.getEngineType());

        Car car2 = new Car("Crysler", "4WD");
        Car.Engine c2engine = car2.new Engine();
        c2engine.setEngine();
        System.out.println("Engine Type for 4WD = " + c2engine.getEngineType());
    }
}
```

**输出**：:

```java
Engine Type for 8WD= Bigger
Engine Type for 4WD = Smaller
```

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

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

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

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

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

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

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

* * *

## 静态嵌套类

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

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

```java
OuterClass.NestedClass obj = new OuterClass.NestedClass();
```

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

### 示例 3：静态内部类

```java
class MotherBoard {

   // static nested class
   static class USB{
       int usb2 = 2;
       int usb3 = 1;
       int getTotalPorts(){
           return usb2 + usb3;
       }
   }

}
public class Main {
   public static void main(String[] args) {

       // create an object of the static nested class
       // using the name of the outer class
       MotherBoard.USB usb = new MotherBoard.USB();
       System.out.println("Total Ports = " + usb.getTotalPorts());
   }
}
```

**输出**：:

```java
Total Ports = 3
```

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

```java
MotherBoard.USB usb = new MotherBoard.USB();
```

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

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

* * *

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

```java
class MotherBoard {
   String model;
   public MotherBoard(String model) {
       this.model = model;
   }

   // static nested class
   static class USB{
       int usb2 = 2;
       int usb3 = 1;
       int getTotalPorts(){
           // accessing the variable model of the outer classs
           if(MotherBoard.this.model.equals("MSI")) {
               return 4;
           }
           else {
               return usb2 + usb3;
           }
       }
   }
}
public class Main {
   public static void main(String[] args) {

       // create an object of the static nested class
       MotherBoard.USB usb = new MotherBoard.USB();
       System.out.println("Total Ports = " + usb.getTotalPorts());
   }
}
```

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

```java
error: non-static variable this cannot be referenced from a static context
```

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

* * *

### 要记住的要点

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