黑马程序员技术交流社区
标题: String建立对象写new和不写new关键字的 区别是什么? [打印本页]
作者: 郭孟涛 时间: 2013-3-12 19:57
标题: String建立对象写new和不写new关键字的 区别是什么?
当用“==”等号来判断的String对象的时候,判断的结果还是有些不太明白。- class StringDemo
- {
- public static void main(String[] args)
- {
- String x = new String("word");
- String y = "Excel"; // 写new和不写new关键字, 区别是什么?
- System.out.println(y=="Excel");// 比较对象地址,输出true? 这里的内存地址相同了吗?.
-
- System.out.println(x=="word"); // 比较对象地址,输出false.
-
- //当用equals比较对象内容,均输出true。内容上很明显都是相同的。
- //System.out.println("word".equals(x));
- //System.out.println("Excel".equals(y));
- }
- }
复制代码“==”号用来判断对象的内存地址是否一致,
内存地址如果相同,内容就一定相同。而内容相同内存地址完全可以不是一个。好比u盘,同一个u盘,内容自然一样。而相同内容的u盘却不一定是一个u盘。
作者: 彭波 时间: 2013-3-12 20:09
本帖最后由 彭波 于 2013-3-12 20:14 编辑
看这个例子
class StringDemo
{
public static void main(String[] args)
{
String s1 = "abc";//s1是一个类类型变量,“abc”是一个对象。字符串最大特点,一旦初始化就不可以被改变
String s2 = new String("abc");
//s1和s2有什么区别?
//s1在内存中有一个对象
//s2在内存中有两个对象,此时你题目中的x==true就为false了
System.out.println(s1==s2);//false,
System.out.println(s1.equals(s2));//true,String类复写了Object类中equals方法,该方法用于判断字符串是否相同
}
}
再看这个例子:http://bbs.itheima.com/thread-40672-1-2.html
作者: fighting 时间: 2013-3-12 20:26
new出的字符串与直接用等号赋值的字符串区别就是是否在内存的堆中创建新的字符串。
在java中,因为字符串经常使用到,因此java在设计时就单独为字符串开辟出一块区域---字符串池,专门用于存放字符串。
当使用等号时,程序只在字符串池中查找是否存在这样一个字符串,如果存在直接返回地址,如果不存在,就在字符串池中
创建一个字符串将地址返回回来。
当使用new关键字时,无论在字符串池中是否存在该字符串,程序都会在堆中创建一个新的字符串对象,如果在字符串池没有
这样一个字符串,则在字符串池中创建一个同样的字符串,将堆中的字符串返回回来
作者: 何旭程 时间: 2013-3-12 20:27
本帖最后由 何旭程 于 2013-3-12 20:30 编辑
String s1 = "abc";
String s2 = new String("abc");
第一句执行时,会先在字符串常量池中查找是否已经存在了值为"abc"的对象,它的判断依据是Stringequals(Object obj)方法的返回值,如果有,则不再创建新的对象,如果没有,则先创建这个对象,然后把它加入到字符串常量池中,将引用变量s1指向这个对象;
第二句执行后内存中有两个对象,一个由new String("abc")中的"abc"在字符串常量池里生成一个值为"ABC"的对象,第二个由new在堆里产生一个值为“abc”的对象,该对象完全是字符串常量池里的"abc"的一个拷贝,引用变量变量s2最后指向堆中产生的"abc"对象。
作者: 张亚青 时间: 2013-3-12 21:23
这里主要涉及了JAVA中的常量池技术:(下面会介绍何为常量池技术)
1、用new String()创建的字符串不是常量,不能在编译期就确定,所以new String()创建的字符串不放入常量池中,他们有自己的地址空间。
因此,String x = new String("word");变量x指向新创建的字符串对象地址,而System.out.println(x=="word"); 中常量"word"地址存在于常量池中,因此他们地址不同;
2、String 对象(内存)的不变性机制会使修改String字符串时,产生大量的对象,因为每次改变字符串,都会生成一个新的String。 java 为了更有效的使用内存,常量池在编译期遇见String 字符串时,它会检查该池内是否已经存在相同的String 字符串,如果找到,就把新变量的引用指向现有的字符串对象,不创建任何新的String 常量对象,没找到再创建新的。
因此String y = "Excel"; 变量y指向了常量"Excel"在常量池中的地址,System.out.println(y=="Excel");所以语句中y和常量"Excel"地址相同。
补充:【常量池技术】
1、常量池的概念
在Java程序中,有很多的东西是永恒的,不会在运行过程中变化。而这些东西在JVM解释执行程序的时候又是非常重要的。那么编译器将源程序编译成class文件后,会用一部分字节分类存储这些东西。这一部分字节我们就称为【常量池】。常量池也是为了方便快捷地创建某些对象而出现的,当需要一个对象时,就可以从池中取一个出来(如果池中没有则创建一个),则在需要重复创建相等变量时节省了很多时间。
2、常量池中的内容
常量池中除了包含代码中所定义的各种基本类型(如int、long等等)和对象型(如String及数组)的常量值外,还包含一些以文本形式出现的符号引用,比如:
类和接口的全限定名;
字段的名称和描述符;
方法和名称和描述符。
3、八种基本类型的包装类和对象池
java中基本类型的包装类的大部分都实现了常量池技术,这些类是Byte,Short,Integer,Long,Character,Boolean,另外两种浮点数类型的包装类则没有实现。另外Byte,Short,Integer,Long,Character这5种整型的包装类也只是在对应值小于等于127时才可使用对象池,也即对象不负责创建和管理大于127的这些类的对象。
4、String也实现了常量池技术
String类也是java中用得多的类,同样为了创建String对象的方便,也实现了常量池的技术。
用new String()创建的字符串不是常量,不能在编译期就确定,所以new String()创建的字符串不放入常量池中,他们有自己的地址空间。
String 对象(内存)的不变性机制会使修改String字符串时,产生大量的对象,因为每次改变字符串,都会生成一个新的String。 java 为了更有效的使用内存,常量池在编译期遇见String 字符串时,它会检查该池内是否已经存在相同的String 字符串,如果找到,就把新变量的引用指向现有的字符串对象,不创建任何新的String 常量对象,没找到再创建新的。所以对一个字符串对象的任何修改,都会产生一个新的字符串对象,原来的依然存在,等待垃圾回收。
作者: Benwolf0818 时间: 2013-3-12 21:39
- public class Test
- {
-
- public static void main(String[] args)
- {
-
- String x = new String("word");
-
- String y = "Excel"; // 写new和不写new关键字, 区别是什么?
- //new出来的对象存放在堆内存中,字符串常量对象存放在常量池中
- System.out.println(y=="Excel");// 比较对象地址,输出true? 这里的内存地址相同了吗?.
- //""中的字符串常量存放在常量池中,在常量池中只有一份
-
- System.out.println(x=="word"); // 比较对象地址,输出false.
- //new出来的对象在对内存中可以存在多个
-
- //当用equals比较对象内容,均输出true。内容上很明显都是相同的。
-
- //System.out.println("word".equals(x));
- //System.out.println("Excel".equals(y));
- }
-
- }
复制代码
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |