您的位置:首页 > 编程语言 > Java开发

JavaSE 番外篇之String(一)

2014-03-21 00:46 274 查看
String是Java中一个比较特殊的类,刚接触的时候被弄的是一头雾水,百般求证之后得到些许成果,现在分享给大家

常见疑惑:

一、String是什么类型的数据?

二、String的两种创建方式有什么不同?

三、String是如何比较的?

解惑一:String是引用型数据

有的人就问了Java引用类型没有String啊,刚开始我被问的一愣!class是引用类型的啊,String是一种class并且是Java自定义的类。所以Java是引用类型数据。

解惑二:先让我们简单的了解下Java的内存管理机制

 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域都有各自的用途,以及创建和销毁的时

间,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用户线程的启动和结束而建立和销毁。根据《Java虚拟机规范(第2版)》的规

定,Java虚拟机所管理的内存将会包括以下几个运行时数据区域,如下图所示:



当然对于我们的问题而言 无须分的这么复杂就简单的分为堆和栈、方法区。

栈的存取速度仅次于CPU中的寄存器比堆的存取速度快,但是存于栈中的数据她的生存周期是确定的所以缺乏灵活性

常量池位于方法区内常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。常量池还具备动态性,运行期间可以将新的常量放入池中,String类的intern()方法是这一特性的典型应用。不懂吗?后面会介绍intern方法的。虚拟机为每个被装载的类型维护一个常量池,池中为该类型所用常量的一个有序集合,包括直接常量(string、integer和float常量)和对其他类型、字段和方法的符号引用

堆是存放对象的地方所有new出来的东西都是存于堆中,可以动态的分配内存的大小,生存周期以不必提前告诉编译器且GC会自动回收垃圾内存

有了内存管理的知识我们还需要知道“==”和equals()的区别

这也是个非常复杂的问题这里不做详细讨论以后也会设专题讨论的,在这里只要知道在String中

"=="是内存地址的比较;

equals()是字符串值的比较;

请看以下代码





对于直接赋值的情况在栈中创建引用s1、s2如果常量池里面已经有了hello那么让s1,s2都指向这个hello故s1==s2

对于第二种创建方式在栈中创建引用s3,s4,并且在堆中new出两个新的对象,其内存地址是不一样的所以s3 !=s4的

而s5是指向s4所指向的堆中的实例所以s4==s5的;

解惑三:关于这个问题在解惑二中也谈及了一些

当字符串是直接赋值产生时且内容相同那么他们指向的都是常量池里的同一字符串故其内容(值)和内存地址都是一样的所以“==”和equals()都是true

当字符串是new出来的在堆中并不是同一个对象所以其地址是不一样的理所当然“==”是false;

但是如果其内容是一样的那么equals()是true的因为他比较的是值

另外谈谈字符串的哈希码,大家在图中已经可以看出只要内容相同那么他们的哈希码是相同的

什么是哈希码,在Java中哈希码就是对象的特征值,可以是地址,也可以是内容。哈希码是根据一定的算法产生的一个字符序列,让同一个类的每一个对象按照自己特征上的不同尽量拥有不同的哈希码,但是不保证不同的对象会有相同的哈希码,这是和算法相关的

但是在Sring类中类重写了hashcode方法,它返回的是根据字符串的内容运算出来的哈希码,所以只要字符串相同,它们的哈希码也相同。并且String类重写的equals方法就是比较哈希码是否一样来判断字符串序列是否相同。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  javase 编程