allbetgaming官网:Java 字符串对照、拼接问题

admin/2020-07-12/ 分类:科技/阅读:

@

目录
  • 1.字符串的对照
    • 1. 1 字符串常量池
    • 1.2 String类型的对照方式
    • 1.3 String的建立方式
      • 1.3.1 直接使用“=”举行赋值
      • 1.3.2 使用“new”关键字建立新工具
      • 1.3.3 intern()方式返回的引用地址
  • 2. 字符串类的可变性与不能变性
  • 3. 字符串的相加/拼接
    • 3.1 字符串与非字符串类型的相加/拼接
    • 3.2 两个String类型工具相加/拼接原理
  • 4. final类型的String类字符串

/—————————————————— 字符串类型—————————————————/
Java中用于处置字符串常用的有三个类:

1、java.lang.String

2、java.lang.StringBuffer

3、java.lang.StrungBuilder

相同点: 都是final类, 不允许被继续;

不同点:

  • StringBuffered/StringBuilder 都继续自抽象类AbstractStringBuilder
    (实现了Appendable, CharSequence接口),可以通过append()、indert()举行字符串的操作
  • String实现了三个接口: Serializable、Comparable 、CarSequence,
    String的实例可以通过compareTo方式举行对照
    StringBuilder/StringBuffer只实现了两个接口Serializable、CharSequence
  • StringBuffer是线程平安的(Synchronized 加锁),可以不需要分外的同步用于多线程中
    StringBuilder不是线程平安的,然则效率比StringBuffer高

/—————————————本篇主要讨论String类型————————————/

1.字符串的对照

1. 1 字符串常量池

字符串常量池(以下简称常量池/字符串池)的存在意义:现实开发中,String类是使用频率异常高的一种引用工具类型。然则不断地建立新的字符串工具,会极大地消耗内存。因此,JVM为了提升性能和削减内存开销,内置了一块特殊的内存空间即常量池,以此来制止字符串的重复建立。JDK 1.8 后,常量池被放入到堆空间中。

字符串池中维护了共享的字符串工具,这些字符串不会被垃圾收集器接纳。

1.2 String类型的对照方式

若直接使用“==”举行对照工具,则对照的是两个工具的引用地址;

若使用str1.equals(str2)方式举行对照,由于String类内部已经笼罩Object类中的equals()方式,现实对照的是两个字符串的值。

  • 对照原理:
    先判断工具地址是否相等,若相等则直接返回true;
    若不相等再去参数判断括号内传入的参数是否为String类型的:若不是字符串将最终返回false;若是字符串,再依次对照所有字符是否一样。
// 源码 public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String aString = (String)anObject; if (coder() == aString.coder()) { return isLatin1() ? StringLatin1.equals(value, aString.value) : StringUTF16.equals(value, aString.value); } } return false; } 

1.3 String的建立方式

1.3.1 直接使用“=”举行赋值

String str_01 = "aa"; String str_02 = "aa"; System.out.println(str_01 == str_02); 

使用这种方式建立字符串,会先在栈中建立一个引用变量str_01,再去常量池中寻找是否已存在值为"aa"的字符串:

  1. 若是不存在这样的字符串,则会在常量池中新建一个"aa"字符串工具,并把这个字符串工具的引用地址赋值给工具str_01;
  2. 若是常量池中寻找已存在这样的字符串,则不会再建立新的工具,直接返回已存在的工具地址,并将其赋值给工具str_02;
// result true 

1.3.2 使用“new”关键字建立新工具

String str_01 = new String("xyz"); String str_02 = new String("xyz"); System.out.println(str_01 == str_02); 

这种方式至少会建立一个工具,由于本质是挪用了String类的组织器方式public String(String original){...},在堆中一定会建立一个字符串工具。

使用"new"关键字缔造工具主要分为三步:

  1. 在堆中会建立一个字符串工具;
  2. 判断常量池是否存在与组织器参数中的字符串值相等的常量;
  3. 若是常量池中已有这样的字符串存在,则直接返回堆中的字符串工具引用地址,赋值给栈中的变量;若是不存在,会先建立一个字符串工具在常量池中,然后返回堆中的工具引用地址,赋值给栈中的变量。
// result false 

1.3.3 intern()方式返回的引用地址

String str_01 = new String("abc").intern(); String str_02 = "abc"; String str_03 = new String("abc"); System.out.println(str_01 == str_02); System.out.println(str_02 == str_03); String str_04 = new String("cba"); String str_05 = new String("cba").intern(); System.out.println(str_04 == str_05); 

当使用组织器建立字符串挪用 intern()方式时,若是常量池中已经存在一个值相同的字符串(内部使用equals()方式来确定),则返回常量池中的字符串工具的引用地址;否则,将堆中新建立的字符串工具添加到常量池中,并返回池中字符串工具的引用地址。

// result true false false 

2. 字符串类的可变性与不能变性

字符串的本质:char类型数组 private final char[] str
String类实现了CharSequence接口

String类型的不能变性指的是内存地址不能变,若是将一个工具重新赋值,则本质上是改变了其引用工具。

String a = "hello"; System.out.println(a.hashCode()); a = "hey"; System.out.println(a.hashCode()); 
// result 99162322 103196 

StringBuffer类型和StringBuilder类型的字符串界说好后可以举行值改变,而且不会建立新的内存地址。

StringBuilder a = new StringBuilder(); System.out.println(a.hashCode()); a.append("Hello"); a.append("World"); System.out.println(a.hashCode()); 
// result 1395089624 1395089624 

3. 字符串的相加/拼接

3.1 字符串与非字符串类型的相加/拼接

String类中的valueOf(Object obj)方式可以将随便一个工具转换为字符串类型。

// 源码 public static String valueOf(Object obj) {   return (obj == null) ? "null" : obj.toString(); } 

String类中,重载了 与 =运算,这也是Java中唯一重载的两个运算符。
两个字符串相加即是字符串的拼接,在举行拼接时,会先挪用valueOf(Object obj)方式将其为字符串类型,再举行拼接。从源码可以看出,若是字符串为null,会将其转换为字面值为"null"的字符串。

String s = null; s = s "World"; System.out.println("Hello " s); // result: Hello nullWorld 

因此在举行字符串拼接时,初始字符串应该设置成空字符串"",而非null。

3.2 两个String类型工具相加/拼接原理

在字符串间使用加法运算时:

  • 若是常量字符串相加,如: "AB" "CD",则是编译优化。
    通常单独使用双引号" "引用起来的内容直接拼接时,均会被编译优化,编译时就已经确定其值,即为拼接后的值。
  • 若是字符串变量相加,如:
    String temp1 = "AB";
    String temp2 = "CD";
    String str = temp1 temp2;
    则是在底层挪用了StringBuilder类中的组织方式及append()方式来辅助完成:
    String str = new StringBuilder().append(temp1).append(temp2).toString();
 String str1 = "ABCD"; String str2 = "AB" "CD"; String str3 = "A" "B" "C" "D"; String temp1 = "AB"; String temp2 = "CD"; String str4 = temp1 temp2; // String str4 = new StringBuilder().append(temp1).append(temp2).toString(); String temp = "AB"; String str5 = temp "CD"; // String str4 = new StringBuilder(String.valueOf(temp)).append("CD").toString(); System.out.println(str1 == str2); System.out.println(str1 == str3); System.out.println(str1 == str4); System.out.println(str1 == str5); 
// result true true false false 

4. final类型的String类字符串

public class test { public static final String str1 = "abc"; public static final String str2 = "def"; public static void main(String[] args) { String str3 = str1 str2; String str4 = "abcdef"; System.out.println(str3 == str4); } } 

str1和str2都是final类型的,而且在编译阶段都是已经被赋值了,相当于一个常量,当执行Strings str3 = str1 str2 的时刻,str3已经是"abcdef"常量了,已被建立在常量池中,以是地址是相等的。

// result true 
public class test { public static final String s1; public static final String s2; static{ s1 = "ab"; s2 = "cd"; } public static void main(String[] args) { String s3 = s1 s2; String s4 = "abcd"; System.out.println(s3 == s4); } } 

虽然s1和s2都是final类型,然则早先并没有初始化,在编译期还不能确定详细的值,此处是变量,以是这里会挪用StringBuilder类中的组织方式及append()方式来建立新的字符串s3,返回的新字符串s3在堆中的地址,以是与s4不相等。

// result false 

参考内容:

  1. java-String常量池的知识点你知道若干?-连系jdk版本调换 by hz90s
  2. java中String、StringBuffer和StringBuilder的区别(简朴先容) by 韦邦杠
  3. Java String:字符串常量池(转)by 暖暖-木木

If you have any question, please let me know, your words are always welcome.*
新人入坑,若有错误/不妥之处,迎接指出,配合学习。

,

欧博开户www.allbetgame.us

欧博开户www.allbetgame.us

TAG:
阅读:
广告 330*360
广告 330*360

热门文章

HOT NEWS
Sunbet_进入申博sunbet官网
微信二维码扫一扫
关注微信公众号
新闻自媒体 Copyright © 2002-2019 Sunbet 版权所有
二维码
意见反馈 二维码