Java中的默认访问说明符是什么?


108

我刚开始读一本Java书籍,就纳闷了。如果未指定,则哪个访问说明符是默认的?


正确的术语是“访问修饰符”。JLS中未出现单词“ specifier”。
罗恩侯爵

Answers:


116

默认可见性称为“ package-private”(尽管您不能显式使用此属性),这意味着可以从该类所属的同一包内部访问该字段。

正如mdma指出的那样,接口成员的情况并非如此,其默认值为“ public”。

请参阅Java的访问说明符


25
错误-接口成员不正确。则默认访问权限为public
mdma

2
实际上,它被称为“私有包”。第三方网站不是规范性引用。您应该仅引用JLS。
罗恩侯爵

81

默认说明符取决于上下文。

对于类和接口声明,默认为包私有。这介于受保护的和私有的之间,仅允许访问同一包中的类。(受保护就是这样,但也允许访问包外部的子类。)

class MyClass   // package private
{
   int field;    // package private field

   void calc() {  // package private method

   }
}

对于接口成员(字段和方法),默认访问权限是public。但是请注意,接口声明本身默认为私有包。

interface MyInterface  // package private
{
   int field1;         // static final public

   void method1();     // public abstract
}

如果我们有声明

public interface MyInterface2 extends MyInterface
{

}

然后,使用MyInterface2的类可以从超级接口查看field1和method1,因为它们是公共的,即使它们看不到MyInterface本身的声明。


1
“ Package private”(有时以source的形式写成/* pp */)只是默认访问的方便名称。不是JLS名称。
汤姆·霍顿

10
@Tom-是的,JLS使用“默认访问权限”。我可以写“默认是默认访问权限”。但这似乎并没有太大帮助!
mdma

16

如果未提供访问说明符,则为类和类成员的包级别访问权限(对此没有明确的说明符)。接口方法是隐式公共的。


9

默认可见性(无关键字)为package,这意味着它可用于同一包中的每个类。

有趣的一点是,protected不仅限制了子类的可见性,而且还限制了同一包中的其他类的可见性


8

这取决于事物是什么。

  • 默认情况下,顶级类型(即未在另一种类型内声明的类,枚举,接口和注释类型)是程序包专用的。(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)其语法不允许任何访问说明符。使用反射,您可以从其他地方实例化匿名类,它们和它们生成的构造函数都是包私有的,尽管我不确定该细节是否在JLS中。

  • 实例和静态初始化块没有在语言级别(访问说明JLS第8.6节和8.7),但静态初始化块被实现为命名的方法<clinit>JVMS§2.9),所以该方法必须在内部,有一定的出入符。我使用十六进制编辑器检查了由javac和Eclipse的编译器编译的类,发现两者都将方法生成为package-private。但是,您不能<clinit>()在语言中调用,因为方法名称中的<>字符无效,并且反射方法被硬连线以拒绝其存在,因此有效地其访问说明符是 access。该方法只能在类初始化期间由VM调用。实例初始化程序块不会编译为单独的方法;它们的代码被复制到每个构造函数中,因此即使通过反射也无法单独访问它们。


7

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");
    }    
}

但是,仅适用于Java 8版本

官方文件

Java中的访问修饰符


3

有关更多详细信息,请参见此处。默认值不是私有/公共/受保护的,而是完全不同的访问规范。它没有被广泛使用,我希望在访问定义中更加具体。


3

默认的访问说明是package。类可以访问同一包中其他类的成员。但是在包外部,它显示为private


3

以下是Java创造者James Gosling访谈中有关程序包级别可见性的报价:

Bill Venners:Java具有四个访问级别。默认为包。我一直想知道将程序包访问设置为默认值是否方便,因为C ++的人们已经知道这三个关键字分别是private,protected和public。或者,如果出于某些特殊原因,您认为应该将程序包访问权限作为默认访问权限。

詹姆斯·高斯林:程序包通常是将某些东西写在一起的一组东西。所以一般来说,我可以做两件事之一。一种是强迫您始终输入可以提供域的关键字。否则我可能有一个默认值。然后问题是,是什么使明智的违约呢?而且我倾向于最危险的事情。

因此,公开默认是一件很不好的事情。如果仅因为人们实际上并不经常编写私有方法,那么私有默认设置可能是一件坏事。与受保护的事物相同。在查看我拥有的一堆代码时,我认为最合理的最普通的东西是包装。而且C ++对此没有关键字,因为它们没有包的概念。

但是我喜欢它而不是朋友的概念,因为与朋友一起您必须枚举您所有朋友的身份,因此,如果将新类添加到程序包中,则通常最终必须去所有的朋友。包中的课程并更新他们的朋友,我一直发现这完全是一个痛苦。

但是朋友列表本身会引起某种版本问题。因此就有了友善阶级的概念。我将默认值设为了很好的一件事-我将解决问题,所以关键字应该是什么?

有一阵子实际上是一个友好的关键字。但是因为所有其他字符都以“ P”开头,所以它以“ PH”开头。但是那只可能在那里呆了一天。

http://www.artima.com/intv/gosling2P.html




-2

首先让我说一件事,在Java中没有“访问说明符”这样的术语。我们应该将所有内容称为“修饰符”。众所周知,最终的,静态的,同步的,易变的....被称为修饰符,甚至公共,私有,受保护,默认,抽象也应称为修饰符。默认是这样的修饰符,其中不存在物理存在但没有放置修饰符,则应将其视为默认修饰符。

为了证明这一点,请举一个例子:

public class Simple{  
    public static void main(String args[]){  
     System.out.println("Hello Java");  
    }  
}  

输出将是: Hello Java

现在将public更改为private,然后看到您遇到什么编译器错误:上面写着“此处不允许使用修饰符private”,可以得出结论:某人可能是错误的,或者某些教程可能是错误的,但是编译器不能是错误的。因此,可以说Java中没有术语“访问说明符”,所有内容都是修饰符。


第一句话很明确,但是外部类不能私有的事实并不能证明Java中不存在访问说明符。
洛恩侯爵,

@EJP这只是一个例子。我的意思是,访问说明符一词已在其他语言(如c,.net等)中使用,但java中的技术术语是修饰符。如果使用eclipse或任何其他IDE,则可以看到在创建新类时,我们被要求提供修饰符名称,并且在列表中它们提供公共,私有,抽象等
Sagar Raut

在我的示例中,我尝试说的是编译器给出错误消息:不允许使用修饰符private,它不提供不允许访问说明符private之类的消息。因此,我们应该说的技术术语是Java中的修饰符,而不是Java中的访问说明符
Sagar Raut
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.