初学者对于java继承、多态,子类对象的内存分配的一些问题,百度了好多,但感觉没有系统的,在此提问,希望前辈们传到授业解惑

问题描述

由于是初学者,所以有些表述可能有误,都只是自己的一些理解。我是纯初学者,看过两个星期的C++,之前也学过C。感觉看C++的时候,更容易去理解C++中的面向对象技术的实现,但看JAVA的时候,可能隔着一层虚拟机,有些实现很难理解。第一个问题:我了解到一个对象里面,隐含了一个引用this,可以用this来特别地引用本对象的成员或者函数,然后还有一个super关键字,书上说这个关键字不是一个引用,但怎么看都感觉这个super是一个指向本对象的父类类型的引用。我想问这个super到底是什么,如果是一个变量,他属于什么类型的,在内存中如何存在?我为什么想知道这个问题的答案呢,这个源于多态。当我new一个子类对象,并用一个父类引用指向该对象的时候,那么可以根据这个引用来调用在子类中定义并覆盖的具有相同函数签名的函数。百度一下,有人说这个是因为对象中包含一个函数列表(在C++中叫做虚函数列表),这个列表就是一个指针数组,指向了各个可以被覆盖的函数的地址(C++中对应虚函数)。在调用对象的方法时,根据该对象包含的函数列表来寻找对应函数签名的函数,进而调用。他们的描述中,一般是这样的:函数列表从上往下的顺序与定义时候一样,先放父类中的函数,再放子类的函数;如果子类有覆盖父类的某个函数,则函数列表中,被覆盖的函数的位置就如同覆盖一样,放在父类被覆盖的函数应该放置的位置。也就是说子类中的函数列表中不包括父类中被覆盖的函数地址。按照这种说法,用super关键字如何找到父类中被覆盖的那个方法地址呢?所以我感觉不单纯是这种函数列表的形式。这种形式是C++中的,C++中的虚函数被子类覆盖了的话,就是真正的被覆盖了,子类对象无法调用父类对象的被覆盖的方法。(当然,很多时候可能并没有必要通过子类对象来调用父类对象中被覆盖的方法,但这里我只是想知道一些可能的实现机制)Java中的函数列表是由虚拟机来加载控制的吗?关于这些,我想有一个详细的了解。第二个问题:代码复用可以通过组合和继承两种方式。继承的话可以通过动态绑定实现多态,从而提高代码的可扩展性。组合相当于一个类包含了另一个类,在这一点上和继承很像。在构造一个组合而成的类的时候,相当于构造了一个大的对象,这个对象内部包含一个小对象的引用,这个引用指向的小对象也被构造出来。相比较组合的类的这个构造以及初始化过程。继承的子类在构造的时候,是什么样的方式呢?是不是申请一整块内存,然后通过调用父类和子类的构造函数给内存中的各个变量赋值吗?继承的子类在初始化的时候是不是一次性分配一个连续内存,然后通过不同层次的构造函数逐一初始化。而组合的好像是每一层有一次内存分配,一步一步执行的。也就是说子类在构造的时候,虽然构造函数是逐层调用,但内存分配却只有一次。我不知道我说清楚了没有......第三个问题:继承和组合,我也许没有说清楚,说白了,我其实是想知道一个类B继承另一个类A的时候,到底做了什么事情?应该不是单纯地把人家的代码拿过来赋值就行了。直觉上觉得是一种链接的技术。比如类A在一个文件中,类B在另外一个文件中,编译后运行的时候,虚拟机要讲两个文件都加载,得到两个文件的信息才能创建一个类B的对象吧?如果是如此的话,这个创建的过程是什么呢?因为两个类的代码不在一起,他们如何联系起来以至于形成这种继承的层次关系的?通过什么来联系呢?联系起来之后,又是通过什么机制来实现多态或者动态绑定的呢。类B中到底包含哪些变量,这些变量的组织关系是什么样的。初学JAVA一个月不到,也是刚刚踏足编程领域。但是真的是想涉足这个领域,很多东西很模糊,所以可能也没有描述清楚。但感觉就是和继承、多态、对象内存的分配有关的。真心希望有人解答,越系统越好,或者提供链接,感激不尽!

解决方案

