A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© barlay 中级黑马   /  2013-12-12 21:45  /  2771 人查看  /  25 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 barlay 于 2013-12-13 00:51 编辑

public class StringTest{
public static void main(String[] args) {
String a = "abc";
String b = new String("abc");
System.out.println(a == b);
int c = 1;
Integer d = new Integer(1);
//c = 4;
System.out.println(c == d);
}
}
== 不是比较的地址吗?第一个返回false,第二个为啥返回true,原生类型与引用类型比。

评分

参与人数 1技术分 +1 收起 理由
简★零度 + 1

查看全部评分

25 个回复

倒序浏览
本帖最后由 松子 于 2013-12-12 21:57 编辑

string 是引用类型,用==进行比较时,比较他们在内存中的地址值,a和b的地址值当然是不同的,所以是false;
int 值类型,比较的是二者的值,c和d的值都是1,结果为true。
回复 使用道具 举报
这是包装类的特性,String不是包装类,Integer是包装类!
回复 使用道具 举报
这个毕老师的视频里有解释,对于引用变量,==比较的是两个对象的内存地址值,如果两个引用指向同一个对象,则铁定它们是相等的,谁会不等于自己呢?
当Java程序中直接使用形如"abc"的字符串直接量时,JVM将会使用常量池来管理这些字符串;当使用new String("abc")时,JVM会先使用常量池来管理"abc"直接量,再调用String类的构造方法来创建一个新的String对象,新创建的String对象被保存在堆内存中。换句话说,new String("abc")一共产生了两个对象。所以两者在内存中的位置是不一样的,通过==比较,结果即为false。
d与c比较时,d被自动拆箱了,意即它不再是一个对象而变成了一个整型数值。此时两者均为基本类型变量,只要两个变量的值相等,结果就返回true。
哎,Java挺闹心啊。
回复 使用道具 举报
视频讲到Integer有个自动拆包封包特性
第一个new String("abc")就是一个新对象,String s = "abc";只是赋给地址值
你可以试试String s = "abc";String s1 = "abc";比较s和s1
回复 使用道具 举报
Integer是包装类
包装类有一个特性:
基本数据类型和包装类之间可以自动的相互转换,这个就是自动装箱和自动拆箱
例子:
Integer in = 60; 自动装箱
int x = in + 10; 自动拆箱
回复 使用道具 举报 0 1
Kyle 中级黑马 2013-12-12 23:07:49
7#
本帖最后由 Kyle 于 2013-12-13 01:02 编辑

String a ="abc"                      这种创建方式是在常量池中创建了一个常量abc,然后a作为引用变量指向它。
String b = new String("abc");   这种创建方式是在堆内存中创建了一个对象“abc”,然后b作为引用变量指向它。
所以a和b所保存的地址值不同,==的结果返回false。

int c = 1                                   是在栈内存中保存了一个局部基本型变量。
Integer d = new Integer(1);    当d和c比较的时候,因为c是基本型变量,d会自动拆箱与c比较,所以返回的是true。

评分

参与人数 1技术分 +1 收起 理由
贺奕凯 + 1

查看全部评分

回复 使用道具 举报
简单地说,“==”,用于比较原生类型,当然也可以比较自动装箱拆箱的Integer包装类型,还可以比较在引用类型在栈内存中的地址值
“equals”不可以比较原生类型,比较引用类型时,实际上比较的是引用变量指向的对象的内容。

评分

参与人数 1黑马币 +1 收起 理由
barlay + 1 很给力!

查看全部评分

回复 使用道具 举报 1 0
icyyaww 中级黑马 2013-12-12 23:33:04
9#
String: 是地址比较所以是false。
integer:①无论如何,Integer a=1;与Integer b = new Integer(1);不会相等。不会经历拆箱过程,b 的引用指向堆,而 a 指向专门存放他的内存(常量池),他们的内存地址不一样,所以为false
  ②两个都是非new出来的Integer,Integer a =1; Integer b = 1;如果数在-128到127之间,则是true,否则为false
  java在编译Integer a = 128的时候,被翻译成-> Integer a = Integer.valueOf(128);而valueOf()函数会对-128到127之间的数进行缓存
  ③两个都是new出来的new Integer(1),new Integer(1),都为false
  ④int和integer(无论new否)比,都为true,因为会把Integer自动拆箱为int再去比

评分

参与人数 1技术分 +1 收起 理由
简★零度 + 1

查看全部评分

回复 使用道具 举报
barlay 中级黑马 2013-12-12 23:45:16
10#
Kyle 发表于 2013-12-12 23:07
String a ="abc"                      这种创建方式是在常量池中创建了一个常量abc,然后a作为引用变量指 ...

int c = 1;是在栈中存的1吧
楼下说的挺对的,“==”,用于比较原生类型,当然也可以比较自动装箱拆箱的Integer包装类型,还可以比较在引用类型在栈内存中的地址值
当原生类型和包装类型比较是,包装类型自动拆箱

评分

参与人数 1技术分 +1 收起 理由
简★零度 + 1

查看全部评分

回复 使用道具 举报
barlay 中级黑马 2013-12-12 23:51:31
11#
icyyaww 发表于 2013-12-12 23:33
String: 是地址比较所以是false。
integer:①无论如何,Integer a=1;与Integer b = new Integer(1); ...

分析的太详细了,非常感谢!
另外有一个问题:你确定Integer a=1;中a 指向专门存放 1 的内存(常量池),而不是存在栈中?int a = 1的话a肯定存在栈中啊。
回复 使用道具 举报
Kyle 中级黑马 2013-12-12 23:59:01
12#
barlay 发表于 2013-12-12 23:45
int c = 1;是在栈中存的1吧
楼下说的挺对的,“==”,用于比较原生类型,当然也可以比较自动装箱拆箱的I ...

