access-control.md 8.5 KB
Newer Older
沉默王二's avatar
沉默王二 已提交
1
---
沉默王二's avatar
沉默王二 已提交
2 3 4
title: Java访问权限修饰符:掌握封装的核心原则
shortTitle: Java访问权限修饰符
description: 访问权限修饰符在Java编程中扮演着重要角色,它们有助于实现代码的封装与模块化。本文将详细解析Java中的四种访问权限修饰符:public、private、protected和默认(package-private),探讨它们的使用场景和作用。学习本文后,您将能够灵活运用访问权限修饰符,编写出高质量的Java代码。
沉默王二's avatar
沉默王二 已提交
5
category:
沉默王二's avatar
沉默王二 已提交
6
  - Java 核心
沉默王二's avatar
沉默王二 已提交
7
tag:
沉默王二's avatar
沉默王二 已提交
8 9 10 11
  - 面向对象编程
head:
  - - meta
    - name: keywords
沉默王二's avatar
沉默王二 已提交
12
      content: Java,访问权限修饰符,public,private,protected
沉默王二's avatar
沉默王二 已提交
13 14
---

沉默王二's avatar
沉默王二 已提交
15
# 5.8 Java访问权限修饰符
沉默王二's avatar
沉默王二 已提交
16

沉默王二's avatar
沉默王二 已提交
17
“我们先来讨论一下为什么需要访问权限控制。其实之前我们在讲[类和对象](https://javabetter.cn/oo/object-class.html)的时候有提到,今天我们来详细地聊一聊,三妹。”我开门见山地说,“三妹,你打开思维导图,记得做笔记哦。”
沉默王二's avatar
沉默王二 已提交
18 19 20 21

“好的。”三妹应声回答。

考虑两个场景:
沉默王二's avatar
沉默王二 已提交
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

场景 1:工程师 A 编写了一个类 ClassA,但是工程师 A 并不希望 ClassA 被其他类都访问到,该如何处理呢?

场景 2:工程师 A 编写了一个类 ClassA,其中有两个方法 fun1、fun2,工程师只想让 fun1 对外可见,也就是说,如果别的工程师来调用 ClassA,只可以调用方法 fun1,该怎么处理呢?

此时,访问权限控制便可以起到作用了。

在 Java 中,提供了四种访问权限控制:

- 默认访问权限(包访问权限)
- public
- private
- protected

类只可以用默认访问权限和 public 修饰。比如说:

沉默王二's avatar
沉默王二 已提交
38
```java
沉默王二's avatar
沉默王二 已提交
39 40 41 42 43
public class Wanger{}
```

或者

沉默王二's avatar
沉默王二 已提交
44
```java
沉默王二's avatar
沉默王二 已提交
45 46 47 48 49
class Wanger{}
```

但变量和方法则都可以修饰。

沉默王二's avatar
沉默王二 已提交
50
### 1. 修饰类
沉默王二's avatar
沉默王二 已提交
51 52 53 54 55 56 57 58 59

- 默认访问权限(包访问权限):用来修饰类的话,表示该类只对同一个包中的其他类可见。
- public:用来修饰类的话,表示该类对其他所有的类都可见。


例 1:

Main.java:

沉默王二's avatar
沉默王二 已提交
60
```java
沉默王二's avatar
沉默王二 已提交
61 62 63 64 65 66 67 68 69 70 71 72 73 74
package com.tobetterjavaer.test1;

public class Main {
	public static void main(String\[\] args) {

		People people = new People("Tom");
		System.out.println(people.getName());
	}

}
```

People.java

沉默王二's avatar
沉默王二 已提交
75
```java
沉默王二's avatar
沉默王二 已提交
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
package com.tobetterjavaer.test1;

class People {//默认访问权限(包访问权限)

	private String name = null;

	public People(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}
```

从代码可以看出,修饰 People 类采用的是默认访问权限,而由于 People 类和 Main 类在同一个包中,因此 People 类对于 Main 类是可见的。

例子 2:

People.java

沉默王二's avatar
沉默王二 已提交
102
```java
沉默王二's avatar
沉默王二 已提交
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
package com.tobetterjavaer.test2;

class People {//默认访问权限(包访问权限)

	private String name = null;

	public People(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}
```

此时 People 类和 Main 类不在同一个包中,会发生什么情况呢?

下面是 Main 类中的提示的错误:


沉默王二's avatar
沉默王二 已提交
128
![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/nice-article/bokeyuan-jianxijavazhongdifangwenquanxiankongzhi-154ae82f-72a5-45fc-ad3c-e1eb575d8572.png)
沉默王二's avatar
沉默王二 已提交
129 130 131 132 133 134


提示 Peolple 类在 Main 类中不可见。从这里就可以看出,如果用默认访问权限去修饰一个类,该类只对同一个包中的其他类可见,对于不同包中的类是不可见的。

正如上图的快速修正提示所示,将 People 类的默认访问权限更改为 public 的话,People 类对于 Main 类便可见了。

沉默王二's avatar
沉默王二 已提交
135
### 2. 修饰方法和变量
沉默王二's avatar
沉默王二 已提交
136 137 138 139 140 141 142 143 144 145 146 147 148

- 默认访问权限(包访问权限):如果一个类的方法或变量被包访问权限修饰,也就意味着只能在同一个包中的其他类中显示地调用该类的方法或者变量,在不同包中的类中不能显式地调用该类的方法或变量。
- private:如果一个类的方法或者变量被 private 修饰,那么这个类的方法或者变量只能在该类本身中被访问,在类外以及其他类中都不能显式的进行访问。
- protected:如果一个类的方法或者变量被 protected 修饰,对于同一个包的类,这个类的方法或变量是可以被访问的。对于不同包的类,只有继承于该类的类才可以访问到该类的方法或者变量。
- public:被 public 修饰的方法或者变量,在任何地方都是可见的。


例 3:

Main.java 没有变化

People.java

沉默王二's avatar
沉默王二 已提交
149
```java
沉默王二's avatar
沉默王二 已提交
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
package com.tobebetterjavaer.test1;

public class People {

	private String name = null;

	public People(String name) {
		this.name = name;
	}

	String getName() {    //默认访问权限(包访问权限)
		return name;
	}

	void setName(String name) {   //默认访问权限(包访问权限)
		this.name = name;
	}
}
```

此时在 Main 类是可以显示调用方法 getName 和 setName 的。

但是如果 People 类和 Main 类不在同一个包中:

沉默王二's avatar
沉默王二 已提交
174
```java
沉默王二's avatar
沉默王二 已提交
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
package com.tobebetterjavaer.test2;    //与Main类处于不同包中

public class People {

	private String name = null;

	public People(String name) {
		this.name = name;
	}

	String getName() {    //默认访问权限(包访问权限)
		return name;
	}

	void setName(String name) {   //默认访问权限(包访问权限)
		this.name = name;
	}
}
```

此时在 Main 类中会提示错误:


沉默王二's avatar
沉默王二 已提交
198
![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/nice-article/bokeyuan-jianxijavazhongdifangwenquanxiankongzhi-b3e9dc56-53e8-42f1-b8ee-35115edfe7e7.png)
沉默王二's avatar
沉默王二 已提交
199 200 201 202 203 204 205 206


由此可以看出,如果用默认访问权限来修饰类的方法或者变量,则只能在同一个包的其他类中进行访问。

例 4:

People.java

沉默王二's avatar
沉默王二 已提交
207
```java
沉默王二's avatar
沉默王二 已提交
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
package com.tobebetterjavaer.test1;

public class People {

	private String name = null;

	public People(String name) {
		this.name = name;
	}

	protected String getName() {
		return name;
	}

	protected void setName(String name) {
		this.name = name;
	}
}
```

此时是可以在 Main 中显示调用方法 getName 和 setName 的。

如果 People 类和 Main 类处于不同包中:

沉默王二's avatar
沉默王二 已提交
232
```java
沉默王二's avatar
沉默王二 已提交
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
package com.tobebetterjavaer.test2;

public class People {

	private String name = null;

	public People(String name) {
		this.name = name;
	}

	protected String getName() {
		return name;
	}

	protected void setName(String name) {
		this.name = name;
	}
}
```

则会在 Main 中报错:


沉默王二's avatar
沉默王二 已提交
256
![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/nice-article/bokeyuan-jianxijavazhongdifangwenquanxiankongzhi-b1d4b7ed-fc87-47d4-bdd9-3f6a8ea96100.png)
沉默王二's avatar
沉默王二 已提交
257 258 259 260


如果在 com.cxh.test1 中定一个类 Man 继承 People,则可以在类 Man 中显示调用方法 getName 和 setName:

沉默王二's avatar
沉默王二 已提交
261
```java
沉默王二's avatar
沉默王二 已提交
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
package com.tobebetterjavaer.test1;

import com.tobebetterjavaer.test2.People;

public class Man extends People {

    public Man(String name){
        super(name);
    }

    public String toString() {
        return getName();
    }
}
```

补充一些关于 Java 包和类文件的知识:

1)Java 中的包主要是为了防止类文件命名冲突以及方便进行代码组织和管理;

