Java-字符串

学习笔记

  1. 认识String类。
  2. 熟悉Java中String类的常用方法。
  3. 认识 StringBuffer 和 StringBuilder
  4. StringAPI来辅助学习熟练操作。
  5. C语言字符串与Java字符串的区别.

认识String类

C语言中的字符串用字符指针,字符数组和特殊结束字符’\0’表示。
Java没有内置一个字符串类型,而是封装成了一个类。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence,
               Constable, ConstantDesc

String是公共类.
它不能派生子类(被final修饰)
默认继承Object类.
它还实现了我们比较熟悉的Comparable接口。
String内部封装了一个字符数组,char[] value。但其被final修饰,因此String类是不可变的。

String类很重要,面试要考!

字符串使用操作

字符串构造

  1. 和C语言一样,用双引号引起的字符序列就是一个字符串,如"hello"。
    String s="hello"; 右边的"hello"是常量字符串。用String类的引用变量接收。
  2. String类,类实例化对象用new关键字和构造器。
    String s = new String("hello")
    String类构造器有多种重载形式,比如String s = new String(),默认构造一个空字符串。
  3. 通过字符数组构造
    String类有一种构造器,通过字符串数组作为构造器参数来实例化对象。
 public static void main(String[] args) {
        char[] arr={'h','e','l','l','o'};
        String s=new String(arr);
        System.out.println(s);
    }

String是一个类,引用类型变量存储的是地址,是对象在堆上内存的地址。堆上放的是对象具体的内容。
"hello"同样看作String类的对象。它可以调用String类的方法。System.out.println("hello".length()); 调用length方法计算字符串长度。
int length():返回字符串长度。

String类的比较

讨论==,equals方法,compareTo方法的区别。

"=="比较

  String s1 = new String("hello");
  String s2 = new String("hello");
  String s3 = new String("world");
  String s4 = s1;
  System.out.println(s1 == s2);  // false
  System.out.println(s2 == s3);  // false
  System.out.println(s1 == s4);  // true

Java在等号比较上更像C
如果你熟悉C语言,可以明白上面的s1与s2,s3,s4比较。它们实际上比较引用对象所在地址。
实际上Java仍然脱离这一套,Java中的引用变量是地址,s1,s4引用同一个对象,s1和s4的地址相同,因此s1==s4结果为true.s2实际上new一个对象,只不过内容与s1一样,它们在JVM上的内存地址不同,所以不相等。s3更不言说了。

  • 总结:==只能判断两者是不是虚拟内存的同一位置。

equals方法

String类没显式继承任何一个类,则其默认继承Object类,equals方法是其父类Object类中的。如果你熟悉父类的equals方法,它与"=="功能相同,我们通常认为里面的字段相同就认为它们是同一事物,所以String类重写了equals方法。

  public boolean equals(Object anObject) {
     // 先检测this 和 anObject 是否为同一个对象比较,如果是返回true
        if (this == anObject) {
            return true;
        }
        //判断传入参数是不是String类,再进行内容比较。
        return (anObject instanceof String aString)
                && (!COMPACT_STRINGS || this.coder == aString.coder)
                && StringLatin1.equals(value, aString.value);
    }

扩展了equals方法,现在字符串内容相同也视为相等。

