1. 在java中的情况
再java中,子类继承父类的属性,那么这个继承的属性是在子类的堆栈中还是在父类的堆栈中? 如果父类的这个属性的值改变,那么这个子类的值会改变吗?或者一个子类改变此属性会影响其他子类的这个属性吗?
在Java中,子类继承的属性存储在自己的堆内存中,并且父类属性值的改变不会影响子类中的对应属性值。
Java的面向对象编程模型支持类的继承,允许子类继承父类的方法和属性。当一个子类继承自一个父类时,子类会获得父类的公有(public)和受保护(protected)的属性,这些属性在子类中是可见的。但是,每个对象实例有自己的状态,存储在堆内存中,而对象的引用则存储在栈内存中。因此,即使子类继承了父类的属性,实际上它们是存储在子类自己的堆内存区域里的。
如果父类中的属性不是私有的(private),那么子类可以直接访问这些属性,并且有可能改变它们的值。例如,通过使用super
关键字,可以在子类的构造方法或方法中调用父类的公有(public)或者受保护(protected)的方法来修改属性的值。但是,这种修改只会影响当前子类对象中继承的属性值,而不会更改父类对象中的属性值。换句话说,子类对象对继承自父类的属性所做的任何修改都是独立的,不会影响到其他子类对象或者父类对象自身的相应属性值。
综上所述,在Java中,继承的属性存在于子类对象的堆内存中,子类可以修改这些属性的值,但这样的修改仅局限于当前子类对象,并不会影响其他对象。
其在TestSubB中的运行结果为:
总结 ,可以看出:
若属性为静态static的,则其属性为引用的同一地址值,即改变了一个子类的属性,其他子类属性都会更改。 若不是static的,则属性只会存在各自子类的堆栈中,更改一个子类的属性值不会影响其他的子类
2. 在spring中默认单例的作用域下
但是如果在spring中,因为spring默认都是单例的模式,那么效果是怎么样的呢?
其和1也是一样的。即父类的属性也会存在于各个子类的堆栈中,所以一个子类的属性值修改不会影响另一个子类的属性值的
以下为验证方式:
父类redisCacheBase
子类:
配置类核心代码:只配置了2个redis
启动后的打印信息:可以看到expire和redisTemplate都被赋不同的值
接口及打印信息如下:可以看出其他的属性依然会被赋值,这是因为继承了父类的属性,会从配置文件进行赋值,如果expire也赋值,则会覆盖为配置文件的值。
结论:
1. 可以看出各个子类修改自己的属性值也是不会影响其他子类的
2. 继承了父类的从配置文件赋值的属性,也是会进行赋值的
3.Java中创建子类对象会创建父类对象么?
答案是:不会创建父类的对象,尽管调用了父类的构造方法,但是构造方法的作用是开辟堆栈的。java中只有new才会创建实例对象。构造方法没有new, 但是如果new肯定就会调用构造方法,如此说来,确实没有创建实例
可以参考文章:Java中创建子类对象会创建父类对象么?_子类对象创建时父类对象-CSDN博客
难怪我在springboot项目中,一直没有验证成功。
4. 验证方法如下:(此为错误验证)
有一个父配置类和2个子配置类,通过查看子配置类的hashcode和父配置类的hashcode来确认是否两个子类的父类实例是否是同一实例?
结果显示:子类的hashcode与父类中打印的hashcode始终相同,原先以为是无法正确获取父类的实例hashcode,现在看来是压根就没创建父类的实例。(父类实例还是spring给实例化的)
结论:
创建子类时并没有对应的创建父类的实例,父类的实例只是由spring创建了一个。所以在下图代码中子类hashcode和所调用的打印父类hashcode始终是同一个。
父类: TestParentA
子类:TestSubB
子类TestSubC:
项目启动时打印的信息如下:
其中1为实例化TestSubB所打印,2为TestSubC所打印,3为实例化TestParentA所打印
接口信息与调用打印信息如下: