ChatGPT解决这个技术问题 Extra ChatGPT

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

在 Java 中,何时使用每个访问修饰符,即默认(包私有)、publicprotectedprivate,同时制作 classinterface 并处理继承是否有明确的规则?

private 对包中的其他类隐藏。 public 暴露给包外的类。 protectedpublic 的一个版本,仅限于子类。
@Tennenrishin — 不;与 C++ 不同,在 Java protected 中,该方法也可以从整个包中访问。 Java 可见性模型中的这种愚蠢破坏了 protected 的目标。
@Nicolas 可以从整个包中访问它,无论是否有 protected。作为访问修饰符protected 所做的只是暴露给包外的子类。
@tennenrishin - 好吧,这就是尼古拉斯所说的......你现在只是在重复它。你最初说的是protected - 我引用 - '是一个仅限于子类的 public 版本',你自己承认这不是真的,因为 protected 还允许访问整个包(ergo,它不 限制对子类的访问。)
我也同意 Nicolas 的观点,Java 中的受保护访问模式是愚蠢的。发生的事情是 Java 将水平(格)和垂直访问限制限定符混为一谈。默认范围是水平/格子限制,格子是包。公共是另一个横向限制,其中格是整个世界。 Private 和 (C++) protected 是垂直的。如果我们有一个横切访问权会更好,例如,protected-package 用于我们实际需要它的极少数情况,让 protected 等效于受保护的 C++ 版本。

M
M. Justin

The official tutorial 可能对您有所帮助。

Class Package Subclass (same pkg) Subclass (diff pkg) World public + + + + + protected + + + + no modifier + + + private +

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


