Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/353.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 保护区的可见性_Java - Fatal编程技术网

Java 保护区的可见性

Java 保护区的可见性,java,Java,据我所知,如果字符串被声明为受保护,则print语句将不起作用,因为它在其他包中不可见。但是,当声明为静态保护时,为什么它可以工作呢?静态修饰符与可见性无关,所以不会发生任何更改。您不能从不同的包访问受保护的成员(即字段、方法),无论它是否是静态的 但在您的情况下,MyClass2扩展了MyClass1。您可以从超类访问受保护的成员。不过,静态与此无关 编辑: 这是一个非常有趣的案例,因为它涉及两个不同的方面: 1) 从不同包中的子类访问受保护的成员, 2) 允许您访问静态(类)成员(如实例成员

据我所知,如果字符串被声明为受保护,则print语句将不起作用,因为它在其他包中不可见。但是,当声明为静态保护时,为什么它可以工作呢?

静态修饰符与可见性无关,所以不会发生任何更改。您不能从不同的包访问受保护的成员(即字段、方法),无论它是否是静态的

但在您的情况下,MyClass2扩展了MyClass1。您可以从超类访问受保护的成员。不过,静态与此无关

编辑:

这是一个非常有趣的案例,因为它涉及两个不同的方面: 1) 从不同包中的子类访问受保护的成员, 2) 允许您访问静态(类)成员(如实例成员)的语法技巧

我将扩展您的示例,以显示您在这段代码中实际在做什么:

package p1;

public class MyClass1 {

      protected static  String str = "ss1";

    }

package p2;

import p1.MyClass1;

public class MyClass2 extends MyClass1 {

     public static void test(){

         MyClass1 mc1 = new MyClass1();

         System.out.println(mc1.str); 

         }

}
现在,什么是“语法技巧”。编译器允许您像访问实例成员一样访问静态成员:

package p1;

public class MyClass1 {

    protected String protectedString = "example";

    protected static String protectedStaticString = "example";

}

package p2;

import p1.MyClass1;

public class MyClass2 extends MyClass1 {

    public void testProtected() {

        MyClass1 otherMC1 = new MyClass1();
        MyClass2 otherMC2 = new MyClass2();

        String testProtected;

        testProtected = this.protectedString; // OK, protectedString is inherited, so it's instance member of this class
        testProtected = super.protectedString; // OK, it's also instance member of superclass

        testProtected = otherMC1.protectedString; // ERROR. You can't access protected members of other instance of superclass
        testProtected = otherMC2.protectedString; // OK. As it's inherited member of MyClass2, you can access it if it belongs to other instance of your class

    }

    public void testProtectedStatic() {

        MyClass1 otherMC1 = new MyClass1();
        MyClass2 otherMC2 = new MyClass2();

        String testProtectedStatic;

        testProtectedStatic = this.protectedStaticString; // OK - syntax trick
        testProtectedStatic = super.protectedStaticString; // OK - syntax trick

        testProtectedStatic = otherMC1.protectedStaticString; // OK - syntax trick
        testProtectedStatic = otherMC2.protectedStaticString; // OK - syntax trick

        testProtectedStatic = MyClass1.protectedStaticString; // OK - you can access protected static members from superclass
        testProtectedStatic = MyClass2.protectedStaticString; // OK - this also static member of your class
    }

}
但实际编译成字节码的是:

MyClass mc = new MyClass();
Object o = mc.STATIC_FIELD;
以这种方式访问静态成员被认为是不好的做法,因为它具有误导性。您应该始终以静态方式访问静态成员,以避免在读取代码时出现混淆

这就是你的情况。静态字段是以非静态方式访问的,所以它看起来像实例字段。删除静态修改器后,它将成为实例成员。访问此字段的方式已更改,但由于object.staticField语法的原因,您没有注意到。

静态修饰符与可见性无关,因此不会发生任何更改。您不能从不同的包访问受保护的成员(即字段、方法),无论它是否是静态的

但在您的情况下,MyClass2扩展了MyClass1。您可以从超类访问受保护的成员。不过,静态与此无关

编辑:

这是一个非常有趣的案例,因为它涉及两个不同的方面: 1) 从不同包中的子类访问受保护的成员, 2) 允许您访问静态(类)成员(如实例成员)的语法技巧

我将扩展您的示例,以显示您在这段代码中实际在做什么:

package p1;

public class MyClass1 {

      protected static  String str = "ss1";

    }

package p2;

import p1.MyClass1;

public class MyClass2 extends MyClass1 {

     public static void test(){

         MyClass1 mc1 = new MyClass1();

         System.out.println(mc1.str); 

         }

}
现在,什么是“语法技巧”。编译器允许您像访问实例成员一样访问静态成员:

package p1;

public class MyClass1 {

