Java 中的 public、protected、package-private 和 private 有什么区别?

What is the difference between public, protected, package-private and private in Java?

提问人:intrepion 提问时间:10/19/2008 最后编辑:Steve Chambersintrepion 更新时间:10/19/2023 访问量:2564390

问:

在 Java 中,在进行和处理继承时,是否有关于何时使用每个访问修饰符的明确规则,即默认(包私有)、和 ?publicprotectedprivateclassinterface

Java 私有 公共 保护 访问修饰符

评论

189赞 Museful 2/13/2013
private对包中的其他类隐藏。 向包外部的类公开。 是 仅限于子类的版本。publicprotectedpublic
108赞 Nicolas Barbulesco 8/21/2013
@Tennenrishin — 否 ;与 C++ 相反,在 Java 中,该方法也可以从整个包中访问。Java 可见性模型中的这种愚蠢行为打破了 的目标。protectedprotected
41赞 Museful 3/14/2014
@Nicolas 它可以从整个包中访问,无论是否带有 .作为访问修饰符,它所做的只是向包外部的子类公开。protectedprotected
17赞 luis.espinal 4/7/2014
@tennenrishin - 嗯,尼古拉斯就是这么说的......而你现在只是在重复它。你最初说的是——我引用——“是一个仅限于子类的公共版本”,你自己承认这是不正确的,因为受保护还允许通过整个包进行访问(呃,它不限制对子类的访问。protected
14赞 luis.espinal 4/7/2014
我也同意 Nicolas 的观点,因为 Java 中的受保护访问模式是愚蠢的。实际情况是,Java 混淆了水平(格子)和垂直访问限制限定符。默认范围是水平/晶格限制,晶格是封装。公共是另一个水平限制,其中格子是整个世界。私有和 (C++) 保护是垂直的。如果我们有一个横切访问,比如说,在我们实际需要它的极少数情况下,它会更好,让它等同于 C++ 版本的受保护。protected-packageprotected

答:

6333赞 David Segonds 10/19/2008 #1

官方教程可能对您有所帮助。


子类
(同包)
子类
(diff pkg)
世界
public + + + + +
protected + + + +
无修饰符 + + +
private +

+ : 可访问 空白 : 不可访问

评论

12赞 adprocas 5/3/2018
世界在您的项目中。我应该进一步解释。库位于您的项目中,如果您要创建库,它们也会公开这些公共类和方法。所以,只在你的项目里说有点不对劲。 “使用它的一切”是一个更好的描述。
7赞 adprocas 5/4/2018
例如,如果我有并且我正在这样做,我将可以从内部访问所有受保护的公共方法和属性。如果我在某个地方做 - 假设构造函数 - 如果它位于不同的包中,我将只能访问公共方法。请注意,如果我这样做,我似乎可以访问受保护的方法,但这与扩展它相同,但改为内联。MyClassAnotherClass extends MyClassAnotherClassMyClass myClass = new MyClass();AnotherClass= new MyClass() { @Override protected void protectedMethod() { //some logic } };
13赞 Dawood ibn Kareem 7/11/2018
不幸的是,这个答案过于简单化了。现实有点复杂,尤其是当你考虑时(这实际上是一个相当难以完全理解的访问修饰符 - 大多数认为自己知道什么的人实际上不知道)。此外,正如 Bohemian 所指出的,它没有回答这个问题——它没有说明何时使用每个访问修饰符。在我看来,这个答案还不足以投反对票,但很接近。但是超过 4000 个赞成票?这是怎么发生的?protectedprotected
22赞 Jack 10/15/2020
@niks受保护的成员可以由不同包中的子类访问。这不是重点吗?否则,默认和受保护之间有什么区别?
8赞 Piovezan 2/5/2021
@Jack是的,尼克斯的评论是错误的,尽管许多赞成票表明情况并非如此。答案中的 Java Tutorials 链接清楚地表明,也可以从不同的包在子类中访问受保护的成员。他/她的意思似乎是“包级”而不是“受保护”,或者指的是不同的编辑。
177赞 John Nilsson 10/19/2008 #2

简单的规则。首先将所有内容声明为私有。然后随着需求的出现和设计需要而向公众迈进。

公开成员时,问问自己是公开表示选择还是抽象选择。第一种是您要避免的,因为它会引入对实际表示的过多依赖,而不是对其可观察行为的依赖。

作为一般规则,我尽量避免通过子类化来覆盖方法实现;搞砸逻辑太容易了。如果要重写抽象受保护的方法,请声明它。

此外,在重写时使用 @Override 注解,以防止在重构时中断。

评论

4赞 Andrejs 2/27/2016
@RuchirBaronia,“世界”= 应用程序中的所有代码,无论它位于何处。
0赞 nbro 4/5/2022
尽管此答案中的信息可能有用,但问题不在于我们是否应该首先声明所有内容为私有,然后根据需要公开内容。
22赞 Joe Phillips 10/19/2008 #3

差异可以在已经提供的链接中找到,但使用哪一个通常归结为“最少知识原则”。只允许所需的最低可见性。

541赞 Schwern 10/19/2008 #4

(注意:我不是Java程序员,我是Perl程序员。Perl没有正式的保护,这也许就是为什么我如此理解这个问题的原因:) )

私人

就像你想象的那样,只有声明它的才能看到它。

套餐私人

它只能由声明它的查看和使用。这是 Java 中的默认设置(有些人认为这是一个错误)。

保护

包私有 + 可以由子类或包成员看到。

公共

每个人都可以看到它。

发表

在我控制的代码之外可见。(虽然不是 Java 语法,但它对本次讨论很重要)。

C++定义了一个称为“朋友”的附加级别,对此了解得越少越好。

什么时候应该使用什么?整个想法是封装以隐藏信息。您希望尽可能地向用户隐藏如何完成某事的细节。为什么?因为这样你以后就可以更改它们,而不会破坏任何人的代码。这使您可以优化、重构、重新设计和修复错误,而不必担心有人正在使用您刚刚修改的代码。

因此,经验法则是只使事物在必须的范围内可见。从专用开始,仅根据需要添加更多可见性。只公开用户需要知道的内容,你公开的每一个细节都会限制你重新设计系统的能力。

如果您希望用户能够自定义行为,而不是公开内部结构以便他们可以覆盖它们,那么将这些内脏推入对象并使该接口公开通常是一个更好的主意。这样,他们就可以简单地插入一个新对象。例如,如果你正在编写一个 CD 播放器,并且希望“go find info about this CD”位可自定义,而不是将这些方法公开,而是将所有这些功能放入其对象中,并仅公开对象 getter/setter。这样一来,吝啬暴露你的胆量会鼓励良好的构图和关注点的分离

我坚持只使用“私人”和“公共”。许多面向对象语言就是这样。“受保护”可能很方便,但这是作弊。一旦一个接口不仅仅是私有的,它就超出了你的控制范围,你必须去寻找其他人的代码来寻找用途。

这就是“发布”概念的用武之地。更改接口(重构)需要找到所有使用它的代码,并对其进行更改。如果接口是私有的,那没问题。如果它受到保护,你必须去找到你所有的子类。如果它是公开的,你必须找到所有使用你的代码的代码。有时这是可能的,例如,如果您正在处理仅供内部使用的公司代码,则接口是否为公共接口并不重要。您可以从企业存储库中获取所有代码。但是,如果一个接口是“发布”的,如果有代码在你的控制之外使用它,那么你就被淹没了。您必须支持该接口,否则可能会破坏代码。即使是受保护的接口也可以被认为是已发布的(这就是为什么我不打扰受保护的)。

许多语言发现公共/受保护/私有的等级性质过于局限,不符合现实。为此,有特质类的概念,但那是另一个节目。

评论

27赞 Sebastian Mach 6/7/2011
朋友 -> “你知道的越少越好” ---> 它提供了选择性的可见性,这仍然优于包装隐私。在 C++ 中,它有它的用途,因为不是所有的函数都可以是成员函数,friends 比 public'ing 更好。当然,存在被邪恶思想滥用的危险。
33赞 Rhys van der Waerden 10/2/2011
还应该注意的是,C++ 中的“protected”具有不同的含义 - 受保护的方法实际上是私有的,但仍然可以从继承类调用。 (与Java相反,它可以由同一包中的任何类调用。
9赞 Konrad Morawski 10/16/2013
@RhysvanderWaerden C# 在这方面与 C++ 相同。我发现很奇怪,Java 不允许声明子类可以访问的成员,但不允许整个包访问。这对我来说有点颠倒 - 包的范围比子类更广泛!
16赞 Eponymous 5/23/2014
@KonradMorawski恕我直言,包的范围比子类小。如果你还没有声明你的类是final,用户应该能够对它进行子类化 - 所以java protected是你发布接口的一部分。OTOH,软件包由单个组织隐式开发:例如.com.mycompany.mypackage。如果你的代码在我的包中声明自己,你就隐式地声明自己是我组织的一部分,所以我们应该进行沟通。因此,包发布给比子类(扩展我的对象的人)更小/更容易接触到的受众(我公司的人),因此被视为较低的可见性。
3赞 Dennis 12/8/2014
friend适用于定义类之间的特殊关系。如果使用得当,它在许多情况下可以实现卓越的封装。例如,特权工厂类可以使用它来将内部依赖项注入构造类型。它有一个坏名声,因为那些不关心正确维护设计良好的对象模型的人可能会滥用它来减轻他们的工作量。
10赞 Dov Wasserman 10/19/2008 #5

David 的回答提供了每个访问修饰符的含义。至于何时使用每个类,我建议公开所有供外部使用的类和每个类的方法(其 API),以及其他所有私有内容。

随着时间的流逝,您将对何时将某些类打包为私有以及何时声明某些受保护的方法以在子类中使用产生一种感觉。

11赞 dameng 3/15/2012 #6

这个页面写得很好,关于受保护和默认的访问修饰符

.... 受保护:受保护的访问修饰符有点棘手,可以说是默认访问修饰符的超集。就同一包中的访问权限而言,受保护的成员与默认成员相同。不同之处在于,受保护的成员也可以由声明成员的类的子类访问,这些子类位于父类所在的包之外。

但这些受保护的成员“只能通过继承在包外部访问”。也就是说,您可以直接访问某个子类中某个子类的受保护成员,该成员存在于其他包中,就好像该成员存在于子类本身中一样。但是,通过使用父类的引用,在包外部的子类中将无法访问该受保护成员。 ....

评论

0赞 Anand 10/28/2012
只是为了添加这个“一旦子类获得了对父类的受保护成员的访问权限,它就成为子类的私有(或者更确切地说,我会说一个特殊的私有成员,可以由子类的子类继承)子类的成员。
123赞 Mechanical snail 9/13/2012 #7

它实际上比简单的网格显示要复杂一些。网格告诉您是否允许访问,但究竟什么构成访问?此外,访问级别以复杂的方式与嵌套类和继承进行交互。

“默认”访问(由缺少关键字指定)也称为 package-private。例外:在接口中,no modifier 表示公共访问;禁止使用除 public 以外的修饰符。枚举常量始终是公共的。

总结

是否允许访问具有此访问说明符的成员的访问?

  • Member is :仅当成员在与调用代码相同的类中定义时。private
  • 成员是包私有的:仅当调用代码位于成员的直接封闭包中时。
  • Member 是 :相同的包,或者成员是在包含调用代码的类的超类中定义的。protected
  • 会员是 : Yes.public

访问说明符适用于哪些内容

局部变量和形式参数不能采用访问说明符。由于根据范围规则,它们本质上是无法向外界访问的,因此它们实际上是私有的。

对于顶层作用域中的类,只允许使用 package 和 package-private。这种设计选择可能是因为在包级别上是多余的(没有包的继承)。publicprotectedprivate

所有访问说明符都可以在类成员(构造函数、方法和静态成员函数、嵌套类)上使用。

相关新闻: Java 类可访问性

次序

访问说明符可以严格排序

公共>保护>包-专用>专用

这意味着提供最多的访问,最少的访问。对私有成员的任何可能的引用也对包私有成员有效;对包专用成员的任何引用在受保护成员上都有效,依此类推。(向受保护的成员授予对同一包中其他类的访问权限被认为是一个错误。publicprivate

笔记

  • 允许类的方法访问同一类的其他对象的私有成员。更准确地说,C 类的方法可以访问 C 的任何子类的对象上的 C 私有成员。 Java 不支持按实例限制访问,只支持按类限制访问。private[this]
  • 您需要访问构造函数才能构造对象。因此,如果所有构造函数都是私有的,则类只能由类中的代码(通常是静态工厂方法或静态变量初始值设定项)构造。同样,对于包私有或受保护的构造函数也是如此。
    • 只有私有构造函数也意味着该类不能在外部被子类化,因为 Java 要求子类的构造函数隐式或显式调用超类构造函数。(但是,它可以包含一个嵌套类,该类是它的子类。

内部类

您还必须考虑嵌套作用域,例如内部类。复杂性的一个例子是,内部类具有成员,这些成员本身可以采用访问修饰符。因此,您可以有一个带有公共成员的私有内部类;可以访问会员吗?(见下文。一般规则是查看范围并递归思考,看看是否可以访问每个级别。

但是,这非常复杂,有关完整的详细信息,请参阅 Java 语言规范。(是的,过去曾有过编译器错误。

要了解它们如何相互作用,请考虑以下示例。可以“泄露”私有内部类;这通常是一个警告:

class Test {
    public static void main(final String ... args) {
        System.out.println(Example.leakPrivateClass()); // OK
        Example.leakPrivateClass().secretMethod(); // error
    }
}

class Example {
    private static class NestedClass {
        public void secretMethod() {
            System.out.println("Hello");
        }
    }
    public static NestedClass leakPrivateClass() {
        return new NestedClass();
    }
}

编译器输出:

Test.java:4: secretMethod() in Example.NestedClass is defined in an inaccessible class or interface
        Example.leakPrivateClass().secretMethod(); // error
                                  ^
1 error

一些相关问题:

评论

3赞 MC Emperor 8/26/2018
“禁止使用除 public 以外的修饰符”——从 Java 9 开始,情况不再如此:接口也可以有私有方法。
58赞 Ravi 10/28/2012 #8

简而言之

  • public:可从任何地方访问。
  • protected:由同一包的类和驻留在任何包中的子类访问。
  • 默认值(未指定修饰符):可由同一包的类访问。
  • private:仅在同一类中可访问。
99赞 Hoa Nguyen 12/19/2012 #9

根据经验:

  • private:类范围。
  • default(或):包范围。package-private
  • protected:(类似于包,但我们可以从不同的包中对其进行子类化)。protected 修饰符始终保持“父子”关系。package scope + child
  • public:到处。

因此,如果我们将访问权分为三种权利:

  • D)irect(从同一类中的方法调用,或通过“this”语法调用)。
  • R)eference(使用对类的引用或通过“点”语法调用方法)。
  • I)继承性(通过子类化)。

然后我们有这个简单的表格:

+—-———————————————+————————————+———————————+
|                 |    Same    | Different |
|                 |   Package  | Packages  |
+—————————————————+————————————+———————————+
| private         |   D        |           |
+—————————————————+————————————+———————————+
| package-private |            |           |
| (no modifier)   |   D R I    |           |
+—————————————————+————————————+———————————+
| protected       |   D R I    |       I   |
+—————————————————+————————————+———————————+
| public          |   D R I    |    R  I   |
+—————————————————+————————————+———————————+
226赞 Abdull 1/10/2013 #10
____________________________________________________________________
                | highest precedence <---------> lowest precedence
*———————————————+———————————————+———————————+———————————————+———————
 \ xCanBeSeenBy | this          | any class | this subclass | any
  \__________   | class         | in same   | in another    | class
             \  | nonsubbed     | package   | package       |
Modifier of x \ |               |           |               |
————————————————*———————————————+———————————+———————————————+———————
public          |       ✔       |     ✔     |       ✔       |   ✔
————————————————+———————————————+———————————+———————————————+———————
protected       |       ✔       |     ✔     |       ✔       |   ✘
————————————————+———————————————+———————————+———————————————+———————
package-private |               |           |               |
(no modifier)   |       ✔       |     ✔     |       ✘       |   ✘
————————————————+———————————————+———————————+———————————————+———————
private         |       ✔       |     ✘     |       ✘       |   ✘
____________________________________________________________________

评论

2赞 vanguard69 8/16/2016
值得一提的是 - “protected 修饰符使对象在其他包中可用,而 default/no-modifier 限制对同一包的访问”
3赞 Abdull 8/16/2016
@vanguard69,修饰符使标记的事物(类、方法或字段)可用于其他包中的其他类,而该类声明该标记事物的类的子类。protectedprotected
53赞 Eng.Fouad 11/16/2013 #11

Java 中最容易被误解的访问修饰符是 。我们知道它类似于默认修饰符,但有一个例外,子类可以在其中看到它。但是如何?这里有一个例子,希望能澄清这种混淆:protected

  • 假设我们有 2 个类; 和 ,每个都位于其自己的包中:FatherSon

    package fatherpackage;
    
    public class Father
    {
    
    }
    
    -------------------------------------------
    
    package sonpackage;
    
    public class Son extends Father
    {
    
    }
    
  • 让我们向 中添加一个受保护的方法。foo()Father

    package fatherpackage;
    
    public class Father
    {
        protected void foo(){}
    }
    
  • 该方法可以在 4 个上下文中调用:foo()

    1. 在位于定义 () 的同一包中的类中:foo()fatherpackage

      package fatherpackage;
      
      public class SomeClass
      {
          public void someMethod(Father f, Son s)
          {
              f.foo();
              s.foo();
          }
      }
      
    2. 在子类中,在当前实例上通过 或 :thissuper

      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod()
          {
              this.foo();
              super.foo();
          }
      }
      
    3. 在类型为同一类的引用上:

      package fatherpackage;
      
      public class Father
      {
          public void fatherMethod(Father f)
          {
              f.foo(); // valid even if foo() is private
          }
      }
      
      -------------------------------------------
      
      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Son s)
          {
              s.foo();
          }
      }
      
    4. 在类型为父类且位于包内的引用上,其中定义了 () [这可以包含在上下文 1 中]:foo()fatherpackage

      package fatherpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Father f)
          {
              f.foo();
          }
      }
      
  • 以下情况无效。

    1. 在类型为父类且位于包外部的引用上,其中定义了 ():foo()fatherpackage

      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Father f)
          {
              f.foo(); // compilation error
          }
      }
      
    2. 子类包中的非子类(子类从其父类继承受保护的成员,并使它们成为非子类的私有成员):

      package sonpackage;
      
      public class SomeClass
      {
          public void someMethod(Son s) throws Exception
          {
              s.foo(); // compilation error
          }
      }
      

