【Java SE】String类(上)

简介: 在我们前面也对字符串进行了简单的使用,在Java当中,String是字符串类型,本质上也是一个类,这个类中提供了很多的方法,我们后续会学习到,现在先来简单看一下String类常见的构造方法

1、字符串的构造  

1.1 简单初始化字符串

在我们前面也对字符串进行了简单的使用,在Java当中,String是字符串类型,本质上也是一个类,这个类中提供了很多的方法,我们后续会学习到,现在先来简单看一下String类常见的构造方法:

public static void main(String[] args) {
        String str1 = "hello";
        String str2 = new String("hello");
        char[] array = { 'h','e','l','l','o' };
        String str3 = new String(array);
}

还有其他的构造方法,但是常用的就上面这三种,分别是使用常量字符串构造,也就是直接用一个常量字符串赋值给String类型的变量(引用),第二种就是new一个String的对象,第三种是将字符数通过String构造方法转换成字符串。

至于第一种和第二种写法有什么区别,等后面我们学了字符串常量池放在那个时候讲解。

1.2 String是引用类型

因为String是引用类型,所以内部并不存储字符串本身,在String内部原码中,String类实例变量如下:

通过查看String类的原码可以发现,其实一个String引用的对象里面是有两个实例变量的,分别是value 字符数组 和 hash 也就是哈希, 所以在JDK1.8中,字符串实际保存在char类型的数组里头,这里我们先来简单的看一段代码:

public static void main(String[] args) {
        // s1和s2引用的是不同对象 s1和s3引用的是同一对象
        String s1 = new String("hello");
        String s2 = new String("hello");
        String s3 = s1;
        System.out.println(s1 == s2); // false
        System.out.println(s1 == s3); // true
    }

为了方便大家更好的了解,我们给上面的代码画一个草图,并不是真正的内存布局图!但不影响我们的理解,等到字符串常量池会给大家画真实的内存布局:

所以上面的代码打印的结果也就是 fasle 和 ture,因为引用使用 == 比较比较的是存储的地址是否相同,而通过上图就能发现 s1 和 s3 存储的地址是相同的,所以打印结果正如我们猜想的一样:

这里我们还需要注意一点,使用 "" 引起来的也是String类型对象,也可也调用对象中可以调用的属性:

// 打印"hello"字符串(String对象)的长度
System.out.println("hello".length());

2、String类常用方法

2.1 String对象的比较方法

在Java中我们有四种的比较方法,当然对于初学者见过最多的就是 == 的比较,但是这个在引用类型比较的是引用的地址是否相同,而基本类型则是比较里面存储的值是否相同,简单来说就是比较变量存储的值,所以 == 号我们不做过多的阐述。

2.1.1 boolean equals(Object anObject) 方法

这个方法其实也不陌生,之前也见过,他是按照字典序也就是字符大小的顺序进行比较,而Sting类中重写了 equals 方法,具体我们可以看一下方法的实现:

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

这个就是String类中重写 equals 方法的实现代码了,我们简单分析一下:

第一步:首先判断当前引用和 anObject也就是传过来的引用所引用的对象是否相同,因为Object是所有类的父类,这里用到了向上转型,如果引用的是同一个对象则返回 true

第二步:判断 anObject 里面的对象是不是 String 类型对象,如果是就继续比较,不是则直接返回false。

第三步:如果 anObject里面的对象是String类型对象,我们就先把anObject向下转型成String对象,这样就能访问本身对象自己的属性了,接着把当前对象里面字符数组的长度赋值给了n,在判断当前两个对象的里面存放的字符数组长度是否相同,相同则继续比较不是还是返回false。

第四步:如果if里面的字符长度相同,我们就按照字典序逐个字符往后比较,当这个if里面循环成功走完了,也就返回了true,一旦发现有一个字符不相同就会返回false

原码已经简单的分析过了,至于这个方法的使用前面也见到过,所以剩下使用就交给各位感兴趣的下来摸索了。

2.1.2 int compareTo(String s)方法

这个方法是实现的 Comparable 接口里面的 compareTo 方法,与上面不同的是,他返回的是int类型,并不是boolean类型,具体比较方式也是按照字典序进行比较,如果出现不同的字符,就直接返回这两个字符的差值,如果前 k 个字符(k为两个字符串最小的长度值),就返回两个字符串的差值。

public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;
        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }

这个原码实现的也很简单我们上面也简单说明了一下,就不多说,感兴趣的还是要自己下来用一用这个方法。

2.1.3 int compareToIgnoreCase(String s)方法

这个方法跟上面的  compareTo 方法的区别就是忽略了大小写比较,这里如果要看原码已目前的知识储备是不好理解的,这个知道如何使用就行:

public class Main {
    public static void main(String[] args) {
        String s1 = "HeLLO";
        String s2 = "hEllo";
        System.out.println(s1.compareToIgnoreCase(s2));
    }
}

2.2 字符串查找方法

字符串查找是很常见的操作,在日常刷题的过程中也会碰到,而Java中用的比较多的就是 char charAte(int index) ,int indexOf(...),int lastIndexOf(...),里面打三个点是因为这些方法都被重载了,形参列表是不同的,具体看下面代码和注释:

