Commit ebaa4e0
committed
---
title: 30-Java 中的包和访问修饰符
date: 2024-12-13 10:16:42
icon: java
author: AI悦创
isOriginal: true
category:
- Java体系课
tag:
- Java体系课
sticky: false
star: false
article: true
timeline: true
image: false
navbar: true
sidebarIcon: true
headerDepth: 5
comment: true
lastUpdated: true
editLink: false
backToTop: true
toc: true
footer: 长期招收编程一对一学员!微信:Jiabcdefh, <a href="https://beian.miit.gov.cn/" target="_blank">闽ICP备19021486号-6</a>
---
## 0. 目录
- 类多太混乱?用 package 管理
- 类使用太繁琐怎么办?用 import
- 属性访问修饰符:public
- 类的全限定名
## 1. 类多太混乱?用 package 管理
- 为了避免类在一起混乱,可以把类放在文件夹里。这时就需要用 package 语句告诉 Java 这个类在哪个 package 里。 package 语句要和源文件的目录完全对应,大小写要一致。
- package 读作包。一般来说,类都会在包里,而不会直接放在根目录;
- 不同的包里可以有相同名字的类;
- 一个类只能有一个 package 语句,如果有 package 语句,**则必须是类的第一行有效代码**;
上一节课,我们创建了很多类,放在了 src 的目录下,咋眼一看有可能会比较乱,接下来我们看看怎么组织。

