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


当前回答

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

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

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

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

其他回答

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

仅对类可见(私有)。

对世界(公众)可见。

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

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

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

}

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

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

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

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

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

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

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

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

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

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

考虑到我在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中的密封类是什么?有关详细信息

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

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

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

希望这有帮助!

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

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

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

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

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