JAVA基础5——与String相关的系列(2)
差异点比较
String使用+直接拼接
这种情况需要分两种情况来讨论:
1、 都是确定的字符串常量之间进行的+号拼接的时候,由于在编译器就可以确定其具体值了,所以编译器在编译期的时候就会把这些常量拼接的字符串解析为一个整的字符串常量。举例如下:
String s1="helloworld";
String s2="hello" + "word";
System.out.println( s1==s2 );
执行结果:
true (可以看出s0跟s1是同一个对象,因为编译期的时候s2就已经被解析为helloworld了)
2、 不确定的变量之间使用+拼接的时候,由于编译器无法在编译期进行优化,只能在运行期动态分配处理。举例如下:
String s1 = "a";
String s2 = "b";
String s3 = "c";
String s4 = s1 + s2 + s3;
String s5 = "a" + "b" + "c";
System.out.println( s4==s5 );
执行结果:
false (因为s5编译期就确定为一个常量,而s4运行期动态分配)
s4的JDK层实现逻辑如下:
StringBuffer temp = new StringBuffer();
temp.append(s1).append(s2).append(s3);
String s = temp.toString();
由JDK层的实现代码可以看出,每执行一次+操作,就会生成一个StringBuffer对象,然后生成一个新的字符串对象。因此,如果是for循环中对多个字符串进行拼接的时候,可以直接使用StirngBuffer或者StringBuilder进行append操作,可以减少N-1次StringBuffer对象的创建。
3、 final修饰的字符串变量,在编译的时候也会被当做常量进行优化,如下所示:
String s0 = "ab";
final String s1 = "b";
String s2 = "a" + s1;
String s3 = "b";
String s4 = "a" + s3;
System.out.println((s0 == s2));
System.out.println((s0 == s4));
执行结果:
true
false
因为s1是final型的,所以编译期会被当做确定常量,s2直接编译期被优化为ab,而s3只是普通变量,无法编译期优化,所以按照字符串拼接的方式,会生成新的字符串对象。
关于String不同操作过程生成几个对象的问题
关键点:对于字符串字面量的形式(即双引号的方式),只有当字符串常量池中不存在相同的字符串的时候才会创建;对于new的方式一定会有新对象产生。
1、 String s = "abc"创建了几个对象?
这个语句创建了一个对象或者0个对象,取决于abc这个字符串是否已经在常量池中存在。
2、 String s = new String("abc")创建了几个对象?
这个语句等价于下面的语句:
String param = "abc";
String s = new String(param);
因此,这个过程一共创建了两个对象或者一个对象,即param与s(取决于常量池中是否已经有abc字符串了)。
3、 String s1 = "abc"; String s2 = "abc"创建了几个对象?
这个情况也是只创建了一个对象或者0个对象"abc",然后s1和s2都只是指向同一个"abc"内存地址的引用,如果"abc"已经在常量池中的时候,就不会新创建。
4、 String s = "a" + "b"创建了几个对象?
这个实际上与String s = "ab"是等价的,这个过程新创建了1个对象或者0个对象。
5、 String c = "xx" + "yy " + a + "zz" + "mm" + b创建几个对象?
这个语句编译优化后等价于下面的逻辑:
String c = (new StringBuilder().append("xxyy").append(a).append("zz").append("mm").append(b)).toString();
即:如果+进行拼接的时候,从左往右,会将最初的几个常量都直接合并为1个常量(比如xx和yy),然后与变量进行拼接,然后出现在变量后面的常量就没法再合并到一起了(比如zz和mm),只能逐个累加。
此过程中,会产生1个StringBuilder对象和一个String对象。
关于==与equals以及HashCode
简而言之,==用于比较简单的数据类型,或者看下某两个对象引用是否指向堆内存中的同一块地址;equals用于比较两个对象的内容是否相同。
对于Object对象而言,其默认提供的equals方法实现就是简单的return this == obj;即只有两个对象都指向了同一个内存地址对象的时候,才会return true。 对于需要比较内容是否相等的情况时,必须要自行覆写equals方法。
对于覆写equals方法的时候,通常要求必须同时覆写HashCode()方法。hashCode即对象的散列码,int类型。
约定:
- 覆写equals方法时必须覆写hashcode()
- 如果两个对象的equals方法返回值为true,则两个object对应的HashCode值应该相同
- 如果两个对象的equals方法返回false,但是这两个object对应的HashCode是有可能会相同的,(但是必须意识到: HashCode返回独一无二的值,对后续存储此对象的hashtable\hashmap等容器更好的处理有很大帮助。因此覆写的时候可以考虑下hashcode的算法,尽量避免重复情况。 当然,就算出现重复,HashMap等容器也是有容错处理机制的,也是可以放入Map的,这个后续会深入分析。)
常见的几个String操作类的比较
- StringBuilder
线程不安全,但是性能比较高。
- StringBuffer
线程安全,但是性能比StringBuilder略差。因为其中的很多方法实现上都加了线程同步锁。
- StringTokenizer
字符串分割处理工具类。
JAVA基础5——与String相关的系列(2)的更多相关文章
- JAVA基础5——与String相关的系列(1)
与String相关的系列 String, 是JAVA中常见的一个引用类型,且其具有一定的特殊性. String类型被设置为final型,即不可继承,也就不可修改其中的实现. String可以改变吗 S ...
- Java基础笔记之String相关知识
(二)String Sring 被声明为 final ,因此不可被继承. String的不可变性: 看String的定义(java9版本): public final class String imp ...
- Java基础-字符串(String)常用方法
Java基础-字符串(String)常用方法 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.java的API概念 Java的API(API:Application(应用) Pr ...
- java基础学习日志--String、StringBuffer方法案例
package StringDemo; import java.util.Arrays; /* * 常用String.StringBufer类的方法 */ public class Demo1 { p ...
- 【JAVA - 基础】之String存储机制浅析
本文主要解决以下几个问题 String源码解析? String和new String的区别? String通过"+"或concat累加时的对象创建机制? StringBuilder ...
- Java 基础 - 如何理解String不可变
ref: https://www.zhihu.com/question/20618891 第一个答案. 扩展“ Java 基础 - System.arraycopy() 浅拷贝 深拷贝
- JAVA基础--常用类 String,StringBuffer, 基础数据类型包装类, Math类, Enum类
字符串相关类: String, StringBuffer String类为不可变的字符序列 String s1="hello"; String s2="hello&quo ...
- Java基础知识总结--String、StringBuffer、StringBuilder
1.Java String 类 String类是final类,也即意味着String类不能被继承,并且它的成员方法都默认为final方法.在Java中,被final修饰的类是不允许被继承的,并且该类中 ...
- Java基础--常用API--日期相关API
一.java.util.Date 1.只用于显示系统时间,其大部分操作由Calendar代替. 格林威治时间(GMT):指的是1970年1月1日0时,不同地区有时间差. 默认输出格式:星期.月.日.时 ...
随机推荐
- win10 uwp 打电话
UWP可以使用打电话功能,在PC是用Skype,在手机是直接使用电话功能. UWP可以通过Skype打电话,那么如何通过应用间通讯,很简单使用Launcher. Skype电话使用Skype:(电话号 ...
- PHP中提问频率最高的11个面试题和答案
问题:请用最简单的语言告诉我PHP是什么? 回答:PHP全称:Hypertext Preprocessor,是一种用来开发动态网站的服务器脚本语言. 问题:什么是MVC? 回答:MVC由Model(模 ...
- (转)利用JConsole工具监控java程序内存和JVM
转自:http://www.cnblogs.com/luihengk/p/5446279.html 一.找到java应用程序对应的进程PI 性能测试应用程序访问地址:http://192.168.29 ...
- 使用ftp软件上传下载php文件时换行丢失bug(全部变为一行)
文章来源:http://www.piaoyi.org/computer/ftp-php-r-n-bug.html 正 文: 在使用ftp软件上传下载php源文件时,我们偶尔会发现在本地windows下 ...
- 域名系统DNS
一.域名系统是什么 域名系统其实就是一个把主机名解析为IP地址的名字系统. 因特网使用层次树状结构的命名方法,并使用分布式的域名系统DNS.因特网的域名系统DNS被设计成一个联机分布式数据库系统,并采 ...
- Java语言实现机制
Java语言实现机制 1.Java虚拟机(Java Virtual Machine) Java虚拟机(JVM)是在一台计算机上由软件模拟也可以用硬件来实现的假想的计算机.它定义了指令集(相当于中央处理 ...
- LR多分类推广 - Softmax回归*
LR是一个传统的二分类模型,它也可以用于多分类任务,其基本思想是:将多分类任务拆分成若干个二分类任务,然后对每个二分类任务训练一个模型,最后将多个模型的结果进行集成以获得最终的分类结果.一般来说,可以 ...
- Mongoose之 SchemaTypes 数据类型
SchemaTypes 数据类型 SchemaTypes handle definition of path defaults, validation, getters, setters, field ...
- [MYSQL] 记一次MySQL性能调优
最近在做数据迁移工作,已有一堆数据文件,要把这些数据文件写到MySQL 数据库里面去. MySQL数据库上架了一层服务接口,可以直接调用.博主写了一个迁移程序,放在服务器A上. *********** ...
- jQuery_事件学习
一.click事件 click事件----鼠标单击事件 $('.bt').click(function() { alert("本身的事件");}) 当class为bt的div被但单 ...