代码应该也是有层级关系的,比如:Phone 的 CPU & Storage 等这些零件,其实不应该和 phone 是平级的,应该是有个层级关系的。
那 Java 中怎么做到这一点呢?
## 2. **类使用太繁琐怎么办?用 import**
### 2.1 知识点
- 当使用另一个包里类的时候,需要带上包名;
- 每次使用都带包名很繁琐,可以在使用的类的上面使用 import 语句,一次性解决问题,就可以直接使用类了。就好像我们之前用过的 Scanner 类;
- import 语句可以有多个;
- 如果需要 import 一个包中的很多类,可以使用 `*` 通配符;
如果没有 import 时,我们使用 Scanner 类需要如下实现:
::: code-tabs
@tab 正常使用
```java
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
}
}
```
@tab 不使用 import 时
```java
public class Main {
public static void main(String[] args) {
java.util.Scanner scanner = new java.util.Scanner(System.in);
}
}
```
:::
### 2.2 创建具体项目
::: code-tabs
@tab Tree
```bash
(base) ➜ Code30 tree .
.
├── Code30.iml
└── src
└── com
└── phone
├── MyPhone.java
├── Phone.java
├── PhoneMaker.java
└── parts
├── CPU.java
├── Mainboard.java
├── Memory.java
├── Screen.java
└── Storage.java
5 directories, 9 files
```
@tab CPU
```java
/*
* @time : 2024/12/13 10:41
* @author : AI悦创
* @filename: CPU.java
* @software: IntelliJ IDEA
* @Version: V1.0
* @Blog : https://bornforthis.cn/
* Code is far away from bugs with the god animal protecting
* I love animals. They taste delicious.
*/
package com.phone.parts;
public class CPU {
public double speed;
public String producer;
}
```
@tab Mainboard
```java
/*
* @time : 2024/12/13 10:42
* @author : AI悦创
* @filename: Mainboard.java
* @software: IntelliJ IDEA
* @Version: V1.0
* @Blog : https://bornforthis.cn/
* Code is far away from bugs with the god animal protecting
* I love animals. They taste delicious.
*/
package com.phone.parts;
public class Mainboard {
public CPU cpu;
public Memory memory;
public Storage storage;
public String model;
// 上市年份
public int year;
}
```
@tab Memory
```java
/*
* @time : 2024/12/13 10:45
* @author : AI悦创
* @filename: Memory.java
* @software: IntelliJ IDEA
* @Version: V1.0
* @Blog : https://bornforthis.cn/
* Code is far away from bugs with the god animal protecting
* I love animals. They taste delicious.
*/
package com.phone.parts;
public class Memory {
public long capacity;
public String producer;
}
```
@tab Screen
```java
/*
* @time : 2024/12/13 10:47
* @author : AI悦创
* @filename: Screen.java
* @software: IntelliJ IDEA
* @Version: V1.0
* @Blog : https://bornforthis.cn/
* Code is far away from bugs with the god animal protecting
* I love animals. They taste delicious.
*/
package com.phone.parts;
public class Screen {
public double size;
public String producer;
}
```
@tab Storage
```java
/*
* @time : 2024/12/13 10:49
* @author : AI悦创
* @filename: Storage.java
* @software: IntelliJ IDEA
* @Version: V1.0
* @Blog : https://bornforthis.cn/
* Code is far away from bugs with the god animal protecting
* I love animals. They taste delicious.
*/
package com.phone.parts;
public class Storage {
public long capacity;
public String producer;
}
```
@tab MyPhone
```java
/*
* @time : 2024/12/13 10:34
* @author : AI悦创
* @filename: MyPhone.java
* @software: IntelliJ IDEA
* @Version: V1.0
* @Blog : https://bornforthis.cn/
* Code is far away from bugs with the god animal protecting
* I love animals. They taste delicious.
*/
package com.phone;
import com.phone.parts.*;
public class MyPhone {
Memory memory;
Storage storage;
}
```
@tab Phone
```java
/*
* @time : 2024/12/13 10:35
* @author : AI悦创
* @filename: Phone.java
* @software: IntelliJ IDEA
* @Version: V1.0
* @Blog : https://bornforthis.cn/
* Code is far away from bugs with the god animal protecting
* I love animals. They taste delicious.
*/
package com.phone;
//用到什么导入什么
import com.phone.parts.Mainboard;
import com.phone.parts.Screen;
public class Phone {
Screen screen;
Mainboard mainboard;
double price;
boolean hasFigurePrintUnlocker;
}
```
@tab PhoneMaker
```java
/*
* @time : 2024/12/13 10:37
* @author : AI悦创
* @filename: PhoneMaker.java
* @software: IntelliJ IDEA
* @Version: V1.0
* @Blog : https://bornforthis.cn/
* Code is far away from bugs with the god animal protecting
* I love animals. They taste delicious.
*/
package com.phone;
//import com.phone.parts.CPU;
//import com.phone.parts.Memory;
//import com.phone.parts.Screen;
//import com.phone.parts.Mainboard;
//import com.phone.parts.Storage;
import com.phone.parts.*;
public class PhoneMaker {
public static void main(String[] args) {
// 创建一个 Phone 的实例
Phone phone = new Phone();
// 可以设置断点查看实例内部状态
phone.hasFigurePrintUnlocker = true;
phone.price = 2999.9;
// 创建一个 Screen 的实例,给 phone 实例的 screen 引用赋值
phone.screen = new Screen();
// 通过引用 phone 找到 Phone 的对象,通过 screen 找到 Screen 对象,通过 .producer 给之赋值
phone.screen.producer = "京东方";
phone.screen.size = 6.6;
Mainboard mainboard = new Mainboard();
mainboard.model = "EA888";
mainboard.year = 2019;
mainboard.cpu = new CPU();
mainboard.cpu.producer = "德州仪器";
mainboard.cpu.speed = 3.5;
mainboard.memory = new Memory();
mainboard.memory.producer = "三星";
mainboard.memory.capacity = 4;
mainboard.storage = new Storage();
mainboard.storage.producer = "Intel";
mainboard.storage.capacity = 256;
// 想想我们创建了几个对象,有创建了几个引用?
}
}
```
:::
### 2.3 注意点
**Java 只能直接看到同级别的类,其他级别是看不到的。**
下面这么写就会报错:
::: code-tabs
@tab Tree
```bash {10}
(base) ➜ Code30 tree .
.
├── Code30.iml
└── src
└── com
└── phone
├── MyPhone.java
├── Phone.java
├── PhoneMaker.java
├── Test.java
└── parts
├── CPU.java
├── Mainboard.java
├── Memory.java
├── Screen.java
└── Storage.java
5 directories, 10 files
```
@tab Test
```java
/*
* @time : 2024/12/13 11:10
* @author : AI悦创
* @filename: Test.java
* @software: IntelliJ IDEA
* @Version: V1.0
* @Blog : https://bornforthis.cn/
* Code is far away from bugs with the god animal protecting
* I love animals. They taste delicious.
*/
package com.phone;
public class Test {
public static void main(String[] args) {
Memory memory;
}
}
```
@tab 报错
```java
/Users/huangjiabao/IdeaProjects/Code30/src/com/phone/Test.java:15:9
java: 找不到符号
符号: 类 Memory
位置: 类 com.phone.Test
```
:::
**解决方法:**
::: code-tabs
@tab 方法一
```java {5}
package com.phone;
public class Test {
public static void main(String[] args) {
com.phone.parts.Memory memory;
}
}
```
@tab 方法二
```java {3,7}
package com.phone;
import com.phone.parts.Memory;
public class Test {
public static void main(String[] args) {
Memory memory;
}
}
```
:::
对于方法一每次写 `com.phone.parts.Memory memory` 这么长显然有点累,所以可以使用 import。
## 3. 属性访问修饰符
Java 语言提供了很多修饰符,主要分为以下两类:
- 访问修饰符
- 非访问修饰符
修饰符用来定义类、方法或者变量,通常放在语句的最前端。我们通过下面的例子来说明:
```java
public class ClassName {
// ...
}
private boolean myFlag;
static final double weeks = 9.5;
protected static final int BOXWIDTH = 42;
public static void main(String[] arguments) {
// 方法体
}
```
### 3.1 public
- 被 public 修饰的属性,可以被任意包中的类访问。「可以被任何地方访问,不受包或类的限制。」「对所有类可见。使用对象:类、接口、变量、方法」
- 没有访问修饰符的属性,称作缺省的访问修饰符,可以被本包内的其他类和自己的对象
- 访问修饰符是一种限制或者允许属性访问的修饰符
到这里的时候,你会发现我提供的代码里面多了 public 或者你自己操作少了 public。这个时候我们可以发现 CPU 等类代码没有问题,但是其他位置的代码出现了问题。
我直接操作上面提供的类:删除 Mainboard.java 中 CPU 前面的 public,这个文件自己本身没有问题。
```java
package com.phone.parts;
public class Mainboard {
CPU cpu;
public Memory memory;
public Storage storage;
public String model;
// 上市年份
public int year;
}
```

