本帖最后由 lwj123 于 2015-3-17 17:52 编辑
本帖讲的内容是实例变量和类变量的深入理解:
一:局部变量的位置
二:成员变量,类变量的定义
三:什么是非法前向引用并举例说明
四:实例变量的初始化时机
五:类变量的初始化时机
六:JDK:javap <option> <class>的使用
-----------------------------------------------------------
1:局部变量分为3类:
·形参:由方法调用者为其赋值,随方法的执行完毕而消失
·方法内的局部变量:必须在方法中显示赋值,随方法的执行完毕而消失
·代码块内的局部变量:必须在代码块中显示赋值,随代码块的执行完毕而消失
2:成员变量:类体定义的没有被static修饰的变量
类变量:类体定义的被static修饰的变量
3:非法前向引用:表面上看,java类里定义的成员变量时是没有先后顺序的,但是jav
定义成员变量时,必须采用合法的前向引用
举例:
// 实例变量
// int num1 = num2 +2;//不合法的前向引用
int num2 = 3;
// 类变量
// static int num3 = num4+9;//不合法的前向引用
static int num4 = 3;
// 实例变量和类变量:因为类变量的初始化时机比实例变量要早
// 编译是通过的
int num5 = num6 + 4;
static int num6 = 5;
//-------------------------------------------------------------------------
4:实例变量的初始化时机
(1)实例变量是属于java对象,每次程序创建java对象时都需要为实例变量分配内存空间
,并执行初始化。
(2)由此可知实例变量的初始化时机:
·定义实例变量时指定初始值
·非静态初始化块对实例变量指定初始值
·构造器对实例变量指定初始值
(3)执行顺序:
定义实例变量指定初始值和非静态代码块指定实例变量的初始值都比构造
方法先执行。
定义实例变量指定初始值和非静态代码块指定实例变量的初始值的执行顺序跟在类
中的定义一样。
举例:
public class VariableDemo3 {
public static void main(String[] args) {
Cat c1 = new Cat("kitty", 12);
System.out.println(c1);
}
}
class Cat {
// 定义name,age两个实例变量
String name;
int age;
// 使用构造器初始化name和age两个实例变量
Cat(String name, int age) {
System.out.println("执行构造器");
this.name = name;
this.age = age;
}
// 非静态代码块初始化指定的初始值
{
System.out.println("执行非静态代码块");
weight = 2.0;
}
// 定义时指定初始值
double weight = 2.4;
@Override
public String toString() {
return "Cat [name=" + name + ", age=" + age + ", weight=" + weight
+ "]";
}
}
执行结果:
执行非静态代码块
执行构造器
Cat [name=kitty, age=12, weight=2.4]
分析:
为什么执行的结果不是Cat [name=kitty, age=12, weight=2.0]?
很多人认为double weight = 2.0代码会获得先执行的机会,但实际上定义变量时指
定的初始值和初始化中指定的初始值,与它们在源程序的排列顺序有关的。
5:JDK中提供一个javap工具的使用
定义实例变量时指定的初始化值和初始化块中指定初始化值的语句地位是平等的,当经
过编译器处理之后,他们都会被提取到构造器中.
也就是说double weight = 2.3;实际上会被分成2次执行:
(1)double weight;:创建java对象时系统根据该语句为该对象非配内存。
(2)weight = 2.3;:这条语句将会被提取到Java类中构造器中去执行
JDK中提供一个javap工具。主要用于帮助开发者深入了解Java编译器的机制:
格式:javap <option> <class>
javap -c JavaToolTest
结果:
截图如下:
public JavaToolTest(java.lang.String);
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":
()V
4: aload_0
5: bipush 20
7: putfield #2 // Field count:I
10: aload_0
11: bipush 12
13: putfield #2 // Field count:I
16: getstatic #3 // Field java/lang/System.out:Ljava/
io/PrintStream;
19: aload_1
20: invokevirtual #5 // Method java/io/PrintStream.printl
n:(Ljava/lang/String;)V
23: return
}
3种为实例变量赋值的语句的作用的都是类似的,经过编译器处理之后,他们对应的
语句会被合并到构造器中,定义语句赋值和初始代码块赋值的语句都会放在构造器所有语句之前,两者的的顺序保持他们在源代码中的顺序。
|