public class Cat { String name; int age; static void test(){ System.out.println("test static"); } public Cat(String name,int age){ System.out.println("执行构造器"); this.name = name; this.age = age; } {//这里一定要用花括号 System.out.println("执行非静态初始化块"); weight =2.0; } double weight =2.3; /** * 分两步执行: * double weight; * weight = 2.3;(这条语句将会被提取到java类的构造器中执行,与非静态初始化代码块合并并且地位平等) */ /** * 初始化块中指定初始值和定义weight时指定初始值都属于对该实例变量执行的初始化操作,它们的 * 执行顺序与它们在源程序中的排列顺序相同 */ public String toString(){ return "name:"+name+","+"age:"+age+","+"weight:"+weight; } public static void main(String[] args) { Cat cat = new Cat("kitty",2); System.out.println(cat); Cat cat2 = new Cat("tom",3); System.out.println(cat2); } /** * console: * 执行非静态初始化块 * 执行构造器 * name:kitty,age:2,weight:2.3 * 执行非静态初始化块 * 执行构造器 *name:tom,age:3,weight:2.3 *总结: *1、同一个jvm中,每个类只对应一个Class对象但每个类可以创建多个java对象 *2、用static修饰的成员变量是类变量,属于类本身,通过类访问 *3、没有使用static的成员变量是实例变量,属于该类的实例 *4、实例变量的初始化时机如上例所示 * */ }
用jdk提供的javap工具了解java编译器的机制。
1、javac Cat.java
2、javap -c Cat.class
3、当创建任何java对象时,程序总会先一次调用每个父类非静态初始化块、父类构造器(总是从Object开始)执行初始化,最后
才会调用本类的非静态初始化块、构造器执行初始化。