您的位置:首页 > 编程语言 > Java开发

Java的继承及继承中类的加载顺序

2013-04-12 11:04 1256 查看

Java继承的概念

Java继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。这种技术使得复用以前的代码非常容易,能够大大缩短开发周期,降低开发费用。

JAVA不支持多重继承,单继承使JAVA的继承关系很简单,一个类只能有一个父类,易于管理程序,同时一个类可以实现多个接口,从而克服单继承的缺点。

继承所表达的就是一种对象类之间的相交关系,它使得某类对象可以继承另外一类对象的数据成员(成员变量)和成员方法。若类B继承类A,则属于B的对象便具有类A的全部或部分性质(数据属性)和功能(操作),我们称被继承的类A为基类、父类或超类,而称继承类B为A的派生类或子类。

继承避免了对一般类和特殊类之间共同特征进行的重复描述。同时,通过继承可以清晰地表达每一项共同特征所适应的概念范围——在一般类中定义的属性和操作适应于这个类本身以及它以下的每一层特殊类的全部对象。运用继承原则使得系统模型比较简练也比较清晰。

Java继承的特征

(1)继承关系是传递的。若类C继承类B,类B继承类A,则类C既有从类B那里继承下来的属性与方法,也有从类A那里继承下来的属性与方法,还可以有自己新定义的属性和方法。继承来的属性和方法尽管是隐式的,但仍是类C的属性和方法。继承是在一些比较一般的类的基础上构造、建立和扩充新类的最有效的手段。
(2)继承简化了人们对事物的认识和描述,能清晰体现相关类间的层次结构关系。
(3)继承提供了软件复用功能。若类B继承类A,那么建立类B时只需要再描述与基类(类A)不同的少量特征(数据成员和成员方法)即可。这种做法能减小代码和数据的冗余度,大大增加程序的重用性。
(4)继承通过增强一致性来减少模块间的接口和界面,大大增加了程序的易维护性。

(5)Java出于安全性和可靠性的考虑,仅支持单重继承,而通过使用接口机制来实现多重继承。

Java继承中类的加载顺序

( 昨天有一个好友看过我的这篇文章之后,跟我狠狠地讨论了一下关于类中内容加载顺序的相关问题。现在觉得昨天的文章的确有些模糊不清,很多地方还存在不足,今天重新写一遍。若各位读者看过之后有不同意见,希望可以提出,留下您的见解。对Java的学习我也还是菜鸟级,若有大神不小心瞄到拙作,望能不吝赐教)

我们直接来看一段代码(一个类中 静态变量, 静态代码块与 数据成员 )

public class Demo1 {

private int b = 2;
{
System.out.println( "common code block in demo1 b=" + b );
System.out.println( "common code block in demo1 a=" + a );
}

static int a = 1;
static{
System.out.println( "static code block in demo1 a=" + a );
}

public Demo1(){
System.out.println( "constructor in demo1" );
}

public static void main(String[] args) {
Demo1 demo1 = new Demo1();
}
}

//output-->
//static code block in demo1 a=1
//common code block in demo1 b=2
//common code block in demo1 a=1
//constructor in demo1
从输出结果,我们可以看到他们的执行顺序是:被static修饰的数据、代码块 ==》 普通的数据成员 、代码块==》构造器。对于这段代码我们能够得出 static、数据成员的执行顺序,但是对于static变量、代码块或普通成员、普通代码块的执行先后顺序却不得而知

下面,我们再来看一段代码

public class Demo1 {
private int a;
private int b = 2;

{
System.out.println( "common code block in demo1 b=" + b );
a = test();
System.out.println( "common code block in demo1 a=" + a );
}

public int test(){
System.out.println( "method test in demo1 c=" + c );
return c;
}
private int c = 3;

public Demo1(){
System.out.println( "constructor in demo1" );
}

public static void main(String[] args) {
Demo1 demo1 = new Demo1();
}
}

//output-->
//common code block in demo1 b=2
//method test in demo1 c=0
//common code block in demo1 a=0
//constructor in demo1
从这里我们可以看到 c 的定义在代码块 之后,但是我们能够通过方法去调用c,那么由此我们可以推出属性和方法的定义是在代码块之前的。从方法的定义在成员变量 c 之前,而没有出现编译或运行错误,可以推出属性的定义又是在方法之前的。

之后,我们从输出中可发现 c = 0; a = 0,对于属性的初始化却是按出现的先后顺序来的。

在理解了上面的内容之后,我们再来看看继承中的加载顺序是如何的?

public class Demo1 {
static int a = 4;
static{
System.out.println( "static code block in demo1 a=" + a );
}
private int b = 2;

{
System.out.println( "common code block in demo1 b=" + b );
}

private int c = 3;

public Demo1(){
System.out.println( "constructor in demo1" );
System.out.println( "constructor in demo1 b=" + b );
System.out.println( "constructor in demo1 c=" + c );
}

public static void main(String[] args) {
Demo1 demo1 = new Demo2();
Demo1 demo2 = new Demo2();
}
}

class Demo2 extends Demo1{
static int e = 5;

static{
System.out.println( "static code block in demo2 e=" + e );
}

private int f = 6;
{
System.out.println( "common code block in demo2 f=" + f );
}

public Demo2(){
System.out.println( "constructor in demo2" );
}
}

//output-->
//static code block in demo1 a=4
//static code block in demo2 e=5
//common code block in demo1 b=2
//constructor in demo1
//constructor in demo1 b=2
//constructor in demo1 c=3
//common code block in demo2 f=6
//constructor in demo2
//common code block in demo1 b=2
//constructor in demo1
//constructor in demo1 b=2
//constructor in demo1 c=3
//common code block in demo2 f=6
//constructor in demo2


从输出中我们可以看到,执行顺序大体上可以说是先父类后子类,父类static域 ==》子类static域 ==》父类数据成员域 ==》父类构造器 ==》子类数据成员域 ==》子类构造器。而且从结果中我们还可以看到,无论实例化多少个对象,static 域仅有一份,而且只执行一次。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java 继承 类的加载