认识 String 类

  • Post author:
  • Post category:其他




认识 String 类



1.创建字符串

// 方式一
String str = "Hello Bit";
// 方式二 调用构造方法进行构造对象
String str2 = new String("Hello Bit");
// 方式三
char[] array = {'a', 'b', 'c'};
String str3 = new String(array);


注意事项

:

“hello” 这样的字符串字面值常量, 类型也是 String.

String 也是

引用类型

. String str = “Hello”;



2.字符串比较相等

  • String 使用 == 比较并不是在比较字符串

    内容

    , 而是比较两个引用是否

    指向同一个对象

    .
String str1 = "hello";
String str2 = "hello";
System.out.println(str1 == str2);
// 执行结果
true

str1 和 str2 是指向同一个对象的. 此时如 “hello” 这样的字符串常量是在字符串常量池中.

String str1 = "hello";
String str2 = new String("hello");
System.out.println(str1 == str2);
//执行结果
false

str2 是新建一个这样的方式创建的 String 对象相当于再堆上另外开辟了空间来存储

“hello” 的内容, 也就是内存中存在两份 “hello”

  • 想比较字符串的内容, 必须采用String类提供的equals方法
String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(str1.equals(str2));
// System.out.println(str2.equals(str1)); // 或者这样写也行
// 执行结果
true

equals 使用注意事项:

String str = new String("Hello");
// 方式一
System.out.println(str.equals("Hello"));
// 方式二
System.out.println("Hello".equals(str));

上面两种方式,更推荐使用 “方式二”. 一旦 str 是 null, 方式一的代码会抛出异常, 而方式二不会。



3.字符串常量池

字符串常量池主要是存储字符串常量,本质上是一个哈希表。

是因为Java为String开辟的一块内存缓冲区,为了提高性能同时减少内存开销。在JVM中,字符串常量池由一个哈希表实现。默认容量为1009。当字符串常量池中的存储比较多的字符串时,会导致hash冲突,从而每个节点形成长长的链表,导致性能下降。所以在使用字符串常量池时,一定要控制容量。

它的主要使用方法有两种:

  • 直接使用双引号声明出来的

    String

    对象会直接存储在常量池中。
  • 如果不是用双引号声明的

    String

    对象,可以使用

    String

    提供的

    intern

    方法。intern 方法会从字符串常量池中查询当前字符串是否存在,若不存在就会将当前字符串放入常量池中

Java中两种创建字符串对象的方式的分析:

String str1 = "hello";
String str2 = "hello";
System.out.println(str1 == str2);

采用双引号创建一个字符串时,JVM首先会去字符串池中查找是否存在”hello”这个对象,如果不存在,则在字符串常量池中创建并存放一个”hello”对象,然后将池中”hello”这个对象的引用地址返回给”hello”对象的引用str1,这样str1会指向字符串常量池中”hello”这个字符串对象;如果存在,则不创建任何对象 ,直接将池中”hello”这个对象的地址返回,赋给引用str2。因为str1、str2都是指向同一个字符串池中的”hello”对象,所以结果为true。

String str1 = new String("hello");
String str2 = new String("hello");
System.out.println(str1 == str2);
//执行结果
false

采用new关键字新建一个字符串时,JVM首先在字符串常量池中查找有没有”hello”这个字符串对象,如果有,则直接在在池中寻找”hello”字符串,在堆中创建一个”hello”字符串对象,然后将堆中的这个”hello”对象的地址返回赋给引用str1,这样,str1就指向了堆中创建的这个”hello”字符串对象;如果没有,则首先在字符串常量池中创建一个”hello”字符串对象,然后再在堆中创建一个”hello”字符串对象,然后将堆中这个”hello”字符串对象的地址返回赋给str1引用,这样,str1指向了堆中创建的这个”hello”字符串对象。str2则指向了堆中创建的另一个”hello”字符串对象。str1 、str2是两个指向不同对象的引用,结果当然是false。



4.理解String字符串不可变

字符串是一种不可变对象. 它的内容不可改变。

String str = "hello" ;
str = str + " world" ;
str += "!!!" ;
System.out.println(str);
// 执行结果
hello world!!!

形如 += 这样的操作, 表面上好像是修改了字符串, 其实不是,而是创建了一个新的字符串。



5.字符, 字节与字符串



5.1 字符与字符串

字符串内部包含一个字符数组,String 可以和 char[] 相互转换.

1.将字符数组的所有内容都转换为字符串

char[] value = {'a','b','c','d','e'};
String str = new String(value);
System.out.println(str); //abcde

2.将字符数组的指定部分内容都转换为字符串

char[] value = {'a','b','c','d','e'};
String str1 = new String(value,1,4);
System.out.println(str1); //bcde

