java继承机制本质的思考

      从C++初入JAVA,地址没有了指针没有了,用起来方便了,但是对于我这种想知其所以然的人就很纠结了。今天来讨论个关于继承的问题,说说我的观点,如果说的不对,特别特别特别希望有人来指正。谢谢!

      关于java继承,在书本上我们大多看到的都是讲一些特性和表象,大概也就是通过继承,子类能获得父类的属性和方法,根据访问权限的不同,不同包间的继承只能访问public和protected的,同包的可以访问包访问权限的,但是都不能访问private的成员。

      然而爱思考的人总是会问,private成员不能访问到底是继承了但没有权限呢?还是压根就没有继承呢?在网上简单搜索搜索就会发现,无论是论坛博客,甚至一些教学视频里,都会有人明确的选择其中一种解释来告诉你,每个人的回答都挺明确,挺肯定,但就是说什么的都有,所以实时到底是什么呢?我觉得可以换一个角度来思考,从表象上来讲,可以认为说的都对,毕竟这个知识点可以看做是个“接口”,怎么理解都基本不影响使用的。但是里面封装的内在,也就是继承到底是如何体现的呢,我通过看博客(当然答案各不相同,没有一个能让人信服的),翻阅Think in java,加上个人思考和代码实验的结果认为,继承,简单讲(一把奥卡姆剃刀快刀斩乱麻),讨论的是能不能访问的问题,而不是存不存在的问题,继承其实是访问权限的一层外衣,当用extends了另一个类之后,在存在的问题上,子类已经有用了父类的一切,但是却并不都能访问。对于可以访问的部分,还有this和super进行了区分。如果子类没有重新定义和父类中已由的域或方法,那每个域和方法只有一份,这时你用this和super访问到的是同一个对象的时候,就是子类中包含的父类子对象对应的部分,如果指向的是不同对象,那就是子类自己重写了或者新增加的,这也可以捎带解释了“构造函数不能被继承”这个说法,毕竟任何类,任何子类,都必须有自己的构造函数,哪怕自己不写,系统也会帮你写一个默认的无参构造函数的,所以你的this只能指向自己本类的构造函数,你用this是访问不到父类的构造函数的,所以这就是没有继承。而至于private的域或方法,是属于无权访问的部分,即this和super都不能访问,无论是各门各派说的“没有继承”,还是“继承了但是没有权限访问”,其实就是不能访问父类的private成员而已,如果非要二选一,我倾向于是没有继承的说法,毕竟继承了却访问不到,为何要做这么毫无意义的事情呢,但这也只是个名头而已,并不代表在子类中不存在,当new一个子类时调用子类构造函数,子类构造函数又调用父类构造函数,开辟了一段内存空间,在这份空间中,其父类的private成员肯定是真实存在的,他的存在是因为new了一个子类,所以才创建的它,所以应当理解为这个成员属于新建的子类的,是因它而生的,只是访问不到而已,但可以通过setter或者getter方法得到,这也证明了private对象的存在;有人用可以通过getter得到来证明子类是继承到了private成员的,用getter方法返回的是子类继承来的private成员,对他们来说好像子类成员的private成员和父类的被继承private成员不是一个一样。其实就是同一个,也就是说在继承关系中,new子类时内存里只可能有一份父类private的成员,因为子类无法重写父类private成员。至于网上有人问继承的时候是否创建了父类的对象呢,有人说没有创建,这显然是不对的,创建子类是要调用父类构造函数的,调用构造函数是要分配空间的,父类对象应当是创建了的,并且无论是在子类中新定义的域和方法,还是父类中定义的域和方法,在内存中能够真实分配空间都是因为实例化了一个新的子类,只不过是由父类定义的那部分成员所对应的内存,多了一个super访问的途径,以及特殊的访问权限。另外Thinking in java中是这样说的:

When you create an object of the derived class, it contains within it a subobject of the 
base class. This subobject is the same as if you had created an object of the base class by 
itself. It’s just that from the outside, the subobject of the base class is wrapped within 
the derived-class object.

     也就是说通过子类构造器调用父类构造器和直接用父类创建一个父类对象时一样的,只是这个父类对象被包含在了子类对象中,且这部分代码是通过super来访问的,this能否访问以及能否用super访问,则取决于访问权限和成员是否被覆盖或重写,那样的话this就不会指向父类对象创建的成员了。

废话这么多,也来一点代码,网上总是举子类覆盖屏蔽父类的例子,来看一个没有覆盖的例子:

class A{
	I i=new I();
	I get(){return i;}
}
class I{}
public class B extends A
{
	//I i=new I();
	
	//I get(){return i;}
	void print(){
		System.out.println(System.identityHashCode(this.i));
		System.out.println(System.identityHashCode(super.i));
	}
	public static void main(String [] args)
	{
		B b=new B();
		b.print();
	}
}
//输出结果:
366712642
366712642

可以看出来,在子类里用this和super访问到的成员变量是同一个对象,除非子类里又重新覆盖了这个成员变量,那么子类的this访问到的就是本类中定义的新成员:

class A{
	I i=new I();
	//I get(){return i;}
}
class I{}
public class B extends A
{
	I i=new I();
	
	//I get(){return i;}
	void print(){
		System.out.println(System.identityHashCode(this.i));
		System.out.println(System.identityHashCode(super.i));
	}
	public static void main(String [] args)
	{
		B b=new B();
		b.print();
	}
}
//输出结果:
366712642
1829164700
class A{
	private I i=new I();
	I get(){
        return i;
    }
}
class I{}
public class B extends A
{
	I i=new I();
	void print(){
		System.out.println(System.identityHashCode(super.get()));
        System.out.println(System.identityHashCode(this.i));
	}
	public static void main(String [] args)
	{
		B b=new B();
		b.print();
	}
}}
}
//输出结果
366712642
1829164700

 

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值