5.2 Java访问指示符

针对类内每个成员的每个定义,Java访问指示符poublic,protected以及private都置于它们的最前面——无论它们是一个数据成员,还是一个方法。每个访问指示符都只控制着对那个特定定义的访问。这与C++存在着显著不同。在C++中,访问指示符控制着它后面的所有定义,直到又一个访问指示符加入为止。

通过千丝万缕的联系,程序为所有东西都指定了某种形式的访问。在后面的小节里,大家要学习与各类访问有关的所有知识。首次从默认访问开始。

5.2.1 “友好的”

如果根本不指定访问指示符,就象本章之前的所有例子那样,这时会出现什么情况呢?默认的访问没有关键字,但它通常称为“友好”(Friendly)访问。这意味着当前包内的其他所有类都能访问“友好的”成员,但对包外的所有类来说,这些成员却是“私有”(Private)的,外界不得访问。由于一个编译单元(一个文件)只能从属于单个包,所以单个编译单元内的所有类相互间都是自动“友好”的。因此,我们也说友好元素拥有“包访问”权限。

友好访问允许我们将相关的类都组合到一个包里,使它们相互间方便地进行沟通。将类组合到一个包内以后(这样便允许友好成员的相互访问,亦即让它们“交朋友”),我们便“拥有”了那个包内的代码。只有我们已经拥有的代码才能友好地访问自己拥有的其他代码。我们可认为友好访问使类在一个包内的组合显得有意义,或者说前者是后者的原因。在许多语言中,我们在文件内组织定义的方式往往显得有些牵强。但在Java中,却强制用一种颇有意义的形式进行组织。除此以外,我们有时可能想排除一些类,不想让它们访问当前包内定义的类。

对于任何关系,一个非常重要的问题是“谁能访问我们的‘私有’或private代码”。类控制着哪些代码能够访问自己的成员。没有任何秘诀可以“闯入”。另一个包内推荐可以声明一个新类,然后说:“嗨,我是Bob的朋友!”,并指望看到Bob的“protected”(受到保护的)、友好的以及“private”(私有)的成员。为获得对一个访问权限,唯一的方法就是:

(1) 使成员成为“public”(公共的)。这样所有人从任何地方都可以访问它。

(2) 变成一个“友好”成员,方法是舍弃所有访问指示符,并将其类置于相同的包内。这样一来,其他类就可以访问成员。

(3) 正如以后引入“继承”概念后大家会知道的那样,一个继承的类既可以访问一个protected成员,也可以访问一个public成员(但不可访问private成员)。只有在两个类位于相同的包内时,它才可以访问友好成员。但现在不必关心这方面的问题。

(4) 提供“访问器/变化器”方法(亦称为“获取/设置”方法),以便读取和修改值。这是OOP环境中最正规的一种方法,也是Java Beans的基础——具体情况会在第13章介绍。

5.2.2 public:接口访问

使用public关键字时,它意味着紧随在public后面的成员声明适用于所有人,特别是适用于使用库的客户程序员。假定我们定义了一个名为dessert的包,其中包含下述单元(若执行该程序时遇到困难,请参考第3章3.1.2小节“赋值”):

//: Cookie.java
// Creates a library
package c05.dessert;public class Cookie {public Cookie() { System.out.println("Cookie constructor"); }void foo() { System.out.println("foo"); }
} ///:~

请记住,Cookie.java必须驻留在名为dessert的一个子目录内,而这个子目录又必须位于由CLASSPATH指定的C05目录下面(C05代表本书的第5章)。不要错误地以为Java无论如何都会将当前目录作为搜索的起点看待。如果不将一个“.”作为CLASSPATH的一部分使用,Java就不会考虑当前目录。 现在,假若创建使用了Cookie的一个程序,如下所示:

//: Dinner.java
// Uses the library
import c05.dessert.*;public class Dinner {public Dinner() {System.out.println("Dinner constructor");}public static void main(String[] args) {Cookie x = new Cookie();//! x.foo(); // Can't access}
} ///:~

就可以创建一个Cookie对象,因为它的构建器是public的,而且类也是public的(公共类的概念稍后还会进行更详细的讲述)。然而,foo()成员不可在Dinner.java内访问,因为foo()只有在dessert包内才是“友好”的。

  1. 默认包

大家可能会惊讶地发现下面这些代码得以顺利编译——尽管它看起来似乎已违背了规则:

//: Cake.java
// Accesses a class in a separate
// compilation unit.class Cake {public static void main(String[] args) {Pie x = new Pie();x.f();}
} ///:~

在位于相同目录的第二个文件里:

//: Pie.java
// The other classclass Pie {void f() { System.out.println("Pie.f()"); }
} ///:~

