C# 中的 String类型分析

equals方法和==的区别

首先大家知道,String既可以作为一个对象类来使用,又可以作为一个基本类型来使用。这里指的作为一个基本类型来使用只是指使用方法上的,比如String s = "Hello",它的使用方法如同基本类型int一样,比如int i = 1;,而作为一个对象来使用,则是指通过new关键字来创建一个新对象,比如String s = new String("Hello")。但是它的内部动作其实还是创建了一个对象,这点稍后会说到。

其次,对String对象的比较方法需要了解。C#里对象之间的比较有两种概念,这里拿String对象来说:一种是用"=="来比较,这种比较是针对两个String类型的变量的引用,也就是说如果两个String类型的变量,它们所引用同一个String对象(即指向同一块内存堆),则"=="比较的结果是true。另一种是用Object对象的equals()方法来比较,String对象继承自Object,并且对equals()方法进行了重写。两个String对象通过equals()方法来进行比较时,其实就是对String对象所封装的字符串内容进行比较,也就是说如果两个String对象所封装的字符串内容相同(包括大小写相同),则equals()方法将返回true。

现在开始将对String对象的创建做具体的分析:

1、/////////////////////////////////////////////////////////////////////////

String s1 = new String("Hello");

String s2 = new String("Hello");

System.out.println(s1 == s2);

System.out.println(s1.equals(s2));

以上代码段的打印结果是:

false

true

这个结果相信大家很好理解,两个String类型的变量s1和s2都通过new关键字分别创建了一个新的String对象,这个new关键字为创建的每个对象分配一块新的、独立的内存堆。因此当通过"=="来比较它们所引用的是否是同一个对象时,将返回false。而通过equals()方法来比较时,则返回true,因为这两个对象所封装的字符串内容是完全相同的。

2、//////////////////////////////////////////////////////////////////////////////////

String s1 = new String("Hello");

String s2 = s1;

System.out.println(s1 == s2);

System.out.println(s1.equals(s2));

以上代码段的打印结果是:

true

true

这个结果应该更好理解,变量s1还是通过new关键字来创建了一个新的String对象,但这里s2并没有通过new关键字来创建一个新的String对象,而是直接把s1赋值给了s2,即把s1的引用赋值给了s2,所以s2所引用的对象其实就是s1所引用的对象。所以通过"=="来比较时,返回true。既然它们引用的都是同一个对象,那么通过equals()方法来比较时,肯定也返回true,这里equals()方法其实在对同一个对象进行比较,自己肯定等于自己咯。

3、//////////////////////////////////////////////////////////////////////////////

String s1 = "Hello";

String s2 = "Hello";

System.out.println(s1 == s2);

System.out.println(s1.equals(s2));

以上代码段的打印结果是:

true

true

为什么这个结果?那么来分析一下。首先这两个String对象都是作为一个基本类型来使用的,而不是通过new关键字来创建的,因此虚拟机不会为这两个String对象分配新的内存堆,而是到String缓冲池中来寻找。

首先为s1寻找String缓冲池内是否有与"Hello"相同值的String对象存在,此时String缓冲池内是空的,没有相同值的String对象存在,所以虚拟机会在String缓冲池内创建此String对象,其动作就是new String("Hello");。然后把此String对象的引用赋值给s1。

接着为s2寻找String缓冲池内是否有与"Hello"相同值的String对象存在,此时虚拟机找到了一个与其相同值的String对象,这个String对象其实就是为s1所创建的String对象。既然找到了一个相同值的对象,那么虚拟机就不在为此创建一个新的String对象,而是直接把存在的String对象的引用赋值给s2。

这里既然s1和s2所引用的是同一个String对象,即自己等于自己,所以以上两种比较方法都返回ture。

到这里,对String对象的基本概念应该都已经理解了。现在我来小结一下:

针对String作为一个基本类型来使用:

1。如果String作为一个基本类型来使用,那么我们视此String对象是String缓冲池所拥有的。

2。如果String作为一个基本类型来使用,并且此时String缓冲池内不存在与其指定值相同的String对象,那么此时虚拟机将为此创建新的String对象,并存放在String缓冲池内。

3。如果String作为一个基本类型来使用,并且此时String缓冲池内存在与其指定值相同的String对象,那么此时虚拟机将不为此创建新的String对象,而直接返回已存在的String对象的引用。

针对String作为一个对象来使用:

1。如果String作为一个对象来使用,那么虚拟机将为此创建一个新的String对象,即为此对象分配一块新的内存堆,并且它并不是String缓冲池所拥有的,即它是独立的。

理解了以上内容后,请看以下代码段:

4、/////////////////////////////////////////////////////////////////////////////

String s1 = "Hello";

String s2 = new String("Hello");

System.out.println(s1 == s2);

