黑马程序员技术交流社区

标题: 抽象类的疑惑 [打印本页]

作者: 静以修身    时间: 2013-8-17 20:55
标题: 抽象类的疑惑
本帖最后由 静以修身 于 2013-8-17 22:48 编辑

抽象类不可以实例化,即不能创建对象,那么为什么还会有构造函数呢?有构造函数不就代表可以创建对象了么?难道该构造函数是私有的?抽象类不可以实例化是指不能在类外实例化,只能在本类中创建对象?还是其它的什么原因?很矛盾,就解释??{:soso_e132:}


作者: 深知一生短暂    时间: 2013-8-17 21:02
本帖最后由 深知一生短暂 于 2013-8-17 21:20 编辑

1.在JAVA中,抽象类只是多了关键字abstract和抽象方法。其他特性和普通的类几乎一样。
2.不能创建对象代表没有构造函数是不成立的。。。这个说法不存在
3.抽象类的构造函数可以很方便子类的成员方法的复写,在抽象类中初始化了属性等,子类继承就变得方便多了。
4.在单例设计模式中,private 构造函数是防止在外部创建对象,你可能在那个地方类推然后混淆了。。。5.抽象类也可以有实体的部分,并不一定全部抽象方法。

abstract class GetTime{
        public final void getTime(){ //此功能如果不需要复写,可加final限定
                long start = System.currentTimeMillis();
                code(); //不确定的功能部分,提取出来,通过抽象方法实现
                long end = System.currentTimeMillis();
                System.out.println("毫秒是:"+(end-start));
        }
        public abstract void code(); //抽象不确定的功能,让子类复写实现
}
class SubDemo extends GetTime{
        public void code(){ //子类复写功能方法
                for(int y=0; y<1000; y++){
                        System.out.println("y");
                }
        }
}


作者: 静以修身    时间: 2013-8-17 21:20
第2句话的逆否问题就是说有构筑函数就能创建对象了,好像不是吧!我是这样理解的,创建对象必须要有构造方法,而有构造方法不一定可以创建对象。
第3点好像有点为题,抽象类的构造函数可以很方便子类成员函数复写?子类的成员函数或者说构造函数不是不可以复写父类的构造函数么?好像构造函数不可以复写的。
至于第四点好像跟我提得问题没有太大关系吧!
作者: 静以修身    时间: 2013-8-17 22:43
邪恶飞猫 发表于 2013-8-17 21:35
实际上一个抽象类中是允许存在构造方法的,因为抽象类依然使用的是类的继承关系,而且抽象类中也存在各种属 ...

实例化的应该是子类对象吧,父类中进行的是初始化,初始化有几种方式,调用构造函数是其中一种,而且调用构造函数进行初始化时并没有建立父类的实例,抽象类是不能实例化的,即使通过对象的多态,只是初始化,而不是实例,应该是这样的吧

作者: 静以修身    时间: 2013-8-17 23:02
实例化的应该是子类吧,实例化意味着可以创建对象,而抽象类是不可以创建对象的,只能初始化。

我是参考这段文字的,一起学习学习吧!
1、子类在创建实例后,类初始化方法会调用父类的初始化方法(除了java.lang.Object类,因为java.lang.Object类没有父类),而这种调用会逐级追溯,直到java.lang.Object的初始化方法。

初始化方法是由java源程序的三个部分组成的:

一个部分是成员字段后的直接的初始化语句,例如private int i=0;private Date date=new Date();等等。

第二个部分是由初始化块组成,例如:
Java code
publicclass Test{privateint i=0;//初始化第一部分 //以下大括号内为初始化第二部分{this.i=4; \\dosomething......}}

第三个部分就是java源代码中的构造方法中的代码,java源代码中有几个构造方法,那么class文件中就有几个初始化方法,编译器会把第一部分与第二部分分别复制到每个初始化方法的前端,然后把初始化方法对应参数的构造方法的代码复制到相应初始化方法中。

那么说初始化方法如何追溯其父类的,这关系到初始化方法的结构,初始化方法的执行顺序以及结构就如上所说,但是如果初始化方法的第一个执行指令就是调用另外一个初始化方法,这个初始化方法可能是自身类某个初始化方法,例如构造函数中第一句有类似this(...)这种语句,那么初始化方法就会调用自身类的指定构造方法;如果你的构造方法中没有指定构造方法调用,那么初始化方法会默认调用父类无参数初始化方法,如果你的构造方法的第一句为super(....), 那么初始化方法会调用父类的指定初始化方法。这种调用过程会递归进行调用,直到这个类是java.lang.Object类。

调用初始化方法并不代表会生成对象,java代码中出现new关键字加上构造方法的调用,只会生成一个对象,其父类对象不会生成,所以调用父类为抽象类的构造方法完全是合理的。而且初始化方法对于虚拟机来说只是一个名称叫做"<init>"的普通方法,区别只是生成对象以后调用而已。

2、抽象类中的构造方法其实是用来给继承的子类来用的,因为构造方法相当于初始化方法,当子类调用构造方法时必须调用父类构造方法,所以可以在子类产生对象时抽象类中按需求初始化抽象类中的字段以及执行一些初始化代码。其实并不是一定要生成某个类的实例才调用构造方法,子类也需要调用父类构造方法。而生成实例也并不一定会调用构造方法,在某些特殊实现中或者特殊情况下,生成实例不会调用构造方法。而调用了构造方法也不一定就生成了一个实例,但是那一定是一个实例调用的,就像一个普通的实例方法一样。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2