天天看点

JAVA的访问控制2-public,protected,private和package-private

作者:小朝的编程生涯

JAVA的访问控制2-public,protected,private和package-private

在前文JAVA的访问控制1-访问控制的必要性,包中介绍了访问控制的由来以及包的概念,本文将继续介绍访问控制的关键字public,protected,private以及没有关键字时默认的package-private。

这些关键字可以用于修饰字段,方法和内部类,另外,只有public和默认的package-private可以用于外部类定义。

package-private默认权限

当字段等没有任何修饰符时,就是默认权限,也就是包访问权限。包访问权限可以让当前包的所有类进行调用,其他包的类则无法调用。

比如,类Persion在包org.xxx.model下,代码如下:

package org.xxx;

public class Person {
    String name;

    String getName() {
        return name;
    }
}
           

那么,同样在包org.xxx.model下的其他类就可以访问到name字段和getName()方法,而其他包,比如org.xxx.util包下的类,就无法访问。

默认权限的一个用途是单元测试,被测试类中一些待测试字段和方法设置为默认权限,测试类可以方便地设置和调用。

大部分的方法都可以设置为包访问权限。

public

public关键字表示所有人都可以访问,通常是用于对外开放的方法上,如下所示:

package org.xxx.package1;

public class Formatter{
    public String describe() {
        return "formatter";
    }
}
           

Formatter的包是org.xxx,提供了一个describe()的方法,该方法可以被任何类调用。可以像下面这样来使用:

package org.xxx.package2;

import org.xxx.package1.Formatter;

public class User{
    public String describeFormatter() {
        Formatter formatter = new Formatter();
        return formatter.describe();
    }
}
           

使用Formatter的类位于另一个包下面,是可以正常使用的。

一般而言,不建议public修饰字段,如果开放某个字段,可以提供对应的getter和setter方法,比如:

public class Person {
    // private修饰符 后面会提到
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
           

这个也叫java bean,是一种非常常见的使用方法。

public修饰字段一般是用于常量的声明,比如一周有七天,很多地方需要使用这个信息,就可以声明一个常量public static final int DAYS_OF_WEEK = 7;,后面需要用这个数字进行计算的都使用DAYS_OF_WEEK常量来计算,可以使代码比较清晰明了。

private

private关键字意味着这个方法/字段无法被其他类以常规方法(非常规方法指反射)访问,包括同一个包里面的其他类,也无法访问。下面是一个样例:

public class Constants {
    public static final int DAYS_OF_WEEK = 7;

    private Constants() {
    }
}
           

这个样例中,private被用到了构造器上,说明这个类无法被其他类通过new Constants()的方法实例化,原因是这个类是用于定义常量的类,它本身不需要被实例化。上文提到的常量一般可以通过这种方式定义。

如果某个常量只在一个类里面使用,也可以直接定义在类内部,比如:

public class WeekUtil {
    private static final int DAYS_OF_WEEK = 7;

    public static int daysOfWeeks(int weekNum) {
        return DAYS_OF_WEEK * weekNum;
    }
}
           

daysOfWeeks(int weekNum)方法可以计算指定周数有多少天,这里就使用private来定义了DAYS_OF_WEEK常量。

protected

protected修饰的内容可以被子类访问,无论子类在哪个包下都可以。

比如我们有一个类Animal在包org.example下,声明了一个age字段:

package org.example;

public class Animal {
    protected int age;
}
           

有一个类Duck继承了这个类,它在org.example.duck下:

package org.example;
import org.example.Animal;

public class Duck extends Animal{
    public int ageOfDuck(){
        return age;
    }
}
           

在Duck中是可以自由使用age字段的。

package-private与protected

这两种权限很容易混淆,在使用时,可以分开来看。**两种权限是相互独立的,只要满足其中一条就可以访问到。**比如上文的类Animal,加了个字段:

package org.example;

public class Animal {
    protected int age;
    String name;
}
           

子类在org.example包里面时,包权限生效,name可以被访问到,子类不在org.example里面时,只能访问到age。同一个包里面的其他类,只能访问到name字段。

继续阅读