Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/api/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么我能';是否在未初始化的局部变量上设置断点?_Java_Breakpoints_Local Variables - Fatal编程技术网

Java 为什么我能';是否在未初始化的局部变量上设置断点?

Java 为什么我能';是否在未初始化的局部变量上设置断点?,java,breakpoints,local-variables,Java,Breakpoints,Local Variables,为什么我不能在字符串a的第行设置断点 public void localMethod() { String a; a = "haha"; System.out.println(a); } 我知道在我显式地给局部变量赋值之前,它不会被初始化。 但这是一行代码,它做了一些事情。为什么我不能停在那里? 哪些行可以作为断点 我使用的是Eclipse,jdk6_31声明本身并不是真正的可执行代码——它只是声明某些东西的存在。您应该能够在第二行上放置断点,这实际上起到了作用 诚然,

为什么我不能在
字符串a的第行设置断点

public void localMethod() {
    String a;
    a = "haha";
    System.out.println(a);
}
我知道在我显式地给局部变量赋值之前,它不会被初始化。 但这是一行代码,它做了一些事情。为什么我不能停在那里? 哪些行可以作为断点


我使用的是Eclipse,jdk6_31

声明本身并不是真正的可执行代码——它只是声明某些东西的存在。您应该能够在第二行上放置断点,这实际上起到了作用

诚然,我不认为IDE有任何理由不支持在非可执行行中添加断点的概念-它可能必须在执行环境中的可执行点安装断点

编辑:为了澄清我的意思,此代码:

public void foo() {
    String a;
    String b;
    a = "hello";
    b = " world";
    System.out.println(a + b);        
}
将编译为与以下相同的字节码:

public void foo() {
    String a;
    a = "hello";
    String b;
    b = " world";
    System.out.println(a + b);        
}

由于声明的原因,不需要执行任何代码-它在该时间点或类似的时间点上不保留空间。编译器在方法的堆栈空间中分配一个“插槽”,并将在整个方法中使用该插槽,但它可以重用相同的插槽,而无需额外初始化,例如,即使变量在循环中声明。

断点是由IDE/编译器监视正在执行的某些行生成的。这些由字节码中的行号表示。表示变量声明和初始化的字节码在编译期间合并为一个步骤。因此,如果变量的声明从赋值中分离出来,则生成的字节码中没有断点可用

下面是您示例的字节码:

public class Example {
    public void localMethod() {
        String a;
        a = "haha";
        System.out.println(a);
    }
}
致:

公共类堆栈溢出/示例{
//编译自:Example.java
//访问标志0x1
公共()V
L0
6号线L0
阿洛德0
调用特定的java/lang/Object。()V
返回
L1
LOCALVARIABLE此Lstackoverflow/示例;L0 L1 0
MAXSTACK=1
最大局部数=1
//访问标志0x1
公共localMethod()V
L0
9号线L0
土发公司“哈哈”
阿斯托尔1号
L1
线路号10 L1
GETSTATIC java/lang/System.out:Ljava/io/PrintStream;
阿洛德1号
INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
L2
行号11 L2
返回
L3
LOCALVARIABLE此Lstackoverflow/示例;L0 L3 0
LOCALVARIABLE a Ljava/lang/String;L1 L3 1
MAXSTACK=2
最大局部数=2
}

请注意,第8行没有行号标记,它在我的IDE中表示
字符串a
声明。

没有与
a
局部变量声明相对应的字节码,因此不能在声明时设置断点,只能在初始化时设置

Sample.java:

class Sample {
public void localMethod() {
    String a;
    a = "haha";
    System.out.println(a);
}
}
javac Sample.java;javap-c示例

class Sample extends java.lang.Object{
Sample();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public void localMethod();
  Code:
   0:   ldc #2; //String haha
   2:   astore_1
   3:   getstatic   #3; //Field java/lang/System.out:Ljava/io/PrintStream;
   6:   aload_1
   7:   invokevirtual   #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   10:  return

}
类示例扩展了java.lang.Object{
样本();
代码:
0:aload_0
1:invokespecial#1;//方法java/lang/Object。“:()V
4:返回
public void localMethod();
代码:
0:ldc#2;//字符串哈哈
2:astore_1
3:getstatic#3;//字段java/lang/System.out:Ljava/io/PrintStream;
6:aload_1
7:invokevirtual#4;//方法java/io/PrintStream.println:(Ljava/lang/String;)V
10:返回
}

断点允许用户在特定位置暂停程序的执行。断点通常与源代码一起显示在UI中。当在程序执行过程中遇到断点时,程序将挂起并触发以断点为原因的挂起调试事件。
现在。。当你编译它的时候。。声明和赋值在一个步骤中完成。。首先声明,然后分配一个值。因此,最后一步是分配。因此,您可以在分配上设置断点,但不能在声明上设置断点。

在这段代码中,您试图在何处设置断点?在
字符串a
?您使用的是什么IDE/调试器?什么Java版本?我认为这个答案很有道理。谢谢。我添加了更多的内容来演示这个想法。实际上没有任何字节码来表示变量的声明。对,这就是我的观点。没有表示变量声明的字节码。这基本上与字节码中变量的初始赋值相结合。@Ziyanzhang:你认为呢?你认为当这个代码被“执行”时会发生什么?请记住,方法所需的堆栈空间是在方法开始时分配的,而不是“按需”…我的理解是字符串;和a=“哈哈”;编译后编写原子可执行命令集。在一个原子可执行命令集的中间停止是没有意义的,所以我不能在“string a”上断点,但是可以在a=“哈哈”上做。我可能误解了你所说的“可执行文件”的意思。@ziyanzhang:它根本不是原子的。您可能早就声明了这个变量。赋值是原子的,但声明是完全独立的,不做任何事情。假设您将另一个变量的声明放在
a
声明和赋值之间。这本来是完全合法的——但和你们关于“声明和赋值”组成“原子可执行命令集”的想法相矛盾“您并不是在调试您所看到的内容。您实际上是在调试字节码,而不是源代码。一些在源代码中不相邻的句子可能会被编译成一组原子命令“我想了想你说的话。我认为在这种情况下,编译器将重新排列声明和初始化语句,并将它们变成几个原子命令集。每个命令集包括声明和初始化。更重要的是,如果一个局部变量只是声明的,而不是初始化的,编译器可能会忽略这一行。@Ziyanzhang:不,它不会“洗牌”它们-它根本不需要
class Sample extends java.lang.Object{
Sample();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public void localMethod();
  Code:
   0:   ldc #2; //String haha
   2:   astore_1
   3:   getstatic   #3; //Field java/lang/System.out:Ljava/io/PrintStream;
   6:   aload_1
   7:   invokevirtual   #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   10:  return

}