Java第八章-包和内部类

Java第八章-包和内部类

1 Java类包

类包(Class Package)是一种用于组织和管理Java类和接口的一种方式。类包是一种命名空间(Namespace)的概念,用于避免类和接口之间的命名冲突。

类包通过将相关的类和接口组织在一起,形成一个包(Package),从而使代码更加有序和可维护。包是Java中的一种层次化的文件目录结构,用于将相关的类和接口组织在一起,可以包含其他包、类和接口。类包可以通过关键字 package 来定义,并且通常与文件系统的目录结构相对应。

1.1.类名冲突

类名冲突是指在Java程序中使用相同名称的类或接口,从而导致编译时或运行时出现命名冲突的现象。当在同一个作用域内存在相同名称的类或接口时,Java编译器或Java虚拟机无法区分它们,从而导致错误或异常。

为了避免类名冲突,可以采取以下方法:

  1. 使用不同的类名:为类和接口选择有意义且唯一的名称,以避免冲突。
  2. 使用完全限定名(FQN):在使用类或接口时,可以使用完全限定名(包括包名和类名)来明确指定使用的类或接口,从而避免冲突。例如,使用 “com.example.package1.Utils” 或 “com.example.package2.Utils” 来明确指定使用的 “Utils” 类。
  3. 使用包级访问控制:通过使用包级访问控制(例如,将类或接口的访问修饰符设置为包私有或默认访问),可以限制对包内的类和接口的访问,从而减少类名冲突的可能性。
  4. 使用不同的包名:为不同的类或接口选择不同的包名,从而避免在同一个包内出现相同名称的类或接口,从而减少类名冲突的可能性。

综上所述,合理的命名约定、使用完全限定名和包级访问控制等方法可以帮助解决类名冲突的问题,从而提高Java程序的可维护性和稳定性。

1.2完整的类路径

完整的类路径(Fully Qualified Name,FQN)是指包括包名和类名的完整类的名称。完整的类路径用于唯一地标识一个类或接口,以便在编译时或运行时明确指定要使用的类或接口,避免类名冲突。

完整的类路径的格式为:包名.类名

例,如有一个名为 “com.example.package1.Utils” 的类,它位于包 “com.example.package1” 下,那么它的完整类路径就是 “com.example.package1.Utils”。

在Java代码中,可以使用完整的类路径来引用一个类或接口,例如:

javaCopy code
com.example.package1.Utils utils = new com.example.package1.Utils(); // 使用完整的类路径创建 Utils 类的实例

或者可以使用 import 语句引入完整的类路径,从而在代码中直接使用类名,而无需每次都写完整的类路径,例如:

javaCopy codeimport com.example.package1.Utils;

// ...

Utils utils = new Utils(); // 直接使用类名引用 Utils 类

使用完整的类路径可以明确指定要使用的类或接口,避免类名冲突,并提高代码的可读性和维护性。在引用类或接口时,尽量使用完整的类路径或使用 import 语句,以便代码更加清晰和可理解。

1.3创建包

包(Package)是一种用于组织和管理类和接口的一种方式,它可以包含多个相关的类和接口,并提供了命名空间(Namespace)的概念,从而避免类名冲突。要创建一个包,可以按照以下步骤进行:

  1. 选择一个合适的包名:包名应该是唯一的,且应该符合Java的命名规范。包名一般以小写字母开始,后面可以包含小写字母、数字和下划线(_),多个单词之间使用点(.)进行分隔。例如,包名可以是 “com.example.package1”。
  2. 在文件系统中创建包目录结构:根据包名,在文件系统中创建相应的包目录结构。例如,如果包名是 “com.example.package1”,则可以在文件系统中创建如下的目录结构:
markdownCopy codecom
  └─ example
      └─ package1
  1. 在包目录中创建Java文件:在包目录中创建Java文件,并定义类和接口。Java文件的文件名应该与类名相同,并且以 .java 为扩展名。例如,如果要创建一个名为 “Utils” 的类,可以在 “com.example.package1” 包目录中创建一个名为 “Utils.java” 的文件,并在其中定义 Utils 类的内容。
  2. 在Java文件中使用包声明:在Java文件的开头,使用 package 关键字来声明包名。例如,对于 “Utils.java” 文件,可以在文件开头添加如下的包声明:
javaCopy code
package com.example.package1;
  1. 编写类或接口的代码:在Java文件中编写类或接口的代码,实现相应的功能。

注意:包名应该与文件系统中的包目录结构保持一致,包声明应该与包名一致。同时,Java文件中的类或接口的访问修饰符应该与包级访问控制相匹配,例如,如果包声明为 “com.example.package1”,则类或接口的访问修饰符应该设置为 publicprotected 或默认(包私有),以控制包外的访问权限。

创建包可以帮助组织和管理Java程序的代码,提高代码的可维护性和可读性。同时,使用合适的包名可以避免类名冲突,使得Java程序更加健壮和稳定。

例题:创建自定义的Math类

1.4导入包

使用 import 关键字可以导入其他包中的类或接口,从而在当前的Java文件中可以直接使用这些类或接口的简单类名,而不需要使用完整的类路径。以下是导入包的一般步骤:

  1. 在Java文件的开头添加 import 语句:在Java文件的开头,可以使用 import 关键字来导入其他包中的类或接口。例如,如果要导入包名为 “com.example.package1” 下的 “Utils” 类,可以在文件开头添加如下的 import 语句:
