成员变量与局部变量分析

说出如下main方法的运行结果

public class VariableTest {
    static int s;
    int i;
    int j;

    {
        int i = 1;
        i++;
        j++;
        s++;
    }

    public void test(int j) {
        j++;
        i++;
        s++;
    }

    public static void main(String[] args) {
        VariableTest obj1 = new VariableTest();
        VariableTest obj2 = new VariableTest();
        obj1.test(10);
        obj1.test(20);
        obj2.test(30);
        System.out.println(obj1.i + "," + obj1.j + "," + obj1.s);
        System.out.println(obj2.i + "," + obj2.j + "," + obj2.s);
    }
}

考点

  • 就近原则
  • 变量的分类
    • 成员变量:类变量、实例变量
    • 局部变量
  • 非静态代码块的执行:每次创建实例对象都会执行
  • 方法的调用规则:调用一次执行一次

局部变量与成员变量的区别:

  • 声明的位置
    • 局部变量:方法体{}中,形参,代码块{}中
    • 成员变量:类中方法外
    • 类变量:有static修饰
    • 实例变量:没有static修饰
  • 修饰符
    • 局部变量:final
    • 成员变量:public、protected、private、final、static、volatile、transient
  • 值存储的位置
    • 局部变量:栈
    • 实例变量:堆
    • 类变量:方法区
  • 作用域
    • 局部变量:从声明处开始,到所属的}结束
    • 实例变量:在当前类中“this.”(有时this.可以缺省),在其他类中“对象名.”访问
    • 类变量:在当前类中“类名.”(有时类名.可以省略),在其他类中“类名.”或“对象名.”访问
  • 生命周期
    • 局部变量:每一个线程,每一次调用执行都是新的生命周期
    • 实例变量:随着对象的创建而初始化,随着对象的被回收而消亡,每一个对象的实例变量是独立的
    • 类变量:随着类的初始化而初始化,随着类的卸载而消亡,该类的所有对象的类变量是共享的

当局部变量与xx变量重名时,如何区分:

  • 局部变量与实例变量重名
    • 在实例变量前面加“this.”
  • 局部变量与类变量重名
    • 在类变量前面加“类名.”

内存图分析

image-1659916287647

完整代码

/**
 * 变量测试
 *
 * @author Administrator
 */
public class VariableTest {
    static int s;//成员变量,类变量
    int i;//成员变量,实例变量
    int j;//成员变量,实例变量

    {
        int i = 1;//非静态代码块中的局部变量i
        i++;//就近原则:上面一行的i
        //this.i++;
        j++;
        s++;
    }

    public void test(int j) {//形参,局部变量,j
        j++;//就近原则:形参j
        //this.j++;
        i++;
        s++;
    }

    public static void main(String[] args) {//形参,局部变量,args
        VariableTest obj1 = new VariableTest();//局部变量,obj1
        VariableTest obj2 = new VariableTest();//局部变量,obj2
        obj1.test(10);
        obj1.test(20);
        obj2.test(30);
        System.out.println(obj1.i + "," + obj1.j + "," + obj1.s);
        System.out.println(obj2.i + "," + obj2.j + "," + obj2.s);
    }
}
/**
 * 运行结果:
 * 2,1,5
 * 1,1,5
 * <p>
 * 非静态代码块中的i++改为this.i++
 * test方法中的j++改为this.j++看运行结果:
 * 3,3,5
 * 2,2,5
 */

JVM运行时数据区

image-1659916316079

  • 堆,栈,方法区解释
    image-1659916327537

彩蛋

  • 1.jls8.pdf【The Java Language Specification】 java语言规范书籍
    官网
  • 2.栈内存区域是以 方法 区分开的
  • 3.局部变量无默认值,成员变量是有默认值的
  • 4.方法执行与(出栈,入栈)
最近的文章

Spring Bean作用域

Spring Bean的作用域有哪些?可以通过scope属性来指定bean的作用域 singleton:默认值。当IOC容器一创建就会创建bean的实例,而且是单例的,每次得到的都是同一个 prototype:原型的。当IOC容器一创建不再实例化该bean,每次调用getBean方法时再…

继续阅读
更早的文章

递归与迭代分析

编程题:有n步台阶,一次只能上1步或2步,共有多少种走法?递归循环迭代核心代码递归TestStep.java public class TestStep { /** * 实现f(n):求n步台阶,一共有几种走法 * * @param n * @return */ publi…

继续阅读