由类的private成员引发的思考

  昨天晚上在寝室上网,突然同事问了我一个问题:在C#中,在一个类A的成员函数里,new 自己的实例,然后居然可以访问这个实例的private成员变量,他觉得这个两个实例不是都应该被完好封装吗,怎么一个实例里面能访问另一个类实例的private呢?说的有点抽象,代码是这样的:
  class  A
{
      private int i;
      publice void get()
      {
           A  a = new A(); 
           System.out.println( a.i); 
       }
      public static void main(String args[])
      {
           A a = new A();
            a.get();
      }
}
        初看起来感觉确实是main方法中的a通过get方法访问了get中动态new出来的a的private成员,似乎说的有那么一点道理。我马上用C++试了一下,结果还是一样的,这其中的原因应该都差不多。我一时也说不出个所以然来。但是冥冥之中,感觉这确实是可行的并且是合理的,因为get本身是在类的内部,他当然可以看见自己的所有成员了。话又说回来了,这明明是不同的实例啊。
       后来我想了一个很牵强的理由,在类还没有构造完成之前,所有的封装机制、继承机制以及多态、虚函数等都是不能成立的,也就是说在类的内部,类本身还没构造完成,所以其private机制不能生效,所以是能看到其他实例的private成员的。这个理由我自己都不是很信服。
       在开发人员看来,这确实是合理的。因为封装本来就是不希望别人随便访问或者修改类的成员,而且类本身的开发者当然能够随便改变类的成员了, 所以在一个类的内部,应该而且必须能够看到任何同类型的实例的所有成员啊。这个解释似乎还可以,但是仍不具备很好的说服力。
       同事跟我说过,在java中的反射机制很厉害,可以通过反射找出java的弱泛型或者伪泛型的真面目。当场就给我演示了一遍。他先是定义了一个List<String>,理论上或者一般的方法上这个list应该只能存放String对象,但是通过反射的invoke方法,居然他能把任何类型的对象(比如Integer、Boolean等)放入了list中,所以说java没有真正意义上的泛型,java的泛型只是做给编译器看的。对于这点,我对C++还是蛮有信心的,因为C++支持真正意义上的泛型。对于刚才的问题,同事说他同样可以通过这种反射机制访问到任意对象的private成员!所以java中的权限控制也是做给编译器看的。对java了解不深入的我,感觉有点不可思议。这好像颠覆了面向对象的设计初衷。我纳闷了,既然使用了private这种访问控制权限,为何还要允许反射机制来破坏这个控制权限呢?在C++中,这种是绝对被禁止的,只有一种渠道访问private成员,那就是友元。C++的友元就是为了实现这种功能而存在的,而java的反射应该不仅仅于此吧?
      无论java的这种设计是不是故意而为之,我觉得都需要反思。这也是C#出于java高于java的缘故。
       有点跑题了。回到刚才的问题,我昨晚半夜醒来,突然有了一个想法。 在类的所有非static方法中,其实都有一个默认的参数this指针,指向这个类实例,我们可以在这些成员函数中任意访问类的所有成员,就是得益于这个this指针。我们现在换个角度思考刚才的问题,即不在方法中new新的实例,而是在函数参数中传入这个新的实例,我想这两种效果是一样的。代码如下:
 
  publice void get(default param A this, A a)
      {
          // A  a = new A(); 
           System.out.println( a.i); 
       }
如果能解释这个方法 中为何可以访问a的private成员,那么刚才的问题也就是同样的答案了。想到这,答案就呼之欲出了。既然this指针能随意访问类的所有成员,为什么同类型的a不能访问呢?在底层看来,this和a都同样是class A的一个指针而已,并没有本质的区别,编译器和执行器对这两个指针是平等对待的。我很相信这个解释是对的,可以愉快的睡着了~~

       今天早上吃早饭的时候,跟同事又重新讨论这个问题,我说了我的想法,他也表示这个解释很有道理,哈哈,太好了。 

       纯属个人理解,如有偏差或错误,希望指正!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值