public static void main(String[] args) {
  String s1 = new String("hello");
  String s2 = new String("hello");
  String s3 = new String("world");
  // s1、s2、s3引用的是三个不同对象,因此==比较结果全部为false
  System.out.println(s1 == s2);    // false
  System.out.println(s1 == s3);    // false
  // equals比较:String对象中的逐个字符
  // 虽然s1与s2引用的不是同一个对象,但是两个对象中放置的内容相同,因此输出true
  // s1与s3引用的不是同一个对象,而且两个对象中内容也不同,因此输出false
  System.out.println(s1.equals(s2));  // true
  System.out.println(s1.equals(s3));  // false

补充equalsIgnoreCase方法,功能与equal方法一致,但是忽略大小写!!!

compareTo方法

String类实现了comparable泛型接口,该接口有且只有一种抽象方法compareTo方法。
String类不是抽象类,它必然实现了这个方法。 public int compareTo(String anotherString)

  1. 它的比较逻辑和C中的strcmp函数一样,它是字符串比较大小函数。
    它会将两个字符串按顺序逐字符比较大小,知道决出胜负。
    当且仅当两个字符串长度相等且每个对应位置字符相同时,返回0.
  2. 与equals(String类中重写的)方法区别:equals方法判断字符串是不是相等,返回值是布尔类型(true或者false),compareTo方法比较两个字符串的“大小”返回类型是int。
  3. 与String类的equals方法一样,针对compareTo方法也提供了忽略大小写的方法。int compareToIgnoreCase(String str) 方法:与compareTo方式相同,但是忽略大小写比较

字符串查找

建议去隔壁力扣坐牢刷题,不用死记。

  • char charAt(int index) : 返回index位置上字符,如果index为负数或者越界,抛出IndexOutOfBoundsException异常
  • int indexOf(int ch) 返回ch第一次出现的位置,没有返回-1
  • int indexOf(int ch, intfromIndex) 从fromIndex位置开始找ch第一次出现的位置,没有返回-1
  • int indexOf(String str) 返回str第一次出现的位置,没有返回-1
  • int indexOf(String str, intfromIndex)从fromIndex位置开始找str第一次出现的位置,没有返回-1
  • int lastIndexOf(int ch) 从后往前找,返回ch第一次出现的位置,没有返回-1
  • int lastIndexOf(int ch, intfromIndex) 从fromIndex位置开始找,从后往前找ch第一次出现的位置,没有返回-1
  • int lastIndexOf(String str) 从后往前找,返回str第一次出现的位置,没有返回-1
  • int lastIndexOf(String str, intfromIndex) 从fromIndex位置开始找,从后往前找str第一次出现的位置,没有返回-1

总而言之,三个函数charAt函数,indexof函数,lastIndexOf函数。
根据下标找字符,根据字符找下标。

字符串转化

非字符串转字符串

  • 记住一个方法valueOf()。
  1. 整型,浮点数,布尔类型转字符串。
    String s1 = String.valueOf(1234);
    String s2 = String.valueOf(12.34);
    String s3 = String.valueOf(true);

valueOf()方法重载,可以接受各种基本数据类型,以字符串形式返回。

为什么可以这样,你需要了解包装类的知识,请自行搜索学习。
同样字符串转基本数据类型也涉及包装类的知识。(相关方法)

  1. 对象转字符串
    如果valueOf方法接收的是对象,那么会调用对象的toString方法。
    String s4 = String.valueOf(new Student("Hanmeimei", 18));
//Student类
public class Student implements Comparable<Student>{
    private String name = null;
    private int score = 0;

    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }

    @Override
    public String toString() {
        return "[" + name + ":" + score + "]";
    }

    public static void main(String[] args) {
        Student[] students = new Student[]{
                new Student("张三", 95),
                new Student("李四", 96),
                new Student("王五", 97),
                new Student("赵六", 92),
        };
        Arrays.sort(students);
        System.out.println(Arrays.toString(students));
    }

    @Override
    public int compareTo(Student o) {
        //这里根据分数比较。
        return this.score-o.score;
    }
}

这里来解释这个valueOf干了什么?

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

valueOf重载,支持接受一个对象为参数。接受参数若空引用则把字符串初始化"null",否则返回执行toString方法的结果。
这里由于Student类重写了toString方法 ,返回结果如下:

@Override
    public String toString() {
        return "[" + name + ":" + score + "]";
    }

字符串大小写转换

小写转大写 toUpperCase();
大写转小写 toLowerCase();

public static void main(String[] args) {
  String s1 = "hello";
  String s2 = "HELLO";
  // 小写转大写
  System.out.println(s1.toUpperCase());
  // 大写转小写
  System.out.println(s2.toLowerCase());
}

字符串转数组

前面在字符串构造时说明了字符数组转字符串的情况。
构造器传入字符数组名,就转化成字符串。
字符串转字符数组
char[] to


字符串拼接

Java语言中允许+来连接两个字符串。
字符串优先级高,当字符串与非字符串相加时,非字符串会转换成字符串。
+为什么可以实现字符串拼接?实际上它实现了和C++相同的一种运算符重载。Java不允许我们程序员重载运算符,但是它提供了+运算符的重载。
//请自行举例

子串(字符串截取)

