详细聊一聊Java中的包机制
目录
- 1. 定义
- 2. 核心作用
- 3. 讨论
- 总结
1. 定义
包(Package)类似于磁盘上的文件夹,通过包名可以找到对应文件路径,例如包test.demo.example对应文件路径为test/demo/example。
2. 核心作用
- 防止命名冲突假如在包test.demo.example1和test.demo.example2这两个包中都有一个Java类demo01,由于在不同包中相同类名不会引起冲突,所以可以在不同包中命名相同的Java类,但是无法在同一个包下创建另一个相同名字的类。
- 代码组织和管理将功能相似的类集中管理放在同一个包中,便于程序员管理,快速定位到功能模块。
- 访问控制在同一个包中,不同类的设置了public访问属性的成员可以相互访问彼此成员,无需导入对应的包,但是外部包无法直接访问,需要通过导包来调用其他包中的类的成员或方法。
- 支持模块化开发通过包划分功能模块,例如,要完成一个外卖系统,用户模块在包test.demo.user中,订单模块在test.demo.order中,便于团队协作和管理,提升开发效率编程客栈
3. 讨论
- 为什么Java要引入包机制,而不复用C/C++的头文件
解决命名冲突
Java的包机制可以在不同包中创建相同命名的类
package test.demo.example; public class Demo01 {//无修饰符 public String name1="test1"; public Demo01() {} public void getname() { System.out.print(name1); } } package test.demo.example1; public class Demo01{ public String name2="test2"; public Demo01() {} public void getname() { System.out.print(name2); } } package test.demo.example2; public class main { public static void main(String []args) { test.demo.example.Demo01 de01=new test.demo.example.Demo01(); de01.getname(); test.demo.example1.Demo01 de02=new test.demo.example1.Demo01(); de02.getname(); } }
但是在C++中,若两个不同头文件中命名了相同的类,引用这两个头文件后在编译时由于重名冲突会报错。
//test01.h #pragma once #include<IOStream> voidpython demo()//全局可见 { std::cout << "demo" << std::endl; } //test02.h #pragma once #include<iostream> void demo()//全局可见 { std::cout << "demo1" << std::endl; }
//main.cpp #include"test01.h"//包含头文件 #include"test02.h" int main() { demo();//调用全局函数 return 0; }
编译后出现如下错误:
函数“void demo(void)”已有主体 Project1 E:\C++\test\Project1\test02.h
简化依赖管理
简单来说,Java中包通过import自动解析类路径,因为包名就对应相应文件目录,编译器自动根据包名查找类文件,无需手动指定路径。而C++/C中需要手动包含收头文件并处理重复包含,C++/C在引用其他目录的头文件时,需要显示指定路径,例如:
#include"include/my_header.h"
否则编译器无法找到头文件,但是我们在平常写C++代码的时候并没有显示指定头文件路径,原因有两点:
- 若头文件与源文件在同一目录,不需要手动添加路径,编译器默认搜索当前目录
- IDE会自动配置路径,程序员感知不到显示操作
强化封装性
Java中包级访问权限(默认权限修饰符)限制跨包访问,即类、方法、属性若未添加
public
/protected
/private
,仅允许同包内访问,外部包无法通过导入或全限定名绕过权限限制,编译器直接报错。而C++头文件定义的全局函数或变量默认公开,容易被外部随意访问。用以下代码解释:
package test.demo.example; class Demo01 {//无修饰符 public String name1; publijsc Demo01() {} public void test1() { System.out.print("demo01"); } } //同一个包下 package test.demo.example; public class Demo02 { private String name2; public static void main(String[]args) { Demo01 de01=new Demo01(); de01.test1(); } }
package test.demo.example1;//外部包 import test.demo.example.Demo01;//导入Demo01所在包 public class Demo1 { public static void main(String[]args) { Demo01 de01=new Demo01(); de01.test();//编译无法通过 } }
编译出现如图所示错误:该错误显示无法识别demo01类型
//test01.h #pragma once #include<iostream> // 未使用 static 或匿名命名空间python,全局可见 void internalDebug() { std::cout << "内部调试方法" << std::endl; } class test01 { public: // 默认访问权限为 public(若不显式声明 private) void debug() { std::cout << "内部调试方法" << std::endl; } }; //main.cpp #include"test01.h"//包含头文件 int main() { internalDebug();//直接调用全局函数(可能意外暴露) test01 t1; t1.debug();//直接访问类成员 return 0; }
- 头文件中的
internalDebug()
函数默认全局可见,任何包含该头文件的代码均可调用,可能导致命名冲突或误用。 - C++ 类成员默认访问权限为
private
,但此处显式声明为public
,以模拟常见开发习惯 - 即使将
test01.h
视为“内部工具”,其他源文件仍可通过包含头文件直接调用其内容,缺乏模块隔离
面向对象设计深度整合
Java中包与类加载器结合,强制代码模块化,Java中的变量,方法都在类中实现和定义,而C++头文件可能混合全局函数,变量和类的定义
跨平台与标准化
Java中包名使用
.
分隔符,与操作系统无关;而C++头文件路径依赖操作系统分隔符(如\
或/
),Windows系统文件路径用“\”分隔符,linux系统文件路径用“/”分隔符。
总结
到此这篇关javascript于Java中包机制的文章就介绍到这了,更多相关Java包机制内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论