【问题标题】:The use of visibility modifiers in JavaJava中可见性修饰符的使用
【发布时间】:2013-05-19 14:36:59
【问题描述】:
class Orange{

    Orange(){
    }

}

修饰符(在本例中为 package-private)在类前面和构造函数前面的用法有什么区别?我认为构造函数前面的修饰符意味着它可以实例化Orange 类的实例。但是类前面的修饰符呢?

【问题讨论】:

  • 那是有效的 java 吗?你可以阅读任何好书中关于修饰符的文章
  • 你不能将包作为类/方法修饰符。
  • -1 用于询问无效语法...但是,我敢打赌他的意思是默认可见性。
  • 你的意思是访问修饰符吗?公共、私有和受保护。]
  • 好的。谁骗你们说这是无效的语法?

标签: java modifier


【解决方案1】:

类的修饰符定义谁可以访问该类。例如public 类可以被任何包中的类访问,如果没有编写修饰符,则该类只能被相同包中的类访问。

构造函数、方法和字段的修饰符含义相同。但是privateprotected 更有意义。 Private 只能从当前类访问。不受其子类的影响,也不受同一个包中的类的影响。

关于你关于构造函数的问题。类可以有多个构造函数。其中一些可以是私有的,而另一些可以是公开的。你是对的,如果类是包保护的,那么公开构造函数是没有意义的:无论如何,包外的任何人都不能调用这个类。

这就像为抽象类编写公共构造函数一样。由于抽象类本身不能实例化,它的构造函数应该是protectedprivate,尽管编译器并不关心这一点。

顺便说一句,使用默认包不常用也不推荐技术。

【讨论】:

  • 视情况而定。如果您希望公开一个方法以进行单元测试,而不是其他任何方法,那么您可以将其声明为包私有,并确保测试使用相同的包。
【解决方案2】:

您只能在 Java 中声明公共或默认类(仅限顶级类),这些修饰符决定了该类的可访问性。

我也建议你看看“Why can't a class or an interface receive private or protected access modifiers?

现在就构造函数而言,当没有显式定义访问修饰符时,构造函数将具有默认类型的访问控制。因此,此构造函数将具有包级别访问权限。只有那些在该包中定义为具有此默认构造函数的类的类才能访问它。见“Aren't Java constructors public by default?

如果构造函数是私有的,那么只有该类中的代码可以访问它。 为了更好地理解修饰符,您需要查看“Access Modifiers In Java

【讨论】:

  • private 因此,在应用于顶级类时没有任何意义。顺便说一句,您可以将其应用于 non 顶级类,例如静态内部类。
  • 亲爱的在 OP 的例子中,他没有表现出任何内部阶级。所以我只是在他的预期中回答。无论如何我已经编辑了我的问题
【解决方案3】:

类修饰符的作用类似于方法修饰符。公共、私有、最终、抽象等工作。

Public 允许任何包中的类访问该类及其方法。

没有修饰符只允许从它定义的包中访问类。

Private 会阻止所有访问(如果与顶级类一起使用,则没有意义)。

抽象类允许您创建从(抽象)类派生的类。例如,您可以创建一个 Abstract Shape 类并让一个 Rectangle 类扩展 shape,继承它的所有方法、变量,并强制它定义任何抽象方法。