最初可能会把它们看作完全不相干的文件,然而Cake能创建一个Pie对象,并能调用它的f()方法!通常的想法会认为Pie和f()是“友好的”,所以不适用于Cake。它们确实是友好的——这部分结论非常正确。但它们之所以仍能在Cake.java中使用,是由于它们位于相同的目录中,而且没有明确的包名。Java把象这样的文件看作那个目录“默认包”的一部分,所以它们对于目录内的其他文件来说是“友好”的。

5.2.3 private:不能接触!

private关键字意味着除非那个特定的类,而且从那个类的方法里,否则没有人能访问那个成员。同一个包内的其他成员不能访问private成员,这使其显得似乎将类与我们自己都隔离起来。另一方面,也不能由几个合作的人创建一个包。所以private允许我们自由地改变那个成员,同时毋需关心它是否会影响同一个包内的另一个类。默认的“友好”包访问通常已经是一种适当的隐藏方法;请记住,对于包的用户来说,是不能访问一个“友好”成员的。这种效果往往能令人满意,因为默认访问是我们通常采用的方法。对于希望变成public(公共)的成员,我们通常明确地指出,令其可由客户程序员自由调用。而且作为一个结果,最开始的时候通常会认为自己不必频繁使用private关键字,因为完全可以在不用它的前提下发布自己的代码(这与C++是个鲜明的对比)。然而,随着学习的深入,大家就会发现private仍然有非常重要的用途,特别是在涉及多线程处理的时候(详情见第14章)。 下面是应用了private的一个例子:

