Java访问修饰符
Java访问修饰符指定哪些类可以访问给定的类及其字段,构造函数和方法。可以为类,其构造函数,字段和方法分别指定访问修饰符。 Java访问修饰符有时在日常用语中也称为Java访问修饰符,但正确的名称是Java访问修饰符。类,字段,构造函数和方法可以具有四个不同的Java访问修饰符之一:
- private
- default (package)
- protected
- public
这些Java访问修饰符将在本Java访问修饰符教程的以下各节中介绍。下表总结了每个Java访问修饰符可以应用到的Java构造:
private | default | protected | public | |
私有 | 默认 | 受保护 | 公共 | |
类 | 否 | 是 | 否 | 是 |
嵌套类别 | 是 | 是 | 是 | 是 |
构造函数 | 是 | 是 | 是 | 是 |
方法 | 是 | 是 | 是 | 是 |
字段 | 是 | 是 | 是 | 是 |
将访问修饰符分配给类,构造函数,字段或者方法有时也称为"标记"该访问修饰符指定的类,构造函数,字段或者方法。例如,将Java访问修饰符" public"分配给方法将被称为将方法标记为" public"。
专用访问修饰符
如果将方法或者变量标记为"私有"(已为其分配了"私有"访问修饰符),则只有同一类内的代码才能访问该变量或者调用该方法。子类中的代码无法访问变量或者方法,也不能从任何外部类中进行代码。
类不能用" private"访问修饰符标记。用" private"访问修饰符标记一个类将意味着没有其他类可以访问它,这意味着我们根本无法真正使用该类。因此,类不能使用" private"访问修饰符。
这是将" private"访问修饰符分配给字段的示例:
public class Clock { private long time = 0; }
成员变量"时间"已被标记为"私有"。这意味着,不能从"时钟"类外部的代码访问"时钟"类内部的成员变量"时间"。
通过访问器方法访问私有字段
通常将字段声明为"私有",以控制外界对其的访问。在某些情况下,这些字段是真正私有的,这意味着它们仅在类中内部使用。在其他情况下,可以通过访问器方法(例如getter和setter)访问这些字段。这是一个访问器方法示例:
public class Clock { private long time = 0; public long getTime() { return this.time; } public void setTime(long theTime) { this.time = theTime; } }
在上面的示例中,两个方法getTime()和setTime()可以访问time成员变量。这两个方法都声明为" public",这意味着可以在应用程序中任何位置的代码中调用它们。本文稍后将介绍" public" Java访问修饰符。
private构造函数
如果为类中的构造函数分配了"私有" Java访问修饰符,则意味着无法从类外部的任何地方调用该构造函数。仍然可以从其他构造函数或者同一类的static方法中调用一个private构造函数。这是一个Java类示例,说明了这一点:
public class Clock { private long time = 0; private Clock(long time) { this.time = time; } public Clock(long time, long timeOffset) { this(time); this.time += timeOffset; } public static Clock newClock() { return new Clock(System.currentTimeMillis()); } }
这个版本的Clock类包含一个private构造函数和一个public构造函数。从公共构造函数中调用" private"构造函数(语句" this();")。 private构造函数也可以从static方法newClock()中调用。
上面的示例仅向我们显示可以从公共构造函数和同一类中的static方法调用"私有"构造函数。请勿以任何方式将上述示例视为聪明设计的示例。
默认(程序包)访问修饰符
通过根本不编写任何访问修饰符来声明默认的Java访问修饰符。默认访问修饰符意味着,类本身内部的代码以及与此类位于同一包中的类内部代码,都可以访问分配了默认访问修饰符的类,字段,构造函数或者方法。因此," default"访问修饰符有时也称为" package"访问修饰符。如果我们不知道Java包是什么,我已经在Java包教程中对此进行了解释。
子类不能访问超类中的方法和成员变量(字段),如果它们用默认的访问修饰符标记,除非子类与超类位于同一包中。
这是默认的/包访问修饰符示例:
public class Clock { long time = 0; } public class ClockReader { Clock clock = new Clock(); public long readClock{ return clock.time; } }
"时钟"类中的"时间"字段没有访问修饰符,这意味着为它隐式分配了默认/包访问修饰符。因此,只要ClockReader
和Clock
位于同一Java包中,ClockReader
类就可以读取Clock
对象的time
成员变量。
受保护的访问修饰符
" protected"访问修饰符提供与" default"访问修饰符相同的访问权限,此外,子类可以访问" protected"方法和超类的成员变量(字段)。即使子类与超类不在同一个包中,也是如此。
这是一个"受保护的"访问修饰符示例:
public class Clock { protected long time = 0; // time in milliseconds } public class SmartClock() extends Clock{ public long getTimeInSeconds() { return this.time / 1000; } }
在上面的示例中,子类SmartClock具有名为getTimeInSeconds()的方法,该方法访问超类Clock的time变量。即使Clock
和SmartClock
不在同一个包中,这也是可能的,因为time
字段标记有protected
Java访问修饰符。
公共访问修饰符
Java访问修饰符" public"意味着所有代码都可以访问类,字段,构造函数或者方法,而不管访问代码位于何处。访问代码可以在不同的类和不同的包中。
这是一个public
访问修饰符示例:
public class Clock { public long time = 0; } public class ClockReader { Clock clock = new Clock(); public long readClock{ return clock.time; } }
"时钟"类中的"时间"字段标记有"公共" Java访问修饰符。因此,无论ClockReader位于哪个包中,ClockReader类都可以访问Clock中的time字段。
类访问修饰符
重要的是要记住,分配给Java类的Java访问修饰符优先于分配给该类的字段,构造函数和方法的所有访问修饰符。如果该类标记有"默认"访问修饰符,则同一Java包之外的其他任何类都不能访问该类,包括其构造函数,字段和方法。将这些字段声明为" public",甚至是" public static"都无济于事。
Java访问修饰符" private"和" protected"不能分配给一个类。仅适用于类内的构造函数,方法和字段。类只能分配给默认类(包)和" public"访问修饰符。
接口访问修饰符
Java接口用于指定在实现接口的类中公共可用的字段和方法。因此,我们不能在接口中使用"私有"和"受保护"访问修饰符。如果省略访问修饰符,则接口中的字段和方法将隐式声明为" public",因此也不能使用默认访问修饰符(无访问修饰符)。
访问修饰符和继承
当创建某个类的子类时,子类中的方法所分配的访问修饰符不能比超类中的方法少。例如,如果超类中的方法是" public",那么子类中的方法也必须是" public",以防子类覆盖该方法。如果超类中的方法是"保护的",那么它在子类中必须是"保护的"或者"公共的"。
虽然不允许降低覆盖方法的可访问性,但允许扩展覆盖方法的可访问性。例如,如果在超类中为方法分配了默认的访问修饰符,则允许在子类中为" public"访问修饰符分配重写的方法。