静态修饰符会改变java中类成员的访问级别吗?

Posted

技术标签:

【中文标题】静态修饰符会改变java中类成员的访问级别吗?【英文标题】:Does static modifier change the access level of a class member in java? 【发布时间】:2017-09-06 21:20:02 【问题描述】:

我正在阅读有关 Java 7 认证的 OCA 和 OCP 的书,我正在尝试使用 Java 8 进行本书的练习,我注意到一些连线。

我有 Class1 类如下:

package cert;
public class Class1
    protected static void importantMethod()
    System.out.println("importantMethod() method of Class1 class TEST \n");

importantMethod() 方法的修饰符是 protected static 并且包是 cert 如您所见,如书中所述我希望另一个包中的另一个类,在我的例子中显示如下 Class2,只能通过继承访问 importantMethod() 方法,但事实证明,来自 Class2 我也可以通过 Class1 的实例访问 importantMethod() 方法。

Class2 类:

package exam;
import cert.Class1;
class Class2 extends Class1 
    public static void main(String[] args) 
        Class1 c1 = new Class1();
        c1.importantMethod();
    

如果我从 Class1 中删除 static 修饰符,则在尝试从 importantMethod() 方法访问时会出现预期错误>Class2:

exam\Class2.java:7: error: importantMethod() has protected access in Class1
            c1.importantMethod();
              ^

我的问题是,非访问修饰符会改变类成员的访问级别吗?

【问题讨论】:

"Class1 的修饰符是protected static"...你的问题清楚地显示为public @cricket_007 他应该指的是方法“importantMethod”的修饰符。 相关:***.com/questions/24289070/… 静态成员是的属性,非静态成员是对象或实例的属性。快速回答是否定的,static 不会更改访问级别,而是更改访问的类型 嗨@DrewKennedy,所以我可以通过Class1的实例访问importantMethod而不是作为继承的成员对吗? 【参考方案1】:

事实证明,我可以从 Class2 中通过 Class1 的实例访问 importantMethod() 方法

您不需要实例来调用静态方法。 Class1.importantMethod() 工作正常。如果您删除 static,它不会,这就是您所看到的。

如果我从 Class1 中删除静态修饰符,它会给出预期的错误

因为你在不同的包中,而不是像这样通过继承调用方法

package exam;
import cert.Class1;
public class Class2 extends Class1 

    public static void main(String[] args) 
        new Class2().importantMethod();
    

【讨论】:

嗨@cricket_007,你说你不需要实例来调用静态方法。这就是为什么它起作用的原因。,但它不应该起作用,因为我仍然在不同的包中并且 importantMethod() 方法具有受保护的访问修饰符,这就是为什么我问为什么它工作。无论如何它都受到保护,我认为它是否是静态的并不重要,因为静态是非访问修饰符对吗?反正我不能打电话了 c1.importantMethod() 是静态方法时不正确。 Class1.importantMethod() 是指静态方法的方式,protected 不会影响这一点,我不认为 但是 c1.importantMethod() 有效。如果这不正确,我不应该在这种情况下犯错吗? 这是一个编译器警告。它在语法上不正确。您永远不需要实例来调用静态方法。这是我唯一的观点 不,你不是通过实例访问它,它只有一个副本,因为它是一个静态成员,你需要回去重新阅读你的学习资料,因为你没有理解它正确。【参考方案2】:

一切都很好 - 这就是 protected 访问的方式。在JLS 6.6.2.1中指定:

C 成为声明受保护成员的类。仅允许在 C 的子类 S 的主体内访问。

另外,如果Id表示一个实例字段或实例方法,那么:

[与Id 无关的内容表示实例字段或实例方法]

您的代码C 的子类S 的主体内(其中SClass2CClass1)所以没关系。 p>

【讨论】:

嗨@JonSkeet,这本书的这一部分让我感到困惑:这使得认证包内的所有其他类都可以访问该变量,以及** inheritable 任何人包外的子类**。最后,我们看到包外的子类不能使用超类引用来访问受保护的成员。 对于包外的子类,只能通过继承访问受保护的成员。谢谢你的回答。 @ArberHoxha:嗯,这只是说同一件事的一种不太清楚的方式。 “仅通过继承”被用作“仅在 C 的子类 S 的主体内”及其后部分的简写。 请看一下这张图片第38页和第39页之间的例子:dropbox.com/s/4gdl6ry939285gi/Protected.PNG?dl=0 @ArberHoxha:是的,这可以通过“无关内容”中的规则来解释,因为它显示了一个实例字段。您的问题显示了一个静态字段。真的,只需阅读我提到的规范部分。 @ArberHoxha:不,根据语言规范,编译器的行为是正确的。不幸的是,您使用的这本书只是使用了过于简单化的术语。

以上是关于静态修饰符会改变java中类成员的访问级别吗?的主要内容,如果未能解决你的问题,请参考以下文章

python中类成员修饰符

第四周周总结

Java中类变量可以被继承吗

C#中类。方法。字段 的默认访问修饰符分别是啥?

C++中类里面定义 静态成员变量的问题

java中类变量、实例变量和局部变量有何区别?