世界在您的项目中。我应该进一步解释。库在您的项目中,如果您正在创建库,它们也会公开这些公共类和方法。所以,只在你的项目中说有点不对劲。 “使用它的一切”是一个更好的描述。
例如,如果我有 MyClass 并且我正在执行 AnotherClass extends MyClass,我将可以从 AnotherClass 访问所有受保护的和公共的方法和属性。如果我在某处的 AnotherClass 中执行 MyClass myClass = new MyClass(); - 假设是构造函数 - 如果它位于不同的包中,我将只能访问公共方法。请注意,如果我执行 = new MyClass() { @Override protected void protectedMethod() { //some logic } };,我似乎可以访问受保护的方法,但这与扩展它相同,而是内联。
不幸的是,这个答案过于简单化了。现实有点复杂,尤其是当您考虑 protected 时(这实际上是一个很难完全理解的访问修饰符 - 大多数认为他们知道 protected 意味着什么的人实际上并不知道)。此外,正如 Bohemian 指出的那样,它没有回答问题 - 它没有说明何时使用每个访问修饰符。在我看来,这个答案相当不够糟糕,无法投票,但很接近。但是超过 4000 票?这怎么发生的?
@niks 受保护的成员可以被来自不同包的子类访问。这不是重点吗?否则默认和受保护有什么区别?
@Jack 是的,niks 的评论是错误的,尽管很多人反对。答案中的 Java 教程链接清楚地表明,受保护的成员也可以在不同包的子类中访问。似乎他/她的意思是“包级别”而不是“受保护”,或者指的是不同的编辑。
R
R.Kabir

(警告:我不是 Java 程序员,我是 Perl 程序员。Perl 没有正式的保护措施,这也许就是为什么我能很好理解这个问题的原因 :))

私人的

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

包私人

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

受保护

Package Private + 可以被子类或包成员看到。

上市

每个人都可以看到它。

发表

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

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

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

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

如果您希望用户能够自定义行为,而不是公开内部结构以便他们可以覆盖它们,那么将这些胆量放入一个对象并公开该接口通常是一个更好的主意。这样他们就可以简单地插入一个新对象。例如,如果您正在编写一个 CD 播放器并希望“查找有关此 CD 的信息”有点可定制,而不是将这些方法公开,您会将所有这些功能放入它的对象中,并且只公开您的对象 getter/setter。通过这种方式,对暴露你的胆量吝啬鼓励良好的组合和关注点分离

我只坚持“私人”和“公共”。许多 OO 语言就是这样。 “受保护”可能很方便,但它是个骗子。一旦接口不再是私有的,它就超出了你的控制范围,你必须去查看其他人的代码才能找到用途。

这就是“发布”的概念出现的地方。更改接口(重构它)需要您找到所有正在使用它的代码并对其进行更改。如果接口是私有的,那没问题。如果它受到保护,您必须找到所有子类。如果它是公开的,你必须去查找所有使用你的代码的代码。有时这是可能的,例如,如果您正在处理仅供内部使用的公司代码,那么接口是否公开并不重要。您可以从公司存储库中获取所有代码。但是,如果一个接口被“发布”了,如果有代码在你的控制之外使用它,那么你就完蛋了。您必须支持该接口或冒着破坏代码的风险。甚至受保护的接口也可以被认为是已发布的(这就是我不关心受保护的原因)。

许多语言发现 public/protected/private 的等级性质过于局限且不符合现实。为此,有 trait class 的概念,但那是另一回事。


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

这是一个更好的表格版本,它还包括一个模块列。

https://i.stack.imgur.com/aiFvH.png

解释

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

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

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

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

选择哪个修饰符?

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

例子:

字段 long internalCounter 可能应该是私有的,因为它是可变的并且是实现细节。

一个只应该在工厂类(在同一个包中)实例化的类应该有一个包受限的构造函数,因为它不应该直接从包外部调用它。

应该保护在渲染之前调用并用作子类中的挂钩的内部 void beforeRender() 方法。

从 GUI 代码调用的 void saveGame(File dst) 方法应该是公共的。

(*) What is Encapsulation exactly?


只是说:有很多人在区分红色/绿色时存在问题。使用红色/绿色(或黄色/橙色/...)着色方案的表格在任何事情上都很少“更好”;-)
@GhostCat,我不同意。我认为红色/绿色直观地与许多人的“有效”/“无效”对齐,即它比许多替代方案更好。
colourblindawareness.org/colour-blindness/… ... 8% 的色盲男性大致可分为 1% 的氘核、1% 的氘核、1% 的氘核和 5% 的氘核我是那 5% 中的 50% 之一,请放心:红色/绿色很烂。
@GhostCat 好的.. 这比我预期的要大。我在此 color blindness simulator 中上传了图像并测试了所有不同的模式。即使在单色/全色模式下,色差也是合理的。你能看出区别还是模拟器关闭了? (我仍然认为红色/绿色对于看到颜色的人来说非常直观。)
我可以看到差异,但我也能够通过我们必须在德国为驾驶执照进行的一半色盲测试;-) ...但我认为这样的模拟器“足够好”。
C
Clark Kent
____________________________________________________________________
                | 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         |       ✔       |     ✘     |       ✘       |   ✘    
____________________________________________________________________

值得一说 - “受保护的修饰符使对象在其他包中可用,而默认/无修饰符限制对同一包的访问”
@ vanguard69,protected 修饰符使标记的 事物 (类、方法或字段)可用于其他包中的其他类只有当且仅当说其他类是声明该 protected- 标记 thing 的类的子类。
k
kvantour

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

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

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

此外,在重写时使用 @Override 注释以防止在重构时破坏。


@RuchirBaronia,“世界”=应用程序中的所有代码,无论它在哪里。
尽管此答案中的信息可能有用,但问题不在于我们是否应该首先将所有内容声明为私有,然后在需要时将其公开。
C
Community

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

“默认”访问(由缺少关键字指定)也称为 package-private。例外:在接口中,没有修饰符意味着公共访问;禁止使用 public 以外的修饰符。枚举常量总是公开的。

概括

是否允许使用此访问说明符访问成员?

成员是私有的:仅当成员与调用代码在同一类中定义时。

成员是包私有的:仅当调用代码在成员的直接封闭包中时。

成员受保护:相同的包,或者如果成员是在包含调用代码的类的超类中定义的。

成员是公开的:是的。

访问说明符适用于什么

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