【讨论】:

    【解决方案4】:

    首先,3 个访问修饰符创建了 4 个访问级别。

    1. 公共 - 随处可访问
    2. 受保护 - 可在同一个包和儿童中访问
    3. 默认 - 只能在同一个包中访问
    4. private - 只能在同一个类中访问。

    你是对的 - 构造函数级别的修饰符与类的实例化直接相关。

    Class 级别的修饰符决定 Class 的可访问性。

    【讨论】:

    • Class 级别的修饰符决定了 Class 的可访问性。这是什么意思?一个类是通过关键字 import 访问的?
    • OP 是在讨论类本身的修饰符,而不是方法。
    • 好的,这就是交易。一个类只能是公共的或默认的,即您只能使用一个在类级别是公共的修饰符。假设您在编写类(默认访问级别)时没有指定和访问修饰符并尝试在另一个包中访问它,它将无法访问。 不允许导入
    【解决方案5】:

    class 级别修饰符的使用类型

    http://javapapers.com/core-java/access-modifiers-in-java-explain/

    constructor 级别修饰符的使用类型

    http://www.careercup.com/question?id=296844#commentThread302715

    【讨论】:

      【解决方案6】:

      首先,为了缓解任何担忧,您提供的代码完全有效的 Java 语法。

      实际上,您创建了一个只能由默认包中的其他类实例化/使用的类。如果您在包中定义它(例如package foo;),它也可以工作,因为只有包foo 中的类可以看到此类)。

      现在,问题的关键。

      There are different ways to control access to fields and members。他们各自做不同的事情。

      • private 可见性是最不可见的。只有定义类可以访问该字段。

      • 没有修饰符,或者package private 是第二不可见的。定义类包中的所有类都可以访问该字段,但子类和世界其他地方不能。

      • protected 是第二个最明显的。只有其他类被禁止访问该字段。

      • public 是最明显的。 一切都可以访问该字段。

      类级别的修饰符变得有趣。这来自Java Language Specification, §8.1.1

      访问修饰符public (§6.6) 仅适用于顶级类 (§7.6)和成员类(§8.5),而不是本地类(§14.3)或 匿名类(§15.9.5)。

      访问修饰符 protectedprivate (§6.6) 仅适用于 直接封闭类或枚举声明中的成员类 (§8.5)。

      修饰符 static 仅适用于成员类(第 8.5.1 节),不适用于 顶级或本地或匿名类。

      如果同一个修饰符出现多次是编译时错误 在类声明中。

      如果两个或多个(不同的)类修饰符出现在一个类中 声明,那么尽管不是必需的,但习惯上是他们 出现的顺序与上面在生产中显示的顺序一致 对于ClassModifier

      一般来说,类声明看起来像这样:

      ClassDeclaration:
          NormalClassDeclaration
          EnumDeclaration
      
      NormalClassDeclaration:
          ClassModifiers(opt) class Identifier TypeParameters(opt)
                              Super(opt) Interfaces(opt) ClassBody
      

      带有 (opt) 的任何内容都被认为是可选的。

      那么,这意味着什么?

      • JLS 要求类不需要 [class] 修饰符。
      • JLS 规定,如果存在 [class] 修饰符,则它遵循以下规则之一:
        • 如果修饰符是public,那么它只适用于顶级类和成员类。
        • 如果修饰符是protectedprivate,那么它只适用于直接封闭类或枚举中的成员类。
        • static 修饰符可能会出现,但仅适用于成员类。

      Constructors have a similar rule set.

      ConstructorDeclaration:
          ConstructorModifiers(opt) ConstructorDeclarator
                                      Throws(opt) ConstructorBody
      
      ConstructorDeclarator:
          TypeParameters(opt) SimpleTypeName ( FormalParameterList(opt) )
      

      再次,这分解为:

      • JLS 要求构造函数不需要 [constructor] 修饰符。
      • JLS 要求构造函数修饰符不能包含 abstract, static, final, native, strictfp, or synchronized
      • JLS 规定,如果没有为普通类的构造函数指定访问修饰符,则构造函数具有 默认 访问权限(第 8.8.3 节,强调我的)。

      【讨论】:

        【解决方案7】:

        访问修饰符:

        • 公共 - {可以访问项目中的任何位置}
        • 私人 - {只能在班级内访问}
        • 受保护 - {可以在包和子类中访问}
        • 默认 - {可以在包内访问}

        非访问修饰符:

        • 静态 - {用于创建类变量和方法}
        • Final - {用于创建最终变量和方法}
        • 抽象 - {用于创建抽象方法和类}
        • 同步 - {用于线程}

        link 中对上述修饰符进行了一些简要讨论。参考它以获得更好的理解。

        【讨论】:

          【解决方案8】:

          我发现 Java 中最好的可见性级别是 default 可见性,即 package 可见性,因为如果测试放在同一个包中,它使单元测试类能够访问所有方法作为主班。

          此外,package 可见性更短,因为您可以省略可见性声明,因此样板代码更少。

          第二好的可见性级别是protected,因为在某些情况下,您可以将测试类创建为主类的子类。但是,如前所述,如果您正确使用包,包的可见性在大多数情况下效果更好。

          第三,通常如果您运行 Sonar 并对大型项目进行代码审查和静态分析,我发现通常 80% 的方法是 public,而 20% 是 private/protected。因此,使用私有或受保护方法的主要思想是通过绕过访问器来保护数据/属性不被访问。无论如何,大多数方法通常都是公开的。

          最没用的可见性级别(但不幸的是常用)是private,因为它无法测试(不使用反射并将可见性修改为其他东西)。此外,private 禁止在子类中重用代码,这是首先使用面向对象范式的主要思想,因此应该避免。出于同样的原因,在大多数情况下应避免使用关键字 final

          因此,我发现您的示例是定义可见性级别的最佳实践,除了您的构造函数不是公开的:)。但是,您缺少包声明和单元测试。

          【讨论】:

            猜你喜欢
            • 2013-09-25
            • 2011-07-15
            • 1970-01-01
            • 1970-01-01
            • 2014-11-06
            • 1970-01-01
            • 2014-05-28
            • 1970-01-01
            • 2015-09-06
            相关资源
            最近更新 更多