    protected String protectedString = "example";

    protected static String protectedStaticString = "example";

}

package p2;

import p1.MyClass1;

public class MyClass2 extends MyClass1 {

    public void testProtected() {

        MyClass1 otherMC1 = new MyClass1();
        MyClass2 otherMC2 = new MyClass2();

        String testProtected;

        testProtected = this.protectedString; // OK, protectedString is inherited, so it's instance member of this class
        testProtected = super.protectedString; // OK, it's also instance member of superclass

        testProtected = otherMC1.protectedString; // ERROR. You can't access protected members of other instance of superclass
        testProtected = otherMC2.protectedString; // OK. As it's inherited member of MyClass2, you can access it if it belongs to other instance of your class

    }

    public void testProtectedStatic() {

        MyClass1 otherMC1 = new MyClass1();
        MyClass2 otherMC2 = new MyClass2();

        String testProtectedStatic;

        testProtectedStatic = this.protectedStaticString; // OK - syntax trick
        testProtectedStatic = super.protectedStaticString; // OK - syntax trick

        testProtectedStatic = otherMC1.protectedStaticString; // OK - syntax trick
        testProtectedStatic = otherMC2.protectedStaticString; // OK - syntax trick

        testProtectedStatic = MyClass1.protectedStaticString; // OK - you can access protected static members from superclass
        testProtectedStatic = MyClass2.protectedStaticString; // OK - this also static member of your class
    }

}
但实际编译成字节码的是:

MyClass mc = new MyClass();
Object o = mc.STATIC_FIELD;
以这种方式访问静态成员被认为是不好的做法,因为它具有误导性。您应该始终以静态方式访问静态成员,以避免在读取代码时出现混淆


这就是你的情况。静态字段是以非静态方式访问的,所以它看起来像实例字段。删除静态修改器后,它将成为实例成员。访问此字段的方式已更改,但您没有注意到,这是因为您的object.staticField语法。

它与是否为静态字段无关。您可以访问该成员,因为MyClass2扩展了MyClass1

它与它是否为静态无关。您可以访问该成员,因为MyClass2扩展了MyClass1,正如前面指出的,static与可见性无关

在您的例子中,“str”被标记为protected,这意味着有两种类型的类可以看到它: -同一包中的类 -扩展MyClass1的类


您的代码之所以有效,是因为MyClass2扩展了MyClass1。

正如前面指出的,静态与可见性无关

在您的例子中,“str”被标记为protected,这意味着有两种类型的类可以看到它: -同一包中的类 -扩展MyClass1的类


您的代码之所以有效,是因为MyClass2扩展了MyClass1。

这里有一条有趣的规则:您可以访问在超类中定义的受保护实例变量,但不能访问该类的子类中具有私有实例变量的私有实例变量。e、 g

MyClass mc = new MyClass();
Object o = MyClass.STATIC_FIELD;
但是,如果使用了以下内容,则允许:

public class Super {
   private String str;
}

public class Sub extends Super {
    public void getStr(){
        return str; // not allowed.
    }
}

这里有一条有趣的规则:您可以访问在超类中定义的受保护的实例变量,但不能使用私有实例变量访问该类的子类中的私有实例变量。e、 g

MyClass mc = new MyClass();
Object o = MyClass.STATIC_FIELD;
但是,如果使用了以下内容,则允许:

public class Super {
   private String str;
}

public class Sub extends Super {
    public void getStr(){
        return str; // not allowed.
    }
}
  • public
    表示它对所有类都可见
  • protected
    表示包和所有子类都可以看到它
  • (无修改器)表示它仅对包可见
  • private
    表示它只在自己的类中可见
有关更多信息,请参阅。

  • public
    表示它对所有类都可见
  • protected
    表示包和所有子类都可以看到它
  • (无修改器)表示它仅对包可见
  • private
    表示它只在自己的类中可见

有关更多信息,请参阅。

没错,我刚刚注意到了这一点,并编辑了答案。您可以通过继承从不同的包中访问。谢谢您的回答。但是,如果只保护字符串str,为什么它不起作用呢?我仍然在从子类访问它。对不起,我不明白什么对你有效,什么对你无效。你能举个例子,告诉我你犯了什么错误吗?对不起,我没说清楚。上面的代码编译得很好。但是,如果我将字符串ss的访问修饰符从“static protected”更改为“protected”,我会得到一个编译时错误:str在MyClass1 System.out.println(mc1.str)中具有受保护的访问权限^没错,我刚刚注意到了这一点,我编辑了答案。你可以通过继承从不同的包访问。谢谢你的答案。但是,如果只保护字符串str,为什么它不起作用呢?我仍然在从子类访问它。对不起,我不明白什么对你有效,什么对你无效。你能举个例子,告诉我