java的四种访问控制级别对于成员的可见性的整理

来源:互联网 发布:倩女幽魂游戏mac版 编辑:程序博客网 时间:2024/06/08 05:31

        由于最近要考一个scjp的认证,关于这个认证我就不多说了,相信大家都知道,有人说有了这个认证的话工资会比没有的高出30%左右,不知道这是不是真的。但是不管怎么样考一下还是挺好的,最起码会知道一些以前从来不知道的关于java语言的一些细节性的东西。在看官方推荐的那本考试教材之前我自认为对java掌握的还不错,没想到刚看完第一章就发现自己原来还有这么多不懂(或者说不知道)的地方,真是什么时候都不能有自大的心理啊,还是老老实实从头开始学吧。

        以下是我对自己最近学习的成果的一些整理,这次主要介绍java四种访问控制符的用法及使用场合,其中有什么不合适的地方请帮我指出来,互相学习。

下面进入正题,我们都知道java有四种访问控制级别即公共的、私有的、受保护的、默认的(包级访问),对应3个访问控制修饰符public、private、protected(对于默认的来说即是没有任何访问控制修饰符的修饰,

比如

int x = 1;

此时我们就说变量x是默认访问控制级别)。如果读者觉得下面的介绍太过啰嗦或自己对这四种访问控制级别只是有一些不理解的地方,可以直接跳到最后看最后的总结

下面我从这四种访问控制级别由简单到复杂分别介绍

     首先是public即公共的访问控制级别,这个比较简单,公共即是公开的,面向大众的。所以由public修饰的类成员,不管是从同一个类、同一个包中的任何其它类、同一个包中的子类、包外子类还是包外的任何非子类来说,其都是可见的(注意这里说的可见的前提是这两个类之间是可见的,如果连类之间都是不可见的话,那么无论他们的成员是何种访问修饰符修饰都是不可见的),这个比较简单,就不写例子说明了,记住public成员无论在什么地方都是可以访问的就行了

        第二个是private即私有的访问控制级别,对于私有的来说也比较简单,一句话概括就是类的私有成员只在本类中可以访问,对于本类之外的其它类都是不可见的,为便于理解下面我举一个例子进行说明:

 

public class  Father{private int age;public void test(){this.age = 1;              System.out.println(age);}private void outPrint(){System.out.println("这是一个测试方法" );}}class FooTest {public static void main(String args[]){Father foo = new Father();foo.age = 3;  //compile error}}class Son extends Father{public void test(){age = 1;   //compile error}public void outPrint(){System.out.println("test the function");}}

对于上面的Father类来说,其age成员是私有的,当在FooTest中通过Father的实例foo访问age时就会产生编译错误;而对于Fther的子类Son来说,Father的私有成员age并不能被Son继承(对私有方法来说也是如此),
因此当在Son类的test方法中访问age时便会产生编译错误,在这需要注意的一点是在子类中可以声明和父类私有方法相同的方法,但此时子类中方法绝不是对父类方法的重写,就像上面Son类中的outPrint()方法那样,此时outPrint()方法并不是对其父类方法的重写 

这第三个就是默认的访问控制级别(受保护的访问控制级别最复杂,因此放到最后来说),对于这类访问控制级别也可以理解为包级访问控制级别,即该类类成员只对于同一个包中的其它类可见,而对于包外的任何类无论是子类(这是其与受保护成员的唯一区别)还是其他的类都是不可见的

package dir;public class Foo {int x;void test(){}}import dir.Foo;class MyFoo extends Foo{public void test(){x=2;  //compile error Foo foo = new Foo();foo.x = 4; //compile error}}

就像上面那样,由于MyFoo类和Foo类处于不同的包下,所以在MyFoo类中无论试图直接访问Foo类的实例变量x还是通过Foo类的实例访问都会产生编译期错误(即使MyFoo是Foo类的子类也不例外),即使x成员是静态的也是如此

最后一个就是protected修饰的成员,也是最复杂的,就像在上面默认访问控制级别那提到的一样对于其他方面和默认的访问控制级别没有什么差别,唯独有区别的是对于在不同包下的子类的访问限制,此时子类通过继承可以访问父类的受保护的成员,而对于该子类的不同包下的子类依然如此(即同样可以通过继承访问),但是对于和该子类位于同一包下的其它类(非继承类)来说该成员仍然是不可访问的,即仍然无法通过该子类的实例进行访问。说了这么多可能有点晕,我当时就是这样,看到这里都被绕晕了,下面我仍然用一个例子来说明这种情况:

package son;public class Son {protected int x;}import son.Son;public class Parent extends Son{public void test(){x = 5;  //通过继承访问 it's ok//通过父类的实例访问,此时会产生编译错误Son son = new Son();son.x = 5;}}
如上所示在son.x=5处会产生如下的编译错误

---------- 编译java程序 ----------Parent.java:9: x 可以在 son.Son 中访问 protectedson.x = 5;   ^1 错误输出完成 (耗时 0 秒) - 正常终止


到此我们已经说完了四种类成员访问控制级别的的可见性,下面我用一个表格总结一下上面的各种情况下类成员的访问组合


可见性

public

protected

默认

Private

从同一个类

从同一个包中的其他任何类

从同一个包中的子类

从同一个包外的子类

是(通过继承)

从包外的任何非子类的类



转载请注明出处,谢谢




 

原创粉丝点击