关于java 继承抽象类,追溯父类构造方法问题的疑问。

lierenzhifeng 2009-05-11 05:01:21
1. 抽象类不能够被实例化,
2. 子类对象在实例化的时候会追溯父类的构造方法,一直追溯到Object,创建所有父类的实例
3. 我在Eclipse环境下JDK6.0 update 13,写了一个抽象类,可以在里面添加构造方法。

问题:
1. 当子类的父类为抽象类时,构造方法如何追溯?抽象类作为父类也会创建实例么?
2. 抽象类中的构造方法是怎么回事?为什么有构造方法却不能实例化?

恳请高人解疑!

万分感谢~~~
...全文
3189 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
flywings100 2012-03-28
  • 打赏
  • 举报
回复
谢谢LS几位高手的解答,受教了。
lxc8510 2011-12-14
  • 打赏
  • 举报
回复
抽象类有构造方法,但不能实例化!
wjchow 2011-11-29
  • 打赏
  • 举报
回复
非常感谢 你们的讲解 收获很多啊 谢谢
HappyDelano 2011-11-07
  • 打赏
  • 举报
回复
真是受教不浅呀。
xtanmy 2011-10-17
  • 打赏
  • 举报
回复
Java果然深不可测。
yansuihehe 2010-08-21
  • 打赏
  • 举报
回复
快恍然大悟了!
shangzhizhou 2009-12-31
  • 打赏
  • 举报
回复
厉害,今天也是因为这个问题头疼了一天啊!!现在算是明白了啊!!谢谢各位啊!!
yuelengqianfeng 2009-12-06
  • 打赏
  • 举报
回复
佩服佩服
huyangleng123 2009-10-25
  • 打赏
  • 举报
回复
太高深了,还得继续学习,帮顶
liqiang_cna 2009-09-28
  • 打赏
  • 举报
回复
受教了
naiyi1984 2009-06-12
  • 打赏
  • 举报
回复
厉害! spiniper哥把我彻底讲明白了,表达太清晰了!
树成 2009-05-12
  • 打赏
  • 举报
回复
其实不叫做原型区,官方的说法是方法区,方法区存放类类型、类型的方法、类型成员变量等等。
其实子类所谓的追述父类构造方法,更确切的说应该是初始化方法的调用,因为方法信息都存放在方法区,所以都是直接调用方法区中的初始化方法。
lierenzhifeng 2009-05-12
  • 打赏
  • 举报
回复
今天上班后问了一下我们这的讲师,他的回答是这样的:

虚拟机加载类之后,会在原型区(内存中的某一区域)内创建类的原型(不是类的对象),当子类追溯父类构造方法时,追溯的是原型区内的东西。

不知各位高人对以上解释有何想法?
请赐教~~~~
wcwtitxu 2009-05-11
  • 打赏
  • 举报
回复
一个类能不能被实例化,不是看他有没有构造方法(事实上,类都一定有构造方法的)

抽象类不能被实例化是因为此类被认为是没有设计完成的(带有抽象方法或者类的设计者有意的把它作为一个未设计完成的类)

一个类没有设计完成,怎么能被实例化呢



子类继承抽象类后,如果实现了父类的所有抽象方法,就可以作为 非抽象 的类了.
也就能作为一个设计完成了的类. 就能实例化了
踏雪无痕 2009-05-11
  • 打赏
  • 举报
回复

abstract class Person{
private String name;

public Person(String n){
name=n;
}

public String getName() {
return name;
}

public abstract String getInformation();
}

class Employee extends Person{
private double salary;

public Employee(String n,double s) {
super(n);
salary=s;
}

public double getSalary() {
return salary;
}

@Override
public String getInformation() {
return "级别:员工、工资:"+getSalary();
}

}

public class MainTest{
public static void main(String[] args){
Person p=new Employee();
}
}



