萍聚社区-德国热线-德国实用信息网

 找回密码
 注册

微信登录

微信扫一扫,快速登录

萍聚头条

查看: 613|回复: 0

1-1-19-1-1 Java字符串对象的比较

[复制链接]
发表于 2003-2-7 01:40 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册 微信登录

x
发信人: qyjohn (Sweet Potato -- 成功戒BBS中...), 信区: Java      
标  题: Java字符串对象的比较
发信站: BBS 水木清华站 (Tue Jun  5 04:59:19 2001)

最近在翻看有关Java Programmer Certificate的辅导资料,看到一些关于
字符串的说明,归纳以下与大家共享。

String s1 = "Hello";
String s2 = "Hello";
if (s1 == s2)
{
    System.out.println("s1 = s2");
}

String t1 = new String("Hello");
String t2 = new String("Hello");
if (t1 == t2)
{
    System.out.println("t1 = t2");
}

我们知道进行字符串比较需要使用字符串对象String的equals方法。这是
因为操作符 == 进行的是狭义上的比较,而方法equals进行的是广义上的
比较。也就是说,操作符 == 比较的是引用,而方法equals比较的是被引
用的值。用C/C++的术语来说,操作符 == 比较的是指针的值,方法equals
比较的是被指针指向的值。

根据以上认识,我们会认为上述程序片断运行时肯定不会打印s1 = s2,
因为字符串s1和s2是两个不同的String对象,其引用应该是不同的。但是
这样的想法是错误的,因为程序运行时却是打印了s1 = s2。

Java通过重新利用相同的字符串对象从而达到节约系统资源的目的。由于
s1和s2的内容完全相同,因此s1和s2在内存中的地址是完全相同的。正是
因为这样的原因,s1 = s2成立。

那么t1和t2是否象等呢?他们的内容也完全相同。

答案是否定的,因为操作符new强制为t1和t2重新生成新的字符串对象,而
不是重新利用现有的具有相同内容的字符串对象。因此t1和t2在内存中的
地址是不同的,其引用也是不同的。因此,t1 = t2不成立。

小结如下:

1 Java会重复利用现有的字符串对象。
2 操作符new强制生成新的对象。
3 操作符 == 进行狭义上的比较,即引用的比较;方法equals进行广义上
  的比较,即被引用的值的比较。

发信人: liyawei (lili), 信区: Java      
标  题: Re: Java字符串对象的比较
发信站: BBS 水木清华站 (Tue Jun  5 23:36:57 2001)


【 在 FoolsGarden (拼命※重考结束,努力干活) 的大作中提到: 】
: 有些人会问:重用有什么用途?
: 对于我们一班人用的PC环境来说,些许的资源浪费并不能改变什么。但是对于
: Java的两个极端J2ME和J2EE来说,就非同寻常了。在J2ME中,大多的智能设备
: 未能实现纯正的实时系统,Java的处理就必须是单步的。在智能卡中,连内存
: 管理程序都被取消,所以在memery restrict的设备中,你有时需要自己考虑
: 对象重用。对于商业应用,应该是效率优先的原则了,呵呵,当你认为自己的
: 代码需要紧凑的时候,就需要考虑到这一点了:)

我觉得这种现象和JAVA关系不是很大。
这是编译技术的原理。
怎么说呢,即使对于C++,程序中出现的一般primitive
类型常量如i = i+1生成的机器码中包含了的常量硬编码。
而如程序中出现的大字符串常量如"liywawei"是专门放在全局数据段(?记不大清了)
所有对这个常量的引用都是指向该数据的。
所以,我相信JAVA也是如此。而之所以String s1 =new String("liyawei")是创建一个新韵螅
我认为这是new操作符的语义决定的,就是要建一个新对象,与优化无关,当前的编译器也根本无法优化。
下面这段程序:
String s1 =new String("liyawei");
String s2 ="liyawei";
s1="liyawei";
if (s1==s2)
{
        System.out.println("==");      
}
其结果还是相等。当然,与各位描述的也符合。但我认为是C++/JAVA编译器的普遍方法。⒉皇
不是JAVA独有的。


发信人: qyjohn (Sweet Potato -- 成功戒BBS中...), 信区: Java      
标  题: Re: Java字符串对象的比较
发信站: BBS 水木清华站 (Wed Jun  6 00:03:42 2001)

你所举的例子是不合适的。主要有下面几点:

1 字符串s1创建在先,内容为"liyawei"的字符串在内存中已经存在以后再创建
  字符串s2。由于在创建s2的时候没有使用new操作符,字符串s2实际上和s1的
  物理地址是一样的,因此s2和s1的引用也是相同的。

2 在你的第三行代码中重新定义了s1。由于字符串对象String的不可更改性(也
  就是immutable属性,FG解释一下这个中文术语吧),这个操作实际上不是更改
  s1的内容,而是重新创建一个名为s1的字符串,其内容为"liyawei"。根据1,
  内容为"liyawei"的字符串再重新创建s1之前已经存在,因此s1重新使用这个
  已经存在的字符串,所以新的s1和s2的物理地址是一样的,因此s1和s2的引用
  也是相同的。

3 在Java中字符串对象String不属于基本数据类型。