解决方案二:
有什么书也行,讲这方面的,适合初学者看的书。
解决方案三:
字写得太长了,看来楼主是挺会思考的,这是好事。不过也容易钻牛角尖。初学,会用起来就行了,用过一段时间之后,再深究原理。关于面向对象内存布局,建议参考《深度探索C++对象模型》前几章。"传到授业解惑",这句话写得太大了,传道授业,那是老师一辈子的事,试问网上的朋友谁能做到?初学,看经典书就对了,百度找不到准备的答案,第一次就要把知识概念学对,不然后面更麻烦。关键在于坚持。
解决方案四:
引用2楼stupid_boy2007的回复:

字写得太长了,看来楼主是挺会思考的,这是好事。不过也容易钻牛角尖。初学,会用起来就行了,用过一段时间之后,再深究原理。关于面向对象内存布局,建议参考《深度探索C++对象模型》前几章。"传到授业解惑",这句话写得太大了,传道授业,那是老师一辈子的事,试问网上的朋友谁能做到?初学,看经典书就对了,百度找不到准备的答案,第一次就要把知识概念学对,不然后面更麻烦。关键在于坚持。

恩恩,我是在看一些书,但我可能是有点钻牛角尖,有些问题,积压在心里,就不舒服。也是现在迫切需要快速掌握东西,所以才会很着急地想要快速了解一些问题,目前处于想转行的阶段。非常感谢你推荐的书,我会下载下来好好看下的。
解决方案五:
引用2楼stupid_boy2007的回复:

字写得太长了,看来楼主是挺会思考的,这是好事。不过也容易钻牛角尖。初学,会用起来就行了,用过一段时间之后,再深究原理。关于面向对象内存布局,建议参考《深度探索C++对象模型》前几章。"传到授业解惑",这句话写得太大了,传道授业,那是老师一辈子的事,试问网上的朋友谁能做到?初学,看经典书就对了,百度找不到准备的答案,第一次就要把知识概念学对,不然后面更麻烦。关键在于坚持。

哦,不过,这个是C++的呀。应该和JAVA不一样的,不过还是很感谢,我也会下载下来,等以后没这么迫切了再看也行的。
解决方案六:
引用2楼stupid_boy2007的回复:

字写得太长了,看来楼主是挺会思考的,这是好事。不过也容易钻牛角尖。初学,会用起来就行了,用过一段时间之后,再深究原理。关于面向对象内存布局,建议参考《深度探索C++对象模型》前几章。"传到授业解惑",这句话写得太大了,传道授业,那是老师一辈子的事,试问网上的朋友谁能做到?初学,看经典书就对了,百度找不到准备的答案,第一次就要把知识概念学对,不然后面更麻烦。关键在于坚持。

略微瞄了一眼《深度探索C++对象模型》,感觉还是很有用的。虽然只是C++的,但肯定有类似的地方。不过...对我而言,这本书是以后看的,目前看太费劲了..感谢兄弟。我其实需要的是通俗的简单概括就行啦,让我知道他是这么干的,但又不用太细太细,我了解一个大概就OK。现在看的太细太细,会让我无力乏味...我慢慢来吧。
解决方案七:
就回答一点、我觉得、你把this就理解成一个引用变量、或者是一个方法的隐藏的变量、方法调用的时候虚拟机自动把对应对象的引用赋值给了this变量、从而使这个方法内部能调用this指向的那个对象中的成员变量和方法、其他的我觉得目前阶段没必要深究、

时间: 2024-10-03 16:21:55

初学者对于java继承、多态,子类对象的内存分配的一些问题,百度了好多,但感觉没有系统的,在此提问,希望前辈们传到授业解惑的相关文章

java继承 在子类中声明同名变量的问题???