抽象类不能被实例化是说Person p=new Person();这样是错误的;但是Person p=new Employee(); 是可以的,创建子类的实例,父类的引用指向它
在上述主程序中,new Employee后,它会初始化对象,初始化顺序为:
父类静态块初始化---->子类静态块初始化---->父类非静态块初始化---->父类构造方法---->子类非静态块初始化---->子类构造方法。(先静后动,先父后子)
这个主程序会先初始化person类的非静态属性和构造函数再初始化employees类的非静态属性和构造函数

这就是你第一个问题的当子类的父类为抽象类时,构造方法如何追溯?而抽象类作为父类也会创建实例么?没有创建实例只是构造函数在对抽象类Person的属性初始化,对于一个类的声明,赋值 和使用两件事情,前者不需要实例化,后者必须实例化





抽象类中的构造方法是怎么回事?就是初始化属性的作用

为什么有构造方法却不能实例化?没有这样的说法,只能针对类实例化对象


抽象类不能被实例化,构造函数被可以重载不能被覆盖,构造函数不能被继承


构造函数和类名相同,所以,继承下来也不是构造函数了,还有构造函数是一个对类初始化的特殊方法,代表这个类,一个基类是不可能知道子类会扩展什么,如果继承了就可以不写代码了,那么子类的新属性怎么初始化?当然这2点是我个人的看法
树成 2009-05-11
  • 打赏
  • 举报
回复
1、子类在创建实例后,类初始化方法会调用父类的初始化方法(除了java.lang.Object类,因为java.lang.Object类没有父类),而这种调用会逐级追述,直到java.lang.Object的初始化方法。
这个地方我说的是初始化方法,而不是构造方法,因为构造方法是相对于java源程序而言,而编译后的class文件是初始化方法即"<init>"方法(红色部分为方法名),初始化方法是由java源程序的三个部分组成的,一个部分是成员字段后的直接的初始化语句,例如private int i=0;private Date date=new Date();等等,第二个部分是由初始化块组成,例如:
public class Test{
private int i=0;//初始化第一部分
//以下大括号内为初始化第二部分
{
this.i=4;
\\do something......
}
}

第三个部分就是java源代码中的构造方法中的代码,java源代码中有几个构造方法,那么class文件中就有几个初始化方法,编译器会把第一部分与第二部分分别复制到每个初始化方法的前端,然后把初始化方法对应参数的构造方法的代码复制到相应初始化方法中(这里说的复制其实应该说是编译,不过为了让你更好理解所以如此说).
那么说初始化方法如何追述其父类的,这也关系到初始化方法的结构,初始化方法的执行顺序以及结构就如上所说,但是每个初始化方法的第一个执行指令就是调用另外一个初始化方法,这个初始化方法可能是自身类某个初始化方法,例如你的构造函数中第一句有类似this(...)这种语句,那么初始化方法就会调用自身类的指定构造方法;如果你的构造方法中没有指定构造方法调用,那么初始化方法会默认调用父类无参数初始化方法,如果你的子类第一句为super(....),那么初始化方法会调用父类指定初始化方法。这种调用过程会递归进行调用,直到这个类是java.lang.Object类。
调用初始化方法并不代表会生成对象,你的java代码中出现new关键字加上构造方法的调用,只会生成一个对象,其父类对象不会生成,所以调用父类为抽象类的构造方法完全是合理的。而且初始化方法对于虚拟机来说只是一个名称叫做"<init>"的普通方法,区别只是生成对象以后调用而已(sun 的jdk私有包中有绕过构造方法生成对象的方式,可以证明之上说法,具体如何我这里不陈述)。
然后回答你的第二个问题,抽象类中的构造方法其实是用来给继承的子类来用的,因为构造方法相当于初始化方法,当子类调用构造方法时必须调用父类构造方法,所以你可以在子类产生对象时抽象类中按需求初始化抽象类中的字段以及执行一些初始化代码。其实并不是一定要生成某个类的实例才调用构造方法,子类也需要调用父类构造方法。而生成实例也并不一定会调用构造方法,在某些特殊实现中或者特殊情况下,生成实例不会调用构造方法。而调用了构造方法也不一定就生成了一个实例,但是那一定是一个实例调用的,就像一个普通的实例方法一样。
树成 2009-05-11
  • 打赏
  • 举报