4 在C/C++的编译中,有的编译器有可能对你的程序进行优化,譬如说将程序中
  大量出现的常量专门放到指定数据并且可以重用,但是你必须在程序中显式的
  声明这些数据是常量。另外,即使你已经显式的声明这些数据是常量,是否
  进行这些优化还取决于你的编译器和优化参数。而在Java中,由于字符串对象
  的不可更改性,所有的字符串对象都被认为是常量,这种优化是强制性的。

以上所述,有什么不正确的地方,请多多指教。

【 在 liyawei (lili) 的大作中提到: 】
: 我觉得这种现象和JAVA关系不是很大。
: 这是编译技术的原理。
: 怎么说呢,即使对于C++,程序中出现的一般primitive
: 类型常量如i = i+1生成的机器码中包含了的常量硬编码。
: 而如程序中出现的大字符串常量如"liywawei"是专门放在全局数据段(?记不大清了)
: 所有对这个常量的引用都是指向该数据的。
: 所以,我相信JAVA也是如此。而之所以String s1 =new String("liyawei")是创建一个露韵螅
: 我认为这是new操作符的语义决定的,就是要建一个新对象,与优化无关,当前的编译器也根本无法优化。
: 下面这段程序:
: String s1 =new String("liyawei");
: String s2 ="liyawei";
: s1="liyawei";
: if (s1==s2)
: {
:         System.out.println("==");      
: }
: 其结果还是相等。当然,与各位描述的也符合。但我认为是C++/JAVA编译器的普遍方法2⒉皇
: 不是JAVA独有的。

发信人: liyawei (lili), 信区: Java      
标  题: Re: Java字符串对象的比较
发信站: BBS 水木清华站 (Wed Jun  6 00:05:38 2001)


【 在 qyjohn (Sweet Potato -- 成功戒BBS中...) 的大作中提到: 】
: 你所举的例子是不合适的。主要有下面几点:
: 1 字符串s1创建在先,内容为"liyawei"的字符串在内存中已经存在以后再创建
:   字符串s2。由于在创建s2的时候没有使用new操作符,字符串s2实际上和s1的
:   物理地址是一样的,因此s2和s1的引用也是相同的。
: 2 在你的第三行代码中重新定义了s1。由于字符串对象String的不可更改性(也
:   就是immutable属性,FG解释一下这个中文术语吧),这个操作实际上不是更改
:   s1的内容,而是重新创建一个名为s1的字符串,其内容为"liyawei"。根据1,
:   内容为"liyawei"的字符串再重新创建s1之前已经存在,因此s1重新使用这个
:   已经存在的字符串,所以新的s1和s2的物理地址是一样的,因此s1和s2的引用
:   也是相同的。
~~~~~~~~~~~~~~~~~~~~~~~~~~
对,你说的正和我认为的一致
这个相同的物理地址是在一个全局的数据区里面。
呵呵

: 3 在Java中字符串对象String不属于基本数据类型。
: ...................

信人: liyawei (lili), 信区: Java      
标  题: Re: Java字符串对象的比较
发信站: BBS 水木清华站 (Wed Jun  6 00:08:26 2001)


【 在 qyjohn (Sweet Potato -- 成功戒BBS中...) 的大作中提到: 】
: 你所举的例子是不合适的。主要有下面几点:
: 1 字符串s1创建在先,内容为"liyawei"的字符串在内存中已经存在以后再创建
:   字符串s2。由于在创建s2的时候没有使用new操作符,字符串s2实际上和s1的
:   物理地址是一样的,因此s2和s1的引用也是相同的。
我已经说了,只要没有用new,对该字符串常量的引用都是不便的。
因为new的语义就是创建一个对象。
其实,你的三个结论我是赞成的。但是这和JAVA关系不大。是编译器的普遍技术
: 2 在你的第三行代码中重新定义了s1。由于字符串对象String的不可更改性(也
:   就是immutable属性,FG解释一下这个中文术语吧),这个操作实际上不是更改
:   s1的内容,而是重新创建一个名为s1的字符串,其内容为"liyawei"。根据1,
:   内容为"liyawei"的字符串再重新创建s1之前已经存在,因此s1重新使用这个
:   已经存在的字符串,所以新的s1和s2的物理地址是一样的,因此s1和s2的引用
:   也是相同的。
: 3 在Java中字符串对象String不属于基本数据类型。
: ...................


发信人: FoolsGarden (拼命※重考结束,努力干活), 信区: Java      
标  题: Re: Java字符串对象的比较
发信站: BBS 水木清华站 (Wed Jun  6 00:12:26 2001)

为什么会在字符串上大家发生认识模糊,就是qyjohn提到的
java和c中对string类型的不同构造,在c中它是基本数据类型,
而在Java众它是一个类。当然具体到编译那一层,大家都差不多的说
【 在 liyawei (lili) 的大作中提到: 】
: 我已经说了,只要没有用new,对该字符串常量的引用都是不便的。
: 因为new的语义就是创建一个对象。
: 其实,你的三个结论我是赞成的。但是这和JAVA关系不大。是编译器的普遍技术
Die von den Nutzern eingestellten Information und Meinungen sind nicht eigene Informationen und Meinungen der DOLC GmbH.
您需要登录后才可以回帖 登录 | 注册 微信登录

本版积分规则

手机版|Archiver|AGB|Impressum|Datenschutzerklärung|萍聚社区-德国热线-德国实用信息网

GMT+1, 2025-3-12 22:11 , Processed in 0.060590 second(s), 17 queries , MemCached On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表