public static void strFind() {
        String str = "hello";
        //返回字符串某个位置上的字符,不能越界也不能是负数
        System.out.println(str.charAt(1));
        //返回指定字符第一次出现的位置,没有返回-1
        System.out.println(str.indexOf('l'));
        //从fromIndex位置开始找指定字符第一次出现的位置,没有返回-1
        System.out.println(str.indexOf('l', 3));
        //返回一个字符串第一次出现的起始位置,没有返回-1
        System.out.println(str.indexOf("el"));
        //从fromIndex位置开始找指定字符串第一次出现的位置,没有返回-1
        System.out.println(str.indexOf("el", 2));
        //从后往前找,返回指定字符第一次出现的位置,没有返回-1
        System.out.println(str.lastIndexOf('e'));
        //从fromIndex位置从后往前找到指定字符第一次出现的位置,没有返回-1
        System.out.println(str.lastIndexOf('e', 3));
        //从后往前找指定字符串第一次出现的位置,没有返回-1
        System.out.println(str.lastIndexOf("el"));
        //从fromIndex位置从后往前找指定字符串第一次出现的位置,没有返回-1
        System.out.println(str.lastIndexOf("el", 4));
    }

这个比较简单,下来多练习下就好了,至于原码的实现不必太过关心,如果每个都去解读原码那得讲到后年马月, 感兴趣的可以下来自己看一看,按Ctrl+鼠标左键,点一下你要进入的方法名就好了。

注意:上面的方法都是要依赖于对象的,也就是实例方法。

2.3 转换相关的方法

2.3.1 数值和字符串之间的转换

public static void strTransform() {
        //数字转字符串
        String s1 = String.valueOf(123);
        String s2 = String.valueOf('b');
        String s3 = String.valueOf(12345f);
        String s4 = String.valueOf(true);
        String s5 = String.valueOf(new Student("张三", 24));
        //字符串转数字
        int a = Integer.parseInt("1234");
        double d = Double.parseDouble("123.4");
}

2.3.2 大小写转换

public static void strTransform() {
        //大小写转换
        String str1 = "hELlo";
        //转换会产生一个新的对象,不会修改原有的字符串
        System.out.println(str1.toUpperCase()); //小写转大写
        System.out.println(str1.toLowerCase()); //大写转小写
}

2.3.3 字符串转数组

public static void strTransform() {
        //字符串转数组
        String str2 = "hello";
        char[] array1 = str2.toCharArray(); //使用toCharArray方法
        for (int i = 0; i < array1.length; i++) {
            System.out.print(array1[i] + " ");
        }
        System.out.println();
        //数组转字符串
        char [] array2 = new char [] { 'a','b','c' };
        String str3 = new String(array2);
        System.out.println(str3);
}

2.3.4 格式化

public static void strTransform() {
        //格式化
        String str4 = String.format("%d-%d-%d", 2022, 8, 19);
        System.out.println(str4);

最终输出这个字符串也就是会打印:2022-8-19,学过C语言的小伙伴可能会比较的熟悉,这里照葫芦画瓢即可,得注意一个点,如果是特殊字符格式化比如 %d\%d\%d,这里我们要转义一下即可,如果不知道 %d 是什么意思,可以去参考下C语言的文章。

相关文章
|
13天前
|
Java API 索引
Java基础—笔记—String篇
本文介绍了Java中的`String`类、包的管理和API文档的使用。包用于分类管理Java程序,同包下类无需导包,不同包需导入。使用API时,可按类名搜索、查看包、介绍、构造器和方法。方法命名能暗示其功能,注意参数和返回值。`String`创建有两种方式:双引号创建(常量池,共享)和构造器`new`(每次新建对象)。此外,列举了`String`的常用方法,如`length()`、`charAt()`、`equals()`、`substring()`等。
15 0
|
2天前
|
Java 关系型数据库 MySQL
Elasticsearch【问题记录 01】启动服务&停止服务的2类方法【及 java.nio.file.AccessDeniedException: xx/pid 问题解决】(含shell脚本文件)
【4月更文挑战第12天】Elasticsearch【问题记录 01】启动服务&停止服务的2类方法【及 java.nio.file.AccessDeniedException: xx/pid 问题解决】(含shell脚本文件)
26 3
|
4天前
|
存储 安全 C语言
【C++】string类
【C++】string类
|
存储 编译器 Linux
标准库中的string类(中)+仅仅反转字母+字符串中的第一个唯一字符+字符串相加——“C++”“Leetcode每日一题”
标准库中的string类(中)+仅仅反转字母+字符串中的第一个唯一字符+字符串相加——“C++”“Leetcode每日一题”
|
6天前
|
编译器 C++
标准库中的string类(上)——“C++”
标准库中的string类(上)——“C++”
|
7天前
|
Java 编译器
Java Character 类
4月更文挑战第13天
|
8天前
|
存储 Java
Java基础教程(7)-Java中的面向对象和类
【4月更文挑战第7天】Java是面向对象编程(OOP)语言,强调将事务抽象成对象。面向对象与面向过程的区别在于,前者通过对象间的交互解决问题,后者按步骤顺序执行。类是对象的模板,对象是类的实例。创建类使用`class`关键字,对象通过`new`运算符动态分配内存。方法包括构造函数和一般方法,构造函数用于对象初始化,一般方法处理逻辑。方法可以有0个或多个参数,可变参数用`类型...`定义。`this`关键字用于访问当前对象的属性。
|
11天前
|
Java Shell
Java 21颠覆传统:未命名类与实例Main方法的编码变革
Java 21颠覆传统:未命名类与实例Main方法的编码变革
13 0
|
11天前
|
Java
Java 15 神秘登场:隐藏类解析未知领域
Java 15 神秘登场:隐藏类解析未知领域
15 0
|
13天前
|
安全 Java
append在Java中是哪个类下的方法
append在Java中是哪个类下的方法
21 9