1.成员变量和局部变量的区别:
(1).声明的位置:
局部变量:在方法体中,代码块里,形参
成员变量:在类中方法体外
它又分为:类变量(有static修饰的变量)和实例变量(无static修饰的变量)
(2).修饰符:
局部变量:只能用修饰符final
成员变量:可以是 public,protected,private,final,static,volatile,transient
(3).值存储的位置:
局部变量:存储在栈位置
成员变量:实例变量存储在堆位置 类变量存储在方法去
(4).作用域:
局部变量:从声明处开始,到}结尾
成员变量:1.实例变量:在当前类中 this.(this有时候可以省略),其他类中,对象名.访问 2.类变量:在当前类中,类名.(有时候类名可以省略),在其他类中类名.或者对象名.访问
(5).生命周期:
局部变量:每一个线程调用,执行都是新的生命周期
成员变量:1.实例变量:随着对象的创建而初始化,随着对象的消亡而消亡,每一个对象的实例变量都是独立的 2.类变量:随着类的创建而初始化,随着类的消亡而消亡,该类的所有对象的类变量是共享的
经典例子:
/**
* 局部变量和静态变量
* @author 20898
*
*/
public class Class3 {
private static int s;
private int i;
private int j;
{
int i = 1;
i++;
j++;
s++;
}
public void test(int j) {
i++;
j++;
System.out.println("j:"+j);
s++;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
1.Class3 obj1 = new Class3();
2.Class3 obj2 = new Class3();
3.obj1.test(10);
4.obj1.test(20);
5.obj2.test(30);
6.System.out.println(obj1.i+","+obj1.j+","+obj1.s);
7.System.out.println(obj2.i+","+obj2.j+","+obj2.s);
}
}
运行结果:
现在一部部来分析答案为什么是这样,首先将main方法中分解为5步,
1.第一步创建obj1对象,并会在堆中创建对象的实例,在栈中存放对象的引用,这一步会初始化代码块里的局部变量,此时代码块变量中有i,成员变量中也有i,采取就近原则,使用的是代码块中的i,此时i++操作只是修改了局部i的值为2,而j++用的是成员变量(成员变量默认初始化值为0),此时j=1,s是类变量对所有对象共享,此时 s = 1. 最终 成员变量 s =1,obj1.i = 0 ,obj1.J= 1
2.第二步场景obj2对象,这一步也会初始化代码块里的局部变量,但是又会开辟一段新的空间,一样会在堆中创建对象的实例,在栈中存放对象的引用,此时 obj2中i依然采取就近原则obj2的局部变量i=2,obj2的j和obj1的j 是两块不同的区域,这是两个不同对象的区域,所以不会关联起来,所以obj2执行j++也等于1,s被共享,s = 2; 最终 成员变量 s =2,obj2.i = 0 ,obj2.J = 1
3.第三步调用obj1.test(),调用方法也会在栈中开辟一块空间,此时的i用的就是成员变量中的i,而之前在代码块中对i++进行操作,因为是对代码块中的局部变量
int i 进行操作,所以没有影响到成员变量i的值,此时 i = 1,而j用的是形参是传进来的值所以局部变量 j = 11,s = 3 最终 成员变量 s =3,obj2.i = 1 ,obj2.J = 1
4.第四步如上 最终 成员变量 s =4,obj1.i = 2 ,obj1.J = 1
5.第五步,用的是obj2里的成员变量。最终 成员变量 s =5,obj2.i = 1 ,obj2.J = 1
6,7.打印的分别是obj1和obj2里的成员变量,不是局部变量
开发中如果遇到局部变量和成员变量重名情况如何选择:
如上面:
public class Class3 {
private static int s;
private int i;
private int j;
{
int i = 1;
i++;
j++;
s++;
}
}
此时如果要想使用的是成员变量i,就添加this关键字,this.i++; 如果和类变量重名,就类名.xx
如讲的有误,还请指正