浅谈java继承中是否创建父类对象

1.

调用父类构造方法是真的,但是根本没有创建父类对象,只不过是调用父类构造方法来初始化属性。

如果说调用父类构造方法就等于创建父类对象,那就真的无稽之谈。

new指令开辟空间,用于存放对象的各个属/性引用等,反编译字节码你会发现只有一个new指令,所以开辟的是一块空间,一块空间就放一个对象。

然后,子类调用父类的属性,方法啥的,那并不是一个实例化的对象。

在字节码中子类会有个u2类型的父类索引,属于CONSTANT_Class_info类型,通过CONSTANT_Class_info的描述可以找到CONSTANT_Utf8_info,然后可以找到指定的父类啊啥的。

你的方法啊,属性名称都是在这个上面解析出来的,然后实际变量内容存储在new出来的空间那里。。。

super这个关键字只不过是访问了这个空间特定部分的数据(也就是专门存储父类数据的内存部分)。。。。。。

默认的hashcode和equals(直接使用的==比较)都是一样的,所以,这根本就在一个空间里,也不存在单独的出来的父类对象。

如果说子类可以强行转换成父类进行使用,那是因为java虚拟机有个静态类型(外观类型)和实际类型的概念。

如Object t=new Point(2,3);

那么Object属于静态类型(外观类型),Point属于实际类型。

静态类型和实际类型在程序中都可以发生变化,区别是静态类型的变化仅仅发生在使用时发生,而变量本身的静态类型不会改变,并且最终的静态类型是在编译期间可知的;而实际变量类型的变化结果只有在运行期间才能被确定,编译器在编译的时候并不知道变量的实际类型是什么。

2.

java对象的内存布局是由对象所属的类确定。也可以这么说,当一个类被加载到虚拟机中时,由这个类创建的对象的布局就已经确定下来的啦。

Hotspot中java对象的内存布局:

每个java对象在内存中都由对象头和对象体组成。

对象头是存放对象的元信息,包括该对象所属类对象Class的引用以及hashcode和monitor的一些信息。

对象体主要存放的是java对象自身的实例域以及从父类继承过来的实例域,并且内部布局满足由下规则:

规则1:任何对象都是8个字节为粒度进行对齐的。

规则2:实例域按照如下优先级进行排列:长整型和双精度类型;整型和浮点型;字符和短整型;字节类型和布尔类型,最后是引用类型。这些实例域都按照各自的单位对齐。

规则3:不同类继承关系中的实例域不能混合排列。首先按照规则2处理父类中的实例域,接着才是子类的实例域。

规则4:当父类中最后一个成员和子类第一个成员的间隔如果不够4个字节的话,就必须扩展到4个字节的基本单位。

规则5:如果子类第一个实例域是一个双精度或者长整型,并且父类并没有用完8个字节,JVM会破坏规则2,按照整形(int),短整型(short),字节型(byte),引用类型(reference)的顺序,向未填满的空间填充。

以上就是java对象的内存布局的规则。

接下来说一下java对象的实例化方法,也就是常见的<init>方法。

当我们new一个对象时,其实jvm已经把这个对象的整个空间已经分配好,并且整个对象的实例域布局已经确定下来啦。

实例化方法<init>就是将对象实例域的值设置到相应空间中。

<init>方法以调用父类的<init>方法开始,以自身构造方法作为结束。实例域的声明与实例初始化语句块的位置关系会影响编译器生成的<init>方法的字节码顺序。

还是以一个例子说明一下:

class Parent {
private short six;
private int age;
}

class Sub extend Parent{
private String name;
private int age;
private float price;
}

当前Sub对象的内存布局由下:

super所谓的父类存储空间的表示到底是什么意思?

这里的super存储我想就是绿色的那个位置吧!

