1、相同又不同的字符串

String str1 = new String("String");
String str2 = "String";
String str3 = "String";
System.out.println(str2 == str1); //false
System.out.println(str2 == str3); //true
5
 
1
String str1 = new String("String"); 
2
String str2 = "String";
3
String str3 = "String";
4
System.out.println(str2 == str1); //false
5
System.out.println(str2 == str3); //true

如上,我们说String是引用数据类型,那么为什么这里有三个对象,str1和str2的结果是false,而str2和str3为true,表明它们俩最终指向的是同一对象呢?

这要从字符串的创建方式来说明,使用new是每次创建一个新的对象,而用赋值的方式,实际上先搜寻常量池是否有可用,有则直接给予,否则新建。所以问题来了,什么是字符串常量池?

字符串的分配,和其他的对象分配一样,耗费高昂的时间与空间代价,作为最基础的数据类型,大量频繁的创建字符串,极大程度地影响程序的性能,所以JVM为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化:
  • 为字符串开辟一个字符串常量池,类似于缓存区
  • 创建字符串常量时,首先坚持字符串常量池是否存在该字符串
  • 存在该字符串,返回引用实例,不存在,实例化该字符串并放入池中

所以上面str2和str3实际上都是常量池中“String”的引用,自然完全相同,比对结果为true。

有一道经典的面试题:
String str = new String(“abc”) 创建多少个对象?
//所以,如果常量池中没有"abc",则创建了2个对象,一个放在常量池,一个放在堆;否则创建一个对象和一个引用
2
 
1
String str = new String(“abc”) 创建多少个对象?
2
//所以,如果常量池中没有"abc",则创建了2个对象,一个放在常量池,一个放在堆;否则创建一个对象和一个引用

所以变化一下:
String str1 = new String("A"+"B") ; 会创建多少个对象? 

str1:
字符串常量池:"A","B","AB" : 3个
堆:new String("AB") :1个
引用: str1 :1个
总共 : 5个
7
 
1
String str1 = new String("A"+"B") ; 会创建多少个对象? 
2

3
str1:
4
字符串常量池:"A","B","AB" : 3个
5
堆:new String("AB") :1个
6
引用: str1 :1个
7
总共 : 5个

简单总结:
  • 单独使用""引号创建的字符串都是常量,编译期(保存在.class文件中)就已经确定存储到常量池中
  • 使用new String("")创建的对象会存储在堆中,是运行期新创建的
  • 使用只包含常量的字符串连接符如"aa" + "aa"创建的也是常量,编译期就能确定,已经确定存储到常量池中
  • 使用包含变量的字符串连接符如"aa" + str1创建的对象是运行期才创建的,存储在堆中

而之所以能实现这些,也是有基础的:
  • 字符串本质上是不可变的(所谓的字符串连接无非是新建字符串,更改指向,而不是修改原有),不用担心数据冲突进行共享
  • 运行时实例创建的全局字符串常量池中有一个表,总是为池中每个唯一的字符串对象维护一个引用,这就意味着它们一直引用着字符串常量池中的对象,所以,在常量池中的这些字符串不会被垃圾收集器回收

更多参考:



2、常用方法

2.1 String常用方法

