Java Class File Naming Conventions – Java类文件的命名规则

最后修改: 2021年 3月 30日

中文/混合/英文(键盘快捷键:t)

 1. Overview

1.概述

When a Java class is compiled, a class file with the same name is created. However, in the case of nested classes or nested interfaces, it creates a class file with a name combining the inner and outer class names, including a dollar sign.

当一个Java类被编译时,会创建一个同名的类文件。然而,在嵌套类或嵌套接口的情况下,它创建的类文件的名称是结合了内部和外部类的名称,包括一个美元符号。

In this article, we’ll see all those scenarios.

在这篇文章中,我们将看到所有这些情况。

2. Details

2.细节

In Java, we can write a class within a class. The class written within is called the nested class, and the class that holds the nested class is called the outer class. The scope of a nested class is bounded by the scope of its enclosing class.

在Java中,我们可以在一个类中写一个类。写在里面的类被称为嵌套类,而容纳嵌套类的类被称为外层类。嵌套类的范围是由其包围类的范围所限定的。

Similarly, we can declare an interface within another interface or class. Such an interface is called a nested interface.

同样地,我们可以在另一个接口或类中声明一个接口。这样的接口被称为嵌套接口。

We can use nested classes and interfaces to logically group entities that are only used in one place. This not only makes our code more readable and maintainable, but it also increases encapsulation.

我们可以使用嵌套的类和接口来对只在一个地方使用的实体进行逻辑分组。这不仅使我们的代码更具可读性和可维护性,而且也增加了封装性。

In the next sections, we’re going to discuss each of these in detail. We’ll also take a look at enums.

在接下来的章节中,我们将详细讨论其中的每一项内容。我们还将看一下枚举。

3. Nested Classes

3.嵌套类

A nested class is a class that is declared inside another class or interface. Any time we need a separate class but still want that class to behave as part of another class, the nested class is the best way to achieve it.

嵌套类是一个在另一个类或接口内声明的类。任何时候我们都需要一个独立的类,但仍然希望该类的行为是另一个类的一部分,嵌套类是实现这一目的的最佳方式。

When we compile a Java file, it creates a .class file for the enclosing class and separate class files for all the nested classes. The generated class file for the enclosing class will have the same name as the Java class.

当我们编译一个Java文件时,它会为包围类创建一个.class文件,并为所有嵌套类创建单独的类文件。为包围类生成的类文件将与Java类的名称相同。

For nested classes, the compiler uses a different naming convention – OuterClassName$NestedClassName.class

对于嵌套类, 编译器使用不同的命名惯例– OuterClassName$NestedClassName.class

First of all, let’s create a simple Java class:

首先,让我们创建一个简单的Java类。

public class Outer {

// variables and methods...
}
When we compile the Outer class, the compiler will create an Outer.class file.
In the next subsections, we’ll add nested classes in the Outer class and see how class files are named.

3.1. Static Nested Classes

3.1.静态嵌套类

As the name suggests, nested classes that are declared as static are called static nested classes. In Java, only nested classes are allowed to be static.

顾名思义,被声明为static的嵌套类被称为静态嵌套类。在Java中,只有嵌套类被允许是static

Static nested classes can have both static and non-static fields and methods. They are tied to the outer class and not with a particular instance. Hence, we don’t need an instance of the outer class to access them.

静态嵌套类可以有静态和非静态字段和方法。它们与外层类联系在一起,而不是与某个特定的实例联系在一起。因此,我们不需要外层类的实例来访问它们。

Let’s declare a static nested class within our Outer class:

让我们在我们的Outer类中声明一个静态嵌套类。

public class Outer {
    static class StaticNested {
        public String message() {
            return "This is a static Nested Class";
        }
    }
}

When we compile our Outer class, the compiler creates two class files, one for Outer and another for StaticNested:

当我们编译我们的Outer class时,编译器创建了两个类文件,一个用于Outer ,另一个用于StaticNested

3.2. Non-Static Nested Classes

3.2.非静态的嵌套类

Non-static nested classes – also called inner classes – are associated with an instance of the enclosing class, and they can access all the variables and methods of the outer class.

非静态嵌套类–也称为内层类–与包围类的实例相关联,它们可以访问外层类的所有变量和方法。

An outer class can have only public or default access, whereas an inner class can be private, public, protected, or with default access. However, they can’t contain any static members. Also, we need to create an instance of the outer class to access the inner class.

外层类只能有公共的或默认的访问权限,而内层类可以是私有的、公共的、受保护的,或有默认的访问权限。但是,它们不能包含任何静态成员。另外,我们需要创建一个外类的实例来访问内类。

Let’s add one more nested class to our Outer class:

让我们为我们的Outer 类再添加一个嵌套类。

public class Outer {
    class Nested {
        public String message() {
            return "This is a non-static Nested Class";
        }
    }
}

It generates one more class file:

它又生成了一个类文件。

3.3. Local Classes

3.3.地方类

Local classes, also called inner classes, are defined in a block — a group of statements between balanced braces. For example, they can be in a method body, a for loop, or an if clause. The scope of the local class is restricted within the block just like the local variables. Local classes, when compiled, appear as a dollar sign with an auto-generated number.

局部类,也被称为内部类,被定义在一个块中–平衡括号之间的一组语句。例如,它们可以在一个方法体、一个for循环或一个if子句中。就像局部变量一样,局部类的范围被限制在块内。本地类在编译时显示为一个带有自动生成的数字的美元符号。

The class file generated for the local class uses a naming convention – OuterClassName$1LocalClassName.class

为本地类生成的类文件使用了一个命名规则 – OuterClassName$1LocalClassName.class

Let’s declare a local class within a method:

让我们在一个方法中声明一个局部类。

public String message() {
    class Local {
        private String message() {
            return "This is a Local Class within a method";
        }
    }
    Local local = new Local();
    return local.message();
}

The compiler creates a separate class file for our Local class:

编译器为我们的Local类创建了一个单独的类文件。

Similarly, we can declare a local class within an if clause:

同样地,我们可以在if子句中声明一个局部类。

public String message(String name) {
    if (StringUtils.isEmpty(name)) {
        class Local {
            private String message() {
                return "This is a Local class within if clause";
            }
        }
        Local local = new Local();
        return local.message();
    } else
        return "Welcome to " + name;
}

Although we’re creating another local class with the same name, the compiler doesn’t complain. It creates one more class file and names it with the number increased:

尽管我们正在创建另一个同名的局部类,但编译器并没有抱怨。它又创建了一个类文件,并用增加的数字来命名它。

3.4. Anonymous Inner Classes

3.4.匿名内类

As the name suggests, anonymous classes are the inner classes with no name. The compiler uses an auto-generated number after a dollar sign to name the class file.

顾名思义,匿名类是没有名字的内部类。编译器使用美元符号后自动生成的数字来命名类文件。

We need to declare and instantiate anonymous classes in a single expression at the same time. They usually extend an existing class or implement an interface.

我们需要在一个表达式中同时声明和实例化匿名类。它们通常扩展一个现有的类或实现一个接口。

Let’s see a quick example:

让我们看一个快速的例子。

public String greet() {
    Outer anonymous = new Outer() {
        @Override
        public String greet() {
            return "Running Anonymous Class...";
        }
    };
    return anonymous.greet();
}

Here, we’ve created an anonymous class by extending the Outer class, and the compiler added one more class file:

在这里,我们通过扩展Outer类创建了一个匿名类,而编译器又增加了一个类文件。

Similarly, we can implement an interface with an anonymous class.

同样地,我们可以用一个匿名类来实现一个接口。

Here, we’re creating an interface:

在这里,我们正在创建一个接口。

interface HelloWorld {
    public String greet(String name);
}

Now, let’s create an anonymous class:

现在,让我们创建一个匿名类。

public String greet(String name) {
    HelloWorld helloWorld = new HelloWorld() {
        @Override
        public String greet(String name) {
            return "Welcome to "+name;
        }
    };
    return helloWorld.greet(name);
}

Let’s observe the revised list of class files:

让我们观察一下修改后的类文件列表。

As we see, a class file is generated for the interface HelloWorld and another one for the anonymous class with the name Outer$2.

正如我们所看到的,为接口HelloWorld生成了一个类文件,为匿名类生成了另一个类文件,名称为Outer$2

3.5. Inner Class Within Interface

3.5.接口内的内类

We have seen class inside another class, further, we can declare a class within an interface. If the functionality of class is closely associated with interface functionality, we can declare it inside the interface. We can go for this inner class when we want to write the default implementation for interface methods.

我们已经在另一个类中看到了类,此外,我们还可以在一个接口中声明一个类。如果类的功能与接口的功能密切相关,我们可以在接口内声明它。当我们想为接口方法编写默认的实现时,我们可以选择这个内类。

Let’s declare an inner class inside our HelloWorld interface:

让我们在我们的HelloWorld接口内声明一个内类。

interface HelloWorld {
    public String greet(String name);
    class InnerClass implements HelloWorld {
        @Override
        public String message(String name) {
            return "Inner class within an interface";
        }
    }
}

And the compiler generates one more class file:

而编译器又生成了一个类文件。

4. Nested Interfaces

4.嵌套接口

Nested interfaces, also known as inner interfaces, are declared inside a class or another interface. The main purpose of using nested interfaces is to resolve the namespace by grouping related interfaces.

嵌套接口,也被称为内部接口,是在一个类或另一个接口内声明的。使用嵌套接口的主要目的是通过对相关接口进行分组来解决命名空间。

