当前位置:首页分享Java从入门到放弃(三十):包

Java从入门到放弃(三十):包

在Java编程中,为了避免类名冲突,我们使用包(package)这个概念来创建命名空间。每个类实际上都是属于某个特定包的一部分,而这个包名和类名一起构成了完整的类名。这样,即使两个不同的开发者定义了同名的类,只要它们的包名不同,就不会发生冲突。

例如,如果小明和小红各自编写了一个Person类,他们可以将这些类分别放在不同的包中。小明的Person类可以放在ming包中,而小红的Person类可以放在hong包中。这样,两个Person类的完整类名分别是ming.Personhong.Person,它们可以共存而不会相互干扰。

下面是一个示例,展示了如何在Java中使用包来避免类名冲突:

// 小明的Person.java文件
package ming; // 声明类属于ming包

public class Person {
    // 类的实现
}

// 小红的Person.java文件
package hong; // 声明类属于hong包

public class Person {
    // 类的实现
}

在这个例子中,两个Person类通过位于不同的包中来区分。同样,如果小军编写了一个Arrays类,并且想要与JDK中的Arrays类区分开来,他可以将自己的类放在一个独特的包中,例如mr.jun.Arrays

包的结构通常是多层的,使用点(.)分隔不同的层级。例如,java.util表示java包下的util子包。

在定义类时,我们需要在文件的顶部通过package声明来指定类所属的包。这样做可以让Java编译器和虚拟机(JVM)知道如何正确地识别和引用这个类。

除了避免命名冲突,包还有助于组织代码。每个包通常对应于一个目录,包名中的每个层级对应于目录结构中的一个子目录。

编译后的.class文件也应该按照包的结构进行组织。如果使用集成开发环境(IDE),通常会有一个bin目录来存放编译后的类文件,这些类文件的存放位置也应该反映包的结构。

包作用域

在Java中,包(package)提供了一种访问控制的机制,称为包作用域(package scope)。当一个类或接口的成员(字段或方法)没有明确的访问修饰符(如public、protected、private)时,它们具有包作用域,这意味着这些成员在同一个包内的其他类中是可见的,但在包外则不可见。

下面是一个示例,展示了位于同一个包中的类如何访问包作用域的字段和方法:

// 定义在hello包下的Person类
package hello;

public class Person {
    // 这个字段具有包作用域
    String name;

    // 这个方法也具有包作用域
    void sayHello() {
        System.out.println("Hello, my name is " + name);
    }
}

// 同样定义在hello包下的Main类
package hello;

public class Main {
    public static void main(String[] args) {
        // 创建Person类的实例
        Person person = new Person();
        // 给具有包作用域的字段赋值
        person.name = "LBenedict";
        // 调用具有包作用域的方法
        person.sayHello();
    }
}

在这个例子中,Person类中的name字段和sayHello方法都没有使用访问修饰符publicprotectedprivate,因此它们具有包作用域。这意味着,只有在同一包(hello)中的其他类才能访问这些成员。Main类也定义在hello包下,因此它可以创建Person类的实例,设置name字段的值,并调用sayHello方法。

这种机制使得包内的类可以互相协作,而不需要将所有的成员都公开。这有助于保护类内部的实现细节,同时允许包内的其他类访问这些受保护的成员。这是一种平衡封装性和模块间协作的有效方式。

import

在Java中,当一个类需要引用另一个类时,有几种不同的方法来指定所引用的类。以下是三种常见的写法:

1. 使用完整类名

直接在代码中使用完整的类名,包括包名和类名。这种方法最直接,但可能会使代码显得冗长。

// 完整类名的使用
package ming;

public class Person {
    public void run() {
        mr.jun.Arrays arrays = new mr.jun.Arrays();
    }
}

2. 使用import语句

通过import语句,我们可以导入其他类,然后在代码中直接使用简单的类名。这样做可以使代码更加简洁。

// 使用import语句
package ming;

import mr.jun.Arrays; // 导入mr.jun包下的Arrays类

public class Person {
    public void run() {
        Arrays arrays = new Arrays();
    }
}

3. 使用通配符import

可以使用*作为通配符,导入整个包下的所有类。但这种做法可能会导致代码可读性降低,因为不明确指出类的具体来源。

// 使用通配符import
package ming;

import mr.jun.*; // 导入mr.jun包下的所有类

public class Person {
    public void run() {
        Arrays arrays = new Arrays();
    }
}

4. import static

import static用于导入类的静态字段和静态方法,可以直接使用这些静态成员而不需要类名前缀。

// 使用import static导入静态成员
package main;

import static java.lang.System.out; // 导入System类的out静态字段

public class Main {
    public static void main(String[] args) {
        out.println("Hello, world!"); // 直接使用out
    }
}

当编译器遇到一个类名时,它会按照以下顺序进行查找:

  1. 查找当前包(默认包)中的类。
  2. 查找通过import语句导入的类。
  3. 查找java.lang包中的类。

如果按照这些规则仍然无法找到类,编译器将会报错。

以下是一个关于类引用的示例:

// Main.java
package test;

import java.text.Format; 

public class Main {
    public static void main(String[] args) {
        java.util.List list; // 正确:使用完整类名java.util.List
        Format format = null; // 正确:使用导入的类java.text.Format
        String s = "hi"; // 正确:使用java.lang包的String
        System.out.println(s); // 正确:使用java.lang包的System
        // MessageFormat mf = null; // 错误:无法解析类型MessageFormat
    }
}

注意事项

  • 默认情况下,编译器会自动导入当前包和java.lang包中的所有类。
  • 如果存在类名冲突,只能导入其中一个类,其他类必须使用完整类名来区分。
  • 为了保持代码的清晰性和可维护性,推荐使用完整类名或单个import语句,而不是通配符import

 

 

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