Java笔记(八) —— String类基本操作详解

1 创建字符串

  String 在java.lang 这个包中,这是一个特殊的包,最基础最常用,使用这个包不需要导入(import)。

// 第一种
String str = "hello";
// 第二种
String str2 = new String("hello");
// 第三种
char[] array = {'a','b','c'};
String str3 = new String(array);
// 注意:和C不同,Java中的字符串String和字符数组 char[]无关

String 还支持很多的构造方式,可见 API官方文档

2 比较字符串

2.1 比较相同

String a = "hello";
String b = "hello";
String c = new String ("hello");
// 引用a 和 引用b中存储的地址是相同的
System.println(a == b);               // true
// 两个字符串中存储的内容一样
System.println(a.equals(b));          // true
// c 是新创建出来的,和 a 的地址不同
System.println(a == c);               // false
// 存储内容相同
System.println(a.equals(c));          // true

注意区分
(1) " == " 比较引用 a 和 b 中存储的地址;
(2) " .equals " 比较的是两个字符串的内容,依次遍历字符串的内容。
内存中的样子:
在这里插入图片描述

        String a = null;
// 这样写,如果 a 是空指针,会出现异常
//        if(a.equals("hello")) {
//        }

// 这样是可以通过的
        if(("hello").equals(a)) {
//括号中是 false
        }

2.2 比较大小

String a = "Hello";
String b = "hallo";
// a 比 b 大,返回 >0 的结果
// a 比 b 小,返回 <0 的结果
// a 和 b 相等,返回 0
// (并不是 0、1、-1)
// 这里是ASCII码值作差的结果,但不同版本的 JDK不同
// 区分大小写 
int result = a.compareTo(b);   // 小于 0 的结果
int result2 = a.compareToIgnoreCase(b);  // 0
// 不区分大小写
int result3 = a.equalsIgnoreCase(b);  // true

3 字符串常量池

  所谓常量,就是一个不可变的量,而池在计算机中的应用很多,是一个比较重要的术语,是为了降低开销,提高效率,把会频繁使用的东西保存好,然后要用的时候就不用重新创建,直接就可以用。
  如果某个字符串已经存在在常量池中,而我们又重新创建了一个,这样就相当于浪费了内存,这时,有一个办法可以解决这样的问题。

String a = "hello";
String b = new String("hello");
System.out.println(a == b);     // false

String a = new String("hello").intern();
System.out.println(a == "hello");     // true

  这里 .intern( ),调用该方法就会在字符串常量池中找和这个新创建的字符串相同的,如果找到了就将字符串常量池中的字符串的地址返回给引用,然后这里新创建的对象,因为没有引用指向它,就会被垃圾回收机制给回收掉;如果没有找到就返回新创建的这个字符串的地址。
  常量池是JVM划分的一个内存区域,其中的常量一方面来自于编译 java 代码时,识别出字面常量值就会自动加到常量池中,另一方面,调用 .intern 方法时,没有在池中找到当前字符串,就会将该字符串加进去。

4 String 不可变

  String 之所以不可变,一方面,内容不能被外面访问到;另一方面,没有public 方法可以让我们在类的外部修改它。

特殊手段:
反射:

String a = "hello";
// 1)获取到 String 的类对象
// 2)根据 ”value“ 这个字段名字,在类对象中拿到对应的字段
//    (仍然是图纸的一部分)
Field valueField = String.class.getDeclaredField("value");
// 让 value 这个 private 的成员也可以被访问到
valueField.setAccessible(true);
// 3)根据图纸,把 a 这个对象给拆开,取出里面的零件
char[] value = (char[])valueField.get(a);
// 4) 修改零件内容
value[4] = 'a';
System.out.println(a);

反射与封装相对,使用反射打破封装;代码比较复杂,容易出错;牺牲了编译器自身的一些检查校验的机制。

5 String 和字符数组相互转换

//
char[] value = {'a','b','c'};
String s = new String(value);
//
String a = "abcd";
System.out.println(a.charAt(0));
System.out.println(a.charAt(1));
System.out.println(a.charAt(2));
System.out.println(a.charAt(3));
System.out.println(a.intern());
// 相当于重新创建了一个新的字符数组并返回
// 修改这个返回值,不会影响到 a 本身的内容
char[] value2 = a.toCharArray();
for(char v: value){
    System.out.println(v);
}
value[0] = 'x';
// 并未改变
System.out.println(a);

6 String 和字节数组相互转换

// 字节=>字符串
// 字节数组来构造字符串,需要字节数组中保存的内容符合Java字符的编码方式
        byte[] value = {'a','b','c'};
        String s = new String(value);
        System.out.println(s);

//字节=>字符串
// 把字符串的内容拷贝一份,放到字节数组中
        String s = "hello";
        s.getBytes();

7 字符串常用操作

7.1 字符串查找

1、判断字符串是否存在

// b 是 a 的子串
String a = "hello world";
String b = "hello";
System.out.println(a.contains(b));  // true

2、返回要找的字符串起始位置的下标,从左到右找,有重复只返回第一个找到的

String a = "hello world world";
String b = "hello";
int result = a.indexOf(b);
System.out.println(result);
// 找重复的
result = a.indexOf(b,result + 1);
System.out.println(result);      // 12

3、从后往前查找

String a = "hello world";
String b = "hello";
System.out.println(a.lastIndexOf(b));  // 12

4、判断是否以制定字符串开头、结束

String a = "hello world world";
String b = "hello";
System.out.println(a.startsWith(b));     // true
System.out.println(a.endsWith(b));     // false

7.2 字符串替换

String 是不可变对象,针对字符串的替换操作,不是对原字符串,而是创建了一个新的字符串。

String a = "hello world world";
String b = "hello";
String result = a.replaceAll(b,"java"); // "hello java java"
String result2 = a.replaceFirst(b,"java");  // "hello java world"
// 原字符串不变
System.out.println(a);         //"hello world world"

7.3 字符串拆分

把字符串按照一定的分割符,拆成几个部分,放到一个数组中。

String a = "hello world java";
String[] result = a.split(" ");
System.out.println(Arrays.toString(result));
// [hello, world, java]

  由于 .split 方法的参数是正则表达式,而 " . " 在正则表达式中有特殊含义," . " 也是其中之一,所以我们需要用正则表达式中的转义字符。
  " . " 才会被当成 . 本身看待,但是 " . " 会被字符串当成转义字符,所以要再加一个 \ ,用 " \. " 表示才是一个点

String b = "192.168.1.1";
String[] result = b.split("\\.");
System.out.println(Arrays.toString(result));
// [192, 168, 1, 1]

7.4 字符串截取

注意前闭后开

String a = "hello world java";
System.out.println(a.substring(6,11));  // world 
System.out.println(a.substring(6));   // world java

7.5 去左右空白符

String a = "      hello world    \n";
System.out.println(a.trim());   // "hello world"

7.6 变大小写

String a = "Hello";
System.out.println(a.toUpperCase());  // HELLO
System.out.println(a.toLowerCase());  // hello

8 StringBuffer / StringBuilder

可变版本的 String,StringBuffer 和 StringBuilder 操作基本相同。

StringBuilder stringBuilder = new StringBuilder("hello");
stringBuilder.reverse();    // olleh
stringBuilder.delete(2,4);  // heo
stringBuilder.insert(2,"world");   // heworldllo

区别:
StringBuffer 采用同步处理,是线程安全的;StringBuilder是异步处理,线程不安全的。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值