别的文件则出现了问题,原因也很简单,这两个类不在同一个包内。
- Mainboard:`package com.phone.parts;`
- PhoneMaker:`package com.phone;`

但是没有 public 的 CPU 可以被自己包内正常调用:
::: code-tabs
@tab Tree
```bash {17}
(base) ➜ Code30 tree .
.
├── Code30.iml
└── src
└── com
└── phone
├── MyPhone.java
├── Phone.java
├── PhoneMaker.java
├── Test.java
└── parts
├── CPU.java
├── Mainboard.java
├── Memory.java
├── Screen.java
├── Storage.java
└── TestUseMainboard.java
5 directories, 11 files
```
@tab TestUseMainboard
```java
/*
* @time : 2024/12/13 11:37
* @author : AI悦创
* @filename: TestUseMainboard.java
* @software: IntelliJ IDEA
* @Version: V1.0
* @Blog : https://bornforthis.cn/
* Code is far away from bugs with the god animal protecting
* I love animals. They taste delicious.
*/
package com.phone.parts;
public class TestUseMainboard {
public static void main(String[] args) {
Mainboard mainboard = new Mainboard();
mainboard.cpu = new CPU();
mainboard.cpu.producer = "aaa";
}
}
```
:::

::: tip
当然,添加 public 修饰符后,其他包也可以访问。
:::
### 3.2 protected
::: info 定义
在同一类内可见,使用对象:变量、方法。**注意:不能修饰类(外部类)**「可以被同一个包内的类以及其他包中的子类访问。」
:::
### 3.3 default 「无修饰符(默认)」
::: info 定义
如果未指定修饰符,则默认为包级访问权限,只能被同一个包内的类访问。「即默认,什么也不写: 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。」
:::
### 3.4 private
::: info 定义
在同一类内可见。使用对象:变量、方法。 **注意:不能修饰类(外部类)**「只能在当前类内访问。」
:::
### 3.5 总结表格
| 修饰符 | 当前类 | 同包类 | 子类(跨包) | 其它包 |
| --------------- | ------ | ------ | ------------ | ------ |
| public | √ | √ | √ | √ |
| protected | √ | √ | √ | x |
| 默认「default」 | √ | √ | x | x |
| private | √ | x | x | x |
通过以上代码和表格,可以直观了解 Java 中访问修饰符的作用及限制。
### 3.6 代码示例
1. 项目名称:JavaModifiersDemo
2. 在里面创建以下结构:
```java
(base) ➜ JavaModifiersDemo git:(main) ✗ tree .
.
├── JavaModifiersDemo.iml
└── src
└── com
└── example
└── PublicClass.java
4 directories, 2 files
```
3. 开始写第一个类 `PublicClass`。
::: tabs
@tab PublicClass
```java
/*
* @time : 2024/12/15 18:44
* @author : AI悦创
* @filename: PublicClass.java
* @software: IntelliJ IDEA
* @Version: V1.0
* @Blog : https://bornforthis.cn/
* Code is far away from bugs with the god animal protecting
* I love animals. They taste delicious.
*/
package com.example;
// 这是一个公共类,任何地方都可以访问
public class PublicClass {
// 公共字段
public String publicField = "I am public!";
// 公共方法
public void publicMethod() {
System.out.println("This is a public method.");
}
}
```
**讲解:**
1. **`package com.example;`**:
- 声明类所属的包,这是为了组织代码,类似于文件夹结构。
- 代码文件 `PublicClass.java` 位于 `src/com/example` 文件夹中。
2. **`public class PublicClass`**:
- 类的修饰符是 `public`,意味着任何包的类都可以访问它。
3. **字段和方法**:
- **`publicField`** 是一个公共字段,外部类可以直接访问。
- **`publicMethod()`** 是一个公共方法,外部类也可以调用它。
**下一步:** 编译并运行 `PublicClass`,验证它的功能。
@tab MainTest
编写一个测试类来验证 PublicClass 的访问。
**步骤**
- 在 `com.example` 包中,创建一个新的类 `MainTest.java`,测试 `PublicClass` 的功能。
- Tree
```bash
(base) ➜ JavaModifiersDemo git:(main) ✗ tree .
.
├── JavaModifiersDemo.iml
└── src
└── com
└── example
├── MainTest.java
└── PublicClass.java
4 directories, 3 files
```
- MainTest.java
```java
/*
* @time : 2024/12/15 18:51
* @author : AI悦创
* @filename: MainTest.java
* @software: IntelliJ IDEA
* @Version: V1.0
* @Blog : https://bornforthis.cn/
* Code is far away from bugs with the god animal protecting
* I love animals. They taste delicious.
*/
package com.example;
public class MainTest {
public static void main(String[] args) {
// 创建 PublicClass 的实例
PublicClass publicClass = new PublicClass();
// 访问 publicField
System.out.println("Accessing publicField: " + publicClass.publicField);
// 调用 publicMethod
publicClass.publicMethod();
}
}
```
**讲解**
1. **实例化 `PublicClass`**:
- 使用 `new PublicClass()` 创建了一个对象,表示我们在内存中分配了这个类的空间。
2. **访问字段和方法**:
- **`publicField`**:直接访问公共字段,输出 "I am public!"。
- **`publicMethod()`**:调用公共方法,输出 "This is a public method."。
**输出结果:**
```java
Accessing publicField: I am public!
This is a public method.
```
@tab 添加受保护的类成员
**步骤**
- 在 `PublicClass` 的同一个包中添加一个新的类 `ProtectedClass`。
- Tree:
```bash
(base) ➜ JavaModifiersDemo git:(main) ✗ tree .
.
├── JavaModifiersDemo.iml
└── src
└── com
└── example
├── MainTest.java
├── ProtectedClass.java
└── PublicClass.java
4 directories, 4 files
```
- ProtectedClass.java
```java
/*
* @time : 2024/12/15 18:58
* @author : AI悦创
* @filename: ProtectedClass.java
* @software: IntelliJ IDEA
* @Version: V1.0
* @Blog : https://bornforthis.cn/
* Code is far away from bugs with the god animal protecting
* I love animals. They taste delicious.
*/
package com.example;
// 这是一个受保护的类,只能在同一个包中或子类中访问
public class ProtectedClass {
// 受保护字段
protected String protectedField = "I am protected!";
// 受保护方法
protected void protectedMethod() {
System.out.println("This is a protected method.");
}
}
```
**讲解**
1. `protected` 修饰符:
- 字段和方法标记为 `protected`,意味着只能:
- 在 **同一个包** 中访问。
- 或者被 **子类继承** 并访问。
**测试代码**
在 `MainTest` 中添加以下代码来验证:
```java
```
:::
欢迎关注我公众号:AI悦创,有更多更好玩的等你发现!
::: details 公众号:AI悦创【二维码】

