关于java修饰符,以前总让我犯糊涂,今天来个大总结希望能给初学者提供点来帮助。
四点基础介绍
1.public: 这个好理解 他能修饰类,属性,方法,并且被修饰的对象什么地方都能被访问到
2.protected: 首先他只能修饰属性和方法(当然也可以修饰内部类,但这里不对内部类进行讲解,这里的类都是顶层类,下同)。被他修饰的对象在同一个包里都可以访问,如果在不同包,必须要通过其子类进行访问。
3.default:(也就是什么都不填) 默认的,被他修饰的对象在同一个包里都可以访问,与protected相比,他是完全不能从包外进行访问,而protected还可以通过其子类在包外进行访问.
4.private:访问权限最低,只能在自身类内.但这里要注意一点哦,来自同一个类的实例可以相互访问类中声明的属性,这个不好理解吧,那就接着看吧
解惑1: 来自同一个类的实例可以相互访问类中声明的属性
这个说不清楚,先看一段代码吧,先别COPY and run,先自己想下结果会是什么:
- package com.sr178.test;
- public class TestExample {
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- AClass ref1 = new AClass(5);
- AClass ref2 = new AClass(10);
- //System.out.println(ref2.x);
- System.out.println(ref1.add(ref2));
- }
- }
- class AClass{
- private int x;
- public AClass(int x){
- this.x = x;
- }
- int add(AClass ref){
- return ref.x+x;
- }
- }
- //class SubAClass extends AClass{
- // SubAClass(int x){
- // super(x);
- // }
- // int add(AClass ref){
- // return ref.x+x;
- // }
- //}
先别管注释的那几行,知道答案了吗?我想大部分人都会认为这个程序会报错.但不巧,运行后却出来一个结果15,好好体会吧.
解惑2: 关于protected的
问题描述:
第一个包中我建了个父类A,其中有一个protected修饰的属性b.
然后在第二个包中建了一个类B继承了A.
这个时候我用父类引用子类对象时,也就是A x = new B();时,对象属性x.b却访问不到.
但是直接用子类的引用实现子类对象时,即B x = new B();x.b是可以访问的.
注意哦!两个类不再同一个包中.
- package com.sr178.test;
- public class A{
- protected String b="I am A";
- }
- package com.sr178.AnotherTest;
- public class B extends A{
- protected String b ="I am B";
- public static void main(String args[]){
- A x= new B();
- System.out.println(x.b);
- }
- }
到这里程序是编译不过去的,在解释这个问题前,先来解释下 A x= new B();以下是一段摘文。
看到这里,应该明白A x= new B()了吧,因为x定义为A类型,那么编译时候就认为x是A类型的(x是一个存放类A的对象地址的引用型变量),他跟x的实际类型没有关系. 在解释这个问题上,你把A x= new B()看成A x = new A();别看那个后面的new B();这就好理解了,显然A x = new A();然后x.b会出错,因为在不同包中嘛.要改成B x = new B();才可以访问,因为如果在不同包,被protected修饰的属性或方法必须要通过其子类进行访问。
疑惑三:关于静态方法
- package com.sr178.test;
- public class StaticTest {
- public void myExample(){
- System.out.println("Father Class Method myExample");
- }
- public static void myStat(){
- System.out.println("Father Class Method static Method myStat");
- }
- /**
- * @param args
- */
- }
- class SubClass extends StaticTest{
- public void myExample(){
- System.out.println("Sub Class Method myExample");
- }
- public static void myStat(){
- System.out.println("Sub Class Method static Method myStat");
- }
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- StaticTest s = new SubClass();
- s.myExample();
- s.myStat();
- }
- }
运行结果:
Sub Class Method myExample
Father Class Method static Method myStat
此处因为调用的静态方法myStat()是在编译期间就根据其声明类型决定了引用的方式,s是一个StaticTest类型,当然当调用s.myStat()时,就会调用父类的myStat(),而s.myExample()会调用子类的myExample()方法(这个不理解请参照上个疑惑).