返回长度
length() //返回字符串的长度
转换(替换)字符
toLowerCase() //转换字符串为小写(仅针对字符串中的字母进行变化)
toUpperCase() //转换字符串为大写(仅针对字符串中的字母进行变化)
repalce(char oldChar, char newChar) // 将字符串中所有oldChar字符替换为newChar字符 字符串函数替换后需要赋值给新的字符串,旧字符串不会改变也不会重新指向新字符串
repalceFirst(String regex, String replacement) // 用字符串replacement的内容替换当前字符串中遇到的第一个和字符串regex一致的子串,并返回新的字符串(字符串长度可以不同,不会顶替掉未要求替换的字符)
repalceAll(String regex, String replacement) // 用字符串replacement的内容替换当前字符串中遇所有和字符串regex一致的子串,并返回新的字符串(字符串长度可以不同,不会顶替掉未要求替换的字符)
valueOf(Object obj) //将某个对象的实例转换成字符串 return:if the argument is null, then a string equal to "null"; otherwise, the value of obj.toString() is returned. (而对于基本数据类型,如int 1,则会转成"1")
提取字符
charAt(int index) //返回字符串的第index个位置的字符
substring(int beginindex) //返回从beginindex位置(包括该位置)开始到结尾的所有字符
substring(int beginindex, int endindex) //返回从beginindex位置(包括)开始到endindex(不包括)的所有字符
比较字符
compareTo(String anotherString) //字符串比较,返回值为前者减后者的二者差(两个字符串同时从左往右比对,差值为首个不同字符的ASCII码的差值,数字字符为ASCII码相减)两个字符串完全相同输出为0
equals(Object anObject) //比较两个字符串的内容是否相同(大小写敏感),是则返回true,否则返回false
equalsIgnoreCase(String anotherString) //比较两个字符串的内容是否相同(忽略大小写),是则返回true,否则返回false
regionMatches(int toffset, String other, int ooffset, int len) //比较本串从toffset(包含)开始的len个字符和other串从ooffset开始的len个字符是否一致,返回值为boolean型
starstWith(String prefix) //比较字符串是否以prefix开始,返回值为boolean型
endsWith(String suffix) //比较字符串是否以suffix结束,返回值为boolean型
matches(String reg) //某字符串是否匹配reg正则表达式
查找字符位置
indexOf(int ch) //返回某个字符在本字符串中第一次出现的位置,没有找到就输出-1
indexOf(String str) //返回某个字符串在本字符串中第一次出现的位置,没有找到就输出-1
indexOf(int ch, int fromIndex) //返回某个字符在字符串中从fromindex位置开始查找的第一次出现的位置,没有找到就输出-1
indexOf(String str, int fromIndex) //返回某个字符串在字符串中从fromindex位置开始查找的第一次出现的位置,没有找到就输出-1
lastIndexOf(int ch) //返回某个字符在本字符串中最后一次出现的位置,没有找到就输出-1
lastIndexOf(String str) //返回某个字符串在本字符串中最后一次出现的位置,没有找到就输出-1
lastIndexOf(int ch, int fromIndex) //返回某个字符在字符串中到fromindex位置开始查找的最后一次出现的位置,没有找到就输出-1
lastIndexOf(String str, int fromIndex) //返回某个字符串在字符串中到fromindex位置开始查找的最后一次出现的位置,没有找到就输出-1
contains(CharSequence s) //是否包含某个字符
连接字符串
concat(String str) //将参数中的字符串str连接到原字符串的后面
去掉空格
trim() //去掉字符串开头和结尾的空格并返回新字符串,注意,中间的空格不会去掉
35
 
