差异点比较

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类型。

约定:

  1. 覆写equals方法时必须覆写hashcode()
  2. 如果两个对象的equals方法返回值为true,则两个object对应的HashCode值应该相同
  3. 如果两个对象的equals方法返回false,但是这两个object对应的HashCode是有可能会相同的,(但是必须意识到: HashCode返回独一无二的值,对后续存储此对象的hashtable\hashmap等容器更好的处理有很大帮助。因此覆写的时候可以考虑下hashcode的算法,尽量避免重复情况。 当然,就算出现重复,HashMap等容器也是有容错处理机制的,也是可以放入Map的,这个后续会深入分析。)

常见的几个String操作类的比较

  1. StringBuilder

线程不安全,但是性能比较高。

  1. StringBuffer

线程安全,但是性能比StringBuilder略差。因为其中的很多方法实现上都加了线程同步锁。

  1. StringTokenizer

字符串分割处理工具类。

JAVA基础5——与String相关的系列(2)的更多相关文章

  1. JAVA基础5——与String相关的系列(1)

    与String相关的系列 String, 是JAVA中常见的一个引用类型,且其具有一定的特殊性. String类型被设置为final型,即不可继承,也就不可修改其中的实现. String可以改变吗 S ...

  2. Java基础笔记之String相关知识

    (二)String Sring 被声明为 final ,因此不可被继承. String的不可变性: 看String的定义(java9版本): public final class String imp ...

  3. Java基础-字符串(String)常用方法

    Java基础-字符串(String)常用方法 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.java的API概念 Java的API(API:Application(应用) Pr ...

  4. java基础学习日志--String、StringBuffer方法案例

    package StringDemo; import java.util.Arrays; /* * 常用String.StringBufer类的方法 */ public class Demo1 { p ...

  5. 【JAVA - 基础】之String存储机制浅析

    本文主要解决以下几个问题 String源码解析? String和new String的区别? String通过"+"或concat累加时的对象创建机制? StringBuilder ...

  6. Java 基础 - 如何理解String不可变

    ref: https://www.zhihu.com/question/20618891 第一个答案. 扩展“ Java 基础 - System.arraycopy() 浅拷贝 深拷贝

  7. JAVA基础--常用类 String,StringBuffer, 基础数据类型包装类, Math类, Enum类

    字符串相关类: String, StringBuffer String类为不可变的字符序列 String s1="hello"; String s2="hello&quo ...

  8. Java基础知识总结--String、StringBuffer、StringBuilder

    1.Java String 类 String类是final类,也即意味着String类不能被继承,并且它的成员方法都默认为final方法.在Java中,被final修饰的类是不允许被继承的,并且该类中 ...

  9. Java基础--常用API--日期相关API

    一.java.util.Date 1.只用于显示系统时间,其大部分操作由Calendar代替. 格林威治时间(GMT):指的是1970年1月1日0时,不同地区有时间差. 默认输出格式:星期.月.日.时 ...

随机推荐

  1. 从零开始教你封装自己的vue组件

    组件(component)是vue.js最强大的功能之一,它可以实现功能的复用,以及对其他逻辑的解耦.但经过一段时间的使用,我发现自己并没有在业务中发挥出组件的最大价值.相信很多刚开始使用vue的朋友 ...

  2. eclispe中安装hibernate插件

    用eclispe玩ee的朋友,写配置文件的时候没有提示非常苦恼,而配置dtd文件还是没有得到解决,最后试了试安装插件解决了问题 地址:http://download.jboss.org/jbossto ...

  3. 【ASP.NET MVC 学习笔记】- 20 ASP.NET Web API

    本文参考:http://www.cnblogs.com/willick/p/3441432.html 1.ASP.NET Web API(本文简称Web API),是基于ASP.NET平台构建REST ...

  4. PHP操作Memcached

    一.PHP连接Memcached: 一个简单的使用示例: $memcache = new Memcache; $memcache->connect("127.0.0.1",1 ...

  5. bug:未考虑实际使用场景

    最近bug比较多,汗颜. 1.需求背景 (1)app活动页面,用户参与并完成能够以1分钱价格购买指定商品(2)这个页面可分享至app以外的渠道,如微信.QQ等 2.这个bug的表现形式:用户在第三方渠 ...

  6. StringDup(理论AC)

    Problem Statement for StringDup Problem Statement      Create a class called StringDup. Given a stri ...

  7. Problem N

    Problem Description The cows have purchased a yogurt factory that makes world-famous Yucky Yogurt. O ...

  8. git使用教程之了解git

    1.理解git快照 快照的作用就相当于将旧文件所占的空间保留下来,并且保存一个引用,而新文件中会继续使用与旧文件内容相同部分的磁盘空间,不同部分则写入新的磁盘空间.git有一个HEAD指针,这个指针可 ...

  9. asp.net core webapi文件上传

    最近开发一个新项目,使用了asp.net core 2.0,采用webapi开发后台,postgresql为数据库.最先来的问题就是上传文件的问题. POST文件的一些坑 使用默认模板创建webapi ...

  10. Problem E: 可变长数组

    Problem E: 可变长数组 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 472  Solved: 368[Submit][Status][Web ...