在Java中,在创建类和接口以及处理继承时,是否有明确的规则来确定何时使用每个访问修饰符,即默认的(包私有)、公共的、受保护的和私有的?


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


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

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


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

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

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

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


区别可以在已经提供的链接中找到,但使用哪一个链接通常取决于“最少知识原则”。只允许所需的最小可见性。


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

私有的

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

包专用

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

受保护的

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

平民的

每个人都能看到。

出版

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

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

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

因此,经验法则是让事物尽可能地可见。从私密开始,只在需要时增加更多的可见性。只公开用户需要知道的信息,你公开的每一个细节都限制了你重新设计系统的能力。

如果您希望用户能够自定义行为,而不是将内部公开以便他们可以覆盖它们,那么通常最好将这些内容插入到对象中并将接口公开。这样他们就可以简单地插入一个新对象。例如,如果您正在编写一个CD播放器,并希望“go find info about this CD”位可定制,而不是将这些方法公开,那么您应该将所有这些功能放入其对象中,并仅将对象getter/setter公开。通过这种方式,吝啬于暴露自己的内心会鼓励良好的组合和关注的分离

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

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

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


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

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


此页很好地描述了受保护的默认访问修饰符(&D)

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

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


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

“默认”访问(由缺少关键字指定)也称为包专用。异常:在接口中,没有修饰符表示公共访问;禁止公共以外的修饰语。枚举常量始终是公共的。

总结

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

成员是私有的:仅当成员与调用代码在同一类中定义时。成员是包专用的:仅当调用代码位于成员的直接封装包内时。成员受保护:相同的包,或者如果成员是在包含调用代码的类的超类中定义的。成员公开:是的。

访问说明符应用于什么

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

对于顶级作用域中的类,只允许public和package private。这种设计选择大概是因为受保护和私有在包级别是冗余的(没有包的继承)。

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

相关:Java类可访问性

顺序

访问说明符可以严格排序

public>protected>package private>private

这意味着公共提供的访问最多,而私人提供的访问最少。对私有成员的任何引用对包私有成员也是有效的;对包私有成员的任何引用都对受保护成员有效,依此类推。(将受保护成员的访问权限授予同一包中的其他类被认为是错误的。)

笔记