评论

0赞 Eng.Fouad 11/16/2013
Object#clone()是成员的一个示例。protected
1赞 cst1992 10/28/2017
doing 和 the first invalid situation 和有什么不一样?super.foo()f.foo()
4赞 skomisa 1/31/2018
@cst1992 这很令人困惑,但请参阅 Java 语言规范 6.6.2:“对象的受保护成员或构造函数可以从包外部访问,其中仅由负责实现该对象的代码声明”。在 super.foo() 中,引用 “super” 是“直接负责实现”,但引用 “f” 不是。 为什么?因为你可以 100% 确定“super”是 Father 类型,但不是 “f”;在运行时,它可能是 Father 的其他子类型。请参阅 docs.oracle.com/javase/specs/jls/se9/html/...
1赞 Dawood ibn Kareem 7/11/2018
从理解的人那里读到答案令人耳目一新.不幸的是,此页面上定义的所有其他答案都有点错误。protectedprotected
0赞 Jim Balter 11/18/2023
@MarcoSulla skomisa 也引用了“Oracle 官方网站”,但他的报价来自规范,而您的报价来自教程。本教程省略了从包外部的子类访问受保护成员取决于引用的细节。
30赞 Nambi 1/22/2014 #12

私人

  • 方法、变量和构造函数

声明为私有的方法、变量和构造函数只能在声明的类本身中访问。

  • 类和接口

