关于一道J@Whiz1.4的经典问题的说明

探讨Java中父类私有方法在子类中的调用行为,解释为什么父类私有方法不会触发多态特性,并通过示例说明父类final方法和私有方法的区别。

问题的提出:

 class Parent {       

       private void method1() {

              System.out.println("Parent's method1()");

        }

        public void method2() {

                System.out.println("Parent's method2()");

                method1();           // ①

        }

}

class Child extends Parent {

        public void method1() {

                System.out.println("Child's method1()");

        }

        public static void main(String args[]){

                Parent p = new Child();             // ②

                p.method2();        // ③

        }

在②处声明了一个Parent类型的引用p,它指向一个Child对象;通常来说,p应该具有后绑定功能。③处调用method2(),这个method2()肯定是指从Parent类继承而来的method2()

 但问题是Parent类的method2()中,调用了method1(),这个method1()是谁的?Parent的,还是Child的?

 看起来挺难判断的,但结果是调用了Parentmethod1()?也许会问method1()不是Parent的一个私有成员吗?Child对象怎么能调用呢?

 请先看下面的例子,将得到解答——

例子一:

 

class Base5 {

       protected void doStuff1() {

              System.out.println("Base-doStuff1");

       }

       final void doStuff2() {

              System.out.println("Base-doStuff2");

       }

}

 

class Child5 extends Base5 {

       protected void doStuff1() {

              System.out.println("Child-doStuff1");

       }

       protected void doStuff2() {               // ④

              System.out.println("Child-doStuff2");

       }

      

       public static void main(String[] args) {

              Base5 c = new Child5();    

              c.doStuff1();

              c.doStuff2();        

       }

}

 

 

编译结果如下:

 

D:/JavaEx/scjp/tst/tst18.java:14: doStuff2() in Child5 cannot override doStuff2() in Base5; overridden method is final

       protected void doStuff2() {

                       ^

1 error

 

 

由于Base5doStuff2()final的,所以④处Child5无法重写doStuff2(),因此也就不会有后绑定的多态。亦即:父类中final的方法不支持后绑定的多态。

 

 

 

 

 

例子二:

 

class Base5 {

       protected void doStuff1() {

              System.out.println("Base-doStuff1");

       }

       private void doStuff2() {

              System.out.println("Base-doStuff2");

       }

}

 

class Child5 extends Base5 {

       protected void doStuff1() {

              System.out.println("Child-doStuff1");

       }

       protected void doStuff2() {

              System.out.println("Child-doStuff2");

       }

      

       public static void main(String[] args) {

              Base5 c = new Child5();

              c.doStuff1();

              c.doStuff2();

       }

}

 

 

编译结果如下:

 

D:/JavaEx/scjp/tst/tst18.java:21: doStuff2() has private access in Base5

              c.doStuff2();

                 ^

1 error

 

 因为是私有成员,所以c.doStuff2()会产生错误,但更重要的是private就相当于final,父类中的final方法不支持后绑定,则private也是如此。亦即:父类中private的方法不支持后绑定的多态。

只有一步之遥

离解答问题只有一步之遥,还得补充一个基本常识。类的成员方法不论是否接受参数,它其实都隐含地接受了一个参数,即this

 

何谓this?由《Thinking in Java3rd Edition)》中:this是对当前对象的一个引用。

 

 

 

回到最初的问题:

 

class Parent {       

        private void method1() {

                System.out.println("Parent's method1()");

        }

        public void method2() {

                System.out.println("Parent's method2()");

                method1();           // ⑤

        }

}

class Child extends Parent {

        public void method1() {

                System.out.println("Child's method1()");

        }

        public static void main(String args[]){

                Parent p = new Child();

                p.method2();

        }

}

 由上一段补充的知识可知⑤处实际上是:

this.method1();

根据例子一和二可知,父类中private的方法不支持后绑定多态,因此它严格按照引用的类型来调用对应的方法,因此它调用Parent的method1()

当把Parent的method1()前的private换成public/protected/friendly(默认),则后绑定将顺利完成,自动调用Childmethod1()

 总结

父类中final的方法在子类中无法被重写,因此不会有后绑定多态的问题。

 父类中private的方法类似于final,虽然可以被重新定义,但不是重写。

 当出现父类中含有private的方法的后绑定多态问题时,非private方法依然可以根据后绑定对象的实际情况,实时调用对应的方法;而private的方法,不支持此特性,它只根据调用它的引用类型来确定需要调用的方法。

原文地址:http://lslling.blogchina.com/1717345.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值