Java基础------访问修饰符

来源:互联网 发布:新浪微博抱歉网络繁忙 编辑:程序博客网 时间:2024/06/13 11:01

访问修饰符

我们知道不同包之间的类不能直接访问,需要导入相应的包,但是针对类内每个成员的每个定义(包括方法和属性),可以通过访问修饰符来决定它们的访问权限。

Java访问修饰符主要分为public(友好的)protected(受保护的)private(私有的)。无论它们修饰的是一个方法或者是一个数据成员,每个访问修饰符都只控制着对那个特定定义的访问。

public(友好的)

当一个方法或数据成员被修饰为public时,那么也就意味着当前包内的其他所有类都能访问,但对包外的所有类来说,这些方法或成员却是“私有”(private)的,外界不得访问。由于一个java文件只能从属于单个包,所以一个包中的所有类相互之间都是自动“友好”(public)的。因此,我们也说public修饰的元素拥有“包访问”权限

友好访问使得类在一个包内的组合显得有意义,因为当希望类之间可以相互访问,那么把那些类可以放在同一个保中,如果希望排除一些类,不想让他们访问当前包内定义的类,就放在其他包中。

private(私有的)

private关键字表明,除非是在那个特定的类,而且从那个类的方法里,否则没有人能访问那个成员。也就是说,同一个包中的其他类不能访问private成员(无论是属性还是方法)。所以,private允许我们自由地改变那个成员,同时不用关心它是否会影响同一个包内的另一个类。

同时,在涉及多线程处理的时候,private关键字也有非常重要的用途。

例子:private关键字的使用

class 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();  }}

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

此时还会产生另一个影响:由于默认构建器是唯一获得定义的,而且它的属性是private,所以可防止对这个类的继承。

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

protected(受保护的)

用protected修饰的类、类属变量及方法,包内的任何类及包外那些继承了该类的子类才能访问,protected重点突出继承

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

有些时候,基础类的创建者喜欢提供一个特殊的成员,并允许访问扩展类。这正是protected的工作。也就是说,基本类中的protected访问符修饰的成员,不希望被其他类访问,但是希望被扩展类访问,也就是被子类访问,此时,可以使用protected

default(默认的)

如果一个类、类属变量及方法没有用任何修饰符(即没有用public、protected及private中任何一种修饰),则其访问权限为default(默认访问权限)。

默认访问权限的类、类属变量及方法,包内的任何类(包括继承了此类的子类)都可以访问它,而对于包外的任何类都不能访问它(包括包外继承了此类的子类)。default重点突出包;

用访问修饰符控制类访问

在java中,也可以用访问符判断出一个包内的哪些类可以被那个包的其他类访问,哪些类不能。

如果想一个类能被其他类访问(在同一个包中),可在类主体的起始花括号前面某处放置一个public关键字。它控制着在其他类中是否能够创建属于这个类的一个对象。

此时需要注意的点:

1、每个java文件都只能有一个public类。每个文件有一个公共接口的概念是由那个公共类表达出来的。根据自己的需要,它可拥有任意多个提供支撑的public修饰的类。但若在一个文件里使用了多个public类,编译器就会向我们提示一条出错消息。

2、public类的名字必须与包含了编译单元的那个文件的名字完全相符,甚至包括它的大小写形式。同样地,如果出现不符,就会报告一个编译期错误。

3、可能(但并常见)有一个文件根本没有任何公共类。此时,可按自己的意愿任意指定文件名。

不可将类设成private(那样会使除类之外的其他东西都不能访问它),也不能设成protected。

因此,我们现在对于类的访问只有两个选择:“友好的”或者public。若不愿其他任何人访问那个类,可将所有构造器设为private。

这样一来,在类的一个static成员内部,除自己之外的其他所有人都无法创建属于那个类的一个对象。

class Soup {  private Soup() {}  public static Soup makeSoup() {    return new Soup();  }  private static Soup ps1 = new Soup();  public static Soup access() {    return ps1;  }  public void f() {}}class Sandwich {   void f() { new Lunch(); }}public class Lunch {  void test() {    Soup priv2 = Soup.makeSoup();    Sandwich f1 = new Sandwich();    Soup.access().f();  }}

Soup类向我们展示出如何通过将所有构建器都设为private,从而防止直接创建一个类。

第一个选择,我们可创建一个static方法,再通过它创建一个新的Soup,然后返回指向它的一个句柄。如果想在返回之前对Soup进行一些额外的操作,或者想了解准备创建多少个Soup对象(可能是为了限制它们的个数),这种方案无疑是特别有用的。

第二个选择是采用“设计方案”(Design Pattern)技术。通常方案叫作“独子”,因为它仅允许创建一个对象。类Soup的对象被创建成Soup的一个static private成员,所以有一个而且只能有一个。除非通过public方法access(),否则根本无法访问它。

总结

由于C仅有一个“命名空间”,所以名字会开始互相抵触,从而造成额外的管理开销。而在Java中,package关键字、包命名方案以及import关键字为我们提供对名字的完全控制,所以命名冲突的问题可以很轻易地得到避免。

两方面的原因要求我们控制对成员的访问:

第一个是防止用户接触那些他们不应碰的工具。对于数据类型的内部机制,那些工具是必需的。但它们并不属于用户接口的一部分,用户不必用它来解决自己的特定问题。所以将方法和字段变成“私有”(private)后,可极大方便用户。因为他们能轻易看出哪些对于自己来说是最重要的,以及哪些是自己需要忽略的。这样便简化了用户对一个类的理解。

进行访问控制的第二个、也是最重要的一个原因是:允许库设计者改变类的内部工作机制,同时不必担心它会对客户程序员产生什么影响。最开始的时候,可用一种方法构建一个类,后来发现需要重新构建代码,以便达到更快的速度。

如接口和实施细节早已进行了明确的分隔与保护,就可以轻松地达到自己的目的,不要求用户改写他们的代码。

利用Java中的访问指示符,可有效控制类的创建者。那个类的用户可确切知道哪些是自己能够使用的,哪些则是可以忽略的。但更重要的一点是,它可确保没有任何用户能依赖一个类的基础实施机制的任何部分。作为一个类的创建者,我们可自由修改基础的实施细节,这一改变不会对客户程序员产生任何影响,因为他们不能访问类的那一部分。

原创粉丝点击