允许类的方法访问同一类的其他对象的私有成员。更准确地说,类C的方法可以访问C的任何子类的对象上的C的私有成员。Java不支持仅通过类而通过实例限制访问。(与Scala相比,Scala确实支持使用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

一些相关问题:

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


简而言之

公共:随处可见。protected:可由同一包的类和驻留在任何包中的子类访问。默认(未指定修饰符):可由同一包的类访问。private:只能在同一类中访问。


作为经验法则:

private:类范围。默认(或包专用):包范围。protected:包范围+子级(类似于包,但我们可以从不同的包中对其进行子类化)。受保护的修饰符始终保持“父子”关系。公众:无处不在。

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

(D) direct(从同一类内的方法调用,或通过“this”语法调用)。(R) reference(使用对类的引用或通过“dot”语法调用方法)。(一) 继承(通过子类化)。

那么我们有一个简单的表格:

+—-———————————————+————————————+———————————+
|                 |    Same    | Different |
|                 |   Package  | Packages  |
+—————————————————+————————————+———————————+
| private         |   D        |           |
+—————————————————+————————————+———————————+
| package-private |            |           |
| (no modifier)   |   D R I    |           |
+—————————————————+————————————+———————————+
| protected       |   D R I    |       I   |
+—————————————————+————————————+———————————+
| public          |   D R I    |    R  I   |
+—————————————————+————————————+———————————+

____________________________________________________________________
                | 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         |       ✔       |     ✘     |       ✘       |   ✘    
____________________________________________________________________

Java中最容易被误解的访问修饰符是受保护的。我们知道它类似于默认修饰符,只有一个例外,子类可以看到它?这里有一个例子,希望能澄清这一困惑:

假设我们有2个类;父亲和儿子,每个人都有自己的包装:包父包;公共课父亲{}-------------------------------------------package-sonpackage;公共课儿子延伸父亲{}让我们向Father添加一个受保护的方法foo()。包父包;公共课父亲{受保护的void foo(){}}方法foo()可以在4种上下文中调用:在位于定义foo()的同一包中的类内(父包):包父包;公共类SomeClass{公共无效方法(父f,子s){f.foo();s.foo();}}在子类内部,在当前实例上通过this或super:package-sonpackage;公共课儿子延伸父亲{public void sonMethod(){this.foo();super.foo();}}在类型为同一类的引用上:包父包;公共课父亲{公共无效父方法(父f){f.foo();//即使foo()是私有的,也有效}}-------------------------------------------package-sonpackage;公共课儿子延伸父亲{公共无效sonMethod(Sons){s.foo();}}在一个类型为父类的引用上,该引用位于定义foo()的包内(父包)[这可以包含在上下文1中]:包父包;公共课儿子延伸父亲{公共无效sonMethod(父f){f.foo();}}以下情况无效。在类型为父类且位于定义foo()的包(父包)外部的引用上:package-sonpackage;公共课儿子延伸父亲{公共无效sonMethod(父f){f.foo();//编译错误}}子类包中的非子类(子类从其父类继承受保护的成员,并使其成为非子类的私有成员):package-sonpackage;公共类SomeClass{public void someMethod(儿子)引发异常{s.foo();//编译错误}}


私有的

方法、变量和构造函数

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

类和接口

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

Note

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

受保护的

类和接口

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

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

Note

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

平民的

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

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

不同的软件包

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

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

默认-无关键字:

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

在相同的软件包中

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

Note

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

相关答案

重写java中的静态方法

参考链接

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


私人:仅限上课

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

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

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


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

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

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

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

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


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

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

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

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

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

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

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

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

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


包装可见。默认值。不需要修改器。

仅对类可见(私有)。

对世界(公众)可见。

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

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

String name = "john";

public int age(){
    return age;
}

私有访问修饰符-私有:

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

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

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

示例:

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(){

}

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

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

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

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

class Van{

    protected boolean speed(){

    }
}

class Car{
    boolean speed(){
    }

}

公共-可从应用程序中的任何位置访问。默认-可从包访问。protected-可从其他包中的包和子类访问。也private-只能从其类访问。


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


解释

私有成员(i)只能在声明的同一类中访问。没有访问修饰符(j)的成员只能在同一包中的类中访问。受保护的成员(k)可以在同一包中的所有类和其他包中的子类中访问。公共成员(l)对所有类都是可访问的(除非它驻留在不导出声明它的包的模块中)。


要选择哪个修饰符?

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

示例:

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

(*)封装到底是什么?


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

输出:您好


注:这只是对公认答案的补充。

这与Java访问修改器有关。

从Java访问修改器:

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

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

访问级别修饰符确定其他类是否可以使用特定字段或调用特定方法。有两个级别访问控制:在顶层public或package private(没有显式修饰符)。在成员级别public、private、protected或package private(没有显式修饰符)。类可以用修饰符public声明,在这种情况下类对任何地方的所有类都可见。如果类没有修饰符(默认值,也称为包专用),它仅可见在其自己的包装内下表显示了每个成员允许的成员访问权限修改器。╔═════════════╦═══════╦═════════╦══════════╦═══════╗║ 修改器║ 班║ 包裹║ 子类║ 世界║╠═════════════╬═══════╬═════════╬══════════╬═══════╣║ 平民的║ Y║ Y║ Y║ Y║║ 受保护的║ Y║ Y║ Y║ N║║ 无修饰符║ Y║ Y║ N║ N║║ 私有的║ Y║ N║ N║ N║╚═════════════╩═══════╩═════════╩══════════╩═══════╝第一个数据列指示类本身是否有权访问由访问级别定义的成员。正如你所看到的,一个班级总是可以访问自己的成员。第二列指示是否类(无论其父母)有权访问该成员。第三列表示在该包外部声明的类的子类是否具有访问该成员。第四列指示是否所有类可以访问该成员。访问级别以两种方式影响您。首先,当您使用来自另一个源,访问级别决定您自己的这些类的哪些成员类可以使用。第二,当你写一门课时,你需要决定类中每个成员变量和每个方法的访问级别应该有。


我经常意识到,通过创造真实世界的类比,记住任何语言的基本概念都是可能的。下面是我在Java中理解访问修饰符的类比:

让我们假设你是一个大学的学生,你有一个朋友周末来拜访你。假设校园中央有一座大学创始人的大雕像。

当你把他带到校园时,你和你的朋友首先看到的就是这尊雕像。这意味着任何在校园里行走的人都可以在没有大学许可的情况下观看雕像。这使雕像成为公共的。接下来,你想带你的朋友去你的宿舍,但为此你需要将他登记为访客。这意味着他可以获得进入校园各个建筑的通行证(与你的通行证相同)。这将使他的门禁卡受到保护。你的朋友想登录校园WiFi,但没有任何凭据。他唯一可以上网的方式是你和他分享你的登录信息。(记住,每个上大学的学生都拥有这些登录凭据)。这将使您的登录凭据为NO MODIFIER。最后,你的朋友想看看你在网站上发布的学期进度报告。然而,每个学生都有自己的个人登录来访问校园网站的这一部分。这将使这些凭据成为PRIVATE。

希望这有帮助!


当你想到访问修饰符时,你可以这样想(适用于变量和方法):

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

现在,当涉及到默认和受保护时,就会出现混乱

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

protected-->略低于默认值,并且除了相同的包类之外,它可以由声明的包之外的子类访问。


这一切都是关于封装的(或者正如乔·菲利普斯所说的,最起码的知识)。

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

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

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

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

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

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


平民的如果用public声明类成员,则可以从任何地方访问它受保护的如果用关键字protected声明类成员,则可以从相同的类成员、同一包内的外部类成员和继承的类成员访问该类成员。如果类成员受到保护,则不能从外部包类访问它,除非外部包类被继承,即扩展其他包超类。但是,受保护的类成员始终可用于相同的包类,无论是否继承了相同的包类别违约在Java中,默认值不是访问修饰符关键字。如果声明的类成员没有任何访问修饰符关键字,那么在这种情况下,它被视为默认成员。默认类成员始终可用于相同的包类成员。但即使外部类是与受保护成员不同的子类,外部包类成员也不能访问默认类成员私有的如果用关键字protected声明了类成员,那么在这种情况下,它只对相同的类成员可用


我的两分钱:)

私人:

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

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

包专用:

class->顶级类可以是包专用的。它只能从同一个包访问。不是来自子包装,不是来自外包装。

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

受保护的:

class->无法保护顶级类。

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

公众:

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

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

下面是详细的答案

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


Java访问修改

访问修饰符可适用于类、字段[About]和方法。尝试访问、子类化或重写此。

通过类访问字段或方法。继承与开闭原理〔关于〕后继类(子类)访问修饰符可以是任意的。后继方法(重写)访问修饰符应相同或展开

顶级类(一级范围)可以是公共的,也可以是默认的。嵌套类[About]可以包含其中任何一个

包未应用于包层次结构

[Swift访问修饰符]


Java中的访问说明符:java中有4个访问说明符,即private、packageprivate(默认)、protected和public,访问顺序依次递增。

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

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

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

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

受保护的:除了下面描述的访问之外,此访问说明符还将提供由包专用访问说明符指定的访问。

当您正在开发某个包,从而在其中开发某个类(例如Class1)时,如果您不希望在包外部(例如在包的消费者的包中,即使用您的API的客户机)访问Class1中的数据成员,则应在Class1中使用受保护的访问说明符,但您希望创建一个例外,并且仅当客户端编写扩展Class1的Class2类时才允许访问该成员。因此,一般来说,受保护的成员可以在派生类(即Class2)中的“this”引用上访问,也可以在Class2的显式实例上访问。

请注意:

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

所以,底线是,只有当来自此其他包的某个类、包含此受保护成员的扩展类以及受保护成员在扩展类的定义内通过“this”引用或扩展类的显式实例访问时,才能在其他包中访问受保护成员。

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

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


此图将使您轻松了解public、private、protected和default访问修饰符之间的基本区别。当您没有在代码中声明ant访问修饰符时,默认修饰符会自动发生。


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

专用访问修饰符用于:-仅同一类

默认Access修饰符用于:-仅同一类/同一包子类

Protected Access修饰符用于:-同一类/同一包子类/同包非子类/不同包子类

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


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

考虑到我在foo包中开发了MyClass,它有一个很棒的方法,名为print,您有兴趣调用它(它可能是一个方法或属性)

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

您已经开发了YourClass的bar包,您有兴趣使用MyClass#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();
    }
}

您的代码未编译,并且出现错误。方法print()对于类型MyClass未定义

你来找我:

你:我想用你的方法,但它是私人的。你能公开吗?我:不,我不想让别人使用你:我是你的朋友,至少让我不要让别人使用它。我:好的,我将删除私有关键字。我的访问修饰符将是默认的或私有的包。因为你们是我的朋友,你们必须和我在同一个包裹里。所以你们必须来到我的包裹里。我的意思是确切的包,甚至不是子包。

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

不考虑这个:你又来找我了

你:我的老板告诉我我不能改变我的包(在实际世界中,你不能改变你的包以使用其他类方法)我:还有另一种方法,如果你扩展我,我使print()受到保护,那么无论你是否更改包,你都可以使用它。(因此,子类将始终允许您访问我的方法)。

这是我的班级

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

您可能已经注意到,通过使一个方法受到保护,所有其他类都可以通过扩展它来使用它,您无法轻松控制如何使用它。这在java17中通过引入密封和许可词来解决。因此,您可以定义哪些类可以扩展您。类似于公共密封类MyClass允许YourClass参见Java17中的密封类是什么?有关详细信息