1
返回长度
2
length()   //返回字符串的长度
3
转换(替换)字符
4
toLowerCase()   //转换字符串为小写(仅针对字符串中的字母进行变化)
5
toUpperCase()  //转换字符串为大写(仅针对字符串中的字母进行变化)
6
repalce(char oldChar, char newChar)  // 将字符串中所有oldChar字符替换为newChar字符 字符串函数替换后需要赋值给新的字符串,旧字符串不会改变也不会重新指向新字符串
7
repalceFirst(String regex, String replacement)  // 用字符串replacement的内容替换当前字符串中遇到的第一个和字符串regex一致的子串,并返回新的字符串(字符串长度可以不同,不会顶替掉未要求替换的字符)
8
repalceAll(String regex, String replacement)  // 用字符串replacement的内容替换当前字符串中遇所有和字符串regex一致的子串,并返回新的字符串(字符串长度可以不同,不会顶替掉未要求替换的字符)
9
valueOf(Object obj)   //将某个对象的实例转换成字符串 return:if the argument is null, then a string equal to "null"; otherwise, the value of obj.toString() is returned. (而对于基本数据类型,如int 1,则会转成"1")
10
提取字符
11
charAt(int index)   //返回字符串的第index个位置的字符
12
substring(int beginindex)   //返回从beginindex位置(包括该位置)开始到结尾的所有字符
13
substring(int beginindex, int endindex)  //返回从beginindex位置(包括)开始到endindex(不包括)的所有字符
14
比较字符
15
compareTo(String anotherString)  //字符串比较,返回值为前者减后者的二者差(两个字符串同时从左往右比对,差值为首个不同字符的ASCII码的差值,数字字符为ASCII码相减)两个字符串完全相同输出为0
16
equals(Object anObject)   //比较两个字符串的内容是否相同(大小写敏感),是则返回true,否则返回false
17
equalsIgnoreCase(String anotherString)   //比较两个字符串的内容是否相同(忽略大小写),是则返回true,否则返回false
18
regionMatches(int toffset, String other, int ooffset, int len)  //比较本串从toffset(包含)开始的len个字符和other串从ooffset开始的len个字符是否一致,返回值为boolean型
19
starstWith(String prefix)   //比较字符串是否以prefix开始,返回值为boolean型
20
endsWith(String suffix)   //比较字符串是否以suffix结束,返回值为boolean型
21
matches(String reg)   //某字符串是否匹配reg正则表达式
22
查找字符位置
23
indexOf(int ch)   //返回某个字符在本字符串中第一次出现的位置,没有找到就输出-1
24
indexOf(String str)   //返回某个字符串在本字符串中第一次出现的位置,没有找到就输出-1
25
indexOf(int ch, int fromIndex)  //返回某个字符在字符串中从fromindex位置开始查找的第一次出现的位置,没有找到就输出-1
26
indexOf(String str, int fromIndex)  //返回某个字符串在字符串中从fromindex位置开始查找的第一次出现的位置,没有找到就输出-1
27
lastIndexOf(int ch) //返回某个字符在本字符串中最后一次出现的位置,没有找到就输出-1   
28
lastIndexOf(String str) //返回某个字符串在本字符串中最后一次出现的位置,没有找到就输出-1
29
lastIndexOf(int ch, int fromIndex)  //返回某个字符在字符串中到fromindex位置开始查找的最后一次出现的位置,没有找到就输出-1
30
lastIndexOf(String str, int fromIndex)  //返回某个字符串在字符串中到fromindex位置开始查找的最后一次出现的位置,没有找到就输出-1
31
contains(CharSequence s)  //是否包含某个字符
32
连接字符串
33
concat(String str)   //将参数中的字符串str连接到原字符串的后面
34
去掉空格
35
trim()  //去掉字符串开头和结尾的空格并返回新字符串,注意,中间的空格不会去掉

2.2 String的format

另外,String还有一个静态方法format,用于创建格式化的字符串,常用 format (String format, Object... args),指定字符串格式和参数,生成格式化后的新的字符串。

如示例:
public static void main(String[] args) {
String str=null;
str=String.format("Hi,%s", "王力");
System.out.println(str);
str=String.format("Hi,%s:%s.%s", "王南","王力","王张");
System.out.println(str);
System.out.printf("字母a的大写是:%c %n", 'A');
System.out.printf("3>7的结果是:%b %n", 3>7);
System.out.printf("100的一半是:%d %n", 100/2);
System.out.printf("100的16进制数是:%x %n", 100);
System.out.printf("100的8进制数是:%o %n", 100);
System.out.printf("50元的书打8.5折扣是:%f 元%n", 50*0.85);
System.out.printf("上面价格的16进制数是:%a %n", 50*0.85);
System.out.printf("上面价格的指数表示:%e %n", 50*0.85);
System.out.printf("上面价格的指数和浮点数结果的长度较短的是:%g %n", 50*0.85);
System.out.printf("上面的折扣是%d%% %n", 85);
System.out.printf("字母A的散列码是:%h %n", 'A');
}
18
 
1
public static void main(String[] args) {  
2
    String str=null;  
3
    str=String.format("Hi,%s", "王力");  
4
    System.out.println(str);  
5
    str=String.format("Hi,%s:%s.%s", "王南","王力","王张");            
6
    System.out.println(str);                           
7
    System.out.printf("字母a的大写是:%c %n", 'A');  
8
    System.out.printf("3>7的结果是:%b %n", 3>7);  
9
    System.out.printf("100的一半是:%d %n", 100/2);  
10
    System.out.printf("100的16进制数是:%x %n", 100);  
11
    System.out.printf("100的8进制数是:%o %n", 100);  
12
    System.out.printf("50元的书打8.5折扣是:%f 元%n", 50*0.85);  
13
    System.out.printf("上面价格的16进制数是:%a %n", 50*0.85);  
14
    System.out.printf("上面价格的指数表示:%e %n", 50*0.85);  
15
    System.out.printf("上面价格的指数和浮点数结果的长度较短的是:%g %n", 50*0.85);  
16
    System.out.printf("上面的折扣是%d%% %n", 85);  
17
    System.out.printf("字母A的散列码是:%h %n", 'A');  
18
} 