javaCopy code
import com.example.package1.Utils;
  1. 使用导入的类或接口:在导入了类或接口后,就可以在当前的Java文件中直接使用这些类或接口的简单类名,而无需使用完整的类路径。例如,在导入了 “com.example.package1.Utils” 后,可以在代码中直接使用 “Utils” 类,如下所示:
javaCopy code
Utils utils = new Utils(); // 使用导入的类
  1. 可选:使用通配符导入多个类或接口:如果一个包中包含多个类或接口需要导入,也可以使用通配符 * 来导入整个包下的所有类或接口。例如,可以使用如下的 import 语句导入 “com.example.package1” 下的所有类或接口:
javaCopy code
import com.example.package1.*;

但是,使用通配符导入整个包下的所有类或接口可能会导致命名冲突或不必要的类加载,因此不推荐在生产代码中广泛使用。

注意:导入语句应该放在Java文件的包声明之后、类声明之前。同时,导入语句只对当前文件有效,对于其他文件无效。

导入包可以简化代码,提高代码的可读性和维护性,但需要注意避免导入过多的包,以免导致类名冲突或不必要的类加载。建议只导入当前文件中需要使用的类或接口,避免使用通配符导入整个包。

例题:使用Import导入静态成员

2.内部类

2.1成员内部类

成员内部类是定义在一个外部类的内部的类,也被称为内部类。成员内部类可以直接访问外部类的成员变量和方法,并且可以拥有自己的成员变量和方法。

下面是成员内部类的基本语法和用法:

javaCopy codepublic class OuterClass {
    // 外部类的成员变量
    
    // 外部类的构造方法
    
    // 外部类的成员方法
    
    // 成员内部类
    public class InnerClass {
        // 内部类的成员变量
        
        // 内部类的构造方法
        
        // 内部类的成员方法
    }
}

在外部类中,可以通过创建成员内部类的实例来使用它的成员变量和方法,例如:

javaCopy codeOuterClass outer = new OuterClass(); // 创建外部类的实例
OuterClass.InnerClass inner = outer.new InnerClass(); // 创建内部类的实例

// 访问内部类的成员变量和方法
inner.innerMethod();

需要注意的是,成员内部类的实例必须依赖于外部类的实例,因此在创建内部类的实例时需要使用外部类的实例来进行实例化。同时,成员内部类可以访问外部类的私有成员,但外部类不能直接访问成员内部类的私有成员。

成员内部类通常在以下场景中使用:

  1. 需要在内部类中访问外部类的成员变量和方法,或者需要通过外部类的实例来创建内部类的实例。
  2. 需要实现某种特定的功能,该功能与外部类紧密相关,但在外部类之外不需要被访问。
  3. 需要将多个类组织在一起,形成更加合理和封装的结构。

需要注意,成员内部类的使用应该合理,避免过度嵌套和复杂的类关系,以提高代码的可读性和维护性。

例题:使用成员内部类模拟发动机点火

2.2匿名内部类

匿名内部类是一种特殊类型的内部类,它没有显式的类名,并且通常在创建对象的同时定义并实现类的方法。匿名内部类通常用于创建简单的、临时性的对象,并且可以作为接口实现类或抽象类的子类来使用。

使用匿名内部类的语法格式如下:

javaCopy codenew 接口名/抽象类名() {
    // 匿名内部类的类体,包括成员变量、成员方法等
};

或者在匿名内部类中实现接口的方法或继承抽象类的方法:

javaCopy codenew 接口名/抽象类名() {
    // 实现接口的方法或继承抽象类的方法
    // ...
};

以下是匿名内部类的一些特点和用法:

  1. 匿名内部类没有显式的类名,因此只能在创建对象的时候使用,并且无法再次创建相同的对象。
  2. 匿名内部类可以实现接口的方法或继承抽象类的方法,但不能定义构造方法和静态成员。
  3. 匿名内部类可以访问外部类的成员变量和方法,并且可以在匿名内部类的方法中使用外部类的成员变量和方法时,外部类的成员变量需要声明为 final 或者是 effectively final(在Java 8+ 版本中)。
  4. 匿名内部类通常用于创建临时性的对象,例如在事件处理、回调函数等场景中经常使用。
  5. 匿名内部类的语法相对简洁,但可能使代码可读性降低,因此应谨慎使用,特别是在复杂的逻辑和大型项目中。

以下是使用匿名内部类的示例:

使用匿名内部类实现接口:

javaCopy codeinterface MyInterface {
    void doSomething();
}

public class Main {
    public static void main(String[] args) {
        MyInterface myInterface = new MyInterface() {
            @Override
            public void doSomething() {
                System.out.println("Doing something in anonymous inner class.");
            }
        };

        myInterface.doSomething(); // 调用接口方法
    }
}

使用匿名内部类继承抽象类:

javaCopy codeabstract class MyAbstractClass {
    abstract void doSomething();
}

public class Main {
    public static void main(String[] args) {
        MyAbstractClass myAbstractClass = new MyAbstractClass() {
            @Override
            void doSomething() {
                System.out.println("Doing something in anonymous inner class.");
            }
        };

        myAbstractClass.doSomething(); // 调用抽象类方法
    }
}

注意,匿名内部类是一种特殊的语法和用法,可以在某些情况下简化代码,但在实际开发中应根据具体情况进行

例题:使用匿名内部类创建一个抽象狗类的对象

你可能感兴趣的:(java,开发语言)