问题描述 java继承 在子类中声明同名变量的问题??? 如下代码: class Person { String name; int age; public void introduce(){ System.out.println("姓名是" + name + ",年龄是" + age); } } public class Students extends Person{ // String name; public static void main(String[

源码分析:Java对象的内存分配

Java对象的分配,根据其过程,将其分为快速分配和慢速分配两种形式,其中快速分配使用无锁的指针碰撞技术在新生代的Eden区上进行分配,而慢速分配根据堆的实现方式.GC的实现方式.代的实现方式不同而具有不同的分配调用层次.  下面就以bytecodeInterpreter解释器对于new指令的解释出发,分析实例对象的内存分配过程: 一.快速分配 1.实例的创建首先需要知道该类型是否被加载和正确解析,根据字节码所指定的CONSTANT_Class_info常量池索引,获取对象的类型信息并调 用is_

java继承多态-java继承问题,菜鸟求助

问题描述 java继承问题,菜鸟求助 1.定义一个类,包含两个以上的私有成员,两个以上的方法以及一个构造函数 从该超类继承得到至少三个子类,这三个子类分别要在超类的基础上增加至少一个成员,至少一个方法以及同时重写超类中的同一个方法. 3.编写程序,用子类的对象去访问超类的方法和自己的方法 编写一个方法,用超类作为形式参数. 分别用三个子类对象作为实际参数调用该方法,并在方法中实现多态. 要求满足上面的条件,求大神附上代码,谢谢 解决方案 菜鸟不可怕,可怕的是不学的菜鸟.少年,java语法都学会了

java 继承 多态-请问下这段代码正确的原因,为什么父类可以调用抽象方法,执行的是子类重写的方法

问题描述 请问下这段代码正确的原因,为什么父类可以调用抽象方法,执行的是子类重写的方法 public class TestA { public static void main(String[] args) { TestA a = new TestA(); a.start(); } public void start(){ B b = new B(); b.funA(); } public abstract class A { public void funA(){ System.out.pri

浅谈java中对集合对象list的几种循环访问_java

java中对集合对象list的几种循环访问的总结如下  1 经典的for循环  public static void main(String[] args) { List<String> list = new ArrayList(); list.add("123"); list.add("java"); list.add("j2ee"); System.out.println("=========经典的for循环======

Android 优化二 Java内存分配机制及内存泄漏

Java内存分配机制及内存泄漏目录介绍 1.JVM内存管理 1.1 JVM内存管理图 1.2 Java采用GC进行内存管理. 2.JVM内存分配的几种策略 2.1 静态的 2.2 栈式的 2.3 堆式的 2.4 堆和栈的区别 2.5 得出结论 2.6 举个例子 2.7 调用 System.gc();进行内存回收 3.GC简单介绍 3.1 内存垃圾回收机制 3.2 关于GC介绍 3.3 如何监听GC过程 3.4 GC过程与对象的引用类型关系 4.内存泄漏简单介绍 4.1 内存泄漏的定义 4.2 内

深入理解Java之JVM堆内存分配

Java堆是被所有线程共享的一块内存区域,所有对象和数组都在堆上进行内存分配.为了进行高效的垃圾回收,虚拟机把堆内存划分成新生代.老年代和永久代(1.8中无永久代,使用metaspace实现)三块区域. Java把内存分成两种:栈内存和堆内存.关于堆内存和栈内存的区别与联系.简单的来讲,堆内存用于存放由new创建的对象和数组,在堆中分配的内存,由java虚拟机自动垃圾回收器来管理.而栈内存由使用的人向系统申请,申请人进行管理. 堆内存初始化 Java中分配堆内存是自动初始化的,其入口位于Univ

java+ 程序 子类继承父类 创建子类对象时构造方法中无显示调用父类构造方法

问题描述 java+ 程序 子类继承父类 创建子类对象时构造方法中无显示调用父类构造方法 创建子类对象时,Student s = new Student(""school""); 该构造方法中没有显示调用父类的构造方法,但还是编译成功了,该构造方法调用自身的构造函数,此构造函数中有调用父类的构造方法,执行成功的原因是什么 解决方案 不用显示调用,会自动执行父类的构造 解决方案二: 子类的构造方法中,如果没有显示调用父类的构造方法,会默认调用父类无参的构造方法.类似于

java向下转型和直接引用子类对象的区别

问题描述 java向下转型和直接引用子类对象的区别 class A{}class B extends A {}向下转型:A a = new B();B b = (B)a;直接调用子类: B b = new B();这两个 b 实例 有什么区别 解决方案 实现的功能没有区别.但是维护起来就不如第一个.第一个是父类引用指向之类对象.可以降低程序的耦合性,即调用者不必关心调用的是哪个对象,只需要针对接口编程就可以了,被调用者对于调用者是完全透明的.让你更关注父类能做什么而不去关心子类是具体怎么做的你可