//: IceCream.java
// Demonstrates "private" keywordclass Sundae {private Sundae() {}static Sundae makeASundae() { return new Sundae(); }
}public class IceCream {public static void main(String[] args) {//! Sundae x = new Sundae();Sundae x = Sundae.makeASundae();}
} ///:~

这个例子向我们证明了使用private的方便:有时可能想控制对象的创建方式,并防止有人直接访问一个特定的构建器(或者所有构建器)。在上面的例子中,我们不可通过它的构建器创建一个Sundae对象;相反,必须调用makeASundae()方法来实现(注释③)。

③:此时还会产生另一个影响:由于默认构建器是唯一获得定义的,而且它的属性是private,所以可防止对这个类的继承(这是第6章要重点讲述的主题)。

若确定一个类只有一个“助手”方法,那么对于任何方法来说,都可以把它们设为private,从而保证自己不会误在包内其他地方使用它,防止自己更改或删除方法。将一个方法的属性设为private后,可保证自己一直保持这一选项(然而,若一个句柄被设为private,并不表明其他对象不能拥有指向同一个对象的public句柄。有关“别名”的问题将在第12章详述)。

5.2.4 protected:“友好的一种”

protected(受到保护的)访问指示符要求大家提前有所认识。首先应注意这样一个事实:为继续学习本书一直到继承那一章之前的内容,并不一定需要先理解本小节的内容。但为了保持内容的完整,这儿仍然要对此进行简要说明,并提供相关的例子。

protected关键字为我们引入了一种名为“继承”的概念,它以现有的类为基础,并在其中加入新的成员,同时不会对现有的类产生影响——我们将这种现有的类称为“基础类”或者“基本类”(Base Class)。亦可改变那个类现有成员的行为。对于从一个现有类的继承,我们说自己的新类“扩展”(extends)了那个现有的类。如下所示:

class Foo extends Bar {

类定义剩余的部分看起来是完全相同的。

若新建一个包,并从另一个包内的某个类里继承,则唯一能够访问的成员就是原来那个包的public成员。当然,如果在相同的包里进行继承,那么继承获得的包能够访问所有“友好”的成员。有些时候,基础类的创建者喜欢提供一个特殊的成员,并允许访问衍生类。这正是protected的工作。若往回引用5.2.2小节“public:接口访问”的那个Cookie.java文件,则下面这个类就不能访问“友好”的成员:

//: ChocolateChip.java
// Can't access friendly member
// in another class
import c05.dessert.*;public class ChocolateChip extends Cookie {public ChocolateChip() {System.out.println("ChocolateChip constructor");}public static void main(String[] args) {ChocolateChip x = new ChocolateChip();//! x.foo(); // Can't access foo}
} ///:~

对于继承,值得注意的一件有趣的事情是倘若方法foo()存在于类Cookie中,那么它也会存在于从Cookie继承的所有类中。但由于foo()在外部的包里是“友好”的,所以我们不能使用它。当然,亦可将其变成public。但这样一来,由于所有人都能自由访问它,所以可能并非我们所希望的局面。若象下面这样修改类Cookie:

public class Cookie {public Cookie() { System.out.println("Cookie constructor");}protected void foo() {System.out.println("foo"); }
}

那么仍然能在包dessert里“友好”地访问foo(),但从Cookie继承的其他东西亦可自由地访问它。然而,它并非公共的(public)。

from: https://quanke.gitbooks.io/think-in-java/content/5.2%20Java%E8%AE%BF%E9%97%AE%E6%8C%87%E7%A4%BA%E7%AC%A6.html

Java访问指示符 访问修饰符相关推荐

  1. java中的权限修饰符_Java的权限修饰符的区别和用法总结

    类中的数据成员和成员函数据具有的访问权限包括:public.private.protect.friendly(包访问权限). 1.public:public表明该数据成员.成员函数是对所有用户开放的, ...

  2. java修饰方法有哪些,探讨Java语言中那些修饰符

    一.在java中提供的一些修饰符,这些修饰符可以修饰类.变量和方法,在java中常见的修饰符有:abstract(抽象的).static(静态的).public(公共的).protected(受保护的 ...

  3. Java final修饰符的作用,Java中的final修饰符

    1.什么时候可以选择final修饰符 如果想让一个类不被其他类继承,不允许在有子类,这时候就要考虑用到final来修饰. 2.用final修饰的类 首先大家要明白,用final修饰的类是不能被继承的, ...

  4. Java 四种权限修饰符

    Java 四种权限修饰符访问权限 public protected (default) private 同一个类(我自己) yes yes yes yes 同一包(我邻居) yes yes yes n ...

  5. JAVA软件海豚_Java 修饰符

    一.访问控制修饰符 Java中,可以使用访问控制符来保护对类.变量.方法和构造方法的访问.Java支持4种不同的访问权限. 默认的,也称为 default,在同一包内可见,不使用任何修饰符. 私有的, ...

  6. Java常见的各种修饰符

    Java常见的各种修饰符 目录 Java常见的各种修饰符 修饰符的分类 一.访问权限修饰符 二.非访问权限修饰符 修饰符的使用 一.类修饰符 1.外部类修饰符 2.内部类修饰符 二.方法修饰符 三.变 ...

  7. 实际上Java注解与普通修饰符(public、static、void等)的使用方式并没有多大区别

    Java 注解 实际上Java注解与普通修饰符(public.static.void等)的使用方式并没有多大区别 注解的定义 日常开发中新建Java类,我们使用class.interface比较多,而 ...

  8. java 接口中变量修饰符,Java的访问修饰符与变量的作用域讲解

    Java访问修饰符(访问控制符) Java 通过修饰符来控制类.属性和方法的访问权限和其他功能,通常放在语句的最前端.例如: ? Java 的修饰符很多,分为访问修饰符和非访问修饰符.本节仅介绍访问修 ...

  9. 同包类 和 其他类 java_关于继承:为什么Java中的“protected”修饰符允许访问同一个包中的其他类?...

    在Java中,具有"受保护"修饰符的成员不仅可以由同一个类和子类访问,还可以由同一个包中的每个人访问? 我想知道语言设计的原因,而不是实际的应用程序(例如,测试) +1坦率地说我也 ...

最新文章

  1. html文字字号不改变,如何在不改变div大小的情况下更改HTML / css中的字体大小?...
  2. 110. Balanced Binary Tree
  3. matlab简单程序实例视频,matlab编程实例100例.docx
  4. java语言构造顺序树_PAT-1086(Tree Traversals Again)Java语言实现+根据中序和前序遍历构建树并且给出后序遍历序列...
  5. 【JOURNAL】Salles de SV Toulouse
  6. Winform控件学习笔记【第四天】——WebBrowser
  7. android系统关闭wifi,Android以编程方式打开/关闭WiFi HotSpot
  8. Java空字符串与null区别
  9. java简历自我评价_java程序员简历自我评价怎么写
  10. otdr进行多种测试鸿蒙包括,OTDR 测试
  11. LoadRunner压力测试:测试报告
  12. 技术评审之技术文档的规范模板
  13. 看球二三事 - 世界杯征文
  14. 快速识别无效数据(数据有效性/数据验证)
  15. 身份管理的15个安全开发实践
  16. simulink他励直流电动机串电阻启动仿真
  17. 木马免杀原理及方法(超全)
  18. .Net混淆工具和反混淆工具
  19. 关于项目外包的一些总结
  20. mysql存储csv文件_MySQL 查询结果保存为CSV文件

热门文章

  1. 老赖凭本事骗钱,你有本事不被骗吗?
  2. 今年美国广告程序化购买支出将超252亿美元
  3. 为什么JavaScript现在和将来都是编程语言首选?
  4. 转载:谢谢原作者: 块设备驱动实战基础篇二 (继续完善170行过滤驱动代码至200行)
  5. MyBatis-06 MyBatis XML方式之多个接口参数用法
  6. Java-Java I/O流解读之java.io.PrintStream java.io.PrintWriter
  7. Android日期分组,按查询分组在列表视图android中显示一些意...
  8. linux检查是否安装proc编译器,编译安装 GCC 4.9并验证使用
  9. java.lang.InstantiationException 不能实例化某个对象
  10. android唤醒前台,Android将后台应用唤起到前台的方法 (SDK 4.0, ActivityLifecycleCallbacks)...