class A
{
public void fun1()
{
    func2();
}
private void fun2()
{
    System.out.println("This is A::fun2()");
}
}class B extends A
{private void fun2()
{
    System.out.println("This is B::fun2()");
}
}main()
{
    B b = new B();
    b.func1();
}请问,为什么会B实例的func1会调用A的func2呢???
Java的多态到底怎么回事???
如果我想重写func2,而使得func1调用我重写的func2,该如何做?

解决方案 »

  1.   

    还有,我希望func2有个默认实现,如果我不重写的话,它就用默认的实现。
      

  2.   

    这个不是多态,是 override你既然自己实现了 fun2 为何要调用以前的呢?super.fun2() 可以调用,不过必须在 B 里面。 而你的 func1 在 A里面
      

  3.   

    兄弟,这个不是基本的Template method模式吗???
    我重写了func2,但是我并没有重写func1啊
    我希望func1调用我重写的func1啊!!!
      

  4.   

    我希望func1调用我重写的func2,而不是它原来的func2!!!
      

  5.   

    这个程序在C++里给func2加个virtual肯定没问题
    Java里怎么做?
      

  6.   

    问题在于你的fun2()方法是private类型的,在父类的fun1方法中不能调用自类private类型的方法,所以导致只能调用自己的fun2你把fun方法声明的private该城public就可以了
      

  7.   

    protected行不?
    func1是接口方法好不好?func2没必要暴露给用户。如果public的话,接口岂不是变大了?
      

  8.   

    那你重写fun1不就实现了你想要的!
      

  9.   

    呵呵,protected可以,谢天谢地
    Java在面向对象方面还是不如C++方便啊
      

  10.   

    那你重写fun1不就实现了你想要的!
    ——兄弟,B要继承func1的实现啊重写当然可以,那不是多写了一份代码嘛,你可以看看template method模式!
      

  11.   

        你的fun2()就跟本没有被继承,因为A的fun2()是private,也就是说,B的fun2()是你新定义的一个方法,跟本就不是重写!
      

  12.   

    c++只能算半面向对象,你仔细考虑考虑,正因为java是纯面向对象,所以才会有这样的问题发生。
      

  13.   

    这个不是override,由于A类的fun2已经是private了,根本不能被B类继承过来,所以两个类中的fun2不存在override关系,就是两个独立的方法,
    如果是符合override的话那么用B的对象,也就是new B()一定可以调用到B中的fun2方法的。
      

  14.   

    c++只能算半面向对象,你仔细考虑考虑,正因为java是纯面向对象,所以才会有这样的问题发生。
    ——呵呵,纯/半面向对象???面向对象这个概念有确切概念吗?
    ——Java不能多重继承也很让人头疼
      

  15.   


    这个不是override,由于A类的fun2已经是private了,根本不能被B类继承过来,所以两个类中的fun2不存在override关系,就是两个独立的方法, 
    如果是符合override的话那么用B的对象,也就是new B()一定可以调用到B中的fun2方法的。
      

  16.   

    错了吧!
    override是只要你的访问权限更严格或相同都能覆盖吧!
    比如public f(){} 可以用private,protected,public,以及默认的权限覆盖;
        private f(){} 怎么只能由private覆盖;
      

  17.   

    恩,不错。不过我认为首先父类的方法对子类是要可见的才可以override,不然不可以的。
      

  18.   

    还有在override一个方法时候只能增大它的访问权限不能缩小
      

  19.   

    这是由于B实例已经继承了A类中的方法,所以可以直接用B类来调用A类中的方法,如果你想重写func2的话,那么你必须带有参数,只需在func1的方法中将里面的func2()换成func2(参数)就可以了,这样他调用的就是你写的func2了
      

  20.   

    package com.lou.test;import stu.Person;
    public class DBReader extends Person
    {
        private void a()
        {

        }
    }package stu; 
    public class Person{   
        static int i; 
        public static void main(String[] args) 
        { 
         
        }
        void a()
        {

        }
    }建议看下这2段代码,为什么在类DBReader 中可以把方法a声明为private的呢?如果为override那么应该不能够缩小访问权限的。
    正是因为在Person类中a方法为默认级别对不同包中的类DBReader 是不可见的,所以这个时候编译器把DBReader 中的a方法当作一个新的方法,
    根本不是override,这样才可以把DBReader 中的方法a()生命为private
      

  21.   

    方法不应该是归某个对象拥有的吧!是类里面公有的,当你new一个新对象出来的时候只是把他指向方法的地址(对这个地址的访问应该没问题)放进该对象的一个空间里(这个空间应该不是private).你所说的private应该是针对的变量(不包括覆盖)?
    而且方法的覆盖也是在内存中的一个空间里重新写,并没有真正覆盖原来的那个方法;所以他只是改变了那个地址.
    class A 

    public void fun1() 

        func2(); 

    private void fun2() 

        System.out.println("This is A::fun2()"); 

    } class B extends A 
    { private void fun2() 

        System.out.println("This is B::fun2()"); 

    } main() 

        B b = new B();     //这里应该是改变了超类里面的那个地址?
        b.func1(); 

      

  22.   

    你在好好看下。我的意思是说,如果编译器认为这个是方法a为override那么父类中的为默认访问权限,而子类该为private肯定会报错的,
    之所以没有错误就是因为编译器认为这个方法不能构成重载。
      

  23.   

    对不起是说反了,但是在书上才找到一个列子
    class Parent{
      int a;
      private int g(int a,int b){
      ...
      }
    }
    class Child extends Parent{
      int a;
      int b;
      public int g(int a,int b){          //增大访问权限的覆盖,(按你说的,这个也是新定义的?)
      ...
    }
    }
      

  24.   

    嘿嘿,我承认我刚才说的那个权限范围错了,但没说lz的那个题我搞错了,
    访问控制符可以使用与超类相同或比超类权限更大的控制符
    class Parent{ 
      int a; 
      private int g(int a,int b){ 
      ... 
      } 

    class Child extends Parent{ 
      int a; 
      int b; 
      public int g(int a,int b){          //增大访问权限的覆盖,(按你说的,这个也是新定义的?如果改成private也应该是相同道理,只是权限没变化) 
      ... 

    }
      

  25.   

    package com.lou.test;  import stu.Person;  
    public class DBReader extends Person  
    {  
        private void a()  
        {      }  
    }  package stu;   
    public class Person{     
        static int i;   
        public static void main(String[] args)   
        {   
           
        }  
        void a()  
        {      }  
    }  
    呵呵。你的那个例子同属于一个包里面看不出来什么的。还是让你看看我的这个代码,由于父类与子子类处于不同的包中,所以父类Person 中的a()方法
    对于子类DBReader不可见,这个时候子类的a()方法你说还是override吗?如果是就不能声明为private,缩小了权限,同理,也就是说,对于子类不可见的
    父类中的方法,子类中就不能override,只不过,如果父类为private了,子类没办法再缩小权限,如果可以缩小权限也一定不会报错误,因为不是override
      

  26.   

    我知道权限范围不能缩小了,谢谢,但你也要看清楚我在上面写出的那个列子,不是缩小范围了,现在也不是说的那个问题而是讲的lz那个,我认为子类里面的private不用改也应该是覆盖。而且反驳那些说是新定义的朋友。
      

  27.   

    "loujianchengdd "想下还真觉得你说的有道理,但我查了几本书,都说这个属于覆盖,脑袋疼....
      

  28.   

    想明白点了
    覆盖一个方法应该不需要访问它,也没有提到要访问它,我认为不应该对它是否可见进行讨论.用private尽是代表其他类不能访问.
    覆盖的定义:子类拥有与超类相同成员的情况.(并没说是否可见,这个就可以否认可见后才能override,同一个包中的的任何类都可以访问你定义在另一个类中的public和默认访问控制符的方法,所以才用private进行修饰,拒绝其他类访问.)
    一个要求:访问控制符可以使用与超类相同或比超类权限更大的控制符 .
    呵呵,终于明白了,应该这样是对的.
    请提出自己的想法.
      

  29.   

    package com.lou.test;   import stu.Person;   
    public class DBReader extends Person   
    {   
        private void a()   
        {       }   
    }   package stu;    
    public class Person{      
        static int i;    
        public static void main(String[] args)    
        {    
            
        }   
        void a()   
        {       }   
    }   呵呵,那你说我的这个代码怎么解释呢?既然编译器没有报错,就应该不是覆盖,因为明显已经缩小了方法a()的访问权限
      

  30.   

    钻牛角尖你想允许一个成员重写 又不想被外界访问 那就PROTECTED父类既然用PRIVATE 修饰了一个成员 就明确了 这个成员 不想受到外界干扰 外界不需要根本也不能了解
    按LZ的想法 如果别人写B继承你的A 是不是一定要看你的A类设计的源代码 不然他有什么途径知道A里有个 PRIVATE FUNC2() 成员?如果一个成员允许子类重写 干吗要PRIVATE?如果PRIVATE了还可以重写 那还要 PROTECTED干吗?给出这么多修饰符就是为了 完成不同的目的 不要自己和自己搞脑子JAVA 不能多重继承 那就实现多接口  模拟多重继承
      

  31.   

    回过头在看楼主的那个程序,调用fun1()方法的分明是子类对象,那么为什么也就是说在fun1()中调用fun2()方法的也是子类对象,为什么子类对象调用的却是父类的那个方法fun2()方法呢。就是因为JVM在fun1()中调用fun2()的时候由于是用子类的对象调用的所以会先看子类中有没有对fun2()进行覆盖,如果没有就调用父类中的。所以这个根本不是覆盖。
      

  32.   

    回过头在看楼主的那个程序,调用fun1()方法的分明是子类对象,那么为什么也就是说在fun1()中调用fun2()方法的也是子类对象,为什么子类对象调用的却是父类的那个方法fun2()方法呢。就是因为JVM在fun1()中调用fun2()的时候由于是用子类的对象调用的所以会先看子类中有没有对fun2()进行覆盖,如果没有就调用父类中的。所以这个根本不是覆盖。
      

  33.   

    “你可以试试给父类定义一个子类可见的方法,然后在子类覆盖的时候缩小其访问权限,编译器就会报错。“
    这个我明白了。
    我知道覆盖是要继承来做前提,重载就不一定了,在一个类中就可以重载多个方法。
    现在是原归正传,说lz的问题。
    "这个不是override,由于A类的fun2已经是private了,根本不能被B类继承过来,所以两个类中的fun2不存在override关系,就是两个独立的方法, 
    如果是符合override的话那么用B的对象,也就是new B()一定可以调用到B中的fun2方法的。"
    我想你这句话,因为lz的代码中,并没有缩小访问控制符的范围.而且都满足定义和要求,我是围绕这个说的.你的看法现在如何?
      

  34.   

    呵呵,你理解的有问题啊。
    今天这个问题不让你明白我就不睡觉了。
    把楼主的代码放在eclipse里面,然后在子类中让eclipse自动生成父类的override方法,具体步骤
    在eclipse中点工具栏中的Source,然后点Override/Implements Methodes
    你看看让不让你选择覆盖父类中了私有方法。根本private方法就选择不了。
      

  35.   

    是嘛,不能覆盖,但是我改成
    class A 
    {  public void fun2() 

        System.out.println("This is A::fun2()"); 

    } public class C extends A 
    { public void fun2() 

        System.out.println("This is B::fun2()"); 

    public static void main(String[] args) 

        C b = new C(); 
        b.fun2();

    }
    同样也不让我覆盖?
      

  36.   

    重写难道就一定要访问吗?
    private是要引用的时候才有用,这个是我的看法,说了覆盖有用吗?
    现在我是坚持我的看法,明天去问问老师,再说我没钻牛角尖,
    我和宿舍的同学也在讨论虽然他是学c++的,但是也说,这个能覆盖,
      

  37.   

    我说了“同一个包中的的任何类都可以访问你定义在另一个类中的public和默认访问控制符的方法,所以才用private进行修饰,拒绝其他类访问.) 
    ”也是为了避免其他类的修改。private并不是针对覆盖的,是对引用而言。至于protected则是允许子类引用超类的成员,并非覆盖。
    知道内存空间的应该都知道尽管说的覆盖,但在存储空间中仍然是有超类和子类的方法的,并不是真的把超类的方法重写了。在new对象的时候是直接调用的他们的地址。
      

  38.   

    class A 

    public void fun1() 

        func2(); 

    private void fun2() 

        System.out.println("This is A::fun2()"); 

    } class B extends A 
    { private void fun2() 

        System.out.println("This is B::fun2()"); 

    } main() 

        B b = new B(); 
        b.func1(); 

      

  39.   

    func1那里有呀,还有你这样重写就是浪费时间,super就行,这样的做法没有任何意义
      

  40.   

    o !是Private 的,不是 override. 那就更不存在什么问题了!没有啥多态的问题!
      

  41.   

    类中所有的private方法都隐式指定为final,所以就算你在B类中写了fun2()方法但无法覆盖掉父类的fun2()方法你可以运行一下下面的代码对比一下结果,可能你就能理解了。。
    class A 

    public void fun1() 

        fun2(); 

    public  void fun2() 

        System.out.println("This is A::fun2()"); 

    } class B extends A 
    { public  void fun2() 

        System.out.println("This is B::fun2()"); 

    } class C 
    {  public static void main(String [] args )
     {
       B b=new B();
       b.fun1(); 
       b.fun2(); }
    }
      

  42.   

    代码一:
    class A 
    { private void fun2() 

        System.out.println("This is A::fun2()"); 
    }
    public void fun1(){
    fun2();

    } public class B extends A 
    { private void fun2() 

        System.out.println("This is B::fun2()"); 

    public static void main(String[] args) 

        B b = new B(); 
        b.fun2();
        A a = new B();
        a.fun1();

    }
    输出:
    This is B::fun2()
    This is A::fun2()
    代码二:
    class A 
    { public void fun2() 

        System.out.println("This is A::fun2()"); 
    }
    public void fun1(){
    fun2();

    } public class B extends A 
    { public void fun2() 

        System.out.println("This is B::fun2()"); 

    public static void main(String[] args) 

        B b = new B(); 
        b.fun2();
        A a = new B();
        a.fun1();

    }
    输出:
    This is B::fun2()
    This is B::fun2()
    不可覆盖正确,早知道如此简单就早点写这个,光靠理论是不行的呀!
    感谢lz的问题,感谢大家的指导.
      

  43.   

    这就是一个普通的程序而已,哪有什么重写之类的,重写的前提是要继承的,但看清了,访问修饰符是private
      

  44.   

    这么火了啊,
    楼主在你认为重写的方法前加个
    @Override
    看编译让你过不,就知道是不是重写了。
      

  45.   

    楼上正解,不过要用jdk1.5以上,因为只有1.5以上才支持Annotation
      

  46.   

    这不并不复盖,而是因为,你继承了A类,而你自身又实现了Fun2方法,所以在调用时针对的对象还是B的,所以他当然会调用自己的Fun2方法,如果你想在调用A类中的Fun2则你需要指名,或把他多态一下向下转形为A对象就可以调用A 类的Fun2或直接super也行 
      你去看看TIJ中的多态那章,讲的很明确
      

  47.   

    想重写func2,而使得func1调用我重写的func2   那就overide func1,在重写的funct1中调用 func2
      

  48.   

    class A
    {
    public void fun1()
    {
        func2();//B实例中的fun1()实际上还是调用了A中的fun2();
    }
    private void fun2()
    {
        System.out.println("This is A::fun2()");
    }
    }class B extends A
    {private void fun2()
    {
        System.out.println("This is B::fun2()");
    }
    }main()
    {
        B b = new B();
        b.func1();
    } 如果我想重写func2,而使得func1调用我重写的func2,该如何做?class A
    {
    public void fun1()
    {
        func2();
    }
    private void fun2()
    {
        System.out.println("This is A::fun2()");
    }
    }class B extends A
    {
    private void fun1()
    {
    this.func2();
    }private void fun2()
    {
        System.out.println("This is B::fun2()");
    }
    }main()
    {
        B b = new B();
        b.func1();
    } 不知道对不对,如果错了请指正。
      

  49.   

    斑竹....他要求的效果其实也算多态.但是也不是特别的明显.特别是当子类对象中间是直接包含父类方法还是通过包含父类对象来包含方法....这里我不是很了解呢
    相当于this.fun2
    不过写成私有的..就..哇哈哈..太失误了点
      

  50.   

    同意58楼的说法,楼主要调用B调用自己的func2,可以修改A中的func2的private关键字,实现重载,也可以修改B中的参数列表。实现多态.
      

  51.   

    给你个多态的例子
    http://topic.csdn.net/u/20070131/22/6ff91883-6903-471b-9cd1-22387d11af15.html
      

  52.   

    楼上很多正解  private的问题 访问不到的
    建议看看core java或者thinking in java
    讲解得很详细
      

  53.   

    派生类中的方法的访问属性应该与基类中的相应方法的相同,或者限制要少一些,不能有更多限制。就是说如果基类中的方法被声明为public,则派生类一定要是public.
      

  54.   

    好久没看,居然火了,呵呵。
    现在大概总结下:
    Java里的private方法不能被子类重写。
    这个是和C++不一样的一个地方。
    Java这个特点有些怪异:对于父类的private方法,运行时可以访问,设计时却不能重写呵呵。