输出:
Hi,王力
Hi,王南:王力.王张
字母a的大写是:A
3>7的结果是:false
100的一半是:50
100的16进制数是:64
100的8进制数是:144
50元的书打8.5折扣是:42.500000 元
上面价格的16进制数是:0x1.54p5
上面价格的指数表示:4.250000e+01
上面价格的指数和浮点数结果的长度较短的是:42.5000
上面的折扣是85%
字母A的散列码是:41
13
 
1
Hi,王力  
2
Hi,王南:王力.王张  
3
字母a的大写是:A   
4
3>7的结果是:false   
5
100的一半是:50   
6
100的16进制数是:64   
7
100的8进制数是:144   
8
50元的书打8.5折扣是:42.500000 元  
9
上面价格的16进制数是:0x1.54p5   
10
上面价格的指数表示:4.250000e+01   
11
上面价格的指数和浮点数结果的长度较短的是:42.5000   
12
上面的折扣是85%   
13
字母A的散列码是:41 

转换符说明如下:
转换符     说明     e.g.    
%s     字符串类型     "mingrisoft    "
%c     字符类型     'm'    
%b     布尔类型     true    
%d     整数类型(十进制)     99    
%x     整数类型(十六进制)     FF    
%o     整数类型(八进制)     77    
%f     浮点类型     99.99    
%a     浮点类型(十六进制)     FF.35AE    
%e     指数类型     9.38e+5
%g     通用浮点类型 
%h     散列码    
%%     百分比类型    
%n     换行符    
%tx     日期与时间类型


2.3 String的spilt

spilt可以将一个字符串分割为子字符串,然后将结果(子串的数组)作为字符串数组返回。

stringObj.split( separator,[limit] )
  • separator 必填,分隔符,支持正则表达式
  • limit 可选,该值用来限制返回数组中元素的个数

使用时注意以下几点:
  • 如果用“.”作为分隔的话,必须是如下写法:String.split("\\."),这样才能正确的分隔开,不能用String.split(".");
  • 如果用“|”作为分隔的话,必须是如下写法:String.split("\\|"),这样才能正确的分隔开,不能用String.split("|"); “.”和“|”都是转义字符,必须得加"\\";
  • 如果在一个字符串中有多个分隔符,可以用“|”作为连字符,比如:“a=1 and b =2 or c=3”,把三个都分隔出来,可以用String.split("and|or");

2.4 String和char[]

字符串转换为字符数组:
//将当前字符串中一部分复制到指定参数dst数组中去,并从dstBegin处开始存放
void getChars(int srcBegni, int srcEnd, char[] dst, int dstBegin) //初始化一个字符数组,长度和字符串长度相等
char[] toCharArray()
5
 
1
//将当前字符串中一部分复制到指定参数dst数组中去,并从dstBegin处开始存放
2
void getChars(int srcBegni, int srcEnd, char[] dst, int dstBegin)
3

4
//初始化一个字符数组,长度和字符串长度相等
5
char[] toCharArray()

字符数组转字符串,调用字符串的构造方法:
String(char[] value)

String(char[] value, int offset, int count)
x
 
1
String(char[] value)
2

3
String(char[] value, int offset, int count)


3、StringBuffer和StringBuilder

字符串的本质是不可变的,但是如果我们需要频繁地用到字符串的变动更改,就要用到StringBuffer,称之为字符串缓冲对象。实际上,诸如str1+str2这样的操作,也是将两者转换为StringBuffer来进行操作的。

常见构造函数为 new SringBuffer(String str)

StringBuilder是一个和StringBuffer类似的字符缓冲区,与StringBuffer兼容,然而:
  • StringBuffer在一个时候只能让一个线程去访问它,线程安全
  • StringBuilder是非线程安全的,所以单线程的话,StringBuilder的速度更快


