提交 29c12f83 编写于 作者: 沉默王二's avatar 沉默王二 💬

java 包

上级 5b07cc8f
...@@ -133,13 +133,7 @@ ...@@ -133,13 +133,7 @@
- [这次彻底搞清楚了 Java 的三大特征之一:封装](docs/oo/encapsulation.md) - [这次彻底搞清楚了 Java 的三大特征之一:封装](docs/oo/encapsulation.md)
- [一万字彻底搞懂 Java 继承(三大特征之一)](docs/oo/extends-bigsai.md) - [一万字彻底搞懂 Java 继承(三大特征之一)](docs/oo/extends-bigsai.md)
- [几句话,直观解释清楚 Java 多态(三大特征之一)](docs/oo/polymorphism.md) - [几句话,直观解释清楚 Java 多态(三大特征之一)](docs/oo/polymorphism.md)
- [Java instanceof关键字用法](docs/oo/instanceof.md)
- [深入理解Java中的不可变对象](docs/basic-extra-meal/immutable.md)
- [Java中可变参数的使用](docs/basic-extra-meal/varables.md)
- [深入理解Java泛型](docs/basic-extra-meal/generic.md)
- [深入理解Java注解](docs/basic-extra-meal/annotation.md)
- [Java枚举(enum)](docs/basic-extra-meal/enum.md)
- [大白话说Java反射:入门、使用、原理](docs/basic-extra-meal/fanshe.md)
## 集合框架(容器) ## 集合框架(容器)
...@@ -194,6 +188,13 @@ ...@@ -194,6 +188,13 @@
- [为什么JDK源码中,无限循环大多使用for(;;)而不是while(true)?](docs/basic-extra-meal/jdk-while-for-wuxian-xunhuan.md) - [为什么JDK源码中,无限循环大多使用for(;;)而不是while(true)?](docs/basic-extra-meal/jdk-while-for-wuxian-xunhuan.md)
- [先有Class还是先有Object?](docs/basic-extra-meal/class-object.md) - [先有Class还是先有Object?](docs/basic-extra-meal/class-object.md)
- [instanceof关键字是如何实现的?](docs/basic-extra-meal/instanceof-jvm.md) - [instanceof关键字是如何实现的?](docs/basic-extra-meal/instanceof-jvm.md)
- [Java instanceof关键字用法](docs/oo/instanceof.md)
- [深入理解Java中的不可变对象](docs/basic-extra-meal/immutable.md)
- [Java中可变参数的使用](docs/basic-extra-meal/varables.md)
- [深入理解Java泛型](docs/basic-extra-meal/generic.md)
- [深入理解Java注解](docs/basic-extra-meal/annotation.md)
- [Java枚举(enum)](docs/basic-extra-meal/enum.md)
- [大白话说Java反射:入门、使用、原理](docs/basic-extra-meal/fanshe.md)
## Java并发编程 ## Java并发编程
......
...@@ -105,6 +105,7 @@ export const sidebarConfig = sidebar({ ...@@ -105,6 +105,7 @@ export const sidebarConfig = sidebar({
collapsable: true, collapsable: true,
children: [ children: [
"oo/object-class", "oo/object-class",
"oo/package",
"oo/var", "oo/var",
"oo/method", "oo/method",
"oo/construct", "oo/construct",
...@@ -118,36 +119,9 @@ export const sidebarConfig = sidebar({ ...@@ -118,36 +119,9 @@ export const sidebarConfig = sidebar({
"basic-extra-meal/override-overload", "basic-extra-meal/override-overload",
"oo/static", "oo/static",
"oo/final", "oo/final",
"oo/encapsulation",
"oo/extends-bigsai", "oo/extends-bigsai",
"oo/polymorphism", "oo/polymorphism",
{
text: "instanceof",
link: "oo/instanceof",
},
{
text: "不可变对象",
link: "basic-extra-meal/immutable",
},
{
text: "可变参数",
link: "basic-extra-meal/varables",
},
{
text: "泛型",
link: "basic-extra-meal/generic",
},
{
text: "注解",
link: "basic-extra-meal/annotation",
},
{
text: "枚举",
link: "basic-extra-meal/enum",
},
{
text: "反射",
link: "basic-extra-meal/fanshe",
},
], ],
}, },
...@@ -328,6 +302,34 @@ export const sidebarConfig = sidebar({ ...@@ -328,6 +302,34 @@ export const sidebarConfig = sidebar({
text: "instanceof关键字是如何实现的", text: "instanceof关键字是如何实现的",
link: "instanceof-jvm", link: "instanceof-jvm",
}, },
{
text: "instanceof",
link: "oo/instanceof",
},
{
text: "不可变对象",
link: "basic-extra-meal/immutable",
},
{
text: "可变参数",
link: "basic-extra-meal/varables",
},
{
text: "泛型",
link: "basic-extra-meal/generic",
},
{
text: "注解",
link: "basic-extra-meal/annotation",
},
{
text: "枚举",
link: "basic-extra-meal/enum",
},
{
text: "反射",
link: "basic-extra-meal/fanshe",
},
], ],
}, },
{ {
......
...@@ -132,6 +132,7 @@ head: ...@@ -132,6 +132,7 @@ head:
### 面向对象编程 ### 面向对象编程
- [怎么理解Java中的类和对象?](oo/object-class.md) - [怎么理解Java中的类和对象?](oo/object-class.md)
- [Java 包,优雅地解决类名冲突](oo/package.md)
- [Java中的变量:局部变量、成员变量、静态变量、常量](oo/var.md) - [Java中的变量:局部变量、成员变量、静态变量、常量](oo/var.md)
- [Java中的方法:实例方法、静态方法、抽象方法](oo/method.md) - [Java中的方法:实例方法、静态方法、抽象方法](oo/method.md)
- [Java中的构造方法:对象创建时的必经之路](oo/construct.md) - [Java中的构造方法:对象创建时的必经之路](oo/construct.md)
...@@ -148,13 +149,8 @@ head: ...@@ -148,13 +149,8 @@ head:
- [这次彻底搞清楚了 Java 的三大特征之一:封装](oo/encapsulation.md) - [这次彻底搞清楚了 Java 的三大特征之一:封装](oo/encapsulation.md)
- [一万字彻底搞懂 Java 继承(三大特征之一)](oo/extends-bigsai.md) - [一万字彻底搞懂 Java 继承(三大特征之一)](oo/extends-bigsai.md)
- [几句话,直观解释清楚 Java 多态(三大特征之一)](oo/polymorphism.md) - [几句话,直观解释清楚 Java 多态(三大特征之一)](oo/polymorphism.md)
- [Java instanceof关键字用法](oo/instanceof.md)
- [深入理解Java中的不可变对象](basic-extra-meal/immutable.md)
- [Java中可变参数的使用](basic-extra-meal/varables.md)
- [深入理解Java泛型](basic-extra-meal/generic.md)
- [深入理解Java注解](basic-extra-meal/annotation.md)
- [Java枚举(enum)](basic-extra-meal/enum.md)
- [大白话说Java反射:入门、使用、原理](basic-extra-meal/fanshe.md)
### 集合框架(容器) ### 集合框架(容器)
...@@ -208,7 +204,13 @@ head: ...@@ -208,7 +204,13 @@ head:
- [为什么JDK源码中,无限循环大多使用for(;;)而不是while(true)?](basic-extra-meal/jdk-while-for-wuxian-xunhuan.md) - [为什么JDK源码中,无限循环大多使用for(;;)而不是while(true)?](basic-extra-meal/jdk-while-for-wuxian-xunhuan.md)
- [先有Class还是先有Object?](basic-extra-meal/class-object.md) - [先有Class还是先有Object?](basic-extra-meal/class-object.md)
- [instanceof关键字是如何实现的?](basic-extra-meal/instanceof-jvm.md) - [instanceof关键字是如何实现的?](basic-extra-meal/instanceof-jvm.md)
- [Java instanceof关键字用法](oo/instanceof.md)
- [深入理解Java中的不可变对象](basic-extra-meal/immutable.md)
- [Java中可变参数的使用](basic-extra-meal/varables.md)
- [深入理解Java泛型](basic-extra-meal/generic.md)
- [深入理解Java注解](basic-extra-meal/annotation.md)
- [Java枚举(enum)](basic-extra-meal/enum.md)
- [大白话说Java反射:入门、使用、原理](basic-extra-meal/fanshe.md)
### Java并发编程 ### Java并发编程
......
...@@ -253,3 +253,12 @@ public String getCzHTML(){ ...@@ -253,3 +253,12 @@ public String getCzHTML(){
好了,关于封装我们就暂时聊这么多。 好了,关于封装我们就暂时聊这么多。
> 参考链接:[https://www.cnblogs.com/chenssy/p/3351835.html](https://www.cnblogs.com/chenssy/p/3351835.html),整理:沉默王二 > 参考链接:[https://www.cnblogs.com/chenssy/p/3351835.html](https://www.cnblogs.com/chenssy/p/3351835.html),整理:沉默王二
----
最近整理了一份牛逼的学习资料,包括但不限于Java基础部分(JVM、Java集合框架、多线程),还囊括了 **数据库、计算机网络、算法与数据结构、设计模式、框架类Spring、Netty、微服务(Dubbo,消息队列) 网关** 等等等等……详情戳:[可以说是2022年全网最全的学习和找工作的PDF资源了](https://tobebetterjavaer.com/nice-article/itmind/nice-article/itmind/miansjavamsdhmsmsbdjavabdjavaxxzlmsxxzlmszlzlxzmszlfxjlzl.html)
关注二哥的原创公众号 **沉默王二**,回复**111** 即可免费领取。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/xingbiaogongzhonghao.png)
---
title: Java 包,优雅地解决类名冲突
shortTitle: Java包可以优雅地解决类名冲突
description: Java程序员进阶之路,小白的零基础Java教程,Java包可以优雅地解决类名冲突
category:
- Java 核心
tag:
- 面向对象编程
head:
- - meta
- name: keywords
content: Java,Java SE,Java 基础,Java 教程,Java 程序员进阶之路,Java 入门,Java 包,java import,java package
---
## package
在前面的代码中,我们把类和接口命名为`Person``Student``Hello`等简单名字。
在团队开发中,如果小明写了一个`Person`类,小红也写了一个`Person`类,现在,小白既想用小明的`Person`,也想用小红的`Person`,怎么办?
如果小军写了一个`Arrays`类,恰好 JDK 也自带了一个`Arrays`类,如何解决类名冲突?
在 Java 中,我们使用`package`来解决名字冲突。
Java 定义了一种名字空间,称之为包:`package`。一个类总是属于某个包,类名(比如`Person`)只是一个简写,真正的完整类名是`包名.类名`
例如:
小明的`Person`类存放在包`ming`下面,因此,完整类名是`ming.Person`
小红的`Person`类存放在包`hong`下面,因此,完整类名是`hong.Person`
小军的`Arrays`类存放在包`mr.jun`下面,因此,完整类名是`mr.jun.Arrays`
JDK 的`Arrays`类存放在包`java.util`下面,因此,完整类名是`java.util.Arrays`
在定义`class`的时候,我们需要在第一行声明这个`class`属于哪个包。
小明的`Person.java`文件:
```
package ming; // 申明包名ming
public class Person {
}
```
小军的`Arrays.java`文件:
```
package mr.jun; // 申明包名mr.jun
public class Arrays {
}
```
在 Java 虚拟机执行的时候,JVM 只看完整类名,因此,只要包名不同,类就不同。
包可以是多层结构,用`.`隔开。例如:`java.util`
>要特别注意:包没有父子关系。java.util和java.util.zip是不同的包,两者没有任何继承关系。
没有定义包名的`class`,它使用的是默认包,非常容易引起名字冲突,因此,不推荐不写包名的做法。
我们还需要按照包结构把上面的 Java 文件组织起来。假设以`package_sample`作为根目录,`src`作为源码目录,那么所有文件结构就是:
```ascii
package_sample
└─ src
├─ hong
│ └─ Person.java
│ ming
│ └─ Person.java
└─ mr
└─ jun
└─ Arrays.java
```
即所有 Java 文件对应的目录层次要和包的层次一致。
编译后的`.class`文件也需要按照包结构存放。如果使用 IDE,把编译后的`.class`文件放到`bin`目录下,那么,编译的文件结构就是:
```ascii
package_sample
└─ bin
├─ hong
│ └─ Person.class
│ ming
│ └─ Person.class
└─ mr
└─ jun
└─ Arrays.class
```
编译的命令相对比较复杂,我们需要在`src`目录下执行`javac`命令:
```
javac -d ../bin ming/Person.java hong/Person.java mr/jun/Arrays.java
```
在 IDE 中,会自动根据包结构编译所有 Java 源码,所以不必担心使用命令行编译的复杂命令。
## 包作用域
位于同一个包的类,可以访问包作用域的字段和方法。
不用`public``protected``private`修饰的字段和方法就是包作用域。例如,`Person`类定义在`hello`包下面:
```
package hello;
public class Person {
// 包作用域:
void hello() {
System.out.println("Hello!");
}
}
```
`Main`类也定义在`hello`包下面,就可以直接访问 Person 类:
```
package hello;
public class Main {
public static void main(String[] args) {
Person p = new Person();
p.hello(); // 可以调用,因为MainPerson在同一个包
}
}
```
## import
在一个`class`中,我们总会引用其他的`class`。例如,小明的`ming.Person`类,如果要引用小军的`mr.jun.Arrays`类,他有三种写法:
第一种,直接写出完整类名,例如:
```
// Person.java
package ming;
public class Person {
public void run() {
mr.jun.Arrays arrays = new mr.jun.Arrays();
}
}
```
很显然,每次写完整类名比较痛苦。
因此,第二种写法是用`import`语句,导入小军的`Arrays`,然后写简单类名:
```
// Person.java
package ming;
// 导入完整类名:
import mr.jun.Arrays;
public class Person {
public void run() {
Arrays arrays = new Arrays();
}
}
```
在写`import`的时候,可以使用`*`,表示把这个包下面的所有`class`都导入进来(但不包括子包的`class`):
```
// Person.java
package ming;
// 导入mr.jun包的所有class:
import mr.jun.*;
public class Person {
public void run() {
Arrays arrays = new Arrays();
}
}
```
我们一般不推荐这种写法,因为在导入了多个包后,很难看出`Arrays`类属于哪个包。
还有一种`import static`的语法,它可以导入一个类的静态字段和静态方法:
```
package main;
// 导入System类的所有静态字段和静态方法:
import static java.lang.System.*;
public class Main {
public static void main(String[] args) {
// 相当于调用System.out.println()
out.println("Hello, world!");
}
}
```
`import static`很少使用。
Java 编译器最终编译出的`.class`文件只使用 *完整类名*,因此,在代码中,当编译器遇到一个`class`名称时:
- 如果是完整类名,就直接根据完整类名查找这个`class`
- 如果是简单类名,按下面的顺序依次查找:
- 查找当前`package`是否存在这个`class`
- 查找`import`的包是否包含这个`class`
- 查找`java.lang`包是否包含这个`class`
如果按照上面的规则还无法确定类名,则编译报错。
我们来看一个例子:
```
// Main.java
package test;
import java.text.Format;
public class Main {
public static void main(String[] args) {
java.util.List list; // ok,使用完整类名 -> java.util.List
Format format = null; // ok,使用import的类 -> java.text.Format
String s = "hi"; // ok,使用java.lang包的String -> java.lang.String
System.out.println(s); // ok,使用java.lang包的System -> java.lang.System
MessageFormat mf = null; // 编译错误:无法找到MessageFormat: MessageFormat cannot be resolved to a type
}
}
```
因此,编写 class 的时候,编译器会自动帮我们做两个 import 动作:
- 默认自动`import`当前`package`的其他`class`
- 默认自动`import java.lang.*`
>注意:自动导入的是java.lang包,但类似java.lang.reflect这些包仍需要手动导入。
如果有两个`class`名称相同,例如,`mr.jun.Arrays``java.util.Arrays`,那么只能`import`其中一个,另一个必须写完整类名。
## 最佳实践
为了避免名字冲突,我们需要确定唯一的包名。推荐的做法是使用倒置的域名来确保唯一性。例如:
- org.apache
- org.apache.commons.log
- com.tobebetterjavaer.sample
子包就可以根据功能自行命名。
要注意不要和`java.lang`包的类重名,即自己的类不要使用这些名字:
- String
- System
- Runtime
- ...
要注意也不要和 JDK 常用类重名:
- java.util.List
- java.text.Format
- java.math.BigInteger
- ...
## 小结
Java 内建的`package`机制是为了避免`class`命名冲突;
JDK 的核心类使用`java.lang`包,编译器会自动导入;
JDK 的其它常用类定义在`java.util.*``java.math.*``java.text.*`,……;
包名推荐使用倒置的域名,例如`org.apache`
---
> 参考链接:[https://www.liaoxuefeng.com/wiki/1252599548343744/1260467032946976](https://www.liaoxuefeng.com/wiki/1252599548343744/1260467032946976),整理:沉默王二
----
最近整理了一份牛逼的学习资料,包括但不限于Java基础部分(JVM、Java集合框架、多线程),还囊括了 **数据库、计算机网络、算法与数据结构、设计模式、框架类Spring、Netty、微服务(Dubbo,消息队列) 网关** 等等等等……详情戳:[可以说是2022年全网最全的学习和找工作的PDF资源了](https://tobebetterjavaer.com/nice-article/itmind/nice-article/itmind/miansjavamsdhmsmsbdjavabdjavaxxzlmsxxzlmszlzlxzmszlfxjlzl.html)
关注二哥的原创公众号 **沉默王二**,回复**111** 即可免费领取。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/xingbiaogongzhonghao.png)
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册