乐趣区

java的publicprotectedprivate修饰符

前言

我以为程序是严谨的——沿着一个流程图一步一步走下去,那么结果就会自然地呈现出来——这是程序的一种美。

java 作为优秀的程序设计与开发语言,判断一个被 java 修饰符修饰的方法,变量,也应该有这样的美。

学习了网上各种各样的文章,我觉得这一流程可以表述为:

接下来细化流程图中我的一些表达。

同时为了简化表达,之后提及我们讨论的东西,即被修饰符修饰的方法 / 成员时,均使用“课题”一词。

同时修饰符修饰的对象可能是方法,也可能是成员变量。本文不单独讨论成员变量,因为按流程图判断为允许(调用),对于成员变量来说也就是允许(读写)。


正文

0. 内调用和实例调用

内调用:形如 this.method() 为内调用,显然,this通常情况下可以省略。同时对方法的重写也归于此类。
实例调用:课题所属的类的实例变量调用课题即文中说的实例调用。若是静态方法无实例直接调用,亦归属此类。强调:此处的实例变量是课题所属的类的,而不能是课题所属的类的任一子类的。

1. 本类内调用

任意的课题(“课题”一词的含义请见前言段落的最后一段)显然是在一个类(接口)中的。这个类除了我们讨论的东西外,还可能有其它的方法。而在其它的方法中调用课题,就是我这里说的“类内调用”。

代码举例:

package packetA;

public class ParentA {private void privateMethod(){System.out.println("privatedMethod");
    }

    public void test(){privateMethod();
    }
}

在方法 test 中对 privateMethod 方法的调用,即所谓类内调用。

=

2. 子类重写

即通过 extends 关键字,继承课题的类即这里的子类。

重写:对父类的方法的实现过程进行重新编写, 返回值和形参都不能改变。

代码示例:

package packetA;

public class ChildA extends ParentA {

    @Override
    protected void protectedMethod() {System.out.println("childA has overridden the protectedMethod.");
    }
}

3. 子类内调用

代码示例:

package packetA;

public class ChildA extends ParentA {public void test(){this.protectedMethod();
    }
}

4. 本类内部实例调用

代码示例:

package packetA;

public class ParentA {private void privateMethod(){System.out.println("privatedMethod");
    }

    protected void protectedMethod(){System.out.println("protectedMethod");
    }

    public void test(){ParentA parentA = new ParentA();
        parentA.privateMethod();}
}

其中

public void test(){ParentA parentA = new ParentA();
    parentA.privateMethod();}

这样先实例化一个实体后,在由这个实体调用方法的,就是本文说的“……实例调用”。

5. 同包下实例调用

在课题所在的类中实例调用显然也是同包下的实例调用,但这个情况并不会走到这个判断步骤来,会在“4. 本类内部实例调用”时走“是”而到达允许的终结状态。

是的,只要在相同的包下,或者在课题所在的类所在的包的子包下,不论是怎样的类——是课题所在类的子类?与课题所在类无关的类?无所谓——都能正常调用不是 private 修饰符修饰的课题。

如:

package packetA;

public class ParentA {private void privateMethod() {System.out.println("privatedMethod");
    }

    protected void protectedMethod() {System.out.println("protectedMethod");
    }

}
package packetA;

public class DemoA {public static void main(String[] args) {ParentA parentA = new ParentA();
        parentA.protectedMethod();}
}

能够正常运行。

6. 其它一切实例调用

是的,除开上述情况的其它一切实例调用,只要不是用 public 修饰符修饰的课题,全部拒绝。

即便是包外部的子类内调用 protected 修饰的课题(代码如下),也同样禁止。

package packetB;

import packetA.ParentA;

public class GreenhatChild extends ParentA {public void test(){ParentA parentA = new ParentA();
        parentA.protectedMethod();}
}

test方法是无法被运行的,不论是单元测试还是在主函数中示例一个 GreenhatChild 类再调用 test 方法。

退出移动版