我刚开始阅读一本 Java 书籍并想知道;如果没有指定,哪个访问说明符是默认的?
12 回答
默认说明符取决于上下文。
对于类和接口声明,默认为包私有。这介于受保护和私有之间,只允许同一包中的类访问。(protected 是这样的,但也允许访问包外的子类。)
class MyClass // package private
{
int field; // package private field
void calc() { // package private method
}
}
对于接口成员(字段和方法),默认访问是公共的。但请注意,接口声明本身默认为包私有。
interface MyInterface // package private
{
int field1; // static final public
void method1(); // public abstract
}
如果我们有声明
public interface MyInterface2 extends MyInterface
{
}
然后使用 MyInterface2 的类可以从超级接口看到 field1 和 method1,因为它们是公共的,即使它们看不到 MyInterface 本身的声明。
如果没有给出访问说明符,则它是类和类成员的包级访问(没有明确的说明符)。接口方法是隐式公开的。
默认可见性(无关键字)是包,这意味着它将可用于位于同一包中的每个类。
有趣的附注是protected不会限制对子类的可见性,还会限制对同一包中的其他类的可见性
这取决于事情是什么。
默认情况下,顶级类型(即未在其他类型中声明的类、枚举、接口和注释类型)是包私有的。(JLS §6.6.1)
在类中,所有成员(即字段、方法和嵌套类型声明)和构造函数默认情况下都是包私有的。(JLS §6.6.1)
- 当一个类没有显式声明的构造函数时,编译器会插入一个默认的零参数构造函数,该构造函数与 class 具有相同的访问说明符。( JLS §8.8.9 ) 默认构造函数通常被误认为始终是公共的,但在极少数情况下并不等效。
在枚举中,构造函数默认是私有的。事实上,枚举构造器必须是私有的,将它们指定为公共或受保护是错误的。枚举常量始终是public,并且不允许任何访问说明符。默认情况下,枚举的其他成员是包私有的。(JLS§8.9)
在接口和注释类型中,所有成员(同样,这意味着字段、方法和嵌套类型声明)默认情况下都是公共的。实际上,接口和注释类型的成员必须是公共的,将它们指定为私有或受保护是错误的。(JLS §9.3 至 9.5)
本地类是在方法、构造函数或初始化程序块中声明的命名类。它们的作用域仅限于声明它们的
{
..}
块,并且不允许任何访问说明符。( JLS §14.3 ) 使用反射,您可以从其他地方实例化本地类,它们是包私有的,尽管我不确定 JLS 中是否包含该细节。匿名类是使用
new
直接在表达式中指定类主体创建的自定义类。(JLS §15.9.5)它们的语法不允许任何访问说明符。使用反射,您可以从其他地方实例化匿名类,并且它们及其生成的构造函数都是package-private,尽管我不确定该细节是否在 JLS 中。实例和静态初始化程序块在语言级别没有访问说明符(JLS §8.6 和 8.7),但静态初始化程序块被实现为名为
<clinit>
(JVMS §2.9)的方法,因此该方法必须在内部具有一些访问说明符。我使用十六进制编辑器检查了 javac 和 Eclipse 编译器编译的类,发现两者都将方法生成为package-private。但是,您不能<clinit>()
在语言中调用,因为<
和>
字符在方法名称中是无效的,并且反射方法被硬连线以否认其存在,因此它的访问说明符实际上是no access。该方法只能在类初始化期间由 VM 调用。实例初始化程序块不编译为单独的方法;它们的代码被复制到每个构造函数中,因此即使通过反射也不能单独访问它们。
default是一个关键字,用作方法和变量的访问修饰符。
使用此访问修饰符将使您的类、变量、方法或构造函数可以从自己的类或包中访问,如果不存在访问修饰符,它也会被设置。
Access Levels
Modifier Class Package Subclass EveryWhere
public Y Y Y Y
protected Y Y Y N
default Y Y N N
private Y N N N
如果您在接口中使用默认值,您将能够在那里实现一个方法,例如这个例子
public interface Computer {
default void Start() {
throw new UnsupportedOperationException("Error");
}
}
但是它只适用于 8 Java 版本
有关更多详细信息,请参见此处。默认值不是私有/公共/受保护的,而是完全不同的访问规范。它没有被广泛使用,我更喜欢在我的访问定义中更加具体。
默认访问说明符是包。类可以访问同一包中其他类的成员。但在包之外它显示为私有
以下是对 Java 的创建者 James Gosling 的采访中关于包级别可见性的引用:
Bill Venners:Java 有四个访问级别。默认为包。我一直想知道将包访问设为默认是否方便,因为 C++ 的人已经知道的三个关键字是 private、protected 和 public。或者,如果您有某些特殊原因认为包访问应该是默认设置。
James Gosling:一个包通常是一组写在一起的东西。所以一般来说,我可以做两件事之一。一个是强迫你总是输入一个给你域的关键字。或者我可以有一个默认值。然后问题是,什么是合理的默认值?我倾向于选择最不危险的东西。
因此,将其设为默认值将是一件非常糟糕的事情。如果只是因为人们实际上并不经常编写私有方法,那么将其设为默认可能是一件坏事。和受保护的一样。在查看我拥有的一堆代码时,我认为最常见的合理安全的东西是在包中。而 C++ 没有关键字,因为它们没有包的概念。
但我喜欢它而不是朋友的概念,因为对于朋友,你必须列举你所有的朋友是谁,所以如果你向一个包添加一个新类,那么你通常最终不得不去所有的那个包中的课程并更新他们的朋友,我一直觉得这完全是一件令人头疼的事情。
但是朋友列表本身会导致某种版本控制问题。于是就有了友好班级的概念。我将其设为默认值的好处是——我将解决问题,那么关键字应该是什么?
有一段时间实际上有一个友好的关键字。但是因为所有其他都以“P”开头,所以它是“友好的”以“PH”开头。但那只是在那里呆了一天。
首先让我说一件事,java中没有“访问说明符”这样的术语。我们应该称一切为“修饰符”。正如我们所知,final、static、synchronised、volatile.... 被称为修饰符,甚至 Public、private、protected、default、abstract 也应该被称为修饰符。默认是这样的修饰符,其中不存在物理存在但没有放置修饰符,则应将其视为默认修饰符。
为了证明这一点,举一个例子:
public class Simple{
public static void main(String args[]){
System.out.println("Hello Java");
}
}
输出将是: Hello Java
现在将公共更改为私有,看看你得到什么编译器错误:它说“这里不允许修改器私有”什么结论是有人可能是错误的,或者某些教程可能是错误的,但编译器不可能是错误的。所以我们可以说java中没有术语访问说明符,一切都是修饰符。