对于顶级范围内的类,只允许使用 public 和 package-private。这种设计选择可能是因为 protectedprivate 在包级别是多余的(没有包的继承)。

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

相关:Java Class Accessibility

命令

访问说明符可以严格排序

公共>受保护>包私有>私有

表示 public 提供最多的访问权限,private 提供最少的访问权限。对私有成员的任何引用也对包私有成员有效;任何对包私有成员的引用在受保护成员上都是有效的,依此类推。 (授予对同一包中其他类的受保护成员的访问权限被认为是错误的。)

笔记

一个类的方法可以访问同一个类的其他对象的私有成员。更准确地说,C 类的方法可以访问 C 的任何子类的对象上的 C 私有成员。Java 不支持通过实例限制访问,仅支持通过类。 (与 Scala 相比,后者使用 private[this] 支持它。)

您需要访问构造函数来构造对象。因此,如果所有构造函数都是私有的,则只能由存在于类中的代码(通常是静态工厂方法或静态变量初始值设定项)来构造该类。对于包私有或受保护的构造函数也是如此。仅具有私有构造函数也意味着该类不能在外部子类化,因为 Java 要求子类的构造函数隐式或显式调用超类构造函数。 (但是,它可以包含一个嵌套类来继承它。)

仅具有私有构造函数也意味着该类不能在外部子类化,因为 Java 要求子类的构造函数隐式或显式调用超类构造函数。 (但是,它可以包含一个嵌套类来继承它。)

内部类

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

但是,这相当复杂,有关详细信息,请参阅 consult the Java Language Specification。 (是的,过去存在编译器错误。)

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

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

一些相关问题:

Java - 包私有类中的方法可访问性?


“禁止使用 public 以外的修饰符”——从 Java 9 开始,不再是这种情况:接口也可以有私有方法。
H
Hoa Nguyen

根据经验:

私有:类范围。

默认(或包私有):包范围。

protected:包范围+子类(类似于包,但我们可以从不同的包中对其进行子类化)。 protected 修饰符始终保持“父子”关系。

公众:无处不在。

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

