小程序定制开发多少钱一个seo网站诊断流程
Java 访问权限修饰符 public,protected 和 private 位于定义的类名,属性名和方法名之前。每个访问权限修饰符只能控制它所修饰的对象。
如果不提供访问修饰符,就意味着"包访问权限"。所以无论如何,万物都有某种形式的访问控制权。接下来的几节中,你将学习各种类型的访问权限。
-
包访问修饰符
本章之前的所有示例要么使用 public 访问修饰符,要么就没使用修饰符(默认访问)。默认访问权限没有关键字,通常被称为包访问权限(我以前一直以为没有修饰符)(有时也称为 friendly)。这意味着当前包中的所有其他类都可以访问那个成员。对于这个包之外的类,这个成员看上去是 private 的。由于一个编译单元(即一个文件)只能隶属于一个包,所以通过包访问权限,位于同一编译单元中的所有类彼此之间都是可访问的。
- 下来看一个包访问权限的实例
package hiding.dessert;public class Cookie {public Cookie() {System.out.println("Cookie constructor");}void bite() {System.out.println("bite");}
}
记住,Cookie.java 文件产生的类文件必须位于名为 dessert 的子目录中,该子目录在 hiding 下,它必须在 CLASSPATH 的几个目录之下。不要错误地认为 Java 总是会将当前目录视作查找行为的起点之一。如果你的 CLASSPATH 中没有 .
,Java 就不会查找单独当前目录。
接下来创建实现的程序
import hiding.dessert.*;public class Dinner {public static void main(String[] args) {Cookie x = new Cookie();// -x.bite(); // Can't access}
}
输出:
Cookie constructor
进行分析:在这里你可以调用Cookie的构造方法,但是你调用他的bite()方法的时候就会出现错误,因为这个方法默认是包权限,所以必须在同一个包下才可以进行访问。
-
默认包
在同一个目录下创建两个文件
// hiding/Cake.java
// Accesses a class in a separate compilation unit
class Cake {public static void main(String[] args) {Pie x = new Pie();x.f();}
}
// hiding/Pie.java
// The other class
class Pie {void f() {System.out.println("Pie.f()");}
}
输出:
Pie.f()
最初看上去这两个文件毫不相关,但在 Cake 中可以创建一个 Pie 对象并调用它的 f()
方法。(注意,你的 CLASSPATH 中一定得有 .
,这样文件才能编译)通常会认为 Pie 和 f()
具有包访问权限,因此不能被 Cake 访问。它们的确具有包访问权限,这是部分正确。Cake.java 可以访问它们是因为它们在相同的目录中且没有给自己设定明确的包名。Java 把这样的文件看作是隶属于该目录的默认包中,因此它们为该目录中所有的其他文件都提供了包访问权限。
protected: 继承访问权限
要理解 protected 的访问权限,我们在内容上需要作一点跳跃。首先,在介绍本书"复用"章节前,你不必真正理解本节的内容。但为了内容的完整性,这里作了简要介绍,举了个使用 protected 的例子。
关键字 protected 处理的是继承的概念,通过继承可以利用一个现有的类——我们称之为基类,然后添加新成员到现有类中而不必碰现有类。我们还可以改变类的现有成员的行为。为了从一个类中继承,需要声明新类 extends 一个现有类,像这样:
class Foo extends Bar {}
类定义的其他部分看起来是一样的。
如果你创建了一个新包,并从另一个包继承类,那么唯一能访问的就是被继承类的 public 成员。(如果在同一个包中继承,就可以操作所有的包访问权限的成员。)有时,基类的创建者会希望某个特定成员能被继承类访问,但不能被其他类访问。这时就需要使用 protected。protected 也提供包访问权限,也就是说,相同包内的其他类可以访问 protected 元素。
回顾下先前的文件 Cookie.java,下面的类不能调用包访问权限的方法 bite()
:
// hiding/ChocolateChip.java // Can't use package-access member from another package import hiding.dessert.*;public class ChocolateChip extends Cookie {public ChocolateChip() {System.out.println("ChocolateChip constructor");} public void chomp() {//- bite(); // Can't access bite}public static void main(String[] args) {ChocolateChip x = new ChocolateChip();x.chomp();} }
输出:
Cookie constructor
ChocolateChip constructor
如果类 Cookie 中存在一个方法 bite()
,那么它的任何子类中都存在 bite()
方法。但是因为 bite()
具有包访问权限并且位于另一个包中,所以我们在这个包中无法使用它。你可以把它声明为 public,但这样一来每个人都能访问它,这可能也不是你想要的。如果你将 Cookie 改成如下这样:
// hiding/cookie2/Cookie.java package hiding.cookie2;public class Cookie {public Cookie() {System.out.println("Cookie constructor");}protected void bite() {System.out.println("bite");} }
这样,bite()
对于所有继承 Cookie 的类,都是可访问的:
// hiding/ChocolateChip2.java import hiding.cookie2.*;public class ChocolateChip2 extends Cookie {public ChocoalteChip2() {System.out.println("ChocolateChip2 constructor");}public void chomp() {bite(); // Protected method}public static void main(String[] args) {ChocolateChip2 x = new ChocolateChip2();x.chomp();} }
输出:
Cookie constructor
ChocolateChip2 constructor
bite
尽管 bite()
也具有包访问权限,但它不是 public 的。
包访问权限 Vs Public 构造器
当你定义一个具有包访问权限的类时,你可以在类中定义一个 public 构造器,编译器不会报错:
// hiding/packageaccess/PublicConstructor.java package hiding.packageaccess;class PublicConstructor {public PublicConstructor() {} }
有一个 Checkstyle 工具,你可以运行命令 gradlew hiding:checkstyleMain 使用它,它会指出这种写法是虚假的,而且从技术上来说是错误的。实际上你不能从包外访问到这个 public 构造器:
// hiding/CreatePackageAccessObject.java // {WillNotCompile} import hiding.packageaccess.*;public class CreatePackageAcessObject {public static void main(String[] args) {new PublicConstructor();} }
如果你编译下这个类,会得到编译错误信息:
CreatePackageAccessObject.java:6:error:
PublicConstructor is not public in hiding.packageaccess;
cannot be accessed from outside package
new PublicConstructor();
^
1 error
因此,在一个具有包访问权限的类中定义一个 public 的构造器并不能真的使这个构造器成为 public,在声明的时候就应该标记为编译时错误。