嗯,你说的对。 是我没回答完善。

Integer a = 127;
Integer b = 127;
System.out.println(a ==  b);

这种情况就是在常量池中创建127。

Integer a = 128;
Integer b = 128;
System.out.println(a ==  b);

这种情况是在堆内存中创建两个对象。
回复 使用道具 举报
barlay 中级黑马 2013-12-13 00:06:28
13#
Kyle 发表于 2013-12-12 23:59
嗯,你说的对。 是我没回答完善。

Integer a = 127;

还是不对,请参见icyyaww帖子第二条:java在编译Integer a = 128的时候,被翻译成-> Integer a = Integer.valueOf(128);而valueOf()函数会对-128到127之间的数进行缓存
是进行缓存。不是放到常量池中好不好,更不要说在常量池中创建了。
回复 使用道具 举报
barlay 发表于 2013-12-12 23:51
分析的太详细了,非常感谢!
另外有一个问题:你确定Integer a=1;中a 指向专门存放 1 的内存(常量池 ...

确定。:lol:lol:lol
回复 使用道具 举报
Kyle 中级黑马 2013-12-13 00:15:29
15#
barlay 发表于 2013-12-13 00:06
还是不对,请参见icyyaww帖子第二条:java在编译Integer a = 128的时候,被翻译成-> Integer a = Integer. ...

是的,因为128是特殊情况。
Integer a = 127;
这是因为整数类型在常量池中有一定的范围,范围是-128到127之间,也就是说在这个范围内是不会去堆内存创建对象,所以127是在常量池中创建的。
Integer b = 128;
则是超出了127这个数值,所以是在堆内存中创建对象的,缓存也属于在堆内存,概念跟StringBuffer的缓存相同。
若我说的不对,欢迎指正,共同学习!
回复 使用道具 举报
barlay 中级黑马 2013-12-13 00:24:51
16#

我认为是这样的,Integer把-128到127的值缓存起来了,Integer a=1;实际上是把1的缓存地址赋给了a,就是说a中存的是1这个值的地址,而不是1本身,因为a是局部变量,所以a的值存在栈中。和b进行比较的时候,因为b中存的是一个堆中对象的地址,所以和a中存的地址不同,为false。
你说的是对的,我原先理解有点偏差。
分析的太详细了,你是怎么做到的?佩服!
收工。
回复 使用道具 举报
barlay 中级黑马 2013-12-13 00:43:09
17#
Kyle 发表于 2013-12-13 00:15
是的,因为128是特殊情况。
Integer a = 127;
这是因为整数类型在常量池中有一定的范围,范围是-128到127 ...

不要再提常量池了,本来就没有常量池,非得造出这么一个概念来。你们所说的常量池,不就是一块只能读不能写的内存区域么!只能读不能写 你告诉我怎么创建!
二进制文件中存放的有code和data数据,code和data分别被加载到不同的地方,由于data中存放的是程序运行时要用到的数据,这些数据在编写代码时就已经确定了,所以是不可变的,被加载到只读内存,这应该就是你们所说的常量池了吧。
应该是这样的,如有别的想法可以跟帖回复。
回复 使用道具 举报
Kyle 中级黑马 2013-12-13 00:44:18
18#
icyyaww 发表于 2013-12-12 23:33
String: 是地址比较所以是false。
integer:①无论如何,Integer a=1;与Integer b = new Integer(1); ...

barlay的问题结束了。 我的问题来了。
我的观点是非new的情况,Integer a = 1;
只要数值在-128~127之间,这个数就会在常量池中创建。
而你所说的第二点:
  ②两个都是非new出来的Integer,Integer a =1; Integer b = 1;如果数在-128到127之间,则是true,否则为false
  java在编译Integer a = 128的时候,被翻译成-> Integer a = Integer.valueOf(128);而valueOf()函数会对-128到127之间的数进行缓存

即Integer a = 128才会被翻译成valueOf不是吗? 最后一句话反而说对-128~127之间的数进行缓存,这不是自相矛盾了吗?
求解惑一下。
回复 使用道具 举报
barlay 中级黑马 2013-12-13 00:50:51
19#
本帖最后由 barlay 于 2013-12-13 00:53 编辑
Kyle 发表于 2013-12-13 00:44
barlay的问题结束了。 我的问题来了。
我的观点是非new的情况,Integer a = 1;
只要数值在-128~127之间 ...


你理解有误,正确的理解是:
valueOf()函数会对-128到127之间的数进行缓存,所以直接返回缓存地址
128不在缓存中,所以新建对象,返回新建对象的地址
不管要赋值的数是多少,都执行valueOf()函数。
圆满搞定,理解又加深了一步,论坛牛人很多啊,收工!
回复 使用道具 举报
Kyle 中级黑马 2013-12-13 00:55:26
20#
barlay 发表于 2013-12-13 00:43
不要再提常量池了,本来就没有常量池,非得造出这么一个概念来。你们所说的常量池,不就是一块只能读不能 ...

你对常量池的概念理解有偏差,不要激动,冷静分析问题。
Java当中是有常量池的,这个概念我可以100%的跟你保证。
只能读不能写的理解也不对。
常量池里的东西是一旦创建了就不能改变,出现不一样的就再创建一个。
比如
String a = "a";         //这是在常量池当中创建了一个常量“a”
String a =“ab”;  //这并不是在a的基础上加上字符b。 而是舍弃了常量池中的“a”,重新创建了一个常量“ab”。 “a”还是在常量池里。
String c ="a";         //c变量指向了一开始就创建出来的"a"
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马