3.取得指向索引的字符,索引从0开始

String str2 = "hello";
char ch = str2.charAt(2);//获取到2下标的字符
System.out.println(ch);//l

4.将字符串变为字符数组返回

String str2 = "hello";
char[] chars = str2.toCharArray();//把str2指向的字符串对象,变成字符数组
System.out.println(Arrays.toString(chars));//[h, e, l, l, o]



5.2 字节与字符串

字节常用于数据传输以及编码转换的处理之中,String 也能方便的和 byte[] 相互转换

1.将字节数组变为字符串

byte[] bytes = {97,98,99,100};
String str = new String(bytes);
System.out.println(str); //abcd

2.将指定部分字节数组的内容变为字符串

byte[] bytes = {97,98,99,100};
String str = new String(bytes,1,3);//从下标为1开始,长度为3
System.out.println(str); //bcd

3.将字符串以字符数组的形式返回

String str2 = "张杰";
byte[] bytes1 = str2.getBytes(StandardCharsets.UTF_8);
 System.out.println(Arrays.toString(bytes1));//[-27, -68, -96, -26, -99, -80]

4.编码转换处理

public static void main(String[] args) throws UnsupportedEncodingException {
    String str2 = "张杰";
    byte[] bytes1 = str2.getBytes("GBK");
    System.out.println(Arrays.toString(bytes1));[-43, -59, -67, -36]
}


那么何时使用 byte[], 何时使用 char[] 呢?


byte[] 是把 String 按照一个字节一个字节的方式处理, 这种适合在网络传输, 数据存储这样的场景下使用. 更适合

针对二进制数据来操作.

char[] 是把String 按照一个字符一个字符的方式处理, 更适合针对文本数据来操作, 尤其是包含中文的时候



6. 字符串常见操作



6.1 字符串比较

1.区分大小写的比较

String str1 = "abc";
String str2 = "Abc";
System.out.println(str1.equals(str2));// false

2.不区分大小写的比较

String str1 = "abc";
String str2 = "Abc";
System.out.println(str1.equalsIgnoreCase(str2));// true

3.比较两个字符串大小关系

String str1 = "abc";
String str2 = "Abc";
int ret = str1.compareTo(str2);
System.out.println(ret);

在String类中compareTo()方法是一个非常重要的方法,该方法返回一个

整型

,该数据会根据大小关系返回三类内容:

  1. 相等:返回0.
  2. 小于:返回内容小于0.
  3. 大于:返回内容大于0



6.2 字符串查找

1.判断一个字符串是否存在

String str = "abcdef";
String tmp = "abc";
Boolean flg = str.contains(tmp);//true
System.out.println(flg);

2.从头开始查找指定字符串的位置,查到了返回位置的开始索引,如果查不到返回-1

3.从指定位置开始查找子字符串位置

String str = "ababcabcd";
String tmp = "abc";
int index = str.indexOf(tmp);//从头开始找  //类似于C的strstr->  KMP算法
System.out.println(index);//2
int index = str.indexOf(tmp,3);//从下标为3的位置开始找
System.out.println(index);//5

4.从后向前查找子字符串位置

5.从指定位置由后向前查找子字符串位置

    String str = "ababcabcd";
    String tmp = "abc";
    System.out.println(str.lastIndexOf(tmp));//5
    System.out.println(str.lastIndexOf(tmp,4));//2 //指定位置为下标为4的位置

6.判断是否以指定字符串开头

7.从指定位置开始判断是否以指定字符串开头

String str = "ababcabcd";
String tmp = "abc";
System.out.println(str.startsWith(tmp));//false
System.out.println(str.startsWith(tmp,2));//true

8.判断是否以指定字符串结尾

String str = "ababcabcd";
String tmp = "abc";
System.out.println(str.endsWith("cde"));//false



6.3 字符串替换

String str = "ababcabcdabcde";
//替换所有的指定内容 public String replaceAll(String regex,String replacement)
String ret = str.replaceAll("ab","mm");//mmmmcmmcdmmcde
//替换首个内容public String replaceFirst(String regex,String replacement)
String ret1 = str.replaceFirst("ab","pp");//ppabcabcdabcde



6.4 字符串拆分

将字符串全部拆分 public String[] split(String regex)

将字符串部分拆分,该数组长度是limit极限 public String[] split(String regex,int limit)

代码实例:1.实现字符串的拆分处理

String str = "hello world hello bit" ;
String[] result = str.split(" ") ; // 按照空格拆分
for(String s: result) {
    System.out.println(s);
    //hello 
    //world
    //hello 
    //bit
}

代码示例: 2.字符串的部分拆分

代码示例: 3.拆分IP地址

