Java访问权限之public、protected、private详解——【包和访问控制】【访问权限控制】
@
源码:
Gitee https://gitee.com/drip123456/java-se
GIthub https://github.com/Drip123456/JavaSE
专栏: JavaSE笔记专栏
包和访问控制
通过前面的学习,我们知道该如何创建和使用类。
包声明和导入
包其实就是用来区分类位置的东西,也可以用来将我们的类进行分类(类似于C++中的namespace)随着我们的程序不断变大,可能会创建各种各样的类,他们可能会做不同的事情,那么这些类如果都放在一起的话,有点混乱,我们可以通过包的形式将这些类进行分类存放。
包的命名规则同样是英文和数字的组合,最好是一个域名的格式,比如我们经常访问的www.baidu.com
,后面的baidu.com就是域名,我们的包就可以命名为com.baidu
,当然,各位小伙伴现在还没有自己的域名,所以说我们随便起一个名称就可以了。其中的.
就是用于分割的,对应多个文件夹,比如com.test
:
我们可以将类放入到包中:
在这里插入图片描述
我们之前都是直接创建的类,所以说没有包这个概念,但是现在,我们将类放到包中,就需要注意了:
package com.test; //在放入包中,需要在类的最上面添加package关键字来指明当前类所处的包
public class Main { //将Main类放到com.test这个包中
public static void main(String[] args) {
}
}
这里又是一个新的关键字package
,这个是用于指定当前类所处的包的,注意,所处的包和对应的目录是一一对应的。
不同的类可以放在不同的包下:
当我们使用同一个包中的类时,直接使用即可(之前就是直接使用的,因为都直接在一个缺省的包中)而当我们需要使用其他包中的类时,需要先进行导入才可以:
package com.test;
import com.test.entity.Person; //使用import关键字导入其他包中的类
public class Main {
public static void main(String[] args) {
Person person = new Person(); //只有导入之后才可以使用,否则编译器不知道这个类从哪来的
}
}
这里使用了import
关键字导入我们需要使用的类,当然,只有在类不在同一个包下时才需要进行导入,如果一个包中有多个类,我们可以使用*
表示导入这个包中全部的类:
import com.test.entity.*;
实际上我们之前一直在使用的System
类,也是在一个包中的:
package java.lang;
import java.io.*;
import java.lang.reflect.Executable;
import java.lang.annotation.Annotation;
import java.security.AccessControlContext;
import java.util.Properties;
import java.util.PropertyPermission;
import java.util.StringTokenizer;
import java.util.Map;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.AllPermission;
import java.nio.channels.Channel;
import java.nio.channels.spi.SelectorProvider;
import sun.nio.ch.Interruptible;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.security.util.SecurityConstants;
import sun.reflect.annotation.AnnotationType;
import jdk.internal.util.StaticProperty;
/**
* The <code>System</code> class contains several useful class fields
* and methods. It cannot be instantiated.
*
* <p>Among the facilities provided by the <code>System</code> class
* are standard input, standard output, and error output streams;
* access to externally defined properties and environment
* variables; a means of loading files and libraries; and a utility
* method for quickly copying a portion of an array.
*
* @author unascribed
* @since JDK1.0
*/
public final class System {
...
}
可以看到它是属于java.lang
这个包下的类,并且这个类也导入了很多其他包中的类在进行使用。那么,为什么我们在使用这个类时,没有导入呢?实际上Java中会默认导入java.lang
这个包下的所有类,因此我们不需要手动指定。
IDEA非常智能,我们在使用项目中定义的类时,会自动帮我们将导入补全,所以说代码写起来非常高效。
注意,在不同包下的类,即使类名相同,也是不同的两个类:
package com.test.entity;
public class String { //我们在自己的包中也建一个名为String的类
}
当我们在使用时:
由于默认导入了系统自带的String类,并且也导入了我们自己定义的String类,那么此时就出现了歧义,编译器不知道到底我们想用的是哪一个String类,所以说我们需要明确指定:
public class Main {
public static void main(java.lang.String[] args) { //主方法的String参数是java.lang包下的,我们需要明确指定一下,只需要在类名前面添加包名就行了
com.test.entity.String string = new com.test.entity.String();
}
}
我们只需要在类名前面把完整的包名也给写上,就可以表示这个是哪一个包里的类了,当然,如果没有出现歧义,默认情况下包名是可以省略的,可写可不写。
可能各位小伙伴会发现一个问题,为什么对象的属性访问不了了?
编译器说name属性在这个类中不是public,无法在外部进行访问,这是什么情况呢?这里我们就要介绍的到Java的访问权限控制了。
访问权限控制
实际上Java中是有访问权限控制的,就是我们个人的隐私的一样,我不允许别人随便来查看我们的隐私,只有我们自己同意的情况下,才能告诉别人我们的名字、年龄等隐私信息。
所以说Java中引入了访问权限控制(可见性),我们可以为成员变量、成员方法、静态变量、静态方法甚至是类指定访问权限,不同的访问权限,有着不同程度的访问限制:
private
- 私有,标记为私有的内容无法被除当前类以外的任何位置访问。什么都不写
- 默认,默认情况下,只能被类本身和同包中的其他类访问。protected
- 受保护,标记为受保护的内容可以能被类本身和同包中的其他类访问,也可以被子类访问(子类我们会在下一章介绍)public
- 公共,标记为公共的内容,允许在任何地方被访问。
这四种访问权限,总结如下表:
当前类 | 同一个包下的类 | 不同包下的子类 | 不同包下的类 | |
---|---|---|---|---|
public | ✅ | ✅ | ✅ | ✅ |
protected | ✅ | ✅ | ✅ | ❌ |
默认 | ✅ | ✅ | ❌ | ❌ |
private | ✅ | ❌ | ❌ | ❌ |
比如我们刚刚出现的情况,就是因为是默认的访问权限,所以说在当前包以外的其他包中无法访问,但是我们可以提升它的访问权限,来使得外部也可以访问:
public class Person {
public String name; //在name变量前添加public关键字,将其可见性提升为公共等级
int age;
String sex;
}
这样我们就可以在外部正常使用这个属性了:
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name); //正常访问到成员变量
}
实际上如果各位小伙伴观察仔细的话,会发现我们创建出来的类自带的访问等级就是public
:
package com.test.entity;
public class Person { //class前面有public关键字
}
也就是说这个类实际上可以在任何地方使用,但是我们也可以将其修改为默认的访问等级:
package com.test.entity;
class Person { //去掉public变成默认等级
}
如果是默认等级的话,那么在外部同样是无法访问的:
但是注意,我们创建的普通类不能是protected
或是private
权限,因为我们目前所使用的普通类要么就是只给当前的包内使用,要么就是给外面都用,如果是private
谁都不能用,那这个类定义出来干嘛呢?
如果某个类中存在静态方法或是静态变量,那么我们可以通过静态导入的方式将其中的静态方法或是静态变量直接导入使用,但是同样需要有访问权限的情况下才可以:
public class Person {
String name;
int age;
String sex;
public static void test(){
System.out.println("我是静态方法!");
}
}
我们来尝试一下静态导入:
import static com.test.entity.Person.test; //静态导入test方法
public class Main {
public static void main(String[] args) {
test(); //直接使用就可以,就像在这个类定义的方法一样
}
}
至此,有关包相关的内容,我们就讲解到这里。