We can’t directly access nested interfaces. They can only be accessed using the outer class or outer interface. For example, the Entry interface inside the Map interface is nested and can be accessed as Map.Entry.

我们不能直接访问嵌套接口。它们只能用外层类或外层接口来访问。例如,Map接口内的Entry接口是嵌套的,可以用Map.Entry访问。

Let’s see how to create nested interfaces.

我们来看看如何创建嵌套接口。

4.1. Interface Inside an Interface

4.1.接口内的接口

An interface declared inside the interface is implicitly public.

在接口内声明的接口是隐含的公共接口。

Let’s declare our interface inside the HelloWorld interface:

让我们在HelloWorld接口内声明我们的接口。

interface HelloWorld {
    public String greet(String name);
    
    interface HelloSomeone{
        public String greet(String name);
    }
}

This will create a new class file named HelloWorld$HelloSomeone for the nested interface.

这将为嵌套接口创建一个名为HelloWorld$HelloSomeone的新类文件。

4.2. Interface Inside a Class

4.2.类内的接口

Interfaces declared inside the class can take any access modifier.

在类内声明的接口可以采取任何访问修改器。

Let’s declare an interface inside our Outer class:

让我们在我们的Outer 类中声明一个接口。

public class Outer {
     interface HelloOuter {
        public String hello(String name);
    }
}

It will generate a new class file with the name: OuterClass$StaticNestedClass

它将生成一个新的类文件,名称为。OuterClass$StaticNestedClass

5. Enums

5.枚举

The enum was introduced in Java 5. It’s a data type that contains a fixed set of constants, and those constants are the instances of that enum.

enum是在Java 5中引入的。它是一种数据类型,包含一组固定的常量,这些常量是该enum的实例。

The enum declaration defines a class called an enum type (also known as enumerated data type). We can add many things to the enum like a constructor, methods, variables, and something called a constant-specific class body.

enum声明定义了一个叫做enum类型(也被称为枚举数据类型)的。我们可以向enum添加许多东西,如构造函数、方法、变量,以及称为常量特定类体的东西。

When we create an enum, we’re creating a new class, and we’re implicitly extending the Enum class. Enum cannot inherit any other class or can’t be extended. However, it can implement an interface.

当我们创建一个enum时,我们正在创建一个新的类,并且我们隐含地扩展了Enum类。Enum不能继承任何其他类,也不能被扩展。然而,它可以实现一个接口。

We can declare an enum as a standalone class, in its own source file, or another class member. Let’s see all the ways to create an enum.

我们可以将一个enum声明为一个独立的类,在它自己的源文件中,或另一个类成员。让我们看看创建enum的所有方法。

5.1. Enum as a Class

5.1 作为一个类的枚举

First, let’s create a simple enum:

首先,让我们创建一个简单的enum

enum Level {
    LOW, MEDIUM, HIGH;
}

When it is compiled, the compiler will create a class file with the name Level for our enum.

当它被编译时,编译器将为我们的枚举创建一个名为Level的类文件。

5.2. Enum Within a Class

5.2.类中的枚举

Now, let’s declare a nested enum in our Outer class:

现在,让我们在我们的Outer类中声明一个嵌套的enum

public class Outer {
    enum Color{ 
        RED, GREEN, BLUE; 
    }
}

The compiler will create a separate class file named Outer$Color for our nested enum.

编译器将为我们的嵌套枚举创建一个名为Outer$Color的独立类文件。

5.3. Enum Within an Interface

5.3.接口内的枚举

Similarly, we can declare an enum within an interface:

同样地,我们可以在一个接口中声明一个enum

interface HelloWorld {
    enum DIRECTIONS {
        NORTH, SOUTH, EAST, WEST;
    }
}

When the HelloWorld interface is compiled, the compiler will add one more class file named HelloWorld$Directon.

HelloWorld接口被编译时,编译器将增加一个名为HelloWorld$Directon.的类文件。

5.4. Enum Within an Enum

5.4.枚举中的枚举

We can declare an enum inside another enum:

我们可以在另一个enum里面声明一个enum

enum Foods {
    DRINKS, EATS;
    enum DRINKS {
        APPLE_JUICE, COLA;
    }
    enum EATS {
        POTATO, RICE;
    }
}

Finally, let’s take a look at the generated class files:

最后,让我们看一下生成的类文件。

The compiler creates a separate class file for each of the enum types.

编译器为每个enum类型创建一个单独的类文件。

6. Conclusion

6.结语

In this article, we saw different naming conventions used for Java class files. We added classes, interfaces, and enums inside a single Java file and observed how the compiler creates a separate class file for each of them.

在这篇文章中,我们看到了用于Java类文件的不同命名规则。我们在单个Java文件中添加了类、接口和枚举,并观察了编译器如何为每个类创建单独的类文件。

As always, the code examples for this article are available over on GitHub.

像往常一样,本文的代码示例可在GitHub上获得