java静态初始化块深入研究教程
组合部分:
什么时候用,假如仅仅是出于对类的复用目的,可以使用组合。
组合的例子:
public class Base
{
public void test(){
System.out.println("base's test");
}
}
public class Sub
{
private Base b;
public Sub(Base base){
b = base;
}
public void test(){
b.test();
}
public static void main(String[] args){
Sub sub = new Sub(new Base());
sub.test(); // base's test
}
}
这个例子Sub类重用了Base类的test方法,但保持了对Base封装性。
在采用继承还是组合存在疑惑的时候,最好先判断两个类的关系,究竟是“is a”还是“has a”,如果“is a”就是继承,“has a”就用组合。这是选择的依据。
初始化块部分
public class Sub
{
public Sub(){
System.out.println("initial");
}
{
System.out.println("initial block 1");
test();
}
{
System.out.println("initial block 2");
}
public void test(){
System.out.println("sub's test");
}
public static void main(String[] args){
Sub sub = new Sub();
/*
initial block 1
sub's test
initial block 2
initial
*/
}
}
从例子看出,初始化块从上往下执行,且先于构造器执行(即使构造器位于初始化块之前)。在初始化块中可以调用其他函数的。出现多个初始化块是无意义的,出现一个就ok了。初始块里面可以执行if,for等语句。
再来一个例子:
public class Sub
{
{
a = 9;
}
int a;
}
从上面例子,编译不会出错的,{}先于构造器执行,给人错觉就是里面的变量是否要先声明类型呢,如下所示:
public class Sub
{
{
int a = 9;
}
int a;
}
其实这样是无必要的,只要我们在类体内对变量进行了声明,在初始化块中就无需再重复声明类型了。java系统自动先处理声明部分,再执行初始化块,再执行构造器...
注意:初始化块只能用static修饰
public class Sub{
static {
a = 9;
// 编译出错,原因在于此处a被认为是类的变量,而我们声明的int a却是实例变量
}
int a;
}
改为
public class Sub{
static {
a = 9;
}
static int a;
}
注意语句的执行顺序
public class Sub
{
static {
a = 9; // 先执行
}
static int a = 10; // 后执行
public static void main(String[] args){
Sub sub = new Sub();
System.out.println(Sub.a); // 10
}
}
深入静态初始化块
class Root
{
static{
System.out.println("Root static block");
}
{
System.out.println("Root block");
}
public Root(){
System.out.println("Root initial");
}
}
class Mid extends Root{
static{
System.out.println("Mid static block");
}
{
System.out.println("Mid block");
}
public Mid(){
System.out.println("Mid initial");
}
public Mid(String msg){
this();
System.out.println("Mid initial with msg:" + msg);
}
}
class Leaf extends Mid{
static{
System.out.println("Leaf static block");
}
{
System.out.println("Leaf block");
}
public Leaf(){
super("from Leaf");
System.out.println("Leaf initial");
}
}
public class T{
public static void main(String[] args){
new Leaf();
}
}
程序输出结果,我的猜想:
Root static block
Root block
Root initial
Mid static block
Mid block
Mid initial
Leaf static block
Leaf block
Mid initial
Mid initial with msg:from Leaf
Leaf initial
实际结果:
Root static block
Mid static block
Leaf static block
Root block
Root initial
Mid block
Mid initial
Mid initial with msg:from Leaf
Leaf block
Leaf initial
说明的规律,
1)先执行static初始化块
Root static block
Mid static block
Leaf static block
2)再从顶层类依次往下,逐一执行各层类的初始化块和构造器
Root block
Root initial-->无参数的构造器
Mid block
Mid initial --> 选择带一个参数的构造器(Leaf的构造器决定的)
Mid initial with msg:from Leaf
Leaf block
Leaf initial
new Leaf();执行多一次的情况:
public class T{
public static void main(String[] args){
new Leaf();
new Leaf();
}
}
第一个new Leaf();产生以下结果
Root static block
Mid static block
Leaf static block
Root block
Root initial
Mid block
Mid initial
Mid initial with msg:from Leaf
Leaf block
Leaf initial
第二个new Leaf();产生以下结果
Root block
Root initial
Mid block
Mid initial
Mid initial with msg:from Leaf
Leaf block
Leaf initial
结论,静态初始化块只会执行一次,往后再创建再多的实例都不会重复执行。静态那部分都是属于类的范畴,不是实例对象。
本文来源 我爱IT技术网 http://www.52ij.com/jishu/4751.html 转载请保留链接。
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