String str = "192.168.1.1";
String[] strings = str.split("\\.",3);//最多分成3段
for (String s:strings){
    System.out.println(s);
}
//192
//168
//1.1

代码实例:4.多次拆分

String str = "name=zhangsan&age=19";
String[] strings = str.split("&");
for (String s:strings){
    String[] ss = s.split("=");//ss:name  zhangsan
    //System.out.println(s);
    //s:  name=zhangsan   下次:s :    age=19
    for (String tmp:ss) {
        System.out.println(tmp);//name zhangsan age 19
     }
 }


注意事项:

1.字符”|“,”*“,”+“, “.” 都得加上转义字符,前面加上”\\”.

2.而如果是”\\“,那么就得写成”\\\\”.

String str2 = "192\\168\\1\\1";
String[] strings1 = str2.split("\\\\",7);
for (String s:strings1) {
    System.out.println(s);
}

3.如果一个字符串中有多个分隔符,可以用”|”作为连字符

String str = "Java30 12&21#hello";
String[] strings = str.split(" |&|#");
for (String s:strings) {
    System.out.println(s);
}



6.5 字符串截取

1.从指定索引截取到结尾 public String substring(int beginIndex)

String str = "abcdefgh";
String sub = str.substring(2);
System.out.println(sub); //cdefgh

2.截取部分内容 public String substring(int beginIndex,int endIndex)

String str = "abcdefgh";
String sub = str.substring(2,4);
System.out.println(sub); //cd


注意事项:

  1. 索引从0开始
  2. 注意

    前闭后开

    区间的写法, substring(0, 5) 表示包含 0 号下标的字符, 不包含 5 号下标



6.6 其他操作方法

1.去掉字符串的左右空格,保留中间空格 ——trim()方法

String str = "    abc     defg     ";
String sub = str.trim();
System.out.println(sub);

2.字符串转大写、小写——toUpperCase() 、toLowerCase()

String str = "abcdefBFRG123高";
String ret = str.toUpperCase();//ABCDEFBFRG123高
String ret1 = str.toLowerCase();//abcdefbfrg123高

3.字符串入池 public native String intern()

4.拼接——concat()

5.取得字符串长度——length()

6.判断是否为空字符串,但不是null,是长度为0—— isEmpty()

String str = "jinzh";
String ret = str.concat("zh");//拼接
System.out.println(ret);//jinzhzh 拼接后的不入常量池
System.out.println(str.length());//字符串长度为5
System.out.println(str.isEmpty());//false



7. StringBuffer 和 StringBuilder

任何的字符串常量都是String对象,而且String的常量一旦声明就不可改变,如果改变对象内容,改变的是其引用的指向而已。

通常来讲String的操作比较简单,但是由于String的不可更改特性,为了方便字符串的修改,提供StringBuffer和

StringBuilder类。

StringBuilder sb = new StringBuilder();
sb.append("as").append("5");
System.out.println(sb);

用StringBuffer和StringBuilder类的好处:

//String str = "abcdef";
StringBuilder sb = new StringBuilder();
sb.append("abcdef");
//str += "123";//str = str + "123"  //用String很浪费空间
sb.append("123");   //用StringBuilder依然是在原来的对象基础之上拼接,最后返回的还是原来的地址,这样不会浪费空间
//str = sb.toString();
System.out.println(sb);

注意:String和StringBuffer类不能直接转换。如果要想互相转换,可以采用如下原则:

a). String变为StringBuffer:利用StringBuffer的构造方法或append()方法

String str = "abcdef";
StringBuffer sb = new StringBuffer();
sb.append("sji");
return sb;

b). StringBuffer变为String:调用toString()方法

StringBuilder sb = new StringBuilder();
return sb.toString();

除了append()方法外,StringBuffer也有一些String类没有的方法:

1.字符串反转:

public synchronized StringBuffer reverse()

StringBuilder sb = new StringBuilder("abcdef");
System.out.println(sb.reverse());//fedcba

2.删除指定范围的数据:

public synchronized StringBuffer delete(int start, int end)

StringBuffer sb = new StringBuffer("helloworld");
System.out.println(sb.delete(5, 9));//hellod  区间是左闭右开

3.插入数据

public synchronized StringBuffer insert(int offset, 各种数据类型 b)

StringBuffer sb = new StringBuffer("helloworld");
System.out.println(sb.delete(5, 10).insert(0, "你好"));//你好hello

如果在循环里面,进行字符串的拼接。尽量不要使用String,优先使用StringBuffer和StringBuilder。


请解释String、StringBuffer、StringBuilder的区别:



String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.



StringBuffer与StringBuilder大部分功能是相似的



StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作



版权声明:本文为qq_42697165原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。