专用访问修饰符是限制性最强的访问级别。类和接口不能是私有的。

注意

如果类中存在公共 getter 方法,则可以在类外部访问声明为 private 的变量。 在超类中声明受保护的变量、方法和构造函数只能由其他包中的子类或受保护成员类的包中的任何类访问。


保护

  • 类和接口

受保护的访问修饰符不能应用于类和接口。

方法可以声明受保护,但不能将接口中的方法和字段声明为受保护。

注意

受保护的访问使子类有机会使用帮助程序方法或变量,同时防止不相关的类尝试使用它。


公共

声明为公共的类、方法、构造函数、接口等可以从任何其他类访问。

因此,公共类中声明的字段、方法和块可以从属于 Java Universe 的任何类访问。

  • 不同的套餐

但是,如果我们尝试访问的公共类位于不同的包中,则仍然需要导入公共类。

由于类继承,类的所有公共方法和变量都由其子类继承。


默认 -No 关键字:

默认访问修饰符意味着我们不为类、字段、方法等显式声明访问修饰符。

  • 在相同的软件包中

声明的变量或方法没有任何访问控制修饰符,可用于同一包中的任何其他类。接口中的字段是隐式公共的静态 final,接口中的方法默认是公共的。

注意

我们不能覆盖静态字段,如果您尝试覆盖它不会显示任何错误 但它不起作用,我们除外。

