- 代码块:以{}括起来,放在java类中,括号上以static声明的是静态代码块,执行顺序最早,在类加载时就开始执行。静态代码块不可以放在方法中,因为对于普通方法来说,只有实例被创建时才能被访问,而静态方法虽然在类被加载时就已经被加载了,但是它只可以通过类名或实例名访问,与静态代码块相比,方法都是被动运行,静态代码块是主动运行的。静态代码块执行之早可见java核心技术卷一131页下面Hello类的例子。构造代码块和普通代码块不用static修饰,前者放于类中,起到初始化的作用。构造代码块在创建对象时被调用,每次创建对象都会调用一次,但是优先于构造器执行。只要构造类的对象后这些构造代码块就会被执行。尽量将构造代码块放在域定义之后;后者放在方法中定义。有多个同类型代码块时可以按书写顺序执行。
- 构造器:最后决定域的值,可以在构造器中调用另一个构造器,用this(“被调用构造器的参数列表“”),注意调用其他构造器的语句必须放在调用者的第一行。
package thisTest; public class thisTest { private static String name; static { System.out.println("我是静态代码块!!!!!!所以我不能用this~"+name); } static { System.out.println("我是第二个静态代码块!!!!!!所以我不能用this~"+name); } { System.out.println(this+"我是构造代码块"+this.name); } { System.out.println(this+"我是第二个构造代码块"+this.name); } void f1() { System.out.println(this+"我来自f1方法"+this.name); //static 报错 方法中不可以定义普通代码块 { System.out.println(this+"我来自普通代码块"+this.name); } } static void f2() { //System.out.println(this+"我来自f2方法"+this.name); 报错,静态方法不能用this调用实例域。 System.out.println("我来自f2方法" + name); } //System.out.println(this+"我是动态代码块"+this.name);不把它声明为代码块也不把它放在方法里会报错。 public thisTest() { System.out.println(this+"我是无参数的构造方法"+this.name); } public thisTest(String name) { this();//调用无参数构造器 System.out.println(this+"我是有参数的构造方法"+this.name); this.name = name; System.out.println(this+"我也是有参数的构造方法"+this.name); //this();报错,在一个构造器中调用另一个构造器必须放在第一行。 } public static void main(String[] args) { f2(); thisTest child=new thisTest("张三"); child.f2(); child.f1(); System.out.println(child+"普通方法"+child.name); } }
输出结果是:
我是静态代码块!!!!!!所以我不能用this~null 我是第二个静态代码块!!!!!!所以我不能用this~null 我来自f2方法null thisTest.thisTest@15db9742我是构造代码块null thisTest.thisTest@15db9742我是第二个构造代码块null thisTest.thisTest@15db9742我是无参数的构造方法null thisTest.thisTest@15db9742我是有参数的构造方法null thisTest.thisTest@15db9742我也是有参数的构造方法张三 我来自f2方法张三 thisTest.thisTest@15db9742我来自f1方法张三 thisTest.thisTest@15db9742我来自普通代码块张三 thisTest.thisTest@15db9742普通方法张三
首先按顺序执行静态代码块,因为此时对象还未创建因此name被初始化为默认值null;然后执行静态方法f2(),此时name值依然是null,接下来按顺序执行构造代码块,对象还没有被创建;
接下来执行构造器了,构造了一个thisTest对象child,目前它的name还是默认值null。第一行调用无参数构造器,第二行回到带参数的构造器,可以发现现在Name还是null,在this.name = name 之前都没有。注意,接下来,执行this.name = name后,分别调用f2和f1后发现name值为张三。
在构造器中使用了两次this.name。一次在赋值前,一次在赋值后,可以看到执行完this.name = name后实例child的域立即被设置为张三。