Skip to content

Commit ebaa4e0

Browse files
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 的目录下,咋眼一看有可能会比较乱,接下来我们看看怎么组织。 ![](./30.assets/1669471707497-41bd8bc4-7c08-469c-ba16-f73cebe3ae08.png) 代码应该也是有层级关系的,比如: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; } ``` ![](./30.assets/1669612487991-47b7f938-2ecb-4cd2-8176-1c6d8f3072aa.png) 别的文件则出现了问题,原因也很简单,这两个类不在同一个包内。 - Mainboard:`package com.phone.parts;` - PhoneMaker:`package com.phone;` ![](./30.assets/1669612538004-a065c9fb-e5b5-484b-bdcb-044ec5836244.png) 但是没有 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"; } } ``` ::: ![](./30.assets/1669613632190-a4f8f9df-fd6b-4a9f-a0cf-45851ea4c3c8.png) ::: 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悦创【二维码】 ![](/gzh.jpg) ::: ::: 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 ::: ![](/zsxq.jpg)
1 parent 0f2b70c commit ebaa4e0

File tree

3 files changed

+206
-0
lines changed

3 files changed

+206
-0
lines changed

src/Java/.DS_Store

0 Bytes
Binary file not shown.

src/Java/chapter02/.DS_Store

0 Bytes
Binary file not shown.

src/Java/chapter02/30.md

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,212 @@ public class TestUseMainboard {
590590

591591

592592

593+
### 3.6 代码示例
594+
595+
1. 项目名称:JavaModifiersDemo
596+
597+
2. 在里面创建以下结构:
598+
599+
```java
600+
(base) ➜ JavaModifiersDemo git:(main) ✗ tree .
601+
.
602+
├── JavaModifiersDemo.iml
603+
└── src
604+
└── com
605+
└── example
606+
└── PublicClass.java
607+
608+
4 directories, 2 files
609+
```
610+
611+
3. 开始写第一个类 `PublicClass`。
612+
613+
::: tabs
614+
615+
@tab PublicClass
616+
617+
```java
618+
/*
619+
* @Time : 2024/12/15 18:44
620+
* @Author : AI悦创
621+
* @FileName: PublicClass.java
622+
* @Software: IntelliJ IDEA
623+
* @Version: V1.0
624+
* @Blog : https://bornforthis.cn/
625+
* Code is far away from bugs with the god animal protecting
626+
* I love animals. They taste delicious.
627+
*/
628+
package com.example;
629+
630+
// 这是一个公共类,任何地方都可以访问
631+
public class PublicClass {
632+
// 公共字段
633+
public String publicField = "I am public!";
634+
635+
// 公共方法
636+
public void publicMethod() {
637+
System.out.println("This is a public method.");
638+
}
639+
}
640+
```
641+
642+
**讲解:**
643+
644+
1. **`package com.example;`**:
645+
- 声明类所属的包,这是为了组织代码,类似于文件夹结构。
646+
- 代码文件 `PublicClass.java` 位于 `src/com/example` 文件夹中。
647+
2. **`public class PublicClass`**:
648+
- 类的修饰符是 `public`,意味着任何包的类都可以访问它。
649+
3. **字段和方法**:
650+
- **`publicField`** 是一个公共字段,外部类可以直接访问。
651+
- **`publicMethod()`** 是一个公共方法,外部类也可以调用它。
652+
653+
**下一步:** 编译并运行 `PublicClass`,验证它的功能。
654+
655+
@tab MainTest
656+
657+
编写一个测试类来验证 PublicClass 的访问。
658+
659+
**步骤**
660+
661+
-`com.example` 包中,创建一个新的类 `MainTest.java`,测试 `PublicClass` 的功能。
662+
663+
- Tree
664+
665+
```bash
666+
(base) ➜ JavaModifiersDemo git:(main) ✗ tree .
667+
.
668+
├── JavaModifiersDemo.iml
669+
└── src
670+
└── com
671+
└── example
672+
├── MainTest.java
673+
└── PublicClass.java
674+
675+
4 directories, 3 files
676+
```
677+
678+
- MainTest.java
679+
680+
```java
681+
/*
682+
* @Time : 2024/12/15 18:51
683+
* @Author : AI悦创
684+
* @FileName: MainTest.java
685+
* @Software: IntelliJ IDEA
686+
* @Version: V1.0
687+
* @Blog : https://bornforthis.cn/
688+
* Code is far away from bugs with the god animal protecting
689+
* I love animals. They taste delicious.
690+
*/
691+
package com.example;
692+
693+
public class MainTest {
694+
public static void main(String[] args) {
695+
// 创建 PublicClass 的实例
696+
PublicClass publicClass = new PublicClass();
697+
698+
// 访问 publicField
699+
System.out.println("Accessing publicField: " + publicClass.publicField);
700+
701+
// 调用 publicMethod
702+
publicClass.publicMethod();
703+
}
704+
}
705+
```
706+
707+
**讲解**
708+
709+
1. **实例化 `PublicClass`**:
710+
- 使用 `new PublicClass()` 创建了一个对象,表示我们在内存中分配了这个类的空间。
711+
2. **访问字段和方法**:
712+
- **`publicField`**:直接访问公共字段,输出 "I am public!"
713+
- **`publicMethod()`**:调用公共方法,输出 "This is a public method."
714+
715+
**输出结果:**
716+
717+
```java
718+
Accessing publicField: I am public!
719+
This is a public method.
720+
```
721+
722+
@tab 添加受保护的类成员
723+
724+
**步骤**
725+
726+
- 在 `PublicClass` 的同一个包中添加一个新的类 `ProtectedClass`
727+
728+
- Tree:
729+
730+
```bash
731+
(base) ➜ JavaModifiersDemo git:(main) ✗ tree .
732+
.
733+
├── JavaModifiersDemo.iml
734+
└── src
735+
└── com
736+
└── example
737+
├── MainTest.java
738+
├── ProtectedClass.java
739+
└── PublicClass.java
740+
741+
4 directories, 4 files
742+
```
743+
744+
- ProtectedClass.java
745+
746+
```java
747+
/*
748+
* @Time : 2024/12/15 18:58
749+
* @Author : AI悦创
750+
* @FileName: ProtectedClass.java
751+
* @Software: IntelliJ IDEA
752+
* @Version: V1.0
753+
* @Blog : https://bornforthis.cn/
754+
* Code is far away from bugs with the god animal protecting
755+
* I love animals. They taste delicious.
756+
*/
757+
package com.example;
758+
759+
// 这是一个受保护的类,只能在同一个包中或子类中访问
760+
public class ProtectedClass {
761+
// 受保护字段
762+
protected String protectedField = "I am protected!";
763+
764+
// 受保护方法
765+
protected void protectedMethod() {
766+
System.out.println("This is a protected method.");
767+
}
768+
}
769+
```
770+
771+
**讲解**
772+
773+
1. `protected` 修饰符:
774+
- 字段和方法标记为 `protected`,意味着只能:
775+
- 在 **同一个包** 中访问。
776+
- 或者被 **子类继承** 并访问。
777+
778+
**测试代码**
779+
780+
`MainTest` 中添加以下代码来验证:
781+
782+
```java
783+
```
784+
785+
786+
787+
:::
788+
789+
790+
791+
792+
793+
794+
795+
796+
797+
798+
593799

594800

595801

0 commit comments

Comments
 (0)