【if语句作用域】

握草 2018-02-03 02:49:30
我们都知道,方法的调用机制的实现底层原理是“栈结构”,即当一个方法被调用时,它被指针指示在栈顶,这时候方法中的所有局部变量入栈,并进入这些变量的作用区间,我在想,同样的原理是不是可以运用于if语言(或者说以if为代表的一系列语句块,比如switch语句,但是前提是这些语句都是写在方法里面的)

如图,我在if语句块中定义了一个局部变量b,可以看到出了if语句块后它就不可见了——请问它的作用域为什么只限于if语句块里面??
据我所知,只有方法才有所谓的“栈帧”、“弹栈”、“压栈”操作,这样才保证了不同方法见的互相独立性。。可以从这个图片的例子总看到,变量出了“块”(而不仅仅是方法块,是方法块中更小的“if语句块”)也是不可见的——
请问这是怎么实现的??if语句也没有所谓的栈帧??这样的可见性的限制是如何实现的???
...全文
1371 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
a15917579239 2018-02-07
  • 打赏
  • 举报
回复
在java来说这是一个局部变量的问题 b是在if的{}里面定义的,就只能在if{}里面使用, 楼主可以去查看一下局部变量和成员变量你这个问题就解决啦
双木L 2018-02-07
  • 打赏
  • 举报
回复
楼主截图的代码不会报编译错误吗?if(){}花括号里面定义的局部变量在外面怎么可以获取到?首先这是语法错误,更不用说编译原理了
ChongQingJin28 2018-02-05
  • 打赏
  • 举报
回复
楼上 变量只有 abc
ChongQingJin28 2018-02-05
  • 打赏
  • 举报
回复
自己总结吧 好像就是 if else 中两个同名的变量会存放在一起,但是你必须声明 可能的实现就是,if else 有一个变量名与位置的对应总表,但必须通过声明才能加入到 if 或else的子表中 问题: 1.如果 else 中的 int b 不初始化会怎么样(可能编译器不通过 但是可以改Class文件的吧) 2.如果在if else之外加一个 int d ,他是否会用istore_4存储呢?
真相重于对错 2018-02-05
  • 打赏
  • 举报
回复
引用 7 楼 zhouchongzxc 的回复:
自己总结吧 好像就是 if else 中两个同名的变量会存放在一起,但是你必须声明 可能的实现就是,if else 有一个变量名与位置的对应总表,但必须通过声明才能加入到 if 或else的子表中 问题: 1.如果 else 中的 int b 不初始化会怎么样(可能编译器不通过 但是可以改Class文件的吧) 2.如果在if else之外加一个 int d ,他是否会用istore_4存储呢?
那个指向一个新的变量,和前边的d,完全没有关系。
ChongQingJin28 2018-02-05
  • 打赏
  • 举报
回复
以后有问题 可以看看虚拟机规范偶
ChongQingJin28 2018-02-05
  • 打赏
  • 举报
回复
测试一下就知道了吧

public class CC{

  public static void main(String[] args){

    int a = 1;

    if(a==1){
      int b = 2;
      System.out.println(b);
    }else{
      int b = 3;
      System.out.println(b);
    }
  }
}

javac CC.java
javap -c CC

C:\Users\Administrator>javap -c CC
Compiled from "CC.java"
public class CC {
  public CC();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_1
       1: istore_1
       2: iload_1
       3: iconst_1
       4: if_icmpne     19
       7: iconst_2
       8: istore_2
       9: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      12: iload_2
      13: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
      16: goto          28
      19: iconst_3
      20: istore_2                    // 我的注释  看看虚拟机规范就可以了
      21: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      24: iload_2
      25: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
      28: return
}

public class CC{

  public static void main(String[] args){

    int a = 1;

    if(a==1){
      int b = 2;
      System.out.println(b);
    }else{
      b = 3;
      System.out.println(b);
    }
  }
}

javac CC.java

CC.java:11: 错误: 找不到符号
      b = 3;
      ^
  符号:   变量 b
  位置: 类 CC
CC.java:12: 错误: 找不到符号
      System.out.println(b);
                         ^
  符号:   变量 b
  位置: 类 CC
2 个错误


public class CC{

  public static void main(String[] args){

    int a = 1;

    if(a==1){
      int b = 2;
      System.out.println(b);
    }else{
      int b = 3;
      int c = 4;
      System.out.println(b+c);
    }
  }
}

// javac   javap 之后

C:\Users\Administrator>javap -c CC
Compiled from "CC.java"
public class CC {
  public CC();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_1
       1: istore_1
       2: iload_1
       3: iconst_1
       4: if_icmpne     19
       7: iconst_2
       8: istore_2
       9: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      12: iload_2
      13: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
      16: goto          32
      19: iconst_3
      20: istore_2
      21: iconst_4
      22: istore_3
      23: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      26: iload_2
      27: iload_3
      28: iadd
      29: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
      32: return
}


maradona1984 2018-02-05
  • 打赏
  • 举报
回复
个人觉得这个限制是编译器编译的时候限制,而不是执行class的时候去限制
真相重于对错 2018-02-05
  • 打赏
  • 举报
回复
要想深究这些东西,最好用c++看最后的反汇编就清楚,java运行前还要编译一次。 拿你的代码来说,,如果代码里在那个括号外访问b,编译就会出错,b是值类型,括号结束后,它应该还在栈里,只是你无法访问它,如果是引用类型,并且没有任何变量引用它的话,会被回收。
真相重于对错 2018-02-05
  • 打赏
  • 举报
回复
这是由编译器决定的 !
握草 2018-02-03
  • 打赏
  • 举报
回复
我知道。。可是他是怎么实现的呢?又没有用程序指针之类的东西———if语句的粒度太小,程序的指针通常是指向方法栈顶的,而if语句则在方法里面。。
zqfddqr 2018-02-03
  • 打赏
  • 举报
回复
跟着花括号走的

62,612

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