(D) 直接(从同一类中的方法调用,或通过“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   |
+—————————————————+————————————+———————————+

R
Ravi

简而言之

公共:可从任何地方访问。

protected:同一包的类和任何包中的子类都可以访问。

默认值(未指定修饰符):可由同一包的类访问。

private:只能在同一个类中访问。


E
Eng.Fouad

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

假设我们有 2 个类;父子,各自在自己的包中:packagefatherpackage; public class Father { } ------------------------------------------- 包子包;公共类儿子扩展父亲{}

让我们为父亲添加一个受保护的方法 foo()。包父包;公共类父亲 { 受保护的 void foo(){} }

方法 foo() 可以在 4 个上下文中调用: 在定义 foo() 的同一包中的类(父包)中:公共类 SomeClass { public void someMethod(Father f, Son s) { f.foo(); s.foo();在子类中,在当前实例上通过 this 或 super: package sonpackage;公共类儿子扩展父亲 { public void sonMethod() { this.foo();超级.foo();在类型相同的引用上:包父亲包;公共类父亲{公共无效父亲方法(父亲f){f.foo(); // 即使 foo() 是私有的也有效 } } -------------------------- ----- 包子包;公共类儿子扩展父亲 { public void sonMethod(Son s) { s.foo();在类型为父类的引用上,并且它位于定义 foo() 的包内(父包)[这可以包含在上下文号中。 1]:包父包;公共类儿子扩展父亲 { public void sonMethod(Father f) { f.foo(); } }

在定义 foo() 的同一包中的类(fatherpackage)中:公共类 SomeClass { public void someMethod(Father f, Son s) { f.foo(); s.foo(); } }

在子类中,通过 this 或 super 在当前实例上:公共类儿子扩展父亲 { public void sonMethod() { this.foo();超级.foo(); } }

在类型为同一类的引用上:包父亲包;公共类父亲{公共无效父亲方法(父亲f){f.foo(); // 即使 foo() 是私有的也有效 } } -------------------------- ----- 包子包;公共类儿子扩展父亲 { public void sonMethod(Son s) { s.foo(); } }

在类型为父类的引用上,并且它位于定义 foo() 的包内(父包)[这可以包含在上下文号中。 1]:包父包;公共类儿子扩展父亲 { public void sonMethod(Father f) { f.foo(); } }

以下情况无效。在类型为父类且位于定义 foo() 的包之外的引用上(父包):公共类儿子扩展父亲 { public void sonMethod(Father f) { f.foo(); // 编译错误 } } 子类的包中的非子类(子类从其父类继承受保护的成员,并使它们对非子类私有):公共类 SomeClass { public void someMethod(Son s) throws Exception { s.foo(); // 编译错误 } }

在类型为父类且位于定义 foo() 的包之外的引用上(父包):公共类儿子扩展父亲 { public void sonMethod(Father f) { f.foo(); // 编译错误 } }

子类的包中的非子类(子类从其父类继承受保护的成员,并使它们对非子类私有):公共类 SomeClass { public void someMethod(Son s) throws Exception { s.foo(); // 编译错误 } }


Object#clone()protected 成员的一个示例。
super.foo()和第一个无效情况f.foo()有什么区别?
cst1992 令人困惑,但请参阅 Java 语言规范 6.6.2:“对象的受保护成员或构造函数可以从包外部访问,其中仅由负责实现该对象的代码声明它”。使用 super.foo() 引用“super”是“直接负责实现”,但引用“f”不是。为什么?因为您可以 100% 确定“super”是父亲类型,但不是“f”;在运行时,它可能是父亲的一些其他子类型。请参阅docs.oracle.com/javase/specs/jls/se9/html/…
读懂protected的人的回答令人耳目一新。不幸的是,此页面上定义 protected 的所有其他答案都有点错误。
这不是 Oracle 官方网站所说的:“protected 修饰符指定该成员只能在其自己的包中访问(与 package-private 一样),此外, 只能由其类的子类访问在另一个包中。” - docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
C
Community

私人的

方法、变量和构造函数

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

类和接口

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

笔记

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

受保护

类和接口

protected 访问修饰符不能应用于类和接口。

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

笔记

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

上市

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

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

不同的包

但是,如果我们试图访问的公共类在不同的包中,那么仍然需要导入公共类。

因为类继承,一个类的所有公共方法和变量都被它的子类继承。

默认 - 无关键字:

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

在同一个包内

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

笔记

我们无法覆盖静态字段。如果您尝试覆盖它不会显示任何错误,但它不能正常工作。

相关答案

覆盖java中的静态方法

参考链接

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


J
Joe Phillips

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


P
Peter Mortensen

私人:仅限课堂访问

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

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

Public:类、包(全部)和子类都可以访问……简而言之,无处不在。


y
yoAlex5

Java 访问修改

https://i.stack.imgur.com/JqGNs.png

访问修饰符可适用于 classfield[About]method。尝试访问、子类化或覆盖它。

通过类访问字段或方法。

继承与开放封闭原则[关于] 后继类(子类)访问修饰符可以是任意的。后继方法(覆盖)访问修饰符应该相同或扩展它

后继类(子类)访问修饰符可以是任意的。

后继方法(覆盖)访问修饰符应该相同或扩展它

顶级类(第一级范围)可以是 publicdefaultNested class[About] 可以包含其中任何一个

package 未申请包层次结构

[Swift access modifiers]


P
Peter Mortensen

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

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

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

默认值:可以从任何包类在同一个包中访问它。

要访问,您可以创建类的对象。但是你不能在包之外访问这个变量。

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

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

私有:可以在同一个类中访问。

在非静态方法中,由于此引用(也在构造函数中),您可以直接访问,但要在静态方法中访问,您需要创建类的对象。


C
Community

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

输出:你好

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

输出:你好

https://i.stack.imgur.com/E5c6l.png


P
Peter Mortensen

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

仅对班级可见(私有)。

对世界(公众)可见。

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

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

String name = "john";

public int age(){
    return age;
}

私有访问修饰符 - 私有:

声明为私有的方法、变量和构造函数只能在声明的类本身内访问。 private 访问修饰符是最严格的访问级别。类和接口不能是私有的。

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

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

例子:

Public class Details{

    private String name;

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

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

公共访问修饰符 - public:

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

但是,如果我们试图访问的公共类在不同的包中,那么仍然需要导入公共类。

因为类继承,一个类的所有公共方法和变量都被它的子类继承。

例子:

public void cal(){

}

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

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

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

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

class Van{

    protected boolean speed(){

    }
}

class Car{
    boolean speed(){
    }

}

A
Alex Weitz

public - 可从应用程序中的任何位置访问。

默认 - 可从包中访问。

protected - 可从其他包中的包和子类访问。以及

private - 只能从它的类访问。


P
Peter Mortensen

This page writes well about the protected & default access modifier

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

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


只需添加这个“一旦子类访问父类的受保护成员,它就成为子类的私有成员(或者更确切地说,我会说一个可以由子类的子类继承的特殊私有成员)成员。”
P
Peter Mortensen

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

随着时间的推移,您将了解何时将某些类设为包私有以及何时声明某些受保护的方法以供在子类中使用。


r
richa_v

Public Protected Default 和 private 是访问修饰符。

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

类可以是公共的或默认的 类成员可以是公共的、受保护的、默认的或私有的。

Private 在类之外不可访问 Default 只能在包中访问。在包以及扩展它的任何类中受保护。公众对所有人开放。

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


Default 不是访问修饰符,另外两个拼写错误。
י
ישו אוהב אותך

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

这与 Java Access Modifiers 有关。

Java Access Modifiers

Java 访问修饰符指定哪些类可以访问给定类及其字段、构造函数和方法。可以为类、其构造函数、字段和方法单独指定访问修饰符。 Java 访问修饰符在日常用语中有时也称为 Java 访问说明符,但正确的名称是 Java 访问修饰符。类、字段、构造函数和方法可以具有四种不同的 Java 访问修饰符之一: 列表项私有默认(包)受保护公共

来自 Controlling Access to Members of a Class 教程:

访问级别修饰符确定其他类是否可以使用特定字段或调用特定方法。有两个级别的访问控制:在顶层——公共或包私有(没有显式修饰符)。在成员级别——public、private、protected 或 package-private(无显式修饰符)。可以使用修饰符 public 声明一个类,在这种情况下,该类对任何地方的所有类都是可见的。如果一个类没有修饰符(默认值,也称为包私有),则它仅在其自己的包中可见 下表显示了每个修饰符允许的对成员的访问。 ╔═════════════╦═══════╦═════════╦══════════╦══════ ═╗║修饰符║类║cappand║子类║世界║║╠═════════════╬═══════╬═════════╬════╠═════════════╬═══════╬═════════╬════ ══════╬═══════╣ ║ 公开 ║ Y ║ Y ║ Y ║ Y ║ ║ 保护 ║ Y ║ Y ║ Y ║ N ║ ║ 无修饰符 ║ Y ║ Y ║ N ║ Y ║ Y ║ N ║私人║Y║N║N║N║╚═════════════╩═══════╩════════␐════════␐═══ ═══╩═══════╝ 第一个数据列表示类本身是否可以访问由访问级别定义的成员。如您所见,一个类总是可以访问它自己的成员。第二列指示与该类位于同一包中的类(无论其父级如何)是否可以访问该成员。第三列表示在此包外声明的类的子类是否可以访问该成员。第四列表示是否所有类都可以访问该成员。访问级别以两种方式影响您。首先,当您使用来自其他来源的类时,例如 Java 平台中的类,访问级别决定了您自己的类可以使用这些类的哪些成员。其次,当你编写一个类时,你需要决定你的类中的每个成员变量和每个方法应该有什么访问级别。


补充到底是什么,为什么它不是对现有帖子的编辑?
补充是访问修饰符。为什么不编辑?为了历史原因保持已接受的答案不变并给出我的答案。
G
Greedy Coder

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

假设您是大学的学生,并且您有一个朋友周末来拜访您。假设校园中央有一尊大学创始人的大雕像。

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

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

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

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

希望这可以帮助!


M
Mushfiqur Rahman Abir

https://i.stack.imgur.com/nAtpl.png

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


为了更清楚,no modifier == package private | package protected
P
Pritam Banerjee

当您考虑访问修饰符时,只需以这种方式考虑它(适用于变量和方法):

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

现在,当涉及到 defaultprotected 时,就会出现混淆

default -->不存在访问修饰符关键字。这意味着它在类的包中严格可用。 无处可以在该软件包之外访问它。

protected -->比 default 稍微宽松一些,除了相同的包类之外,它可以被声明的 之外的子类访问。


C
Christophe Roussy

这完全是关于封装(或者正如乔菲利普斯所说,最少的知识)。

从最严格的(私人)开始,看看您以后是否需要限制较少的修饰符。

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

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

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

另一件事是,相互依赖很多的类可能最终在同一个包中,如果依赖关系太强,最终可能会被重构或合并。

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


M
Mudassar

我的两分钱:)

私人的:

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

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

包私有:

类 -> 顶级类可以是包私有的。它只能从同一个包中访问。不是来自子包,不是来自外部包。

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

受保护:

类 -> 无法保护顶级类。

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

上市:

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

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

这里有详细解答

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


T
Tiyus98

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

私有访问修饰符用于: - 仅同一个类

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

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

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


正如目前所写的那样,您的答案尚不清楚。请edit添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。您可以找到有关如何写出好答案的更多信息in the help center
V
Vipul Verma

public 如果一个类成员用 public 声明,那么它可以从任何地方访问

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

default 在 Java 中,default 不是访问修饰符关键字。如果声明类成员时没有任何访问修饰符关键字,那么在这种情况下,它被视为默认成员。默认类成员始终对相同的包类成员可用。但是即使外部类是与受保护成员不同的子类,外部包类成员也不能访问默认类成员

private 如果一个类成员是用关键字protected声明的,那么在这种情况下它只对相同的类成员可用


T
Tushar Baviskar

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

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

包私有(默认):除了下面描述的访问之外,此访问说明符将提供由私有访问说明符指定的访问权限。

当您正在开发某个包以及其中的某个类(例如 Class1)时,您可以使用默认(无需明确提及)访问说明符,将类中的成员公开给(相同)包中的其他类。在这些其他类中(在同一个包中),您可以访问 Class1 实例上的这些默认成员。您还可以在 Class1 的子类中访问这些默认成员,例如 Class2(在此引用上或在 Class1 的实例上或在 Class2 的实例上)。

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

protected:除了下面描述的访问之外,此访问说明符将提供包私有访问说明符指定的访问权限。

当您正在开发某个包以及其中的某个类(例如 Class1)时,如果您不希望在您的包之外访问该成员(例如在一般而言,您的包(即使用您的 API 的客户端),但是您希望例外并仅在客户端编写扩展 Class1 的 Class2 类时才允许访问此成员。因此,一般来说,受保护的成员可以在派生类(即 Class2)中的“this”引用上访问,也可以在 Class2 的显式实例上访问。

请注意:

如果您尝试在 Class1 的显式实例上访问它,您将无法访问 Class2 中 Class1 的继承的受保护成员,尽管它是在其中继承的。当您在扩展 Class2 的相同/不同包中编写另一个类 Class3 时,来自 Class1 的受保护成员将可以在此引用以及 Class3 的显式实例上访问。这对于任何扩展的层次结构都是如此,即受保护的成员仍然可以在此引用或扩展类的实例上访问。请注意,在 Class3 中,如果您创建 Class2 的实例,那么您将无法从 Class1 访问受保护的成员,尽管它是继承的。

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

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

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


Y
Yogesh Sharma

当您不希望您的变量/方法/类在该类之外可见时,请使用私有。当您希望只有此类的孩子可以使用该变量时,请使用 protected。当您希望变量/类/方法应该可以从任何地方访问时,请使用 public。当您希望您的变量/类/方法仅在该包内使用时,请使用包私有。