相关回答

参考资料链接

http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html http://www.tutorialspoint.com/java/java_access_modifiers.htm

21赞 samkit shah 6/18/2014 #13

私人:仅对课程的访问受限

默认值(无修饰符):对类和包的访问受限

受保护:对类、包和子类(包内部和外部)的有限访问

Public:可访问类、包(所有)和子类...简而言之,无处不在。

5赞 richa_v 7/30/2014 #14

“公共保护”、“默认”和“私有”是访问修饰符。

它们用于封装或隐藏和显示类的内容。

  1. 类可以是公共类,也可以是默认类
  2. 类成员可以是公共的、受保护的、默认的或私有的。

私人课程在课程外无法访问 默认值仅在包中可访问。 在包中以及扩展它的任何类中受到保护。 公众对所有人开放。

通常,成员变量是私有的,但成员方法是公共的。

评论

0赞 user207421 9/24/2016
Default不是访问修饰符,另外两个是拼写错误的。
17赞 Prashant 12/17/2014 #15

访问修饰符用于在多个级别上限制访问。

公共:它基本上很简单,你可以从任何类访问,无论它是否在同一个包中。

要访问,如果你在同一个包中,你可以直接访问,但如果你在另一个包中,那么你可以创建一个类的对象。

违约:它可以从任何包类的同一包中访问。

