1.java类的初始化顺序:
(1).在一个类中,初始化顺序由变量在类中的声明定义顺序决定,成员变量(非set方法和构造方法的初始化)的初始化发生在方法调用之前,包括构造方法。
(2).静态变量在整个存储区只保留一份拷贝,本地变量不能使用静态关键字,基本类型的静态变量不需要初始化,它会根据类型获得初始化值,引用类型的静态变量默认初始化为null。
静态变量的初始化发生在需要使用的时候,一旦被初始化之后,静态变量就不会再初始化。
(3).静态初始化块和静态变量类似的执行也在构造方法之前,并且仅执行一次。
(4).动态初始化块(与静态初始化块类似,只是没有static关键字,即放在一对大括号中的代码块)在静态初始化块初始化结束后执行,动态初始化块每次创建新对象都会初始化一次。
(5).构造方法执行时,先执行父类的构造方法,后执行子类的构造方法。
(6).本地变量初始化最晚,在方法中初始化。
综述,类的初始化顺序依次为:
a.父类的静态变量/静态初始化块;
b.子类类的静态变量/静态初始化块;
c.父类的动态初始化块、非构造方法和set方法的成员变量初始化
d.子类的动态初始化块、非构造方法和set方法的成员变量初始化
e.父类的构造方法。
f.子类的构造方法。
g.父类本地变量。
h.子类的本地变量。
2.数组初始化:
Java中数组初始化有以下3中方式:
(1).数组声明时直接初始化,如:
int[] a = {1,2,3};
(2).动态数组初始化,如:
int[] a = new int[]{1,2,3};
注意:动态数组初始化时,不能在new()操作符中指定数组的大小,即int[] a = new int[3]{1,2,3}的写法是错误的,数组的大小由初始化数组元素个数决定。
(3).固定长度数组初始化,如:
int[] a = new int[3];
a[1] = 0;
a[2] = 1;
a[3] = 2;
注意:固定长度大小的数组初始化时不能大于所声明的数组长度,没有声明的数组元素使用其默认值,如int默认为0,对象类型的值为引用,默认为null.
3.java代码重用4中方式:
java面向对象编程中提供了如下4中代码重用的方式:
(1).组合:
面向对象编程中最常用的代码复用方式,具体的方式是在一个对象中将另一个对象引用最为成员变量,其最大的优点是既实现松散耦合,有可能提高代码复用率。
(2).继承:
面向对象编程中常用的提高代码复用率的方法之一,适用于子类和父类是同一种抽象类型,具有共同的属性情况。
使用继承,子类可以复用父类除private私有房屋控制权限以为的所有属性和方法,编译器将父类封装为子类对象内部的一个对象。
需要注意的是:调用子类初始化构造方法时,编译器会确保首先调用父类的构造方法初始化父类,然后才初始化子类,如果父类中没有默认的构造方法,即需要显式传入参数的构造方法时,子类必须通过super关键字显式传入参数调用父类的构造方法。
(3).委派:
Java中不支持委派方式的代码复用,但是开发人员可以使用委派机制实现代码的重用。
委派是指,java对象的所有方法其实都是委派调用另一个类的方法实现,但是当前类又不是所委派类的类型,因此使用继承不太合适,解决方式和组合类似,将被委派类作为委派类的成员变量,委派类的方法直接调用被委派类对象应用的方法。
如:
(4).联合使用组合和继承方式:
因为java中不允许多继承,如果某种情况下,一个java类需要使用多个其他类功能,且该类和其中某个类具有很多共同属性,即可以看作同一类,则可以使当前类继承具体共同属性的类,同时将其他类作为成员变量组合引用。
4.组合和继承的区别:
组合和继承都可以复用代码,很多java程序员,甚至是架构师都分不清楚什么情况下该使用组合,什么情况下应该使用继承,具体的区别如下:
(1).组合:
组合通常是在一个类中想使用另一个类已有的特性,但是却不想使用其接口。
使用组合可以可以将一个类作为当前类的内嵌对象,这样在当前类中就可以显式地使用内嵌类已经实现的功能,与此同时又不会影响当前类的调用接口。
(2).继承:
继承是隐式地使用被继承类的功能,相当于提供了一个新版本的父类实现。
使用继承,子类不但可以复用父类的功能,同时还复用了父类的接口,子类和父类的对外调用接口相同的情况下适合使用继承。
使用继承时,很多情况下需要向上类型转换,即将子类看作其父类。在编程时到底选用组合方式还是继承方式,一个简单的判断依据是:是否需要向上类型转换,如果需要就使用继承,如果不需要,则选择组合。
5.final方法:
Java中使用final类型的方法有以下两种原因:
(1).设计原因:
final类型的方法不允许其子类修改方法,即不允许子类覆盖父类的final方法。
(2).效率原因:
在早期的java实现中,如果方法被声明为final,编译器将final方法调用编译为内联调用。
正常的方法调用是:如果方法调用时,将当前的方法上下文保持到栈中,调用被调用的方法,然后在将调用上下文出栈恢复调用现场。
内联调用是:如果方法调用时,将被调用方法体拷贝到当前调用的地方合并成一个方法体,这样就避免因需要保存方法调用线程而进行的进栈和出栈操作,可以提高效率。
新版的使用hotspot技术的java虚拟机可以探测方法调用情况而做效率优化,final方法不再作为提高效率的手段,唯一的作用是确保方法不被子类覆盖。
注意:任何private的方法都是隐式的final类型,同final方法类似,private方法不能被子类所覆盖,但是private比final更严格,基类的private方法对子类不可见,private方法不再是接口的一部分。
6.多态性:
面向对象编程中的多态和继承往往是一起发挥作用的,使用继承,所有的子类和父类使用相同的对外接口,而多态的基础是晚绑定或动态绑定或运行时绑定,即对象引用使用基类类型,在编译时编译器无法确切知道到底调用哪一个具体类,只有在运行时,java虚拟机才通过类型检查确定调用对象的具体类型。
Java中默认对象引用全部是晚绑定,只有static和final类型的引用时早绑定或编译时绑定。
多态的优势是:程序的可扩张性好,无论添加多少个子类,基类的接口都不用改变,只需要在子类对应方法中提供具体实现即可,也就是所谓的将程序变化的部分和程序保持不变的部分分离。
注意:只有正常的方法可以使用多态,字段和静态方法没有多态机制。
构造方法也不支持多态机制,构造方法是隐式的static声明。