System.out.println(s1.equals(s2));

以上代码段的打印结果是:

false

true

根据上面的小结来进行分析。第一行是把String作为一个基本类型来使用的,因此s1所引用的对象是属于String缓冲池内的。并且此时String缓冲池内并没有与其值相同的String对象存在,因此虚拟机会为此创建一个新的String对象,即new String("Hello");。第二行是把String作为一个对象来使用的,因此s2所引用的对象不属于String缓冲池内的,即它是独立的。通过new关键字,虚拟机会为此创建一个新的String对象,即为它分配了一块新的内存堆。因此"=="比较后的结果是false,因为s1和s2所引用的并不是同一个对象,它们是独立存在的。而equals()方法所返回的是true,因为这两个对象所封装的字符串内容是完全相同的。

时间: 2024-11-01 12:37:05

C# 中的 String类型分析的相关文章

C++中关于string类型究竟能不能用cout输出的问题

先让我讲下故事哈 一次在MFC中用cout输出一个string类型字符串,编译时出现这样一个错误: error C2679: binary '<<' : no operator defined which takes a right-hand operand of type 'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >' (or

java 中的String类型

java 中的String类型   (1)String类型的数据可以表示所有的数据类型. (2)String中的字符串常量与一般的字符串:                String str0 = "hello";//字符串常量“hello”被预先放到了数据段的字符串常量池中                String str1 = "hello";//直接从常量池中寻找已有的字符串常量                String str2 = new String

C#中的String类型

C#中的String类型,其实是引用类型,String对象被分配在堆上,而不是栈上.因此,当把一个字符串变量赋予另一个字符串时,会得到对内存中同一个字符串的两个引用.但是,String与引用类型在常见的操作上有一些区别.例如,字符串是不可改变的.修改其中一个字符串,就会创建一个全新的String对象,而另一个字符串不会发生任何变化.如下列代码: string a = "a1"; string b = "b" + a; Console.WriteLine("

c/c++中关于String类型的思考

首先说明:String并不是一种内置类型,因此任何通过String声明出来的实例都不是一个变量,不同于内置类型因此String仅仅能称之为一种特殊的型别,没错String是一个类类型. 一般来说c语言里面是没有类和对象概念的,那么提供给c语言一个<string.h>头文件是做什么用的呢,如果研究过C++中String的构造那么应该会清楚string的底层依赖的就是内置类型的型别char *指针,所以显而易见开放<string.h>接口库给c语言就是为了处理char *字符串时能够很

java中关于String 类型数据 的存储方式

Constant Pool常量池的概念: 在讲到String的一些特殊情况时,总会提到String Pool或者Constant Pool,但是我想很多人都不太 明白Constant Pool到底是个怎么样的东西,运行的时候存储在哪里,所以在这里先说一下Constant Pool的内容. String Pool是对应于在Constant Pool中存储String常量的区域.习惯称为String Pool,也有人称为 String Constant Pool.好像没有正式的命名?? 在java编

[每天一个知识点]18-Java语言-在switch中接受String类型

在Java7中增加了一个新特性,switch可以接受String类型的变量,这就省下了书写大量if ("xxx".equals(yyy))的繁复工作.示例代码就免了,仅仅是一个数据类型的改变而已,如果会用原来的switch而在5分钟内搞不定String类型的switch,建议还是放弃做程序员吧-- 至于内部实现,java一点都没增加新内容,其实代码是被转换成了这个样子 switch (xxx.hashCode()) { case 1024: // 假设原来是"aaa"

如何在ArrayList&lt;Integer&gt;中添加String类型数据

黑马入学测试题: ArrayList list = new ArrayList(); 在这个泛型为Integer的ArrayList中存放一个String类型的对象. package itheima; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; /** * 在这个泛型为Integer的ArrayList中存放一个St

java中的String类型(不知道理解的好不,请教大神)

当执行String a = "abc"; 时候(前提条件是:执行这行代码之前在常量池中没有abc,若有,a直接引用在常量池中abc不在创建一个对象,若无,执行下面的描述) java虚拟机会在栈中创建char型的值'a','b','c',然后在堆中创建一个String 对象,它的值(value)是刚才在栈中创建的三个char类型值组成数组{'a','b','c'},最后这个新创建的String 对象会被添加到字符串池中. String b = new String("abc&q

JavaScript中的String类型

String类型是用的最多的,也是最为复杂的基本数据类型,单独拉出来写一篇 1.字符方法charAt();chartCodeAt();[]; 2.concat(para1,para2...)拼接字符串返回新的字符串. 3.字符串截取方法 slice(start,end),从start开始,到end结束,不包括end的子串.如果为负数则从后往前数,最后一个字符下标是-1 substr(start,length),从start开始截取length个字符,如果start为负数则从后面开始数. subs