java面试之局部变量和成员变量的运算

简介

java常见的面试,有一个比较高频就是考察成员变量和局部变量的区别,掌握好这类题的回答,需要对JVM内存划分需要有一定的了解,需要知道什么数据放在JVM内存的哪一个区域里面。

面试题

public class ParameterTest2 {
    static int s;
    int i;
    int j;
    {
        int i =1;
        // 这里就近原则,i计算的上面i=1的值,而不是this.i的值
        i++;
        // 计算this.j
        j++;
        // 计算this.s
        s++;
    }
    public void test(int j) {
      // 这里就近原则,j计算的上面形参j的值,而不是this.j的值
        j++;
   	  // 计算this.i
        i++;
      // 计算this.s
        s++;
    }
    public static void main(String[] args) {
        ParameterTest2 parameterTest2 = new ParameterTest2();
        ParameterTest2 parameterTest3 = new ParameterTest2();
        parameterTest2.test(10);
        parameterTest2.test(20);
        parameterTest3.test(30);
        System.out.println(parameterTest2.i+","+parameterTest2.j+","+ParameterTest2.s);
        System.out.println(parameterTest3.i+","+parameterTest3.j+","+ParameterTest2.s);
    }
}

如果想轻松答出上面的面试题,你需要具备一下基本知识:变量的分类JVM内存模型变量的就近原则非静态代码块的执行

变量的分类

一个类中变量分为局部变量成员变量,下面介绍两者的区别。

  • 声明的位置
    局部变量通常指的是方法的形式参数,在一个方法体中定义的一个变量以及在非静态的代码块中。
    成员变量是指的类中方法外的定义的,如果有static修饰指的就是类变量,如果没有就是实例变量。
  • 值存储位置
    首先看一下JVM的内存区域划分如下图所示:
    在这里插入图片描述
    堆(Heap) 主要存放所有对象的实例,以及数组。
    虚拟机栈(VM Stack)存放局部变量表,对象引用。
    方法区(Method Area) 存放被虚拟机栈加载的类信息、常量、以及静态变量。
  • 声明周期
  • 局部变量:每一个线程,每一次调用执行都是新的生命周期。
  • 实例变量:随着对象的创建而创建,随着对象的销毁而消亡,每一个对象的实例变量是相互独立的。
  • 类变量:随着类的初始化而初始化,随着类的卸载而消亡,该类的对象类变量都是共享的。

就近原则

上面的面试题有两处应用到了就近原则的问题,分别如下所示:

  • 非静态代码块出就近原则
    在这里插入图片描述
  • 方法中就近原则
    在这里插入图片描述

非静态方法代码块

非静态的方法代码块,会随着每一次对象的创建而执行一次。

面试题分析

有了上面的基础知识支撑,下面将一步步分析面试题main方法代码执行的过程。

ParameterTest2 parameterTest2 = new ParameterTest2();

首先创建了ParameterTest2这个对象,此时初始化静态变量s=0,成员变量i=0,j=0,然后执行非静态方法代码块:

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

这儿i++计算的是局部变量i的值(就近原则),j++计算的是成员变量j,s++计算的是静态成员变量s。
所以 代码执行后i=0,j=1,s=1 ,同理当再次创建ParameterTest2的时候,代码执行后i=0,j=1,s=2(s存储在方法区,被其他对象共享)。

 parameterTest2.test(10);

这个调用了实例方法:

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

parameterTest2对象执行test方法之前:i=0,j=1,s=2
这里计算j++计算的是局部变量j(就近原则),i++计算的是成员变量i,s++计算的是静态成员变量s的值。
所以执行方法完后j=1,i=1,s=3,再次调用 parameterTest2.test(10)的执行完方法后时候j=1,i=2,s=4
然后最重要的最后一步:

  parameterTest3.test(30);

parameterTest3对象执行test方法之前:i=0,j=1,s=4
然后这里执行方法完后i=1,j=1,s=5。注意s静态变量被parameterTest2与parameterTest3对象所共享的。
所以上面面试题的输出结果为:
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值