A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 王小涛 初级黑马   /  2012-8-27 21:07  /  2601 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 王小涛 于 2012-8-27 21:11 编辑

请看下面这个测试代码,子类B是父类A的内部类。
问题1:经测试,程序运行中接连两次调用了父类A的构造函数,为什么?(求此种情形下对象创建的详细过程{:soso_e163:})
问题2 、问题3请见代码中的注释部分。
第一次发主题帖,没排好版,请见谅。
public class A
{          private int test = 1;  
           class B extends A
    {        
          public B(int test)       
               {            
                             System.out.println(super.test);//问题2:为什么此时允许在子类中访问父类的私有变量?而且只能用super访问吗?           
                             System.out.println(test);      
               }   
    }   
          public static void main(String[] args)
            {        
                 A b=new A().new B(3);
                System.out.println(b.test);//问题3:如何禁止子类对象“乔装”成父类而访问到了父类的私有变量呢?   
          }
}
先谢黑马!再谢各位师兄!

7 个回复

倒序浏览
程序运行中接连两次调用了父类A的构造函数
在语句中A b=new A().new B(3);  new A()的时候调用了A的构造函数,new B(3)的时候,由于B继承了A,所以会先调用A的构造函数,再调用B的构造函数。
问题2:为什么此时允许在子类中访问父类的私有变量?而且只能用super访问吗?     
因为类B定义在类A的内部,所以A的成员对类B来说是可见的,而不管变量是用什么修饰符。这里因为B类的构造函数参数名test跟A的变量test同名,所以只能用super访问A的变量test.     
问题3:如何禁止子类对象“乔装”成父类而访问到了父类的私有变量呢?
只要子类不是父类的内部类,就无法访问父类的私有变量。
回复 使用道具 举报
1,程序运行中接连两次调用了父类A的构造函数?
我觉得是因为第一次调用是:B是A的内部类,相当于A的成员,想要创建B的实例,首先要创建A的实例,所以要调用A的构造函数。也就是 A b=new A().new B(3);中的第一个new A()
第二次调用是:因为B继承了A,在对B进行实例化的时候也就是new B(3),B的构造函数第一行默认super(),对父类A的无参构造函数进行了调用。
问题2:为什么此时允许在子类中访问父类的私有变量?而且只能用super访问吗?
因为B类已经在A类的内部,相当于A的内部成员,而私有变量在类的内部可见,所以B可以通过super.test调用父类A的私有变量,存在继承关系只能通super调用;
问题3:如何禁止子类对象“乔装”成父类而访问到了父类的私有变量呢?
子类不是父类的内部类时,也就不能访问父类的私有成员了。
回复 使用道具 举报
梁志仲 发表于 2012-8-27 21:25
程序运行中接连两次调用了父类A的构造函数
在语句中A b=new A().new B(3);  new A()的时候调用了A的构造函 ...

谢谢你的解答啊,我还是有点小疑问
1,创建子类对象会调用一次父类的构造函数,这个我明白,疑问是直接创建内部类的对象的过程中,也会调用外部类的构造函数,那这个过程中,堆内存中是否存在外部类的对象?是否可以认为构造函数被调用N次就表示N个对象被创建了?
2,根据内部类的访问规则,用 A.this也行,疑问是 A.this 和super 这两种方式在此例中是否是完全一样的效果?
3,“可能是因为我把主函数定义在了A类中了。而当我把主函数单独封装在类C(与类A 类B无直接关系)中,即使用多态使父类A的引用指向内部子类B的对象,也不能再访问A的私有变量test了。”
疑问是上面引号中的说法有没有毛病?
谢谢啦{:3_64:}
回复 使用道具 举报
王自强 发表于 2012-8-28 00:57
1,程序运行中接连两次调用了父类A的构造函数?
我觉得是因为第一次调用是:B是A的内部类,相当于A的成员,想 ...

直接创建内部类B的实例,必须先创建外部类A的实例吗?{:3_66:}
回复 使用道具 举报
因为程序中你写的是A b=new A().new B(3);
这句话相当于 A a = new A(); A b = a.new B(3);创建了一个外部类对象,再创建了一个内部类对象,这个内部类在外部类的成员位置上,这个内部类属于外部内对象(一个实例)的成员。
public class Outer {
   
public class Inner{
        
    }
   
void f(){
        
new Inner();//此处不用创建外部类实例就能创建内部类实例,因为相当于在外部类的内部调用外部类的成员一样。内部类在外部类的成员位置上。
    }
   
static void g(){
        
//在静态方法中也要先创建外部类实例才能创建内部类的实例,因为静态不能访问非静态,只能在静态中创建外部类实例再创建内部类实例。
        
        Outer.Inner in
= new Outer().new Inner();
    }
}

回复 使用道具 举报
不确定楼上两位回答是否准确,但让我对内部子类理解更深刻了一些,十分感谢,
希望版主给点技术分鼓励一下。
鉴于这么久一直没人给出更权威的回答,
我担心迟迟不解决会被扣分,就自行搜索了一些资料,
问题已经解决。
回复 使用道具 举报
这多人发帖   不凑热闹了!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马