“java系统会自动为每一用双引号括起来的字符串常量创建一个String对象” --Thinking In Java(中文版) 也就是说“string”和new(“string”)是完全相同的,后者只是前的的一种简略的写法。作用是相同的。这一点,在中国的很多教材都有介绍,希望上面的仁兄多看看相关的资料,不要空想!
楼上的仁兄,希望多自己写程序做做实验,不要只相信所谓教材中的说法。我这里有我写的一个实际的程序可以证明,String s1 = "hello";与String s2 = new String("hello"); 是不同的。//-------------------------------------------------------------- import java.lang.ref.WeakReference; /** * Class to research strings. * constant string like "AAA" won't be reclaimed while instance created by new will. * when you new a String by a constant string, there will be two memory field stored the same value. * so initialize a String by constant String is recommended. */public class StringResearch { public static void main(String[] args) { String a = "AAA"; String b = new String("AAA"); WeakReference wra = new WeakReference(a); WeakReference wrb = new WeakReference(b);
/** * Initializes a newly created <code>String</code> object so that it * represents the same sequence of characters as the argument; in other * words, the newly created string is a copy of the argument string. Unless * an explicit copy of <code>original</code> is needed, use of this * constructor is unnecessary since Strings are immutable. * * @param original a <code>String</code>. */ public String(String original) { this.count = original.count; if (original.value.length > this.count) { // The array representing the String is bigger than the new // String itself. Perhaps this constructor is being called // in order to trim the baggage, so make a copy of the array. this.value = new char[this.count]; System.arraycopy(original.value, original.offset, this.value, 0, this.count); } else { // The array representing the String is the same // size as the String, so no point in making a copy. this.value = original.value; } }
------------------
不知道你是不是想问String p = new String("csdn"); 跟 String p = "csdn";
的区别呢?
前者是在堆中创建一个String 对象,并返回其句柄(或者说引用)p。
后者则先在堆中查询是否有"csdn"这样的对象,如果有,则返回该对象的句柄赋给p
所以你会发现一下代码片段中:
String p1 = "csdn";
String p2 = new String("csdn");
System.out.println(p1.equals(p1));
System.out.println(p2.equals(p2));
System.out.println(p1=="csdn");
System.out.println(p2 == "csdn");输出为:
true
true
true
false
String str2 = str.intern();其效果一样..
String str3 = new String("welcome"); 创建一对象..
前者在堆中分配空间
后者在常量区中分配空间
学习中
强烈反对第一种写法。p = new String("csdn"); // <- 枪毙枪毙 x_x原因:
第二种写法严重浪费系统资源。
第一种写法会在内存中保存一个String类型的常量。无法被垃圾回收机制回收。
第二种写法会在heap中动态开辟一块内存保存一个String类型的对象,可以被垃圾回收。但是在产生这个动态内存的同时,因为使用常量来定义(注意new String之后括号里面的东西),所以,与此同时同样会在内存中保存一个永不被回收的Strign类型常量。造成内存的重复浪费,同时new一个对象时的那不小的CPU开销和随后垃圾回收所用的资源也是白白浪费。综上,忘掉p = new String("csdn");这种垃圾写法吧。永远不要让他出现在我们的代码中。除非你是要写恶意占用资源的软件。
System.out.println(p1 == "csdn"); 大多数虚拟机的结果是true,但是这不是java的规范规定的,而是虚拟机对代码优化(将具有相同值的String常量合并为一个保存)后的结果。所以,根据虚拟机的不同,有出现false的可能性(虽然比较难碰到)。关于对象的比较,强烈建议一律使用equals()方法。(当然,象小猪这样,作实验时使用倒也无可非议。)
这杨说不知道会不会挨骂。。只要给分,让骂声来得更猛烈些吧,不是我人溅,就是想在骂声中学习,并得分
首先和大家说说"=="和"equals()".
先说"==",它是运算符,能应能于任何对象和原始类型,比较的是两者的引用值,决定了引用是否指向同一个对象,也就是说当两个对象的类型和值相时和出的==值也是返回假的.例如:
String s1=String("hello");
String s2=String("hello");
当输出s1==s2时结果为false.因为引用值不同.
再说"euqals()",它是每个类都具有的方法,当两个分离的对象的内容和类型相配的话,String,Date,File类和所有其它override equals()的包装类返回真值.
例如:
String s1=String("hello");
String s2=String("hello");
方法s1.equals(s2)返回true,
尽管指向两个不同的对象,因为在此比较的是实际的内容的值.
但equals()的缺省行为是比较引用值,为什么这样呢?!因为绝大多数类都实现了equals()方法所以比较的是内容而不是引用值.举个例子,当自已写一个类实,再创建两个对象,用equals()方法比较时,比较的是两对象的引用值,因为你写的类中没有实现equals().再深入的可以看看相对资料,见意看Think In Java.
谢谢!
String s1 = new String("hello"); 才是正确的,不过不推荐这么写。equals()方法确实是依赖于实现的,否则与==无异。
比如
StringBuffer sb1 = new StringBuffer("hello");
StringBuffer sb2 = new StringBuffer("hello");
System.out.println(sb1.equals(sb2));
结果就是false,因为StringBuffer没有实现自己的equals()方法,而是沿用了Object的equals()方法,也就是==。另外,值得一提的是,也是几乎所有讨论equals()方法都会说的,实现equals()的同时一定要实现hashCode()方法。并且有那么几条规则,记不清了,自己查一下资料吧。
基本意思就是hashCode()返回值相同的几个对象必然equals()结果均true,hashCode()不同时,必须equals()返回false。并且equals()具有交换率什么之类的。总之,不小心点儿的话,实现起来还是蛮难的。不过好像这个回帖的内容有些跑题了。关于String的equals()和hashCode(),有人实验证明hashCode()方法在非半角英文数字时会有一定的问题。具体情况还是自己查了。呵呵……
强烈反对第一种写法。p = new String("csdn"); // <- 枪毙枪毙 x_x原因:
第一种写法严重浪费系统资源。
第二种写法会在内存中保存一个String类型的常量。无法被垃圾回收机制回收。
第一种写法会在heap中动态开辟一块内存保存一个String类型的对象,可以被垃圾回收。但是在产生这个动态内存的同时,因为使用常量来定义(注意new String之后括号里面的东西),所以,与此同时同样会在内存中保存一个永不被回收的Strign类型常量。造成内存的重复浪费,同时new一个对象时的那不小的CPU开销和随后垃圾回收所用的资源也是白白浪费。综上,忘掉p = new String("csdn");这种垃圾写法吧。永远不要让他出现在我们的代码中。除非你是要写恶意占用资源的软件。
首先和大家说说"=="和"equals()".
先说"==",它是运算符,能应能于任何对象和原始类型,比较的是两者的引用值,决定了引用是否指向同一个对象,也就是说当两个对象的类型和值相时和出的==值也是返回假的.例如:
String s1=new String("hello");
String s2=new String("hello");
当输出s1==s2时结果为false.因为引用值不同.
再说"euqals()",它是每个类都具有的方法,当两个分离的对象的内容和类型相配的话,String,Date,File类和所有其它override equals()的包装类返回真值.
例如:
String s1=new String("hello");
String s2=new String("hello");
方法s1.equals(s2)返回true,
尽管指向两个不同的对象,因为在此比较的是实际的内容的值.
但equals()的缺省行为是比较引用值,为什么这样呢?!因为绝大多数类都实现了equals()方法所以比较的是内容而不是引用值.举个例子,当自已写一个类实,再创建两个对象,用equals()方法比较时,比较的是两对象的引用值,因为你写的类中没有实现equals().再深入的可以看看相对资料,见意看Think In Java.
--Thinking In Java(中文版)
也就是说“string”和new(“string”)是完全相同的,后者只是前的的一种简略的写法。作用是相同的。这一点,在中国的很多教材都有介绍,希望上面的仁兄多看看相关的资料,不要空想!
import java.lang.ref.WeakReference;
/**
* Class to research strings.
* constant string like "AAA" won't be reclaimed while instance created by new will.
* when you new a String by a constant string, there will be two memory field stored the same value.
* so initialize a String by constant String is recommended.
*/public class StringResearch { public static void main(String[] args) {
String a = "AAA";
String b = new String("AAA"); WeakReference wra = new WeakReference(a);
WeakReference wrb = new WeakReference(b);
a = null;
b = null; System.gc();
System.out.println(wra.get());
System.out.println(wrb.get());
}}
//--------------------------------------------------------君可知,马谡是怎么死的?
2. 栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外,栈数据可以共享,详见第3点。堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。
3. Java中的数据类型有两种。基本类型(primitive types), 共有8种,即int, short, long, byte, float, double, boolean, char。存在于栈中。另一种是包装类数据,如Integer, String, Double等将相应的基本数据类型包装起来的类。这些类数据全部存在于堆中.String str = "abc";和String str = new String("abc");和char[] c = {'a','b','c'};String str=new String(c);都采用堆存储String str = "abc";在栈中如果没有存放值为"abc"的地址,等同于:
String temp=new String("abc");
String str=temp;关于String str = "abc"的内部工作。Java内部将此语句转化为以下几个步骤:
(1)先定义一个名为str的对String类的对象引用变量:String str;
(2)在栈中查找有没有存放值为"abc"的地址,如果没有,则开辟一个存放字面值为"abc"的地址,接着创建一个新的String类的对象o,并将o的字符串值指向这个地址,而且在栈中这个地址旁边记下这个引用的对象o。如果已经有了值为"abc"的地址,则查找对象o,并返回o的地址。
(3)将str指向对象o的地址。使用String str = "abc";的方式,可以在一定程度上提高程序的运行速度,因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于String str = new String("abc");的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象,从而加重了程序的负担。char[] c = {'a','b','c'};String str=new String(c);等同于:
String str = new String('a'+'b'+'c');
******************************************************************************
转贴:http://community.csdn.net/Expert/topic/4848/4848360.xml?temp=9.325808E-02
看完之后真正的明白了,感谢! 和大家一起分享!!
******************************************************************************
* Initializes a newly created <code>String</code> object so that it
* represents the same sequence of characters as the argument; in other
* words, the newly created string is a copy of the argument string. Unless
* an explicit copy of <code>original</code> is needed, use of this
* constructor is unnecessary since Strings are immutable.
*
* @param original a <code>String</code>.
*/
public String(String original) {
this.count = original.count;
if (original.value.length > this.count) {
// The array representing the String is bigger than the new
// String itself. Perhaps this constructor is being called
// in order to trim the baggage, so make a copy of the array.
this.value = new char[this.count];
System.arraycopy(original.value, original.offset,
this.value, 0, this.count);
} else {
// The array representing the String is the same
// size as the String, so no point in making a copy.
this.value = original.value;
}
}
不会的就要弄清楚.别在这以老买老,我最看不起了!!