要访问,您可以创建该类的对象。但是,您不能在包外部访问此变量。

受保护:您可以访问同一包中的变量以及任何其他包中的子类。 所以基本上是默认+继承的行为。

若要访问基类中定义的受保护字段,可以创建子类的对象。

Private:可以在同一类中访问。

在非静态方法中,你可以直接访问,因为这个引用(也在构造函数中),但要在静态方法中访问,你需要创建类的对象。

14赞 amila isura 5/26/2015 #16

对包可见。默认值。不需要修饰符。

仅对类可见(私有)。

对世界(公众)可见。

对包和所有子类(受保护)可见。

可以在不调用任何修饰符的情况下声明变量和方法。默认示例:

String name = "john";

public int age(){
    return age;
}

专用访问修饰符 - private:

声明为私有的方法、变量和构造函数只能在声明的类本身中访问。专用访问修饰符是限制性最强的访问级别。类和接口不能是私有的。

如果类中存在公共 getter 方法,则可以在类外部访问声明为 private 的变量。

使用 private 修饰符是对象封装自身并向外界隐藏数据的主要方式。

例子:

Public class Details{

    private String name;

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

    public String getName(){
        return this.name;
    }
}

公共访问修饰符 - public:

声明为公共的类、方法、构造函数、接口等可以从任何其他类访问。因此,公共类中声明的字段、方法和块可以从属于 Java 域的任何类访问。

但是,如果我们尝试访问的公共类位于不同的包中,则仍然需要导入公共类。

由于类继承,类的所有公共方法和变量都由其子类继承。

例:

public void cal(){

}

受保护的访问修饰符 - protected:

在超类中声明受保护的变量、方法和构造函数只能由另一个包中的子类或受保护成员类的包中的任何类访问。

受保护的访问修饰符不能应用于类和接口。方法可以声明受保护,但不能将接口中的方法和字段声明为受保护。

受保护的访问使子类有机会使用帮助程序方法或变量,同时防止不相关的类尝试使用它。

class Van{

    protected boolean speed(){

    }
}

class Car{
    boolean speed(){
    }

}
13赞 Shailendra Singh 8/29/2015 #17
  • 公共 - 可从应用程序中的任何位置访问。

  • default - 可从包访问。

  • protected - 可从其他包中的包和子类访问。 也

  • Private - 只能从其类访问。

536赞 aioobe 11/10/2015 #18

这是该表的更好版本,其中还包括模块列。

enter image description here


解释

  • 私有成员 () 只能在声明的同一类中访问。i

  • 没有访问修饰符 () 的成员只能在同一包中的类中访问。j

  • 受保护的成员 () 可在同一包中的所有类内以及其他包中的子类内访问。k

  • 公共成员 () 可供所有类访问(除非它驻留在不导出声明它的包的模块中)。l


选择哪种修饰符?

访问修饰符是一种工具,可帮助您防止意外破坏封装 (*)。问问自己,你是希望成员是类、包、类层次结构的内部成员,还是根本不是内部成员,并相应地选择访问级别。

例子:

  • 字段可能应该是私有的,因为它是可变的,并且是实现细节。long internalCounter
  • 只应在工厂类(在同一包中)中实例化的类应具有包限制的构造函数,因为不应直接从包外部调用它。
  • 在渲染之前调用并在子类中用作钩子的内部方法应该受到保护。void beforeRender()
  • 从 GUI 代码调用的方法应该是公共的。void saveGame(File dst)

(*) 究竟什么是封装?

评论

25赞 GhostCat 10/11/2018
只是说:有很多人在区分红色/绿色方面有问题。使用红色/绿色(或黄色/橙色/...)配色方案的表格很少在任何方面“更好”;-)
9赞 aioobe 11/14/2018
@GhostCat,我不同意。我认为红色/绿色在直觉上与许多人的“有效”/“不起作用”一致,即它比许多替代品更好。
14赞 GhostCat 11/14/2018
colourblindawareness.org/colour-blindness/.........8%的色盲男性大致可分为1%的氘代、1%的protanopes、1%的protanomalous和5%的deuteranomalous由于我是这 50% 中的一员,请放心:红色/绿色很糟糕。
7赞 aioobe 11/14/2018
@GhostCat好的。这比我预期的要大。我在这个色盲模拟器中上传了图像,并测试了所有不同的模式。即使在单色/色差模式下,色差也是合理的。你能看到区别还是模拟器关闭了?(我仍然认为红色/绿色对于看到颜色的人来说非常直观。
5赞 GhostCat 11/14/2018
我可以看到差异,但我也能够通过我们在德国必须为驾驶执照进行的色盲测试的一半;-)......但我认为这样的模拟器“足够好”。
17赞 Aftab 8/7/2016 #19

Java 中的访问修饰符。

Java 访问修饰符用于在 Java 中提供访问控制。

1. 默认:

仅供同一包中的类访问。

例如

// Saved in file A.java
package pack;

