Java中的包
Java中的包是一种封装一组类、子包和接口的机制。包用于:
- 防止命名冲突。例如,在两个包中可以有两个名为 Employee 的类,college.staff.cse.Employee 和 college.staff.ee.Employee
- 使类、接口、枚举和注释的搜索/定位和使用更容易
- 提供受控访问:受保护和默认具有包级别的访问控制。同一包中的类及其子类可以访问受保护的成员。默认成员(没有任何访问说明符)只能由同一包中的类访问。
- 包可以被认为是数据封装(或数据隐藏)。
我们需要做的就是将相关的类放入包中。之后,我们可以简单地从现有包中编写一个导入类并在我们的程序中使用它。包是一组相关类的容器,其中一些可访问的类是公开的,而其他类则保留用于内部目的。
我们可以在程序中根据需要多次重用包中的现有类。
软件包如何工作?
包名和目录结构密切相关。例如,如果包名称是college.staff.cse ,则存在三个目录, college 、 staff和cse ,这样cse出现在staff中, staff出现在college中。此外,目录学院可通过CLASSPATH 变量访问,即学院的父目录路径存在于CLASSPATH 中。这个想法是为了确保类很容易找到。
包命名约定:包以域名的倒序命名,即org.geeksforgeeks.practice。例如,在一所大学中,推荐的约定是college.tech.cse、college.tech.ee、college.art.history等。
将类添加到包中:我们可以通过在程序顶部使用包名并将其保存在包目录中来向创建的包中添加更多类。我们需要一个新的Java文件来定义一个公共类,否则我们可以将新类添加到现有的. Java文件并重新编译。
子包:位于另一个包中的包是子包。这些默认情况下不导入,它们必须显式导入。此外,子包的成员没有访问权限,即,它们被视为受保护和默认访问说明符的不同包。
例子 :
import java.util.*;
util是在Java包中创建的子包。
访问包内的类
考虑以下两个语句:
// import the Vector class from util package.
import java.util.vector;
// import all the classes from util package
import java.util.*;
- First Statement 用于从包含在Java中的util包中导入Vector类。
- 第二条语句从util包中导入所有类。
// All the classes and interfaces of this package
// will be accessible but not subpackages.
import package.*;
// Only mentioned class of this package will be accessible.
import package.classname;
// Class name is generally used when two packages have the same
// class name. For example in below code both packages have
// date class so using a fully qualified name to avoid conflict
import java.util.Date;
import my.package.Date;
// Java program to demonstrate accessing of members when
// corresponding classes are imported and not imported.
import java.util.Vector;
public class ImportDemo
{
public ImportDemo()
{
// java.util.Vector is imported, hence we are
// able to access directly in our code.
Vector newVector = new Vector();
// java.util.ArrayList is not imported, hence
// we were referring to it using the complete
// package.
java.util.ArrayList newList = new java.util.ArrayList();
}
public static void main(String arg[])
{
new ImportDemo();
}
}
包裹类型:
内置包
这些包由大量的类组成,它们是Java API的一部分。一些常用的内置包是:
1) Java.lang:包含语言支持类(例如定义原始数据类型、数学运算的类)。这个包是自动导入的。
2) Java.io:包含用于支持输入/输出操作的类。
3) Java.util:包含实现数据结构的实用程序类,如链表、字典和支持;用于日期/时间操作。
4) Java.applet:包含用于创建小程序的类。
5) Java.awt:包含用于实现图形用户界面组件的类(如按钮、;菜单等)。
6) Java.net:包含支持网络操作的类。
用户自定义包
这些是用户定义的包。首先我们创建一个目录myPackage (名称应该与包的名称相同)。然后在目录中创建MyClass ,第一条语句是包名。
// Name of the package must be same as the directory
// under which this file is saved
package myPackage;
public class MyClass
{
public void getNames(String s)
{
System.out.println(s);
}
}
现在我们可以在我们的程序中使用MyClass类了。
/* import 'MyClass' class from 'names' myPackage */
import myPackage.MyClass;
public class PrintName
{
public static void main(String args[])
{
// Initializing the String variable
// with a value
String name = "GeeksforGeeks";
// Creating an instance of class MyClass in
// the package.
MyClass obj = new MyClass();
obj.getNames(name);
}
}
注意:我的班级。 Java必须保存在myPackage目录中,因为它是包的一部分。
使用静态导入
静态导入是Java编程语言(版本 5 及更高版本)中引入的一项功能,它允许在类中定义为公共静态的成员(字段和方法)在Java代码中使用,而无需指定定义字段的类。
以下程序演示了静态导入:
// Note static keyword after import.
import static java.lang.System.*;
class StaticImportDemo
{
public static void main(String args[])
{
// We don't need to use 'System.out'
// as imported using static.
out.println("GeeksforGeeks");
}
}
输出:
GeeksforGeeks
处理名称冲突
唯一需要注意包的时候是出现名称冲突的时候。例如, Java.util 和Java.sql 包都有一个名为 Date 的类。因此,如果我们在程序中导入这两个包,如下所示:
import java.util.*;
import java.sql.*;
//And then use Date class, then we will get a compile-time error :
Date today ; //ERROR-- java.util.Date or java.sql.Date?
编译器将无法确定我们想要哪个 Date 类。这个问题可以通过使用特定的 import 语句来解决:
import java.util.Date;
import java.sql.*;
如果我们需要两个 Date 类,那么每次声明该类的新对象时都需要使用完整的包名。
例如:
java.util.Date deadLine = new java.util.Date();
java.sql.Date today = new java.sql.Date();
目录结构
包名与用于存储类的目录结构密切相关。属于特定包的类(和其他实体)一起存储在同一目录中。此外,它们存储在由其包名称指定的子目录结构中。例如,包 com.zzz.project1.subproject2 的类 Circle 存储为“$BASE_DIR\com\zzz\project1\subproject2\Circle.class”,其中 $BASE_DIR 表示包的基本目录。显然,包名中的“点”对应于文件系统的一个子目录。
基本目录 ($BASE_DIR) 可以位于文件系统中的任何位置。因此, Java编译器和运行时必须被告知 $BASE_DIR 的位置以便定位类。这是通过一个名为 CLASSPATH 的环境变量来完成的。 CLASSPATH 类似于另一个环境变量 PATH,命令 shell 使用它来搜索可执行程序。
设置类路径:
CLASSPATH 可以通过以下任何一种方式设置:
- CLASSPATH 可以在环境中永久设置:在 Windows 中,选择控制面板?系统 ?先进的 ?环境变量 ?选择“系统变量”(所有用户)或“用户变量”(仅当前登录用户)?选择“编辑”(如果 CLASSPATH 已经存在)或“新建”?输入“CLASSPATH”作为变量名?输入所需的目录和 JAR 文件(用分号分隔)作为值(例如,“.;c:\javaproject\classes;d:\tomcat\lib\servlet-api.jar”)。请注意,您需要在 CLASSPATH 中包含当前工作目录(用“.”表示)。
要检查 CLASSPATH 的当前设置,请发出以下命令:> SET CLASSPATH
- 可以通过发出以下命令为该特定 CMD shell 会话临时设置 CLASSPATH:
> SET CLASSPATH=.;c:\javaproject\classes;d:\tomcat\lib\servlet-api.jar
- 除了使用 CLASSPATH 环境变量,您还可以使用 javac 和Java命令的命令行选项 -classpath 或 -cp,例如,
> java –classpath c:\javaproject\classes com.abc.project1.subproject2.MyClass3
用户自定义包说明:
创建我们的第一个包:
文件名——ClassOne。Javapackage package_name; public class ClassOne { public void methodClassOne() { System.out.println("Hello there its ClassOne"); } }
创建我们的第二个包:
文件名 – ClassTwo。Javapackage package_one; public class ClassTwo { public void methodClassTwo(){ System.out.println("Hello there i am ClassTwo"); } }
使用两个创建的包:
文件名 - 测试。Javaimport package_one.ClassTwo; import package_name.ClassOne; public class Testing { public static void main(String[] args){ ClassTwo a = new ClassTwo(); ClassOne b = new ClassOne(); a.methodClassTwo(); b.methodClassOne(); } }
输出:
Hello there i am ClassTwo Hello there its ClassOne
现在看看包和测试类文件的目录结构:
要点:
- 每个类都是某个包的一部分。
- 如果未指定包,则文件中的类将进入一个特殊的未命名包(所有文件都使用相同的未命名包)。
- 文件中的所有类/接口都是同一个包的一部分。多个文件可以指定相同的包名。
- 如果指定了包名,则文件必须位于名为 name 的子目录中(即,目录名必须与包名匹配)。
- 我们可以使用以下命令访问另一个(命名的)包中的公共类: package-name.class-name