以上这篇浅谈java继承中是否创建父类对象就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 浅析Java中的继承与组合

    前言 Java是一个面向对象的语言.每一个学习过Java的人都知道,封装.继承.多态是面向对象的三个特征.每个人在刚刚学习继承的时候都会或多或少的有这样一个印象:继承可以帮助我实现类的复用.所以,很多开发人员在需要复用一些代码的时候会很自然的使用类的继承的方式,因为书上就是这么写的(老师就是这么教的).但是,其实这样做是不对的.长期大量的使用继承会给代码带来很高的维护成本. 其实我第一次学习java 的时候根本没有听说过组合这个名词,老师也更没有讲解过,我一直以为是我自己落掉了什么知识点,其实不

  • Java 继承方法实例详解

    继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类.继承可以理解为一个对象从另一个对象获取属性的过程. 如果类A是类B的父类,而类B是类C的父类,我们也称C是A的子类,类C是从类A继承而来的.在Java中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类 继承中最常使用的两个关键字是extends和implements. 这两个关键字的使用决定了一个对象和另一个对象是否是IS-A(是一个)关系. 通过使用这两个关键字,我们能实现一个对象获取另一个对象的属性. 所有Jav

  • 详解Java继承中属性、方法和对象的关系

    大家都知道子类继承父类是类型的继承,包括属性和方法!如果子类和父类中的方法签名相同就叫覆盖!如果子类和父类的属性相同,父类就会隐藏自己的属性! 但是如果我用父类和子类所创建的引用指向子类所创建的对象,父类引用所调用子类对象中的属性值或方法的结果是什么呢? 看代码: public class FieldDemo { public static void main(String[] args){ Student t = new Student("Jack"); Person p = t;/

  • java教程之java继承示例详解

    什么是继承(extends)? 继承是:新定义的类是从已有的类中获取属性和方法的现象. 这个已有的类叫做父类, 从这个父类获取属性和方法的类叫做子类. ExtendsDemo1.java 复制代码 代码如下: /*什么是继承*/public class ExtendsDemo1 {    public static void main(String[] args) {        Truck t = new Truck();        t.size = 100;           //不

  • 浅谈java继承中是否创建父类对象

    1. 调用父类构造方法是真的,但是根本没有创建父类对象,只不过是调用父类构造方法来初始化属性. 如果说调用父类构造方法就等于创建父类对象,那就真的无稽之谈. new指令开辟空间,用于存放对象的各个属/性引用等,反编译字节码你会发现只有一个new指令,所以开辟的是一块空间,一块空间就放一个对象. 然后,子类调用父类的属性,方法啥的,那并不是一个实例化的对象. 在字节码中子类会有个u2类型的父类索引,属于CONSTANT_Class_info类型,通过CONSTANT_Class_info的描述可以

  • 浅谈Java继承中的转型及其内存分配

    看书的时候被一段代码能凌乱啦,代码是这样的: package 继承; abstract class People { public String tag = "疯狂Java讲义"; //① public String name = "Parent"; String getName(){ return name; } } class Student extends People { //定义一个私有的tag实例变量来隐藏父类的tag实例变量 String tag =

  • 浅谈Java编程中string的理解与运用

    一,"=="与equals() 运行以下代码,如何解释其输出结果? public class StringPool { public static void main(String args[]) { String s0="Hello"; String s1="Hello"; String s2="He"+"llo"; System.out.println(s0==s1);//true System.out

  • 浅谈java面向对象中四种权限

    俗话说没有规矩就没有方圆,java作为一门严谨的面向对象的高级编程语言,自然对权限整个重要的问题有严格的控制. Java中,可以通过一些Java关键字,来设置访问控制权限: 主要有 private(私有), package(包访问权限),protected(子类访问权限),public(公共访问权限) 在java里,这些语句都可以修饰类中的成员变量和方法,但是只有public和友好型可以修饰类.举个例子: 接下来就详细解释一下这几种权限的差别(博客最后有表格)按权限由低到高:(高权限有低权限所有

  • 浅谈Java 继承接口同名函数问题

    在Java中如果一个类同时继承接口A与B,并且这两个接口中具有同名方法,会怎么样? 动手做实验: interface A{ void fun(); } interface B{ void fun(); } interface C extends A,B{ } public class Test implements C{ @Override public void fun() { System.out.println("hehe"); } public static void main

  • 浅谈Java开发中的安全编码问题

    1 - 输入校验 编码原则:针对各种语言本身的保留字符,做到数据与代码相分离. 1.1 SQL 注入防范 严重性高,可能性低. (1) 参数校验,拦截非法参数(推荐白名单): public String sanitizeUser(String username) { return Pattern.matches("[A-Za-z0-9_]+", username) ? username : "unauthorized user"; } (2) 使用预编译: Stri

  • 浅谈Java并发中ReentrantLock锁应该怎么用

    目录 1.重入锁 说明 2.中断响应 说明 3.锁申请等待限时 tryLock(long, TimeUnit) tryLock() 4.公平锁 说明 源码(JDK8) 重入锁可以替代关键字 synchronized . 在 JDK5.0 的早期版本中,重入锁的性能远远优于关键字 synchronized , 但从 JDK6.0 开始, JDK 在关键字 synchronized 上做了大量的优化,使得两者的性能差距并不大. 重入锁使用 ReentrantLock 实现 1.重入锁 package

  • 浅谈java Collection中的排序问题

    这里讨论list.set.map的排序,包括按照map的value进行排序. 1)list排序 list排序可以直接采用Collections的sort方法,也可以使用Arrays的sort方法,归根结底Collections就是调用Arrays的sort方法. public static <T> void sort(List<T> list, Comparator<? super T> c) { Object[] a = list.toArray(); Arrays.

  • 浅谈C++继承中的名字查找

    实例如下: #include<iostream> #include<string> using namespace std; class Base { public: void func() { cout << "func() in Base." << endl; } void func(int a) { cout << "func(int a) in Base." << endl; } voi

  • 浅谈java web中常用对象对应的实例化接口

    1. request对象 是javax.servlet.HttpServletRequest接口的实例化 2. response对象 是javax.servlet.HttpServletResponse接口的实例化 3. session 对象 是javax.servlet.HttpSession接口的实例化 4. application对象 是javax.servlet.ServletContext接口的实例化 以上是常用的对象 5. pageContext对象 是javax.servlet.j

随机推荐