class A{
  void msg(){System.out.println("Hello");}
}

// Saved in file B.java
package mypack;
import pack.*;

class B{
  public static void main(String args[]){
   A obj = new A(); // Compile Time Error
   obj.msg(); // Compile Time Error
  }
}

这种访问比公共和受保护更受限制,但比私有访问更少。

2. 公共

可以从任何地方访问。(全球访问)

例如

// Saved in file A.java

package pack;
public class A{
  public void msg(){System.out.println("Hello");}
}

// Saved in file B.java

package mypack;
import pack.*;

class B{
  public static void main(String args[]){
    A obj = new A();
    obj.msg();
  }
}

输出:Hello

3. 私人

只能在同一类中访问。

如果您尝试访问另一个类中一个类的私有成员,则会引发编译错误。例如

class A{
  private int data = 40;
  private void msg(){System.out.println("Hello java");}
}

public class Simple{
  public static void main(String args[]){
    A obj = new A();
    System.out.println(obj.data); // Compile Time Error
    obj.msg(); // Compile Time Error
  }
}

4. 受保护

仅可访问同一包中的类和子类

例如

// Saved in file A.java
package pack;
public class A{
  protected void msg(){System.out.println("Hello");}
}

// Saved in file B.java
package mypack;
import pack.*;

class B extends A{
  public static void main(String args[]){
    B obj = new B();
    obj.msg();
  }
}

输出:Hello

Enter image description here

5赞 ישו אוהב אותך 11/17/2016 #20

注意:这只是对已接受答案的补充

这与 Java 访问修饰符有关。

Java 访问修饰符

Java 访问修饰符指定哪些类可以访问给定的 类及其字段、构造函数和方法。访问修饰符可以 为类、其构造函数、字段和 方法。Java 访问修饰符有时也会在日常中使用 speech 作为 Java 访问说明符,但正确的名称是 Java access 修饰 符。类、字段、构造函数和方法可以具有以下项之一 四种不同的 Java 访问修饰符:

  • 列表项
  • 私人
  • 默认(包)
  • 保护
  • 公共

控制对班级成员的访问教程:

访问级别修饰符确定其他类是否可以使用 特定字段或调用特定方法。有两个级别 访问控制:

  • 在顶层 - public 或 package-private(无显式修饰符)。
  • 在成员级别 - public、private、protected 或 package-private(无显式修饰符)。

可以使用修饰符 public 声明类,在这种情况下, 类对所有位置的所有类都是可见的。如果类没有修饰符 (默认值,也称为 package-private),它仅可见 在自己的包装中

下表显示了对每个成员允许的访问 修饰语。

╔═════════════╦═══════╦═════════╦══════════╦═══════╗
║ Modifier    ║ Class ║ Package ║ Subclass ║ World ║
╠═════════════╬═══════╬═════════╬══════════╬═══════╣
║ public      ║ Y     ║ Y       ║ Y        ║ Y     ║
║ protected   ║ Y     ║ Y       ║ Y        ║ N     ║
║ no modifier ║ Y     ║ Y       ║ N        ║ N     ║
║ private     ║ Y     ║ N       ║ N        ║ N     ║
╚═════════════╩═══════╩═════════╩══════════╩═══════╝

第一个数据列指示类本身是否有权访问 由访问级别定义的成员。正如你所看到的,一个类总是 有权访问自己的成员。第二列指示是否 与类位于同一包中的类(无论其 Parentage) 有权访问该成员。第三列表示 在此包外部声明的类的子类是否具有 访问成员。第四列指示所有类 有权访问该成员。

访问级别以两种方式影响您。首先,当您使用类时 来自另一个来源,例如 Java 平台中的类, 访问级别决定了您自己的这些类的哪些成员 类可以使用。其次,当你写一个类时,你需要决定 类中每个成员变量和每个方法的访问级别 应该有。

评论

1赞 sehe 11/17/2016
补充到底是什么,为什么它不是对现有帖子的编辑?
0赞 ישו אוהב אותך 11/18/2016
补充是访问修饰符。为什么不进行编辑?为了历史的缘故,保持公认的答案不变,并给出我的答案。
4赞 Greedy Coder 4/6/2017 #21

很多时候,我意识到,通过创建现实世界的类比,可以记住任何语言的基本概念。以下是我理解 Java 中访问修饰符的类比:

假设你是一所大学的学生,你有一个朋友周末来看你。假设在校园中间有一尊大学创始人的大雕像。

  • 当你把他带到校园时,你和你的朋友首先看到的就是这座雕像。这意味着任何走进校园的人都可以在未经大学许可的情况下观看雕像。这使得雕像成为公共的。

  • 接下来,你想带你的朋友去你的宿舍,但为此你需要将他注册为访客。这意味着他获得了进入校园内各种建筑物的通行证(与您的通行证相同)。这将使他的门禁卡成为受保护卡。

  • 您的朋友想要登录校园 WiFi,但没有任何凭据。他可以上网的唯一方法是您与他共享您的登录信息。(请记住,每个上大学的学生也都拥有这些登录凭据)。这将使您的登录凭据成为 NO MODIFIER。

  • 最后,您的朋友想阅读您发布在网站上的学期进度报告。但是,每个学生都有自己的个人登录名来访问校园网站的这一部分。这将使这些凭据成为 PRIVATE

希望这有帮助!

评论

0赞 Jim Balter 11/18/2023
值得注意的是,这种胡说八道得到了赞成。
3赞 Pritam Banerjee 6/27/2017 #22

当你考虑访问修饰符时,只需这样想(适用于变量方法):

public--> 可从任何地方访问
-->只能在声明它的同一类中访问
private

现在,当涉及到和defaultprotected

default--> 不存在访问修饰符关键字。这意味着它严格在类的包中可用。 在该包之外的任何地方都无法访问它。

protected--> 它比相同的包类稍微不那么严格,并且除了相同的包类之外,它还可以由它被声明的之外的子类访问。default

2赞 Christophe Roussy 2/14/2018 #23

这一切都与封装有关(或者正如乔·菲利普斯(Joe Phillips)所说,最少的知识)。

从限制性最强的(私有)开始,看看以后是否需要限制性较小的修饰符。

我们都使用方法和成员修饰符,如 private、public、...但是很少有开发人员会做的一件事是使用包来逻辑地组织代码。

例如: 您可以将敏感的安全方法放在“安全”包中。 然后放置一个公共类,该类访问此包中的一些与安全相关的代码,但将其他安全类包保持私有。 因此,其他开发人员将只能使用此包外部的公开可用的类(除非他们更改修饰符)。 这不是一项安全功能,但将指导使用。

Outside world -> Package (SecurityEntryClass ---> Package private classes)

另一件事是,彼此依赖性很强的类可能最终出现在同一个包中,如果依赖性太强,最终可能会被重构或合并。

相反,如果您将所有内容都设置为公共,则不清楚应该访问什么或不应该访问什么,这可能会导致编写大量 javadoc(它不会通过编译器强制执行任何内容......

0赞 Vipul Verma 9/20/2019 #24
  • 公共

如果将类成员声明为公共成员,则可以从任何位置访问该类成员

  • 保护

    如果使用关键字 protected 声明类成员,则可以从相同的类成员、同一包中的外部类成员和继承的类成员访问该类成员。如果一个类成员受到保护,那么它不能从外部包类访问,除非外部打包类是继承的,即扩展另一个包超类。但是,受保护的类成员始终可用于相同的包类,无论是否继承了相同的包类

  • 违约

    在 Java 中,default 不是访问修饰符关键字。如果声明的类成员没有任何访问修饰符关键字,则将其视为默认成员。默认类成员始终可供相同的包类成员使用。但是,外部包类成员不能访问默认类成员,即使外部类是子类,这与受保护成员不同

  • 私人

如果使用关键字 protected 声明类成员,则在这种情况下,它仅对相同的类成员可用

2赞 Mudassar 10/16/2019 #25

我的两分钱:)

私人:

class ->顶级类不能是私有的。内部类可以是私有的,可从同一类访问。

实例变量 -> 只能在类中访问。无法在课堂外访问。

package-private:

class ->顶级类可以是 package-private。它只能从同一个包访问。不是来自子包,不是来自外部包。

实例变量 -> 可从同一包访问。不是来自子包,不是来自外部包。

保护:

class -> 无法保护顶级类。

实例变量 ->只能在同一包或子包中访问。只能在扩展类时访问包外部。

公共:

class -> 可从包/子包/另一个包访问

实例变量 -> 可从包/子包/另一个包访问

这是详细的答案

https://github.com/junto06/java-4-beginners/blob/master/basics/access-modifier.md

22赞 yoAlex5 12/7/2019 #26

Java 访问修改

enter image description here

访问修饰符可以适用于 、[关于]、.尝试访问、子类化或覆盖它。classfieldmethod

  • 访问 或 通过 .fieldmethodclass
  • 继承与开闭原则[关于]
    • 后继(子类)访问修饰符可以是任意class
    • 后继(重写)访问修饰符应相同或展开它method

顶级类(第一级作用域)可以是 和 。[关于]可以有其中任何一个publicdefaultNested class

package未申请包层次结构

[Swift 访问修饰符]

-2赞 Tushar Baviskar 12/23/2019 #27

Java 中的访问说明符: java 中有 4 个访问说明符,分别是 private、package-private(默认)、protected 和 public,按访问顺序递增。

私人: 当你正在开发某个类,并且你希望这个类的成员不暴露在这个类之外时,你应该把它声明为私有的。私有成员只能在定义它们的类中访问,即封闭类。 私有成员可以在“this”引用上访问,也可以在包含这些成员的类的其他实例上访问,但只能在此类的定义范围内访问。

Package-private(默认): 除了下面描述的访问之外,此访问说明符还将提供专用访问说明符指定的访问权限。

当你在开发某个包,从而开发其中的某个类(比如 Class1)时,你可以使用默认的(不需要显式提及的)访问说明符,将类中的成员公开给(同一)包中的其他类。在这些其他类(在同一包中)中,可以在 Class1 的实例上访问这些默认成员。此外,还可以在 Class1 的子类中访问这些默认成员,例如 Class2(在此引用上或在 Class1 的实例上或在 Class2 的实例上)。

基本上,在同一个包中,您可以直接访问类实例上的默认成员,也可以访问子类中的“this”引用。

受保护: 除了下面描述的访问之外,此访问说明符还将提供 package-private 访问说明符指定的访问权限。

当你在开发某个包,从而开发其中的某个类(比如 Class1)时,如果你不希望在包外部访问这个成员(比如在包的消费者包中,即使用你的 API 的客户端),你应该对 Class1 中的数据成员使用受保护的访问说明符,但你希望做一个例外,只有当客户端写入类(比如 Class2)时才允许访问这个成员扩展 Class1。因此,通常,受保护的成员可以在派生类(即 Class2)中的“this”引用以及 Class2 的显式实例上访问。