:::
::: info AI悦创·编程一对一
AI悦创·推出辅导班啦,包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发」,全部都是一对一教学:一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然,还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线,随时响应!微信:Jiabcdefh
C++ 信息奥赛题解,长期更新!长期招收一对一中小学信息奥赛集训,莆田、厦门地区有机会线下上门,其他地区线上。微信:Jiabcdefh
方法一:[QQ](http://wpa.qq.com/msgrd?v=3&uin=1432803776&site=qq&menu=yes)
方法二:微信:Jiabcdefh
:::
1 parent 0f2b70c commit ebaa4e0
3 files changed
+206
-0
lines changedBinary file not shown.
Binary file not shown.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
590 | 590 | | |
591 | 591 | | |
592 | 592 | | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
| 680 | + | |
| 681 | + | |
| 682 | + | |
| 683 | + | |
| 684 | + | |
| 685 | + | |
| 686 | + | |
| 687 | + | |
| 688 | + | |
| 689 | + | |
| 690 | + | |
| 691 | + | |
| 692 | + | |
| 693 | + | |
| 694 | + | |
| 695 | + | |
| 696 | + | |
| 697 | + | |
| 698 | + | |
| 699 | + | |
| 700 | + | |
| 701 | + | |
| 702 | + | |
| 703 | + | |
| 704 | + | |
| 705 | + | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
| 711 | + | |
| 712 | + | |
| 713 | + | |
| 714 | + | |
| 715 | + | |
| 716 | + | |
| 717 | + | |
| 718 | + | |
| 719 | + | |
| 720 | + | |
| 721 | + | |
| 722 | + | |
| 723 | + | |
| 724 | + | |
| 725 | + | |
| 726 | + | |
| 727 | + | |
| 728 | + | |
| 729 | + | |
| 730 | + | |
| 731 | + | |
| 732 | + | |
| 733 | + | |
| 734 | + | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
| 738 | + | |
| 739 | + | |
| 740 | + | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
| 788 | + | |
| 789 | + | |
| 790 | + | |
| 791 | + | |
| 792 | + | |
| 793 | + | |
| 794 | + | |
| 795 | + | |
| 796 | + | |
| 797 | + | |
| 798 | + | |
593 | 799 | | |
594 | 800 | | |
595 | 801 | | |
| |||
0 commit comments