什么是包访问权限?
包访问权限的作用
替代方案:get/set 方法:
修饰符 | 类内 | 同包 | 子类(不同包) | 其他包 |
|---|---|---|---|---|
private | ✅ | ❌ | ❌ | ❌ |
包访问权限(默认,无修饰符) | ✅ | ✅ | ❌ | ❌ |
protected | ✅ | ✅ | ✅ | ❌ |
public | ✅ | ✅ | ✅ | ✅ |
可以跨包继承,即子类可以和父类位于不同包中,但子类对父类成员的访问权限会受限制,具体取决于父类成员的访问修饰符:
父类成员修饰符 | 同包子类访问 | 跨包子类访问 |
|---|---|---|
public | 可以 | 可以 |
protected | 可以 | 可以 |
包访问权限(默认,无修饰符) | 可以 | 不可以 |
private | 不可以 | 不可以 |
注意:import并没有打破访问权限。import只是让代码可以用类名直接访问跨包的类,但能否调用类中的方法(包括构造方法),完全由方法的访问修饰符决定。如果一个类的构造方法是public的,通过import到另一个包的时候,可以通过 new 构造方法 创建对象。因为构造方法是public的,可以挎包使用,但是如果构造方法是private或者是默认的包内使用,就不能new 构造方法 来创建了。 另外private 构造方法 其实是实现单例的一个重要方法。
当 Java 文件中没有写package语句时,该类属于 “默认包”。此时:
注意:默认包在开发中几乎遇不到,默认包就像 “代码的临时垃圾桶”,只在极简单的场景下临时使用,正规开发中几乎见不到。它的存在主要是为了方便初学者入门,但从工程化角度看,违背了 Java 的包管理设计初衷,因此被开发者广泛 “抛弃”。
private修饰的成员(构造方法、属性、方法)仅当前类可见,其他类(包括同包的类)都无法访问。private的关键作用class Sundae {
private Sundae() {} // 私有的构造方法,禁止外部直接new
static Sundae makeASundae() {
return new Sundae(); // 类内部创建实例并返回
}
}
在外部不能通过new Sundae来创建实例对象,只能通过开放的接口makeASundae来创建实例对象,而makeASundae是可以自己来指定逻辑的。相当于控制了对象的创建方式
保护类的内部实现
private,防止被包内其他类误用或修改。private void calculate(),若设为public,可能被其他类错误调用,而private能确保它只在本类内使用。隐藏属性,强制封装
private,通过public的getter/setter方法暴露访问接口,符合面向对象的封装原则(如private int age; public int getAge() { return age; })。 封装原则的本质是将数据与操作数据的方法绑定,并隐藏内部实现细节,仅通过可控接口对外暴露功能。class 儿子 extends 父亲 {},儿子能直接用父亲的东西,还能自己添加新东西。protected修饰的成员,子类(跨包也能访问)和同包的类可以用,但其他包的非子类不能用。注意:允许子类(无论是否跨包)在自身代码中调用父类的protected方法,但禁止非子类通过子类实例访问该方法。
对于上面的注意点,很多人可能会有误区,在这里用代码解释一下。
package A;
public class Parent {
protected void fun(){
System.out.println("父类函数打印test\n");
}
}package B;
import A.Parent;
public class Child extends Parent {
public void funChild(){
fun();
}
public void funB(){
System.out.println("子类自己的打印方法\n");
}
}package C;
import A.Parent;
import B.Child;
public class OutClass {
public void fun(){
Child child=new Child();
child.funChild();
child.funB();
child.fun()//这个是不可以的 会报错
}
}外类OutClass通过子类实例child,调用父类方法fun();是不可以的。child.fun()(错误的)。但是调用 child.funChild();是可以的,这里关键的一点是,OutClass并没有直接调用Child实例的fun()方法,而是调用了funChild()方法,而funChild()是Child类自身的公共方法。
核心逻辑:类的访问权限优先于构造器
类的访问权限是 “包访问权限”(默认修饰符)
public修饰时,它只能在当前包内被访问(即 “包访问权限”)。public构造器)都会被类的访问权限 “覆盖”。构造器的public修饰符在包外无效
A是包访问权限,即使它有public A()构造器,包外代码也无法通过该构造器创建对象,因为类本身不能被包外访问。联系:这个和前面说的默认包不同,默认包是看有没有package不是看public。没有package即使有public也不能跨包访问。因为public 类的访问权限是 “所有包可见”,但默认包的特殊性导致其他包无法引用,因此实际效果与包访问权限类相同(只能在默认包内访问)。
类的访问权限用于控制类库中哪些类可被外部使用。若希望类能被客户端使用,需用public修饰类,这也决定了客户端能否创建该类的对象。
public类public类名必须与文件名一致public类private或protected修饰:类的访问权限只能是包访问权限或public,但可通过将构造器声明为private来间接限制类的使用。原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。