回复
1、子类在创建实例后,类初始化方法会调用父类的初始化方法(除了java.lang.Object类,因为java.lang.Object类没有父类),而这种调用会逐级追述,直到java.lang.Object的初始化方法。
这个地方我说的是初始化方法,而不是构造方法,因为构造方法是相对于java源程序而言,而编译后的class文件是初始化方法即"<init>"方法(红色部分为方法名),初始化方法是由java源程序的三个部分组成的,一个部分是成员字段后的直接的初始化语句,例如private int i=0;private Date date=new Date();等等,第二个部分是由初始化块组成,例如:
public class Test{
private int i=0;//初始化第一部分
//以下大括号内为初始化第二部分
{
this.i=4;
\\do something......
}
}

第三个部分就是java源代码中的构造方法中的代码,java源代码中有几个构造方法,那么class文件中就有几个初始化方法,编译器会把第一部分与第二部分分别复制到每个初始化方法的前端,然后把初始化方法对应参数的构造方法的代码复制到相应初始化方法中(这里说的复制其实应该说是编译,不过为了让你更好理解所以如此说).
那么说初始化方法如何追述其父类的,这也关系到初始化方法的结构,初始化方法的执行顺序以及结构就如上所说,但是每个初始化方法的第一个执行指令就是调用另外一个初始化方法,这个初始化方法可能是自身类某个初始化方法,例如你的构造函数中第一句有类似this(...)这种语句,那么初始化方法就会调用自身类的指定构造方法;如果你的构造方法中没有指定构造方法调用,那么初始化方法会默认调用父类无参数初始化方法,如果你的子类第一句为super(....),那么初始化方法会调用父类指定初始化方法。这种调用过程会递归进行调用,直到这个类是java.lang.Object类。
调用初始化方法并不代表会生成对象,你的java代码中出现new关键字加上构造方法的调用,只会生成一个对象,其父类对象不会生成,所以调用父类为抽象类的构造方法完全是合理的。而且初始化方法对于虚拟机来说只是一个名称叫做"<init>"的普通方法,区别只是生成对象以后调用而已(sun 的jdk私有包中有绕过构造方法生成对象的方式,可以证明之上说法,具体如何我这里不陈述)。
然后回答你的第二个问题,抽象类中的构造方法其实是用来给继承的子类来用的,因为构造方法相当于初始化方法,当子类调用构造方法时必须调用父类构造方法,所以你可以在子类产生对象时抽象类中按需求初始化抽象类中的字段以及执行一些初始化代码。其实并不是一定要生成某个类的实例才调用构造方法,子类也需要调用父类构造方法。而生成实例也并不一定会调用构造方法,在某些特殊实现中或者特殊情况下,生成实例不会调用构造方法。而调用了构造方法也不一定就生成了一个实例,但是那一定是一个实例调用的,就像一个普通的实例方法一样。
dreamhunter_lan 2009-05-11
  • 打赏
  • 举报
回复
调用子类构造方法都会调用它的直接父类的构造方法
我觉得可以认为new才会返回一个实例的引用,而抽象类是不能new的(这个是规定,没理由)
调用子类构造方法是调用了它的抽象父类的构造方法
但构造方法是用来做初始化工作的,它并不会返回实例

这个问题问得好,只能帮顶了
pathuang68 2009-05-11
  • 打赏
  • 举报
回复
楼主深刻。不过在Java中好像很少有人思考过这样的问题,在C++中则比较多。不妨参考:
http://blog.csdn.net/pathuang68/archive/2009/04/23/4101970.aspx
见丰 2009-05-11
  • 打赏
  • 举报
回复

package net.anysoft.test.jc;

abstract class FatherClass {
public FatherClass() {
System.out.println("in abstract father class");
}
}

public class AbstractInit extends FatherClass {

public AbstractInit() {
System.out.println("in abstract init class");
}

public static void main(String[] args) {
//FatherClass f=new FatherClass();
FatherClass f=new AbstractInit();
}
}

62,632

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