Java作用域笔记
1.static块和非static块的区别
结论:
1.非静态域的代码在对象实例化的过程中就会执行
2.静态域中的值在实例化过程中也会执行,但是如果多次实例化同一个类,静态域的代码只会执行一次,而如果是非静态域的代码每次实例化都会执行
3.声明变量时如果希望一个变量被多个对象同步(共用),应该使用static修饰变量,不然每次实例对象都会将值初始化(如类中声明一个名为ticket的对象,需要用这个类创建几个买票的对象,每个对象在出一张票后就对ticket变量-1,这里就必须用static修饰ticket变量)
public class test_9 {
static int x=9;
int y=9;
static int z=9;
{
System.out.println("-------实例化--------");
}
static {
x--;
System.out.print("static的x的值为"+x+"\n");
}
{
y--;
System.out.println("非静态y的值为"+y+"\t");
}
{
z--;
System.out.print("静态z的值为:"+z+"\n");
}
}
public class test_9_Demo {
public static void main(String[] args) {/**
通过这个demo可以发现,static域的内容只在第一次new的时候执行一次,
非static域的内容每次创建对象都会执行一次
1.处理的是static变量的话,每次处理后的状态可以积累,如递减的操作
2.处理是非static的变量的话,每次处理后状态不能积累,每次new对象时变量都会初始化
**/
test_9 t1=new test_9();//x只输出一次
test_9 t2=new test_9();
test_9 t3=new test_9();
test_9 t4=new test_9();//y每次都输出但是值不变
test_9 t5=new test_9();//z每次都输出且会递减
}
}
下面是控制台输出的结果
static的x的值为8
-------实例化--------
非静态y的值为8
静态z的值为:8
-------实例化--------
非静态y的值为8
静态z的值为:7
-------实例化--------
非静态y的值为8
静态z的值为:6
-------实例化--------
非静态y的值为8
静态z的值为:5
-------实例化--------
非静态y的值为8
静态z的值为:4
1.观察控制台输出的结果可以发现static{}包裹的代码多次实例化(也就是new 对象)的过程只执行了一次,同时,如果是按照代码的位置顺序的话控制台第一行的输出是应该出现在第一个实例化的下面才对,但是他跑在第一行去了,这是因为了static{}包裹的代码是优先{}的代码执行的
2.在test_9的代码中我们y和z的值每次执行后都有一个减一的操作,但是我们发现只有用static声明的z完成了这一效果,而y每次递减的结果没有达到同步的效果(不能共享),这和上面买票的那个举例是一个道理
2.java合法的嵌套和嵌套中声明与赋值的区别
结论:
1.java中一般的多重嵌套(同一变量多次进行定义)是不允许的,java允许成员变量,在方法体中再次声明
2.局部声明不会影响成员变量,但是局部的赋值会影响成员变量的值
也就是说如果你想在方法体中使用某个和成员变量同名的变量,但是又不希望使用的过程中改变成员变量的值就可以在方法体中将这个同名变量声明一次,这样就不会在这个方法体中使用这个变量时影响成员变量的值了
public class test_8 {
int x=0; //测试块类赋值的影响
int y=0; //测试合法的多重嵌套,块内声明的影响
int z=0; //测试非法多重嵌套定义
{
x=1; //局部赋值会影响整体
int y=2; //这是一个合法的多重嵌套,局部声明不会影响整体,
System.out.println("块内声明y后块内y的值 "+y);
System.out.println("块内赋值x后块内x的值 "+x);
}
public void soutX(){
System.out.println("块内赋值x后块外x的值 "+x);
}
public void soutY(){
System.out.println("块内声明y后块外y的值 "+y);//java允许类与方法的嵌套
int y=11;
}
public void soutZ(){
int z=0;
if (true){
// int z=1; //这个注释如果打开就会报错
System.out.println("java不允许一般的多重嵌套");
}
}
}
测试类
public class test_8_Demo {//得出结论,块级域中的赋值可以影响块外,但是块内声明的赋值不会影响整体
public static void main(String[] args) {
test_8 t=new test_8();
t.soutX();
t.soutY();
t.soutZ();
}
}
控制台输出
块内声明y后块内y的值 2
块内赋值x后块内x的值 1
块内赋值x后块外x的值 1
块内声明y后块外y的值 0
java不允许一般的多重嵌套
Process finished with exit code 0
为了便于观察测试中三个变量的初始值都为0
分析:
1.声明的影响
观察控制第一行和第四行的内容,可以发现块内声明并赋值后,对块外的值没有影响最后输出还是0(第四行),声明后值影响了块内的值(第一行)
2.赋值的影响:
块内进行的赋值会影响成员变量的值,(第一行和第四行)
3.成员变量和局部变量重名的特殊情况
public class test_13_Demo {
int x=0;
int y=0;
public void test11(){
y=1; //没有嵌套声明,会改变成员变量的值
}
public void test11(int x){//嵌套声明,x与成员变量失去关联
x=1; //赋值不改变成员变量值
System.out.println(x);
}
public static void main(String[] args) {
test_13_Demo test=new test_13_Demo();
//此方法执行一次不改变成员变量,因为成员
//变量和参数同名,优先赋给参数,不改变成员
test.test11(2); //按道理来说整个地方x应该被赋值为1
System.out.println(test.x); //所以这里应该是1才对却是0
//此方法执行一次,改变了成员变量
test.test11();
System.out.println(test.y); //无参方法的赋值又成功了就离谱
}
}
控制台输出
1
0
1
思考:
重名的情况和非重名的情况应该分开讨论
1.出现重名的情况:(在形参和方法体内部嵌套声明都算)
出现这种情况,方法体内部的赋值操作和成员变量脱钩,不会影响成员变量
2.没有出现重名时:
内部的赋值会改变成员变量的值