java - protected详解 - public private protected c++




Java中的public,protected,package-private和private有什么区别? (16)

在Java中,是否有明确的规则来确定何时使用每个访问修饰符,即默认(包私有), publicprotectedprivate ,同时创建classinterface以及处理继承?


私人的

  • 方法,变量和构造函数

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

  • 类和接口

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

注意

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

受保护

  • 类和接口

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

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

注意

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

上市

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

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

  • 不同的包

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

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

默认-No关键字:

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

  • 在同一个包中

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

注意

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

相关答案

参考链接

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


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

  • 假设我们有2个班级; FatherSon ,每个都在自己的包装中:

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

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

    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. 在类型为父类的引用上,它位于包中,其中定义了foo()fatherpackage )[这可以包含在上下文中。 1]:

      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
          }
      }
      

官方教程可能对你有用。

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

+ : accessible
blank : not accessible

此页面很好地描述了受保护和默认访问修饰符

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

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


私人 :仅限课程访问

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

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

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


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

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

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

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

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


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


很短的

  • public :无处不在。
  • protected :可由同一个包的类和驻留在任何包中的子类访问。
  • default(未指定修饰符):可由同一包的类访问。
  • private :只能在同一个班级内访问。

简单的规则。 首先声明一切都是私密的。 然后随着需求的出现向公众发展,设计需要保证。

当暴露成员时,问问自己是否暴露了表示选择或抽象选择。 第一个是你想要避免的东西,因为它会在实际表示中引入太多依赖,而不是它的可观察行为。

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

此外,在重写时使用@Override注释可以防止重构时出现问题。


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

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

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

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

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

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

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

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

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


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

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


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

仅对班级可见(私人)。

对世界可见(公众)。

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

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

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 Universe的任何类访问在公共类中声明的字段,方法,块。

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

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

例:

public void cal(){

}

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

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

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

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

class Van{

    protected boolean speed(){

    }
}

class Car{
    boolean speed(){
    }

}

我只是想解决一个极其普遍错误的细节,包括本页面上的大部分答案。“默认”访问(当不存在访问修饰符时)并不总是与package-private相同。这取决于事物是什么。

  • 非成员类型(即,未在其他类型中声明的类,枚举,接口和注释类型)默认为package-private。(JLS§6.6.1

  • 默认情况下,类成员和构造函数是包私有的。(JLS§6.6.1

  • 枚举构造函数默认私有的。(实际上,枚举结构必须是私有的,尝试将它们公开或受保护是错误的)。枚举常量是公共的,不允许任何访问说明符。枚举的其他成员默认为package-private。(JLS§8.9

  • 默认情况下,接口和注释类型的所有成员都是公共的。(实际上,接口和注释类型的成员必须是公共的,并且尝试将它们设为私有或受保护是错误的。)(JLS§9.3至9.5


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

我们假设您是一所大学的学生,并且您有一位朋友将在周末来访您。假设校园中间有一座大学创始人的大型雕像。

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

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

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

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

希望这可以帮助!


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

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

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

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

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

另一个问题是,彼此依赖很多的类可能最终存在于同一个包中,如果依赖性太强,最终可能会被重构或合并。

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


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




access-modifiers