String类提供了一个substring方法,可以从大的字符串提取一个子串。
它有两种形式。

  1. public String substring(int beginIndex) 只输入起始下标,开始从下标处截取直到原字符串末尾。
  2. public String substring(int beginIndex, int endIndex) 第一个是截取的起始位置,第二个参数是不想截取的第一个位置。从数学角度它是截取下标为[beginIndex,endIndex)的下标。
   public static void main(String[] args) {
        System.out.println("I love JavaSE".substring(2,6));
    }

输出love。

字符串的不可变性

前面的例子似乎在告诉我们字符串可以改变呢,但这是错误的理解,对字符串的修改实际上是新建了字符串对象。
下面我们来说明两点:

  1. 为什么字符串不可变,从String类的哪里可以得出结论。
  2. 如何达到一个字符串被改变的效果。

为什么字符串不可变?

可能会被下面的final引起误解

  1. public final class String implements java.io.Serializable, Comparable<String>, CharSequence,Constable, ConstantDesc
    这里的final说明String不可被继承!
  2. @Stable private final byte[] value;
    这里的final意味着引用的数组不可被修改;本质上对里面的整型还是可以修改。(字符串内容可变)
    真正原因是private修饰,而String类又不提供任何修改值的set方法。

获取字符

不能通过下标获取字符,因为String类对象不可变。
char ch = str.charAt(0); // 'H'

字符串修改

对于改变原对象的内容,要用到反射相关的知识,但我们可以通过新建对象,截取子串,字符串拼接来实现“修改”的目的。
既然String类对象不可变,那我们修改String的引用变量,让它引向一个新的对象。

   public static void main(String[] args) {
        String s="hello";
        System.out.println(s);
        s=s.substring(0,3)+"p";
        System.out.println(s);//输出help
    }

Java中一切String类方法对字符串的“修改”都是返回了一个新的对象

StringBuilder和StringBuffer介绍

由于String不可修改的特性,Java提供了StringBuilder类和StringBuffer类。它们可以直接修改对象的内容,而不会返回新的对象,提升了效率。
StringBuilder在线文档

C系字符串与Java字符串

以下摘自chatgpt

  1. 字符串的定义与存储:
    Java:在Java中,字符串是作为String类的对象存在的。String是一个标准的类,提供了丰富的字符串操作方法。字符串在Java中是不可变的,一旦创建,其值就不能再改变。
    C语言:C语言中没有专门的字符串类型,通常使用字符数组(char类型数组)来表示字符串。字符串以null字符(\0)结尾,用于标识字符串的结束。
  2. 字符集支持:
    Java:Java基于Unicode字符集,支持所有主要语言和书写系统中的字符,包括非拉丁语系的字符,如汉字、希腊字母等。Unicode字符集使用16位编码。
    C语言:C语言传统上使用ASCII字符集,它仅支持基本的拉丁字符集,每个字符使用8位表示。虽然C语言也可以通过其他方式支持Unicode,但这需要额外的编程工作。
  3. 字符串操作:
    Java:String类提供了大量的方法来操作字符串,如连接(concat)、获取长度(length)、提取子字符串(substring)等。这些操作都是基于新的String对象的创建,因为Java中的字符串是不可变的。
    C语言:在C语言中,对字符串的操作通常依赖于标准库函数,如strlen用于计算字符串长度,strcpy和strcat用于字符串的复制和连接,以及strcmp用于比较字符串等。这些操作直接修改原始的字符数组。
  4. 字符串比较:
    Java:在Java中,==操作符用于比较两个对象引用是否相同,而不是比较字符串的内容。要比较字符串的内容是否相等,应使用equals方法。
    C语言:在C语言中,通常使用strcmp函数来比较两个字符串的内容是否相等。如果两个字符串相同,strcmp会返回0。
  5. 内存管理:
    Java:Java有自动的垃圾回收机制来管理内存,因此开发者通常不需要手动管理字符串对象的内存。
    C语言:在C语言中,开发者需要手动管理字符数组的内存分配和释放,这包括为字符数组分配足够的空间以及在使用完毕后释放这些空间,以防止内存泄漏。

另外一点,C语言字符串可以用字符指针加[]访问字符串内的字符,无论这个字符指针指向是在栈上,还是堆上,或者常量区。
Java不允许通过[]访问来操作字符串,这正也与我们前面所说的字符串不可变性不谋而合,charAt()方法可以通过下标返回字符.

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值