2)对于一个 Java 源代码文件,如果存在 public 类的话,只能有一个 public 类,且此时源代码文件的名称必须和 public 类的名称完全相同。

另外,如果还存在其他类,这些类在包外是不可见的。如果源代码文件没有 public 类,则源代码文件的名称可以随意命名。

沉默王二's avatar
沉默王二 已提交
286
“三妹,理解了吧?”我问三妹。
沉默王二's avatar
沉默王二 已提交
287

沉默王二's avatar
沉默王二 已提交
288
“是的,很简单,换句话说,不想让别人看的就 private,想让人看的就 public,想同一个班级/部门看的就默认,想让下一级看的就 protected,对吧?哥”三妹很自信地回答。
沉默王二's avatar
沉默王二 已提交
289

沉默王二's avatar
沉默王二 已提交
290 291 292
“不错不错,总结得有那味了。”

>原文链接:[https://www.cnblogs.com/dolphin0520/p/3734915.html](https://www.cnblogs.com/dolphin0520/p/3734915.html) 作者: Matrix海子,编辑:沉默王二
沉默王二's avatar
沉默王二 已提交
293

沉默王二's avatar
沉默王二 已提交
294
----
沉默王二's avatar
沉默王二 已提交
295

沉默王二's avatar
9000+  
沉默王二 已提交
296
GitHub 上标星 9000+ 的开源知识库《[二哥的 Java 进阶之路](https://github.com/itwanger/toBeBetterJavaer)》第一版 PDF 终于来了!包括Java基础语法、数组&字符串、OOP、集合框架、Java IO、异常处理、Java 新特性、网络编程、NIO、并发编程、JVM等等,共计 32 万余字,可以说是通俗易懂、风趣幽默……详情戳:[太赞了,GitHub 上标星 9000+ 的 Java 教程](https://javabetter.cn/overview/)
沉默王二's avatar
沉默王二 已提交
297

沉默王二's avatar
沉默王二 已提交
298 299

微信搜 **沉默王二** 或扫描下方二维码关注二哥的原创公众号沉默王二,回复 **222** 即可免费领取。
沉默王二's avatar
图片  
沉默王二 已提交
300

沉默王二's avatar
沉默王二 已提交
301
![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/gongzhonghao.png)