115

我刚开始阅读一本 Java 书籍并想知道;如果没有指定,哪个访问说明符是默认的?

4

12 回答 12

123

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

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

查看Java 的访问说明符

于 2010-08-20T10:36:19.590 回答
85

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

对于类和接口声明,默认为包私有。这介于受保护和私有之间,只允许同一包中的类访问。(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 本身的声明。

于 2010-08-20T10:50:22.753 回答
17

如果没有给出访问说明符,则它是类和类成员的包级访问(没有明确的说明符)。接口方法是隐式公开的。

于 2010-08-20T10:39:55.127 回答
10

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

有趣的附注是protected不会限制对子类的可见性,还会限制对同一包中的其他类的可见性

于 2010-08-20T10:41:28.580 回答
9

这取决于事情是什么。

  • 默认情况下,顶级类型(即未在其他类型中声明的类、枚举、接口和注释类型)是包私有的。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 调用。实例初始化程序块不编译为单独的方法;它们的代码被复制到每个构造函数中,因此即使通过反射也不能单独访问它们。

于 2015-10-21T14:05:18.377 回答
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");
    }    
}

但是它只适用于 8 Java 版本

官方文档

Java 中的访问修饰符

于 2018-09-05T05:44:38.433 回答
3

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

于 2010-08-20T10:40:33.277 回答
3

默认访问说明符是。类可以访问同一包中其他类的成员。但在包之外它显示为私有

于 2012-07-19T10:37:28.427 回答
3

以下是对 Java 的创建者 James Gosling 的采访中关于包级别可见性的引用:

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

James Gosling:一个包通常是一组写在一起的东西。所以一般来说,我可以做两件事之一。一个是强迫你总是输入一个给你域的关键字。或者我可以有一个默认值。然后问题是,什么是合理的默认值?我倾向于选择最不危险的东西。

因此,将其设为默认值将是一件非常糟糕的事情。如果只是因为人们实际上并不经常编写私有方法,那么将其设为默认可能是一件坏事。和受保护的一样。在查看我拥有的一堆代码时,我认为最常见的合理安全的东西是在包中。而 C++ 没有关键字,因为它们没有包的概念。

但我喜欢它而不是朋友的概念,因为对于朋友,你必须列举你所有的朋友是谁,所以如果你向一个包添加一个新类,那么你通常最终不得不去所有的那个包中的课程并更新他们的朋友,我一直觉得这完全是一件令人头疼的事情。

但是朋友列表本身会导致某种版本控制问题。于是就有了友好班级的概念。我将其设为默认值的好处是——我将解决问题,那么关键字应该是什么?

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

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

于 2016-01-14T04:16:38.890 回答
2

更新Java 8关键字的使用default:正如许多其他人所指出的默认可见性(无关键字)

可以从该类所属的同一包中访问该字段。

不要与新的Java 8特性(默认方法default)混淆,该特性允许接口在使用关键字标记时提供实现。

请参阅:访问修饰符

于 2016-08-05T16:52:38.240 回答
1

JAVA 中有一个名为“default”的访问修饰符,它只允许在该包中直接创建该实体的实例。

这是一个有用的链接:

Java 访问修饰符/说明符

于 2017-09-21T07:44:12.683 回答
-2

首先让我说一件事,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中没有术语访问说明符,一切都是修饰符。

于 2017-08-22T08:03:04.067 回答