public class TestArray {
public static void main(String[] args) {
String a1[] = new String [3];
String a2[] = new String [3];
System.out.println(a1==a2); //false;
System.out.println(a1[2]==a2[2]); //true; 请用内存解析为什么是true!
a1[1] = new String("hello");
a2[1] = new String("hello");
System.out.println(a1[1] == a2[1]); //false; 请用内存解析 为什么是false;
//并对照上面的true,说出区别!
a1[1] = null;
a2[1] = null;
System.out.println(a1[1] == a2[1]); // true; 对照所有的解析,说出地址分析区别!
}
}
/* 提问: A a[] = new A [a.length];
1.定义一个数组a是new出来的, 里面分配了a.length个空间吗?.
2.这些空间有没有各自的地址以区分他们?例如前驱,后继!
3.== 号是不是地址和值两项的比较?
4.==号是不是只有两项全为true时,才为true?
5. a[i] 代表什么,是代表了值,还是地址,还是代表了两项?
6. 如果a[i] 只代表了一项,那另一项是靠什么来区分?.
7.a[i] == a[j] ; 为true时; 有没有比较他们的地址?,
如果没有! 请说出为什么?
8.综合上述 说出 引用,指针,地址,变量,内存解析和区别!
*/
public static void main(String[] args) {
String a1[] = new String [3];
String a2[] = new String [3];
System.out.println(a1==a2); //false;
System.out.println(a1[2]==a2[2]); //true; 请用内存解析为什么是true!
a1[1] = new String("hello");
a2[1] = new String("hello");
System.out.println(a1[1] == a2[1]); //false; 请用内存解析 为什么是false;
//并对照上面的true,说出区别!
a1[1] = null;
a2[1] = null;
System.out.println(a1[1] == a2[1]); // true; 对照所有的解析,说出地址分析区别!
}
}
/* 提问: A a[] = new A [a.length];
1.定义一个数组a是new出来的, 里面分配了a.length个空间吗?.
2.这些空间有没有各自的地址以区分他们?例如前驱,后继!
3.== 号是不是地址和值两项的比较?
4.==号是不是只有两项全为true时,才为true?
5. a[i] 代表什么,是代表了值,还是地址,还是代表了两项?
6. 如果a[i] 只代表了一项,那另一项是靠什么来区分?.
7.a[i] == a[j] ; 为true时; 有没有比较他们的地址?,
如果没有! 请说出为什么?
8.综合上述 说出 引用,指针,地址,变量,内存解析和区别!
*/
此时候应该还未分配地址空间,应该是都指想同一中间数据结构,所以System.out.println(a1[2]==a2[2]); 这个应该是true;a1[1] = new String("hello");
a2[1] = new String("hello");
System.out.println(a1[1] == a2[1]); 此时才为a1[1]、a2[1]在堆中分别分配了空间,所以会显示false,如果你System.out.println(a1[2] == a2[2]); 你会发现依然是true
public static void main(String[] args) {
String a1[] = new String [3];
String a2[] = new String [3];
System.out.println(a1==a2); //false; 比较的是两个数组在内存中的首地址
System.out.println(a1[2]==a2[2]); //true; 因为String类在内存中有个缓冲池,所以你不赋值给它的时候,他们都是NULL,用同个缓存池中的地址 (你可以用StringBuffer类去对比一下)
a1[1] = new String("hello");
a2[1] = new String("hello");
System.out.println(a1[1] == a2[1]); //false;同上面,因为创建了新空间了
a1[1] = null;
a2[1] = null;
System.out.println(a1[1] == a2[1]); // true; 同上
}
}
String a2[] = new String [3];
System.out.println(a1==a2); // == 用于两个对象之间 比较引用 所以返回false
System.out.println(a1[2]==a2[2]); // a1[2]和a2[2]都是 null 所以返回truea2[1] = new String("hello");
a2[1] = new String("hello"); System.out.println(a1[1] == a2[1]); //false; 用于两个对象之间 比较引用 所以返回false本人小菜哇 说错了别怪
public static void main(String[] args) {
String a1[] = new String [3];
String a2[] = new String [3];
System.out.println(a1==a2); //false; 比较的是两个数组在内存中的首地址
System.out.println(a1[2]==a2[2]); //true; 因为String类在内存中有个缓冲池,所以你不赋值给它的时候,他们都是NULL,用同个缓存池中的地址 (你可以用StringBuffer类去对比一下) a1[1] = new String("hello");
a2[1] = new String("hello");
System.out.println(a1[1] == a2[1]); //false;同上面,因为创建了新空间了
a1[1] = null;
a2[1] = null;
System.out.println(a1[1] == a2[1]); // true; 同上
}
}
String a2[] = new String [3]; 在这里创建了两个数组,他们的引用肯定不一样!System.out.println(a1==a2); 自然没什么好说的! System.out.println(a1[2]==a2[2]); 数组里面在你没有赋值前都是为null的,他们肯定相等阿!a1[1] = new String("hello");
a2[1] = new String("hello");
System.out.println(a1[1] == a2[1]) a1[1],a2[1]别new创建了一个对象,他们的地址也肯定是不同的,如果你改成
a1[1] = new String("hello");
a2[1] = new String("hello");
这样他们的地址肯定是一样的了,a1[1] = null;
a2[1] = null;
System.out.println(a1[1] == a2[1]); 你又再次清空他的引用,他们的他们引用为空,肯定判断地址是相同的,跟你的第一个问题是一样的!1.定义一个数组a是new出来的, 里面分配了a.length个空间吗?.
他是分配了a.length个空间,但是空间里面保存的都是引用,也就是地址,如果你没赋值前都是null,这些空间有没有各自的地址以区分他们
这个空间里面保存的是一个引用,他就是用a[下标]去取的!==号是不是地址和值两项的比较
==号比较对象只是比较地址不比较值的!比较值类型自然就是比较值了!4.==号是不是只有两项全为true时,才为true?
上面的问题都知道了,这个问题没必要回答了吧!5. a[i] 代表什么,是代表了值,还是地址,还是代表了两项?
代表引用,也就是地址!6. 如果a[i] 只代表了一项,那另一项是靠什么来区分?.
有了引用自然可以找到值,String str = new String ("abc");这里str也是引用,为什么你输出str会等于abc为什么不是地址呢?如果要问这样的问题。我确实也不知道怎么回答你!7.a[i] == a[j] ; 为true时; 有没有比较他们的地址?,
就是在比较地址!在java里面没有指针,有的人把引用也当作指针,举例来说。java的引用相当于电视的遥控,有了遥控就可以控制换台,在java中,引用就是地址,
代表引用,也就是地址!String a1[] = new String [3];
String a2[] = new String [3]; 在这里创建了两个数组,他们的引用肯定不一样!System.out.println(a1==a2); 自然没什么好说的! System.out.println(a1[2]==a2[2]); 这是两个数组里的地址, 他们地址怎么会为true呢?
代表引用,也就是地址!
String a1[] = new String [3];
String a2[] = new String [3]; 在这里创建了两个数组,他们的引用肯定不一样!System.out.println(a1==a2); 自然没什么好说的! System.out.println(a1[2]==a2[2]); 这是两个数组里的地址, 他们地址怎么会为true呢?>>>>>>a1[2]记录的是String对象的地址, String对象的地址记录的才是里面数值真正的空间
public static void main(String[] args) {
String a1[] = new String [3];
String a2[] = new String [3];
System.out.println(a1==a2); //false;
System.out.println(a1[2]==a2[2]); //true; 这个比较的不是地址,而是地址里存的值,
a1[1] = new String("hello");
a2[1] = new String("hello");
System.out.println(a1[1] == a2[1]); //false; 两个里边村的是string对象的地址,因为是两个不同地址的string对象,所以不等;
//并对照上面的true,说出区别! a1[1] = null;
a2[1] = null;
System.out.println(a1[1] == a2[1]); // 因为数组里面的地址都是空,所以相等.
}
}
你可以把== 和equal()作以下对比
也就是说: stack , heap data segment, code segment, 里面存放的东西!~stack 是不是存放 变量 和引用?
heap 是不是只存放的指针属性( 也就是连接地址)
data segment 里存放的究竟是什么, 说是常量和静态变量, 只有这些吗?.
按照你的解释,string对象的地址记录才是里面数值真正的空间
也就是说我们建立了一个数组之后, a[i] 只是在代表引用,它指向最后的指向空间吗?
那么再看下面这个!说出你的解释:a1[1] = new String("hello");
a2[1] = new String("hello"); 好象是对象最后都指向了data segment里的"hello";
可是为什么他们却不相同呢?
1.定义一个数组a是new出来的, 里面分配了a.length个空间吗?.
String[] s = new String[5];jvm中有三类内存区域,栈内存、堆内存和静态存储。
栈内存(stack)在随机访问存储器(RAM)内,一般通过堆栈指针进行操作,它是按顺序分配内存空间的,当堆栈指针下移一位则分配一个单元内存空间,上移则释放空间。String[] s = new String[5];这个语句是在栈内存中分配了五个空间,它们可以通过变量s[0]...s[5]进行索引,它的内容是在堆内存中分配的5个空间的内存地址。我们可以把它们当作5个指针。
例如:Java的基本数据类型(int byte boolean ....)分配内存都是在栈内存上。堆内存(heap)同样在RAM中,它保存对象和前者不一样,编译器不知道将要分配多大内存空间给该对象,也不知道这个对象要存在多长时间,用它保存数据将会获得很大的灵活性。我们都知道,JAVA中我们无法直接做任何回收的动作,而只能提示jvm该回收垃圾了。那么堆内存中的对象,时刻要被java回收机制线程监控,判断是否该变量已经超过了作用域,从而回收它。灵活性和回收机制,让堆内存比栈内存更消耗系统资源,效率更低。当我们做s[0] = new String("123");才完成对堆内存中s[0]指向的内存空间初始化,我们才可以引用这个对象。
当你调用System.out.println(s[0]); jvm将会从s[0]中读取到它的内存地址,将内容输出在控制台上。而如果你输出的是s[0].toString();那么你将看到s[0]所保存的内存地址。静态存储(static)同样在RAM中,这里的静态意味着位置固定,它在类被加载时,就已经在RAM中分配了空间,并完成了初始化。例如:
A a;这个类声明语句,就已经完成了初始化。2.==号是不是地址和值两项的比较
“==”比较的是内存地址,例如:
String s1 = "123";
String s2 = "123";
s1 == s2,这里比较的是栈内存中s1与s2的值。java中,比较对象的内容是通过s1.equals(s2);这种方式进行的。
当然上面的比较结果是true的。但是下面这种情况,结果就是false:
String s1 = "123";
String s2 = "1" + "23";
我们通过equals方法比较,才能得到true的结果。
5. a[i] 代表什么,是代表了值,还是地址,还是代表了两项?
a[i]是引用,你可以把它仅仅当作一个名字,它的内容是内存地址,而当你调用它时,jvm拿给你的是它所保存的内存地址(即heap内存上的地址)上的实际值。以前很多关于java值传递和引用传递的帖子,总结一下吧!
class A {
int i = 10;
}int i = 100;
这里有两个对象a.i与i(a是A的一个实例)。接下来有一个方法,如下:
public void Add(int i) {
i = 20;
}
分别调用:
Add(a.i);
Add(i);当你输出a.i和i时,你会发现:
a.i = 20;
i = 100;
a.i传递的是引用,Add方法将a.i的指向转变了,它不在指向heap堆中的内容为“i = 10”的对象了,而指向“i = 20”的对象;i传递的是值,也就是说是一个副本,Add方法修改的只是一个copy,而栈内存中i还是等于100。
6. 如果a[i] 只代表了一项,那另一项是靠什么来区分?.
7.a[i] == a[j] ; 为true时; 有没有比较他们的地址?,
你这样问,让我怎么回答你呢?
“在java里面没有指针,有的人把引用也当作指针,举例来说。java的引用相当于电视的遥控,有了遥控就可以控制换台,在java中,引用就是地址”
java中指针无处不在,只是说,作为程序员你无法感觉到它的存在,无法直接操作它。
但是下面这种情况,结果就是false:
String s1 = "123";
String s2 = "1" + "23";
我们通过equals方法比较,才能得到true的结果。 LS的 上面用s1 == s2;的出来的也是true!
String s1 = "123";
String s2 = "1" + "23";
我们通过equals方法比较,才能得到true的结果。 s1 与 s2还是指向同一个内存地址!
有些说的是对的,可是不知道为什么还是走向误区了呢?
虽然说了很多, 但是还是得不到意想的结果!~第一个:
当然上面的比较结果是true的。但是下面这种情况,结果就是false:
String s1 = "123";
String s2 = "1" + "23"
//错误了, 比较s1==s2,结果还为true! 由此可看比较的不是内存地址!~
第二个:
例如:Java的基本数据类型(int byte boolean ....)分配内存都是在栈内存上。 //根据我目前掌握知识的理解, 变量的分配才在栈内存中,而且不光是基本数据类型,是包括所有的数据类型,
常量是分配在data segment中!
第三个:
当我们做s[0] = new String("123");才完成对堆内存中s[0]指向的内存空间初始化,我们才可以引用这个对象。//(老师讲的) : 堆内存中就是存放那些new出来的东西, 可是老师并没有说new出来的东西究竟是什么, 根据我理解new出来应该属于对象了, 所以对堆内存里面存放的究竟是地址还是别的内容,请解答一下!
String str2 = new String("abc");
String str3 = "abc";
String str4 = "abc";
System.out.println(str1 == str2); //false
System.out.println(str3 == str4); //true
以上这个结果可能大家都知道,但具体的原因是什么啊?str1,str2是new的,而两个是直接赋值的
再一个说明的是数组的问题,
刚才解释第二个的时候说的有点漏了, 静态变量不在栈中, 而在data segment!期望得到内存解析的一个完整的图!~ 我的QQ是42578670!~ 希望大家可以来探讨!
有些说的是对的,可是不知道为什么还是走向误区了呢?
虽然说了很多, 但是还是得不到意想的结果!~
第一个:
当然上面的比较结果是true的。但是下面这种情况,结果就是false:
String s1 = "123";
String s2 = "1" + "23"
//错误了, 比较s1==s2,结果还为true! 由此可看比较的不是内存地址!~ 第二个:
例如:Java的基本数据类型(int byte boolean ....)分配内存都是在栈内存上。 //根据我目前掌握知识的理解, 变量(静态变量除外)的分配才在栈内存中,而且不光是基本数据类型,是包括所有的数据类型,
常量是分配在data segment中! 第三个:
当我们做s[0] = new String("123");才完成对堆内存中s[0]指向的内存空间初始化,我们才可以引用这个对象。 //(老师讲的) : 堆内存中就是存放那些new出来的东西, 可是老师并没有说new出来的东西究竟是什么, 根据我理解new出来应该属于对象了, 所以对堆内存里面存放的究竟是地址还是别的内容,请解答一下!
是不是以前研究C/C++比较多的缘故?我对这个问题的看法是:Java里面没有指针,就无法看到地址,我们都知道==就是比较地址而已,这是永远不变的!
如果楼主觉得诧异,那么我列举这个例子:public class Test{
private staitc String ss ;
public static void main(String args[]){
String[] aa = new String[3]; System.out.println(ss==aa[2]); //楼主觉得这会是true还是false呢?
}
}显然是true,因为大家都是null,所有的null在内存中就是同一地址,否则Java里面那么多没初始化的null,难道每个都需要占据一块内存地址空间么?
如果楼主一定要追寻它的内存地址是多少,那不是属于Java的范畴,在Window内存分配中有表格列出来那片区域,可以找本Windows核心编程查查就知道了
String a3[] ={"中国","日本","美国"};
String a4[] ={"中国","日本","美国"};
System.out.println(a3[1]==a4[1]);这会不是null了吧, 可是还是 true, 你说比较地址, 这个还是同一指向吗?.不是说对地址和指针执着, 是真的想搞清楚内存解析,因为我看的视频是这样讲过来的啊, 可是到这里不明白了,毕竟我是在自学,只能看视频,没有办法跟老师交流,所以才在这里提问出来!~也是希望能解答自己心中的那一个困惑吧!~
返回true一定代表是同一个地址,想都不用想也不用怀疑。因为在Java里面你看不到地址,
我知道你肯定会说如果是这样的话呢?a3[2]=new String("中国");
a4[2]=new String("中国");这样就是false了,对吧?其实这都没问题啊,所有通过默认定义的String在内存中都是一个地方存的,所以下面是true
String a = "hello";
String b = "hello";a==b // true,因为内存里面只有一个hello字符串,也就是存储在前面几位仁兄说的Buffer池中,地址当然一致,是虚拟机给new出来的String a = new String(“hello”);
String b = new String(“hello”);
a==b //false因为显式使用了new,虚拟机的顺序的先开辟两块内存地址,再分别赋值为hello的,那么这个时候地址还一样么?呵呵,楼主如果要想明白,先让指针的
概念从脑海里面消失吧
听你这么解释的话, 你听听我的理解看对不对? a==b 比较的是地址,
地址是存放在堆里面的, 只有 new出来的才会有地址存在,不是new出来的 只能作为元素,
元素是分为变量和常量的,不存在对象, 因为对象也是new出来,没有new出来,只能作为对象引用的一个变量,变量是放在栈里的!所以: String a3[] ={"中国","日本","美国"};
String a4[] ={"中国","日本","美国"};
他们的a3[1]==a4[1]; 他们都指向了同一个常量, 而不是对象,
例如: string s="中国" a3[1]==s==a4[1]; 他们都指向了同一个常量!
所以a3[1] ,a4[1];他们只是一个变量的引用, 他们的地址其实是 a3[] ,a4[]这两个对象,再按你的解释: ==是表示比较地址的;
他们最后的指向都指向了 data segment 中的字符串常量"中国" ;所以它们的地址相同!~如果 a3[1]= new string("中国");
a4[1]= new string("中国") ;
他们是new出来的, 是放在堆里的一个对象, 有地址的,所以不同,
可是他们的值却是相同的, 而现在a3[1] ,a4[1]已不再是变量,
它们现在被当作了一个对象来使用,
而对象是有自己的地址的, 所以他们的比较为false;
不知道我这样解释是否合理呢??????????????
Java中String对象是不可变的,关键看你怎么理解这句话这两天我很想尽快查证这个问题,然后再给你一个最科学的解释。
23楼的理解部分是正确的。如果你是字符串常量,那么只要这些常量是内容相同的,编译时编译器会自动把它们合并成同一个常量,jvm在加载类的时候,对于常量也会合并。这也就是为什么 s1="123" 和 s2="1"+"23" 用==比较会相等的原因,因为它们被指向了同一个地址。
那个例子我也做过如果String a1="中国";
String a2="中国";此时在java的栈内存保存有a1,a2
而在堆内存中只保存一个String对象(中国)
a1和a2都同时指向那个内存地址所以这个时候a1==a2为true;若String a1=new String("中国");
String a2=new String("中国");
此时在堆中就有两个值为"中国"的String 对象,
a1指向其中的一个,a2指向另外一个所以此时a1==a2 就为false,因为他们的指向对象的地址不同最后补充一句,这个帖大家讨论了这么多,楼主也不要吝啬一点分数
这个不光是在string对象里, 在所有的对象里 都是这样的!~
也是大家对java交流意见的增强和认识,
分数也不是很多!~到没有说吸引什么人! 只是希望得到一个完好的解释,
人家常说:"胜利不是因为拿到了奖杯!而是因为拿到奖杯之后那种成就和喜悦!"当发现一个非常合理的答案的时候, 我就会把分数送出去的!~
String s1 = "123";
String s2 = "1" + "23"
//错误了, 比较s1==s2,结果还为true! 由此可看比较的不是内存地址!~ ”没有敲代码就下了结论,不好意思!我只是举个例子,s1 == s2比较的确实是内存地址。
你这样比较一下,就是false了。
String s1 = "123";
String s2 = new String("1") + "23";
常量的拼接得到的结果应该跟前者是一样的。但通过new产生对象,就在heap堆中new了一个内存地址,再次拼接,地址就不一样了。“第二个:
例如:Java的基本数据类型(int byte boolean ....)分配内存都是在栈内存上。 //根据我目前掌握知识的理解, 变量(静态变量除外)的分配才在栈内存中,而且不光是基本数据类型,是包括所有的数据类型,
常量是分配在data segment中!
”如果你留心看上面的帖子,就知道了,我并没有说只有基本数据类型才分配在栈内存上啊!所有的引用型变量都是会在占内存分配空间,而当你对他进行初始化时,使用关键字new时,会在heap堆中分配内存空间。栈内存保存的是堆内存的地址,而堆内存保存的是对象的内容。
“第三个:
当我们做s[0] = new String("123");才完成对堆内存中s[0]指向的内存空间初始化,我们才可以引用这个对象。 //(老师讲的) : 堆内存中就是存放那些new出来的东西, 可是老师并没有说new出来的东西究竟是什么, 根据我理解new出来应该属于对象了, 所以对堆内存里面存放的究竟是地址还是别的内容,请解答一下!”堆内存存放的是对象的机器码(个人理解)。------------------------
String对象是一个特殊的对象,它是一个引用型的对象,但它有自己的特点,就是它无法被更改。
举例:
String s = "123";(jvm为这句代码分配了两块内存空间,堆内存保存字符串对象"123",而栈内存则保存堆内存的地址)
任何针对s的拼接,剪切的操作,都只是更改了栈内存中的内容,换句话说,只是将s指向了其他的字符串。而原本堆内存中的字符串对象"123"没有被更改。
java中可以更改的字符串对象是StringBuffer。
String s1 = "123";
String s2 = "1" + "23"
//错误了, 比较s1==s2,结果还为true! 由此可看比较的不是内存地址!~ ”没有敲代码就下了结论,不好意思!我只是举个例子,s1 == s2比较的确实是内存地址。
你这样比较一下,就是false了。
String s1 = "123";
String s2 = new String("1") + "23";
常量的拼接得到的结果应该跟前者是一样的。但通过new产生对象,就在heap堆中new了一个内存地址,再次拼接,地址就不一样了。“第二个:
例如:Java的基本数据类型(int byte boolean ....)分配内存都是在栈内存上。 //根据我目前掌握知识的理解, 变量(静态变量除外)的分配才在栈内存中,而且不光是基本数据类型,是包括所有的数据类型,
常量是分配在data segment中!
”如果你留心看上面的帖子,就知道了,我并没有说只有基本数据类型才分配在栈内存上啊!所有的引用型变量都是会在占内存分配空间,而当你对他进行初始化时,使用关键字new时,会在heap堆中分配内存空间。栈内存保存的是堆内存的地址,而堆内存保存的是对象的内容。
“第三个:
当我们做s[0] = new String("123");才完成对堆内存中s[0]指向的内存空间初始化,我们才可以引用这个对象。 //(老师讲的) : 堆内存中就是存放那些new出来的东西, 可是老师并没有说new出来的东西究竟是什么, 根据我理解new出来应该属于对象了, 所以对堆内存里面存放的究竟是地址还是别的内容,请解答一下!”堆内存存放的是对象的机器码(个人理解)。------------------------
String对象是一个特殊的对象,它是一个引用型的对象,但它有自己的特点,就是它无法被更改。
举例:
String s = "123";(jvm为这句代码分配了两块内存空间,堆内存保存字符串对象"123",而栈内存则保存堆内存的地址)
任何针对s的拼接,剪切的操作,都只是更改了栈内存中的内容,换句话说,只是将s指向了其他的字符串。而原本堆内存中的字符串对象"123"没有被更改。
java中可以更改的字符串对象是StringBuffer。
首先, 先感谢下32楼同志, 把我的错误也分析的很透彻了!~
对您回答了这么多楼,我也表示衷心感谢了!~ 真的是一个 good man!可是看了你的问题之后,我又产生了雾水! 你说:栈内存保存的是堆内存的地址,而堆内存保存的是对象的内容,
对您这句话的提问:
1.你所说的内容是不是指得数据属性?. 而地址就是指针属性了! 在数据结构上说!
2.数据类型的地址应该都在常量表中吧(data segment)?.
3.我所理解的是堆内存保存的是new出来的地址, new也是新建了一个地址,
所以堆内存应该是预备内存, 是为准备建立新地址而设立的!~ 建立了新的地址之后,将新的数据排序属性放进去!形成了新的内容!
4.栈内存中应该放的是变量!按照你这句话我所感觉的理解好象就是:
栈内存存放的是堆内存的地址, 那应该属于结点中的指针属性了!
5.变量的变量名是不可变的! 而你说这个是地址?.这个就让人理解不透了!
根据我的理解,变量分为变量名和变量值,而这个值在 堆内存和data segment中去寻址, 栈内存中只表示了变量名!
我也不清楚,到底使用关键字new后,jvm到底做了什么操作?堆内存到底是如何对象?(可能这些涉及到数据结构和操作系统的知识)。
google出来的结果,大家大多在解释,new做了什么事情,而没有解释如何做这些事情。
我想短时间也没办法理出个头绪出来。我查阅了一些资料,能肯定的大多如下:
正如你所说变量分为变量名和变量值。java在生成基本数据类型或引用类型的对象时,都会在栈内存中分配内存空间。
如果是基本数据类型,例如:
int i = 0;
jvm首先会在栈中创建一个变量为i的引用,然后遍历栈是否有10这个整型值,若没有则保存这个值(至于怎么保存,我不确定,二进制代码?maybe),然后将a指向这个值;若有则直接指向这个值。
这样做的原因是基本数据类型通常比较小,可以实现决定分配多大内存空间,而这也是堆栈操作必须的:先进后出,在入口处就必须决定它们占用的空间大小以及生存时间。栈内存因为它的存储特性和要求,决定了它不错的访问速度,而它的共享性更是大大增加了内存的利用率。如果是引用型对象,则会在栈中创建一个变量引用(至于jvm怎么引用,我不清楚),而栈内存保存的是堆内存的首地址。如果是new产生的对象,那么不论是否已经有了一样的对象,都回在堆内存中从新分配一个内存空间,存储这个对象的二进制代码。
今天任务多,偷偷在上班时间回帖是不对地,要赶任务了,晚上上来看。
第二,String是一个特殊的对象,他是不可变的
第三,==和equals的区别。如果这三个问题你都能完全明白的话,你的问题很容易解决!我博客有string和==与equals的文章,讲的很细了!
值类型的创建分配内存是在栈上分配的,对象创建是在堆上分配的! 但是他的引用是在栈上分配的!
楼主去看看堆和栈的区别吧,栈上分配需要知道其大小和生命周期,分配内存只需要向上移动指针就可以分配。速度很快,
堆上分配比较慢,但是他的好处就是不需要知道他的大小和生命周期!
你提了那么多问题+其他人那么多的回答,我没有全部看完。
1、A[] a = new A[100];//已经分配空间了,在stack中分配了空间存a;在hea中创建了一个新对象(Array类型),这个对象可以存100个A的对象;stack中的a指向heap中新创建的这个对象(求你了,不要说地址)。这个对象中存了100个引用,分别指向一个A的对象。
刚开始,数组没有初始化,所以里面的100个引用都是指向null,所以都相等。
我有事,回来再回答你。
指出上面回答出现的错误啊!~纯属交流!~第一个:
int i = 5;地址是0x0012FF7c,值是5、
char c = '5'地址是0x0012FF78,值是53
//
上面有人说是值相同, 地址不同, 在现在看来 地址和值都是不同的!
所以还是无法说明==是比较地址的!
不过在对象看来是这样的!其他的类型无法说明
第二个: 先说说39楼这个同志回答的吧!
1、A[] a = new A[100];//已经分配空间了
,在stack中分配了空间存a;在hea中创建了一个新对象(Array类型),
//
这个对象是 A类型的!~
可以存100个数据元素,并非要是A的对象,元素是任何类型的;
2. 刚开始,数组没有初始化,所以里面的100个引用都是指向null,所以都相等。// 数组已经初始化了, 都指向了null!~
第三个: int a =5, b =5; a==b;
//a,b的地址是不同的,因为它们是不可变的,都有自己的地址!
可是今天听说基本数据类型是放在栈里的!
最后竟然比较的是它们的值!第四个: int [] a;
//这应该说明是在栈空间里声明了这么一个数组!
栈的原理是"后进先出" , 那么a[5]a[4]a[3]...是这样出去的吗?
如果是这样的话好象违背了数组的顺序结构了!
a[i] 究竟放在哪里呢?. 如果new了50个数组,那50个a[i]是不是在栈里生成的呢?第五个: new 关键字!
//new 的意思应该是新生成了一个地址吗! 有区分他们的地址属性!~
那么我们平常使用的没有new的对象或者数据元素,他们是不是都是唯一的地址呢?.象这样的: char a = 'A' ; int b = 65;
他们指向的 究竟是不是一个地址呢?
char c = '5 '地址是0x0012FF78,值是53
---
5 == '5' 会把 '5' 换成其int值,也就是十进制的53,再和5比,显然不等。第四个: int [] a;
//这应该说明是在栈空间里声明了这么一个数组!
------
你自己对照第二个去理解吧。这里只是声明了一个变量叫a,其值是一个元素为int的数组,或者说a引用了一个元素为int的数组。这个数组和a是两回事!假如代码如下:
int[] a, b;
a = new int[100];
b = a;
那,这个时候b和a会引用了同一个数组。
象这样的: char a = 'A ' ; int b = 65;
-------
一样,把'A'换成其对应的int值,是65,所以a==b返回真。
给楼主一个建议,随便找本java语言的书,比如tij,都会讲到这些概念,这些都是最基本的。希望楼主不要总是把c/c++的概念硬套到java里来,你就会理解很多东西,否则就是钻牛角了。
其实有人直接把一个程序的内存分析完整的告诉我,应该就了解了吧!
废话不说那么多了!切入正题:[color=#FF0000]
如果你说java没有地址之说的, OK 我不反驳, 想必你学变量的时候应该看到地址了!
变量名就是地址!这便是"按名访问" 原则;
定义的类型是给变量分配足够的空间!
而这个空间里存放的就是你写入的数据了!这是数据结构的原理, 所以,它不光是对java 而言的!
int []a//你自己对照第二个去理解吧。这里只是声明了一个变量叫a,其值是一个元素为int的数组,
或者说a引用了一个元素为int的数组。这个数组和a是两回事!假如代码如下: 你这句话说的是对的! 声明了一个变量a ,
并在栈空间里分配了为int类型变量足够的空间!
这个是我的补充!~再补充查到的一个知识点:
变量名是不可变的, 也就是说它的地址是唯一的,分配了不可再改变!因为变量是有生命周期的,出了大括号就不存在了,所以它的地址是在栈里的!
出栈就消失了!~
它的值究竟在不在栈里呢?> 不太清楚, 估计基本数据类型是在栈里的!
所以基本数据类型==是比较值!不知道你可否还能为 这句话 再做补充,因为"[]" 并没有解释到~!~
第三个:
int[] a, b;
a = new int[100]; //new 的 地址 肯定是在堆里了, 这点大家都不怀疑!
这个时候 变量a 的地址是不可变的!~ 好,抛开地址不谈,
我们谈空间, 这个小块内存肯定是在堆里了!~ 到这里你看出点疑惑了吗?.. 请您把这里解释通!~~
-----
这句错误,在java里,对于Object的子类对象来说(包括Object本身),变量名是引用,不是地址。int []a
你这句话说的是对的! 声明了一个变量a ,
并在栈空间里分配了为int类型变量足够的空间!
这个是我的补充!~
---------
补充是错误的,应该是:在栈空间里分配了一个空间,这个空间用来存放一个对int数组的引用,而不是存放int数组本身。到这里你看出点疑惑了吗?.. 请您把这里解释通!~~
--------
没看出疑惑啊,请明确指出。
我觉得你应该看看书!~
声明变量的作用是什么?>.
1.识别!
2.分配空间!
你自己去看看书 就知道变量的作用是什么了!~
我说的看的出的疑惑就是指,
栈空间有地址和空间, 堆里也有地址和空间!~
很明显:
int[] a, b;
a = new int[100];
很明显,这经过了赋值运算的一个过程!查过的解释:
赋值是将 "=" 右边的值,存储到变量中!
赋值是一个将 " 地址 和值" 两项 都赋值过去!(这条目前没有理解)
赋值两边的类型必须相同;
这样才保证了赋值空间的大小!~
这说明 a经过赋值过程,确实代表了这个这个数组!
栈空间有地址和空间, 堆里也有地址和空间!~
很明显:
int[] a, b;
a = new int[100];
很明显,这经过了赋值运算的一个过程!
----------
楼主一直都是在陈述,一个问句都没有,何惑之有?提醒楼主多次了,不要用地址这个概念来考虑问题,用引用,这个是java里明确给出的概念。当然,引用最终是靠地址来实现的,但从概念上来说,我们把这个地址叫做引用。但从另一个角度想,目前的计算机需要用地址来表示引用,如果有另外一个体系结构的计算机,我可以完全不用地址而一样能表示引用。所以说,地址是与jvm实现相关的,而引用则是java语言自身的概念,独立于jvm。声明变量的作用是什么? >.
1.识别!
2.分配空间!
----------
你的这两句说的没错,变量说白了就是个“助记符”!没有什么特殊意义。我所强调的是:对于primary类型的来说,变量里面存的是值;对于Object的子类(包括Object本身)来说,变量里存的是引用。我并不care变量本身的在哪里,是在堆还是在栈都没关系,我care的是变量里存的东西。new int[100] 结果是在堆上生成一个int数组的存储空间,这个空间可以存放100个int类型的值,并且缺省的,这些值都是0。如果改为 new String[100],则结果在堆上生成一个String数组的存储空间,这个空间可以存放100个String类型对象的引用,并且缺省的,这些引用都是null。这里是对数组的初始化,是java规范里要求的,不应该理解为普通意义上的赋值,因为并没有调用赋值操作。1个int需要4个字节来保存,但new int[100]并不是仅仅生成100*4个字节,还需要为管理这些内存多申请一小块(内存头),具体多大取决于虚拟机实现,用于对这100*4个字节的管理。这也是对楼顶所问的数组的length是怎么得到的一个回答。同时,我也想说明,如果一个变量引用了这个数组,这个引用所代表的地址是指到第一个数组元素所在的地址,还是指到为内存头所在的地址,是和jvm实现相关的。甚至于内存头和其所对应的内存块是连续存放的,还是不连续存放的,也是与jvm实现相关的,java语言并不care这个。用引用这个概念,我可以屏蔽这些差异,而用地址,则太底层了,无法屏蔽。
栈空间有地址和空间, 堆里也有地址和空间!~
很明显:
int[] a, b;
a = new int[100];
很明显,这经过了赋值运算的一个过程!
----------
楼主一直都是在陈述,一个问句都没有,何惑之有?提醒楼主多次了,不要用地址这个概念来考虑问题,用引用,这个是java里明确给出的概念。当然,引用最终是靠地址来实现的,但从概念上来说,我们把这个地址叫做引用。但从另一个角度想,目前的计算机需要用地址来表示引用,如果有另外一个体系结构的计算机,我可以完全不用地址而一样能表示引用。所以说,地址是与jvm实现相关的,而引用则是java语言自身的概念,独立于jvm。声明变量的作用是什么? >.
1.识别!
2.分配空间!
----------
你的这两句说的没错,变量说白了就是个“助记符”!没有什么特殊意义。我所强调的是:对于primary类型的来说,变量里面存的是值;对于Object的子类(包括Object本身)来说,变量里存的是引用。我并不care变量本身的在哪里,是在堆还是在栈都没关系,我care的是变量里存的东西。new int[100] 结果是在堆上生成一个int数组的存储空间,这个空间可以存放100个int类型的值,并且缺省的,这些值都是0。如果改为 new String[100],则结果在堆上生成一个String数组的存储空间,这个空间可以存放100个String类型对象的引用,并且缺省的,这些引用都是null。这里是对数组的初始化,是java规范里要求的,不应该理解为普通意义上的赋值,因为并没有调用赋值操作。1个int需要4个字节来保存,但new int[100]并不是仅仅生成100*4个字节,还需要为管理这些内存多申请一小块(内存头),具体多大取决于虚拟机实现,用于对这100*4个字节的管理。这也是对楼顶所问的数组的length是怎么得到的一个回答。同时,我也想说明,如果一个变量引用了这个数组,这个引用所代表的地址是指到第一个数组元素所在的地址,还是指到为内存头所在的地址,是和jvm实现相关的。甚至于内存头和其所对应的内存块是连续存放的,还是不连续存放的,也是与jvm实现相关的,java语言并不care这个。用引用这个概念,我可以屏蔽这些差异,而用地址,则太底层了,无法屏蔽。
栈空间有地址和空间, 堆里也有地址和空间!~
很明显:
int[] a, b;
a = new int[100];
很明显,这经过了赋值运算的一个过程!
----------
楼主一直都是在陈述,一个问句都没有,何惑之有?提醒楼主多次了,不要用地址这个概念来考虑问题,用引用,这个是java里明确给出的概念。当然,引用最终是靠地址来实现的,但从概念上来说,我们把这个地址叫做引用。但从另一个角度想,目前的计算机需要用地址来表示引用,如果有另外一个体系结构的计算机,我可以完全不用地址而一样能表示引用。所以说,地址是与jvm实现相关的,而引用则是java语言自身的概念,独立于jvm。声明变量的作用是什么? >.
1.识别!
2.分配空间!
----------
你的这两句说的没错,变量说白了就是个“助记符”!没有什么特殊意义。我所强调的是:对于primary类型的来说,变量里面存的是值;对于Object的子类(包括Object本身)来说,变量里存的是引用。我并不care变量本身的在哪里,是在堆还是在栈都没关系,我care的是变量里存的东西。new int[100] 结果是在堆上生成一个int数组的存储空间,这个空间可以存放100个int类型的值,并且缺省的,这些值都是0。如果改为 new String[100],则结果在堆上生成一个String数组的存储空间,这个空间可以存放100个String类型对象的引用,并且缺省的,这些引用都是null。这里是对数组的初始化,是java规范里要求的,不应该理解为普通意义上的赋值,因为并没有调用赋值操作。1个int需要4个字节来保存,但new int[100]并不是仅仅生成100*4个字节,还需要为管理这些内存多申请一小块(内存头),具体多大取决于虚拟机实现,用于对这100*4个字节的管理。这也是对楼顶所问的数组的length是怎么得到的一个回答。同时,我也想说明,如果一个变量引用了这个数组,这个引用所代表的地址是指到第一个数组元素所在的地址,还是指到为内存头所在的地址,是和jvm实现相关的。甚至于内存头和其所对应的内存块是连续存放的,还是不连续存放的,也是与jvm实现相关的,java语言并不care这个。用引用这个概念,我可以屏蔽这些差异,而用地址,则太底层了,无法屏蔽。
1、A[] a = new A[100];//已经分配空间了
,在stack中分配了空间存a;在hea中创建了一个新对象(Array类型),
//
这个对象是 A类型的!~不对,这个对象是Array类型的,里面能存100个引用(或者叫指向,分别指向一个A类型的对象)
可以存100个数据元素,并非要是A的对象,元素是任何类型的;不对,这里是定义了一个Array,里面的元素是A类型的,不是数组是A类型的,数组就是数组类型(Array)
或者说a引用了一个元素为int的数组。这个数组和a是两回事!假如代码如下: 你这句话说的是对的! 声明了一个变量a ,
并在栈空间里分配了为int类型变量足够的空间!
这个是我的补充!~不对,stack中只为a分配了空间,这个a可以指向一个数组(里面存int),但现在这个数组还没有分配空间,所以a指向null,将来给数组分配空间也是在heap中分配,因为数组不是primitive类型。再补充查到的一个知识点:
变量名是不可变的, 也就是说它的地址是唯一的,分配了不可再改变!不对,例如:
Dog d1 = new Dog();
Dog d2 = new Dog();
d1 = d2; //d1的指向已经变了,现在指向后来创建的那个对象了因为变量是有生命周期的,出了大括号就不存在了,所以它的地址是在栈里的!
出栈就消失了!~
它的值究竟在不在栈里呢? > 不太清楚, 估计基本数据类型是在栈里的!
变量在stack中还是在heap中,要看变量是 实例变量(instance variable)还是局部变量(local variable)
instance variable 在heap中, local variable 在stack中
实际上,stack中是按method出入stack的,先调用的method在下面,然后再调用的method在上边,最上边的method是当前运行的methed,local variable就分配在这个methed所占的空间中,当然也是在stack中了。当前的method运行完,弹出stack,这个method里面声明的变量也一起消失了。程序返回到stack中的下一个method继续运行。
所以基本数据类型==是比较值!
int a1 = 3; int a2 = 4; //a1和a2里面存的就是3和4本身。
Dog d1 = new Dog(); Dog d2 = new Dog(); //d1和d2里面分别存这两个独享的引用,这两个引用显然不同,比较结果就是false了。不知道你可否还能为 这句话 再做补充,因为"[]" 并没有解释到~!~
第三个:
int[] a, b;
a = new int[100]; //new 的 地址 肯定是在堆里了, 这点大家都不怀疑!
这个时候 变量a 的地址是不可变的!~ 好,抛开地址不谈,
我们谈空间, 这个小块内存肯定是在堆里了!~ 到这里你看出点疑惑了吗?.. 请您把这里解释通!~~a在 stack中, new int[100]这个数组对象在heap中。建议楼主看下《head first in java》,里面说的非常清楚。