[07] String字符串的更多相关文章

  1. [18/12/07]String 字符串

    一.基础概念 1. String类又称作不可变字符序列. 2. String位于java.lang包中,Java程序默认导入java.lang包下的所有类. 3. Java字符串就是Unicode字符 ...

  2. Java String字符串/==和equals区别,str。toCharAt(),getBytes,indexOf过滤存在字符,trim()/String与StringBuffer多线程安全/StringBuilder单线程—— 14.0

    课程概要 String 字符串 String字符串常用方法 StringBuffer StringBuilder String字符串: 1.实例化String对象 直接赋值  String str=& ...

  3. [CareerCup] 1.3 Permutation String 字符串的排列

    1.3 Given two strings, write a method to decide if one is a permutation of the other. 这道题给定我们两个字符串,让 ...

  4. 03-Java String字符串详解

    1.Java字符串String A.实例化String字符串:直接赋值(更合理一些,使用较多).使用关键字new. B.String内容的比较 // TODO Auto-generated metho ...

  5. C++学习38 string字符串的增删改查

    C++ 提供的 string 类包含了若干实用的成员函数,大大方便了字符串的增加.删除.更改.查询等操作. 插入字符串 insert() 函数可以在 string 字符串中指定的位置插入另一个字符串, ...

  6. C++学习37 string字符串的访问和拼接

    访问字符串中的字符 string 字符串也可以像字符串数组一样按照下标来访问其中的每一个字符.string 字符串的起始下标仍是从 0 开始.请看下面的代码: #include <iostrea ...

  7. java String字符串——进度1

    String字符串    在JAVA中提供了多种创建字符串对象的方法,这里介绍最简单的两种,    第一种是直接赋值,    第二种是使用String类的构造方法:    如下所示:    Strin ...

  8. 关于String字符串反转

    这是网上看到的一篇java面试题中的问题: 问题是: 如何将一个String字符串反转. String str = "1234567"; int length = str.leng ...

  9. JavaScript的内置对象(Date日期+string字符串)基础语法总结

    1.Date日期对象可以储存任意一个日期,并且可以精确到毫秒数(1/1000 秒). 1)定义一个时间对象 : var Udate=new Date(); //注意:使用关键字new,Date()的首 ...

随机推荐

  1. 利用Arduino快速制作Teensy BadUSB, 攻击计算机

    BadUsb介绍 BadUSB是计算机安全领域的热门话题之一,该漏洞由Karsten Nohl和Jakob Lell共同发现,并在2014年的BlackHat安全大会上公布. 虽然已隔一两年,但还是有 ...

  2. 【Java学习笔记之二十五】初步认知Java内部类

    可以将一个类的定义放在另一个类的定义内部,这就是内部类. 内部类是一个非常有用的特性但又比较难理解使用的特性(鄙人到现在都没有怎么使用过内部类,对内部类也只是略知一二). 第一次见面 内部类我们从外面 ...

  3. 【Linux】MySQL解压版安装及允许远程访问

    安装环境/工具 1.Linux( centOS 版) 2.mysql-5.6.31-linux-glibc2.5-x86_64.tar 安装步骤 1.下载mysql解压版(mysql-5.6.31-l ...

  4. LINQ to Entities 中的查询

    MSDN地址:https://msdn.microsoft.com/zh-cn/library/bb399367%28v=vs.100%29.aspx .NET Framework 4 查询是一种从数 ...

  5. [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.js

    解决办法: 双击server,勾选上[Server Options]里面的[Publish module contexts to separte XML files],如下图即可.

  6. 有了 indexOf,为什么 ECMAScript 7 还添加了 Array.prototype.include

    ECMAScript 7 中新增了用于检测数组中是否包含某个元素 Array.prototype.includes() API,想到了 Array 其实有很多相关 API 可以检测到是否包含某个元素, ...

  7. JavaScript 学习笔记 - LocalStorage

    前言 本文主要介绍本地存储的基本使用,以及它和 Cookie.SessionStorage 的区别. 简单回顾 Cookie 在 HTML5 之前,本地存储数据一般是通过 Cookie 来完成的.我们 ...

  8. poj 2763 Housewife Wind (树链剖分)

    题目链接:http://poj.org/problem?id=2763 题意: 给定一棵含n个结点的树和树的边权,共有q次操作,分为两种 0 c :求从位置s到c的距离,然后s变成c 1 a b:把第 ...

  9. Day-1: Python准备知识

    python简介 不同于c语言这种贴近硬件的言语,Python是用来编写应用程序的高级编程语言.Python是一款开源软件,所以它有非常完善的代码库,宝库内置的基本库和众多开发者提供的第三方库.这就允 ...

  10. 快速排序/快速查找(第k个, 前k个问题)

    //快速排序:Partition分割函数,三数中值分割 bool g_bInvalidInput = false; int median3(int* data, int start, int end) ...