问个局部变量问题 java中局部变量int a=3在栈空间是怎么储存的,编译时a的表现形式是啥?,String str=“abc”中的str是不是跟c中的指针一个性质 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 局部变量 int a = 3;变量名a和3是同时储存在栈里面,a指向3。如果这时,也来一个局部变量 int b = 3;那么程序此时就不会重新为3开辟栈空间,而是让b也指向a所指向的3。之后如果b或者a做运算的话例:b=b+3;那么程序会另外开辟一个栈空间存放6,然后b指向储存6的栈空间。------------------------------String str=“abc”中str是跟c指针有相同的性质。 java 分栈 和 堆int a=3, 变量a 在栈中, 3在堆中,a指向3,String str1=“abc”;String str2=“abc”;str1,str2 都指向堆中的abc,abc在堆中只有一个,同一地址 java中的引用变量可以认为是c中的指针变量。Student student = new Student(). studnet指向new Studnet()这个对象,所以可以认为student是指向它的指针变量 吐血了,为什么这么多不一样的结论,那天看到一个帖子分析的,我取一段,"打开class文件,int a=3就4个字节,内容是“06 3B第1个字节06 iconst_3是一个指令,这个指令就是让CPU把寄存器放上3的值第2个字节3B istore_0也是一个指令,就是让CPU把寄存器的值放到第1个变量的内存中,不是很懂,你们的说法好像都被否定了,有人更明白的吗" 大体分析一下1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。//栈都是由运行环境来处理的,这点C++和java没有什么不同.对于堆,不过java多了个GC.2.这里的堆和栈首先要明确是虚拟机栈,和寄存器根本不是一个级别的东西,就别比较了.3.栈数据共享好像是作者自己创造的概念.而且给基本类型也引入了"引用"的概念,不知道出于何种打算.java虚拟机规范中说:Primitive values do not share state with other primitive values. A variable whose type is a primitive type always holds a primitive value of that type.看一下实际的处理情况: int a=3; int b=3; int c=65535; int d=65535; int e=32330; int f=32330;看对应的虚拟机指令,可以知道变量里实际存储的是什么:Code: 0: iconst_3 //3 1: istore_1 2: iconst_3 //3 3: istore_2 4: ldc #2; //int 65535 6: istore_3 7: ldc #2; //int 65535 9: istore 4 11: sipush 32330 14: istore 5 16: sipush 32330 19: istore 6 21: return可以看出每个变量保存自己的值.(具体指令的意义参考java虚拟机规范)这里要注意的是对于int值,如果它大于short能表示的范围,则放到常量池中去.11: sipush 32330 14: istore 5这句,11-13,正好是3个字节的指令大小,一个字节是sipush指令,2个字节用来存储32330这个数.两次使用到这个数,都是把它直接存给变量的,所以原贴中一直强调的"栈中共享" 的说法明显不对.对于65535,它是大于两个字节的,编译的时候把它放入常量池部分,而把取这个数的指令写为ldc#2,我感觉这样一个直观的好处是减少了指令代码的长度.尤其是多次使用到一个相同的数时. 其实,java 对变量的处理很简单,基本类型变量存放值,引用类型存放一个"引用" (实际就是一个"指针" ,以前曾经和别人讨论过,很多人认为是个"句柄",并举了很多证据,但是我后来看到了sun的java hotspot白皮书,里面直接说明了,引用实际就是一个c的"指针" ,使用句柄需要多次间接查找,会带来效率的瓶颈,当然这个指针并不是直接指向实际的对象,实际指向的是一个两个机器字大小的对象头,对于数组是3个机器字大小的对象头,因为还要保存数组的长度) .java设计时保留基本类型而不把一切都设计为对象,就是出于效率考虑,如果对于基本类型再通过"引用"去查找值,何苦呢?4.String也是包装类? 这应该也是作者自己定义了包装类的概念,去java语言规范里看看什么是wrapper class.5.Integer i = 3;编译器如何处理?sun的编译器是这样处理的:Integer i=Integer.valueOf(3);而不是通过new来创建了,因为Integer类中静态的创建了-128~+127之间的对象,需要的数在这个范围之内时,直接返回,此范围之外的数才通过new来创建.简单测试.Integer i=3;Integer j=3;我们测试i==j会发现它是true.String str = new String("abc");去看String类的构造方法会发现,这里用的是String(String original)来创建的,也就是说用一个String来创建一个String,"abc"编译的时候编译器会把它加入常量池部分.不知道原贴所谓的包装类是如何得来的.csdn 的java版有个“推荐”的专门讲String常量池的帖子,很不错。5."JVM发现在栈中没有存放该值的地址,便开辟了这个地址,并创建了一个新的对象,其字符串的值指向这个地址。 "又没有分清编译器和虚拟机的职责分配.编译器会把"abc"放入常量池,并记住它在常量池中的位置,别的地方用到的时候编译器直接生成ldc指令来制定了,不会让jvm去找,去开辟地址等等.7.原贴明显不知道常量池的存在,好像是把常量池的数据都认为是"栈"的了. java新增了StringBuilder来处理可变字符串,如果不需要多线程环境,应该首先选择这个,而不是StringBuffer,一个zangTX大侠总结的. JPanel p=new JPanel(new BorderLayout());问个问题哈,new的对象里面new另外一个东西.这个在java里面有啥学术名称没譬如说new BufferedReader(new InputStreamReader(new FileInputstream()));小弟愚钝,求指教 java源码阅读求指导,有这发面经验的同仁给点建议哈! 构造函数问题 Java Swing JTree的一个问题,急啊!!! [swing]世界地图 JTable选中单元格插入数据? java如何释放内存单元~ 请教JAVA程序员的问题! main方法为什么一定要是static的? 问一个比较简单的关于URL请求的问题 一个菜鸟级的存储过程问题 JApplet可以在appletViewer中查看…却不能在HTML中运行…求解…… 链接是一个增值且简便的过程是什么意思
变量名a和3是同时储存在栈里面,
a指向3。如果这时,也来一个局部变量 int b = 3;
那么程序此时就不会重新为3开辟栈空间,
而是让b也指向a所指向的3。之后如果b或者a做运算的话
例:b=b+3;
那么程序会另外开辟一个栈空间存放6,
然后b指向储存6的栈空间。
------------------------------
String str=“abc”中str是跟c指针有相同的性质。
int a=3, 变量a 在栈中, 3在堆中,a指向3,
String str1=“abc”;
String str2=“abc”;
str1,str2 都指向堆中的abc,abc在堆中只有一个,同一地址
studnet指向new Studnet()这个对象,所以可以认为student是指向它的指针变量
第2个字节3B istore_0也是一个指令,就是让CPU把寄存器的值放到第1个变量的内存中,不是很懂,你们的说法好像都被否定了,有人更明白的吗
"
1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。
//栈都是由运行环境来处理的,这点C++和java没有什么不同.对于堆,不过java多了个GC.
2.这里的堆和栈首先要明确是虚拟机栈,和寄存器根本不是一个级别的东西,就别比较了.
3.栈数据共享好像是作者自己创造的概念.而且给基本类型也引入了"引用"的概念,不知道出于何种打算.
java虚拟机规范中说:Primitive values do not share state with other primitive values. A variable whose type is a primitive type always holds a primitive value of that type.
看一下实际的处理情况:
int a=3;
int b=3;
int c=65535;
int d=65535;
int e=32330;
int f=32330;
看对应的虚拟机指令,可以知道变量里实际存储的是什么:
Code:
0: iconst_3 //3
1: istore_1
2: iconst_3 //3
3: istore_2
4: ldc #2; //int 65535
6: istore_3
7: ldc #2; //int 65535
9: istore 4
11: sipush 32330
14: istore 5
16: sipush 32330
19: istore 6
21: return
可以看出每个变量保存自己的值.(具体指令的意义参考java虚拟机规范)
这里要注意的是对于int值,如果它大于short能表示的范围,则放到常量池中去.
11: sipush 32330
14: istore 5
这句,11-13,正好是3个字节的指令大小,一个字节是sipush指令,2个字节用来存储32330这个数.两次使用到这个数,都是把它直接存给变量的,所以原贴中一直强调的"栈中共享" 的说法明显不对.
对于65535,它是大于两个字节的,编译的时候把它放入常量池部分,而把取这个数的指令写为ldc#2,我感觉这样一个直观的好处是减少了指令代码的长度.尤其是多次使用到一个相同的数时. 其实,java 对变量的处理很简单,基本类型变量存放值,引用类型存放一个"引用" (实际就是一个"指针" ,以前曾经和别人讨论过,很多人认为是个"句柄",并举了很多证据,但是我后来看到了sun的java hotspot白皮书,里面直接说明了,引用实际就是一个c的"指针" ,使用句柄需要多次间接查找,会带来效率的瓶颈,当然这个指针并不是直接指向实际的对象,实际指向的是一个两个机器字大小的对象头,对于数组是3个机器字大小的对象头,因为还要保存数组的长度) .
java设计时保留基本类型而不把一切都设计为对象,就是出于效率考虑,如果对于基本类型再通过"引用"去查找值,何苦呢?
4.String也是包装类? 这应该也是作者自己定义了包装类的概念,去java语言规范里看看什么是wrapper class.
5.Integer i = 3;编译器如何处理?
sun的编译器是这样处理的:
Integer i=Integer.valueOf(3);
而不是通过new来创建了,因为Integer类中静态的创建了-128~+127之间的对象,需要的数在这个范围之内时,直接返回,此范围之外的数才通过new来创建.
简单测试.
Integer i=3;
Integer j=3;
我们测试i==j会发现它是true.
String str = new String("abc");去看String类的构造方法会发现,这里用的是String(String original)来创建的,也就是说用一个String来创建一个String,"abc"编译的时候编译器会把它加入常量池部分.不知道原贴所谓的包装类是如何得来的.
csdn 的java版有个“推荐”的专门讲String常量池的帖子,很不错。
5."JVM发现在栈中没有存放该值的地址,便开辟了这个地址,并创建了一个新的对象,其字符串的值指向这个地址。 "又没有分清编译器和虚拟机的职责分配.编译器会把"abc"放入常量池,并记住它在常量池中的位置,别的地方用到的时候编译器直接生成ldc指令来制定了,不会让jvm去找,去开辟地址等等.
7.原贴明显不知道常量池的存在,好像是把常量池的数据都认为是"栈"的了.
java新增了StringBuilder来处理可变字符串,如果不需要多线程环境,应该首先选择这个,而不是StringBuffer,一个zangTX大侠总结的.
问个问题哈,new的对象里面new另外一个东西.这个在java里面有啥学术名称没
譬如说new BufferedReader(new InputStreamReader(new FileInputstream()));
小弟愚钝,求指教