请注意:

  1. 您将无法访问 Class1 的继承受保护成员 Class2,如果您尝试在 Class1 的显式实例上访问它, 虽然它是在其中继承的。
  2. 当您在相同/不同的包中编写另一个类 Class3 时 扩展 Class2,可以访问 Class1 的受保护成员 在此引用以及 Class3 的显式实例上。这将 对于任何扩展的层次结构(即受保护成员)为 true 仍可在此引用或扩展实例上访问 类。请注意,在 Class3 中,如果创建 Class2 的实例,则 但是,您将无法从 Class1 访问受保护的成员 它是遗传的。

所以底线是,只有在扩展类的定义内,这个其他包中的某个类扩展了包含此受保护成员的扩展类,并且受保护成员在扩展类的定义内的“this”引用或扩展类的显式实例上访问时,才能在其他包中访问。

public:除了下面所述的访问之外,此访问说明符还将提供受保护的访问说明符指定的访问权限。

当您正在开发某个包并因此开发其中的某个类(例如 Class1)时,如果您希望此成员可以在其他包的某个类中创建的 Class1 实例上的其他包中访问,则应为 Class1 中的数据成员使用公共访问说明符。基本上,当您打算无条件地向世界公开您的数据成员时,应使用此访问说明符。

5赞 Mushfiqur Rahman Abir 9/12/2020 #28

Differences between public, private, default and protected access modifiers

此图像将使您轻松了解公共、私有、受保护和默认访问修饰符之间的基本区别。当您未在代码中声明 ant 访问修饰符时,默认修饰符会自动发生。

评论

2赞 Ahmed Nabil 12/19/2020
为了更清楚,== |no modifierpackage privatepackage protected
-2赞 Tiyus98 7/6/2022 #29

在谈论访问修饰符时,我们可以很容易地理解包含它们的非常简单的规则。

Private Access 修饰符用于: - 只有相同的类

默认访问修饰符用于: - 只有相同的类/相同的包子类

受保护的访问修饰符用于: - 相同的类 / 相同的包子类 / 相同的包非 - 子类 / 不同的包子类

公共访问修饰符使用:我们可以在任何地方使用它(同一类/相同的包子类/相同的包非子类/不同的包子类/不同的包非子类)

评论

0赞 ethry 7/6/2022
正如目前所写的那样,你的答案尚不清楚。请编辑以添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。您可以在帮助中心找到有关如何写出好答案的更多信息。
0赞 Alireza Fattahi 1/16/2023 #30

对于初学者来说,考虑这个例子可能会有所帮助;

考虑我在包中开发,它有一个很棒的方法,您有兴趣将其称为(它可以是 or ):MyClassfooprintmethodproperty

package foo;  // I am in foo
public class MyClass {
     private void print() { //This is private
        System.out.println("I can print!");
    }
}

您已经在包中开发,并且您有兴趣使用YourClassbarMyClass#print

package bar; \\You are not in same package as me
import foo.MyClass;
public class YourClass {
    void test() {
        MyClass myClass = new MyClass();
        myClass.print();
    }
}

您的代码未编译,并且出现错误The method print() is undefined for the type MyClass

你来找我:

  • 你:我想用你的方法,但它是.你能做到吗?privatepublic
  • 我:不,我不想用它others
  • 你:我是你的朋友,至少让我使用它。not others
  • 我:好的,我会删除关键字。My Access 修饰符将为 or 。因为你是我的朋友,你必须和我在同一包裹里。所以你来我的包裹.我的意思是确切的包,甚至不是子包。privatedefaultprivate packagemustfoo

然后将是MyClass

package foo;
public class MyClass {
    void print() { // No access modifier means default or package-private
        System.out.println("I can print!");
    }
}

YourClass将是:

package foo;//You come to my package
public class YourClass {
    void test() {
        MyClass myClass = new MyClass();
        myClass.print();
    }
}

现在想一想:你又来找我了

  • 你:我的老板告诉我,我不能改变我的包(在现实世界中,你不能改变你的包,使用其他类的方法)
  • 我:还有另一种方法,如果你我和我做,那么无论你是否更改你的包,你都可以使用它。extendprint()protected

这里是MyClass

package foo;
protected class MyClass { // It is now protected
     protected void print() {
        System.out.println("I can print!");
    }
}

这里是:YourClass

package bar; // You are on your own package
import foo.MyClass;

public class YourClass extends MyClass {
    void  test() {
        // You initiate yourself! But as you extend me, you can call my print()
        YourClass yourClass = new YourClass();
        yourClass.print();
    }
}

您可能已经注意到,通过使方法受到保护,所有其他类都可以使用它,并且您不能轻易地控制它的使用方式。这在 Java 17 中通过引入 和 words 解决了。因此,您可以定义类来扩展您。有关更多信息,请参见 Java 17 中的密封类是什么?extendingsealedpermitswhichcanpublic sealed class MyClass permits YourClass

1赞 Mian Asad Ali 8/24/2023 #31
  1. 公共:用于跨代码库和不同代码库的广泛可访问性 包。适用于要普遍公开的类和方法。
  2. 保护:提供对同一包和子类(甚至在不同包中)的访问。用于平衡封装与子类访问。
  3. 默认值(包专用):没有显式修饰符;可在同一包内访问。提供封装,同时允许在包内进行访问。
  4. 私人:限制对类内的访问。非常适合对其他类隐藏实现细节。

遗产:

类:

  1. 公共:可由任何类子类化。
  2. 保护:可在同一包和不同包中子类化。
  3. 违约:可在同一包中子类化。
  4. 私人:不可子类化。

方法和字段:

  1. 公共:随处可访问。
  2. 保护:可在同一包和子类中访问。
  3. 违约:可在同一包内访问。
  4. 私人:只能在同一类中访问。

子类对被重写的方法或字段的访问不能比其超类更严格。