Java-----String类

1.String类的重要性

经过了C语言的学习,我们认识了字符串,但在C语言中,我们表示字符串进行操作的话需要通过字符指针或者字符数组,可以使用标准库中提供的一系列方法对字符串的内容进行操作,但这种表达和操作数据的方法不太符合面向对象的思想,所以在Java中提供了String类。

2. 认识String类

349fdcf11fd44c86adeb4c3afe06257c.png

在Java中,String类是一种存储字符串数据类型的类。在Java中,String类属于引用数据类型,由String类创建的对象里面存的是引用。

2.1 字符串构造

在Java中,字符串的构造有很多种方式,常用的就以下三种。

public class Test {
    public static void main(String[] args) {
        //使用常量直接构造
        String s1="haha";
        System.out.println(s1);
        
        //直接new String对象
        String s2=new String("man");
        System.out.println(s2);
        
        //使用字符数组进行构造
        char[] array={'w','c','I','s'};
        String s3=new String(array);
        System.out.println(s3);
    }
}

运行代码

c6d84f77301a40f68ca6a9e5af781e07.png

2.2 深刻认识String类

我们知道String类的对象里面存的是引用,那字符串的内容具体是存在哪里的呢?

8e79d4e919a3486a85f57d07c554ef05.png

上图是String类里面的一些具体细节,发现里面有一个char[ ] value数组,所以字符串就是存储在这个数组中。

String类的堆栈图

b445ddec0a944569bb0851ed669065ac.png

2.3 String类的比较 

 1. 用 == 比较

当我们用 == 进行String类的对象进行比较时,是比较对象里面存的引用的值。

public class Test {
    public static void main(String[] args) {
        String s1="man";
        String s2=new String("man");
        String s3=s1;
        System.out.println(s1==s2);
        System.out.println(s1==s3);
        System.out.println(s2==s3);
    }
}

fa84433567e84ee3b4a94353aa8fe468.png

2. equal()方法比较

用equal方法比较String类的对象时,比较的是对象的字符串的内容是否相同。

public class Test {
    public static void main(String[] args) {
        String s1="haha";
        String s2=new String("man");
        String s3=s1;
        System.out.println(s1.equals(s2));
        System.out.println(s1.equals(s3));
        System.out.println(s2.equals(s3));
    }
}

66b23aedaa17494c9026e130be74c422.png

 3.int compareTo(String s)方法比较

1.当我们使用 int compareTo(String s) 方法比较时,比较的规则是:两个字符串对应位置上的的字母比较,直到比到对应的字母不同时,看哪个字母的ASCII值大,对应的那个字符串就长。就直接放回对应两个字母的ASCII值的差值。

2.当比较的两个字符串的长度不一样,一个长,一个短,假设短的字符串的长度为k,如果短的字符串的k个字符的内容与长字符串前k个字符相同,则放回两个字符串的差值。

public static void main(String[] args) {
    String s1 = new String("abc");
    String s2 = new String("ac");
    String s3 = new String("abc");
    String s4 = new String("abcdef");
    System.out.println(s1.compareTo(s2)); // 不同输出字符差值-1
    System.out.println(s1.compareTo(s3)); // 相同输出 0
    System.out.println(s1.compareTo(s4)); // 前k个字符完全相同,输出长度差值 -3
}

4. int compareToIgnoreCase(String str) 方法

与compareTo方式相同,但是忽略大小写比较
public static void main(String[] args) {
    String s1 = new String("abc");
    String s2 = new String("ac");
    String s3 = new String("ABc");
    String s4 = new String("abcdef");
    System.out.println(s1.compareToIgnoreCase(s2)); // 不同输出字符差值-1
    System.out.println(s1.compareToIgnoreCase(s3)); // 相同输出 0
    System.out.println(s1.compareToIgnoreCase(s4)); // 前k个字符完全相同,输出长度差值 -3
}

5.易错点(超级重点)

public static void main(String[] args) {
        String s1="hhh";
        String s2="hhh";
        System.out.println(s1==s2);//结果为true
    }

这时候因为s1和s2都是直接赋值,且内容一样,这时编译器会默认s1和s2指向同一块空间。

3.String类的常用方法

3.1 字符串查找

下图是一些Java中常用的字符串查找功能的方法。

2845c30522b04068b842a281a29d0e51.png

charAt(int index) 方法

用来查找字符串中指定位置上的字符

public class Test {
    public static void main(String[] args) {
        String str="manlebron";
        System.out.println(str.charAt(4));
        //输出e
    }
}

以上代码是查找字符串中下标为4的字符,是e。

int indexOf(int ch)方法

用来查找指定字符第一次出现的位置

public class Test {
    public static void main(String[] args) {
        String str="manlebron";
        System.out.println(str.indexOf('n'));
    }
}

int indexOf(int ch, int fromIndex)方法

用来在字符串中从fromIndex位置开始寻找第一次出现字符ch的位置

public class Test {
    public static void main(String[] args) {
        String str="manlebron";
        System.out.println(str.indexOf('l',2));
    }
}

int indexOf(String str) 方法

用来查找str第一次在字符串中出现的位置

public class Test {
    public static void main(String[] args) {
        String str="manlebron";
        System.out.println(str.indexOf("le"));
    }
}

由于剩下的方法用法差不多,就不 一 一 介绍了。

3.2 字符串转换

1. 数值和字符串之间的转换

public static void main(String[] args) {
        // 数字转字符
        String s1 = String.valueOf(1234);
        String s2 = String.valueOf(12.34);
        String s3 = String.valueOf(true);
        String s4 = String.valueOf(new Student("Hanmeimei", 18));
        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);
        System.out.println(s4);
        System.out.println("=================================");

            // 字符串转数字
        // 注意:Integer、Double等是Java中的包装类型,这个后面会讲到
        int data1 = Integer.parseInt("1234");
        double data2 = Double.parseDouble("12.34");
        System.out.println(data1);
        System.out.println(data2);
}

2. 大小写转换

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

3.字符串和数组之间的转换

public static void main(String[] args) {
        String s = "hello";
        // 字符串转数组
        char[] ch = s.toCharArray();
        for (int i = 0; i < ch.length; i++) {
            System.out.print(ch[i]);
        }
        System.out.println();
        // 数组转字符串
        String s2 = new String(ch);
        System.out.println(s2);
    }

4. 格式化

public static void main(String[] args) {
        String s = String.format("%d-%d-%d", 2019, 9,14);
        System.out.println(s);
}

d3d6fccd700f44d89e9e7fdb29399ea1.png

 4.字符串替换

用来将一个字符串替换原有字符串中指定的一部分。

2f45c374355345d98c7a6fa373fdc4b8.png

 public static void main(String[] args) {
        String str = "helloworld" ;
        System.out.println(str.replaceAll("l", "_"));
        System.out.println(str.replaceFirst("l", "_"));
    }

26a876d777d6496caae43d5c0ed83fcd.png

 5. 字符串拆分------split方法

用来将一个字符串按指定的分割符将原来的字符串分割成多个字符串。

718cf82b7ebf4a519d8100c1d5db4b24.png

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

d5f31b3d88f84c198c1d197d14d83d5c.png

 部分拆分

public static void main(String[] args) {
        String str = "hello world hello bit" ;
        String[] result = str.split(" ",3) ; // 按照空格拆分,分为3组
        for(String s: result) {
            System.out.println(s);
        }
    }

8b531713651743a78e07924d61bf94dc.png

注意事项:拆分是常用的操作,一定要重点掌握。另外,有些特殊的字符无法直接进行拆分,需要加上转移符号 ' \\ ' 。

如拆分IP地址

 如以下代码

public class Test {
    public static void main(String[] args) {
        String IP="192.168.1.1";
        String s[]=IP.split(".");
        for(String tmp:s){
            System.out.println(tmp);
        }
    }
}

运行代码

3a7ee3781af24bc8809b663597134aac.png

5.1 特殊字符的拆分 

1.点字符

我们发现什么输出都没有,这也就意味这分割没成功,因为 " . "是一个特殊的操作符,需要加上转义符号 " \\ " 。

修改如下

public class Test {
    public static void main(String[] args) {
        String IP="192.168.1.1";
        String s[]=IP.split("\\.");  //在 " . " 前加\\
        for(String tmp:s){
            System.out.println(tmp);
        }
    }
}

运行代码

baea70407e56426482cd13e3b292d940.png

 2. " \ " 字符

由于 \ 是一个整除符号,想要在表示 \ 是一个普通的斜杆,就必须在前面再加一个 \ 。

所以将其作为分割符时,要写成 "\\\\".

public static void main(String[] args) {
        String str="haha\\man\\what\\can\\I\\say?";
        for(String tmp:str.split("\\\\")){
            System.out.println(tmp);
        }
    }

9cf27251af6c4ce680e48db73c83eed9.png

5.2 多次拆分

当一个字符串中有多个字符时,我们可以进行多次拆分。


    public static void main(String[] args) {
        String IP="192&man.168.1.1&haha";
        String s[]=IP.split("\\.");  //在 " . " 前加\\
        for(String tmp:s){
            for(String tmp2:tmp.split("&")){
                System.out.println(tmp2);
            }
        }
    }

运行代码:z

871d9e0ab3d54610bea27833cefdfd0c.png

我们也可以用 “ | ” 作为连字符,进行有多个字符的字符串进行拆分。

public static void main(String[] args) {
        String IP="192&man.168.1.1&haha";
        for(String tmp:IP.split("&|\\.")){
            System.out.println(tmp);
        }
    }

3c7b7106006547b58c924288a5d52d63.png

注意:不能在指定的分隔符前加上一个空格,因为空格也算一个字符。 

public static void main(String[] args) {
        String IP="192&man.168.1.1&haha";
        for(String tmp:IP.split("\\. | &")){
            System.out.println(tmp);
        }
    }

4e45573f3b13433d85e151861832f7f1.png

如上图所示,在分隔符前加一个空格,效果就变得不一样了。因为加了空格之后,分隔符就变成了“分隔符+空格”。

 5.3 小总结

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

2.  而如果是  " \ " ,那么就得写成 " \\\\ " 。

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

6. 字符串截取-----substring方法

1cebf5ee05d84e92aea9db21f1f94ae1.png

以上的substring方法是用来截取字符串中的一部分内容的。

代码演示

public static void main(String[] args) {
        String str = "helloworld" ;
        System.out.println(str.substring(5));
        System.out.println(str.substring(0, 5));//左开右闭 [0,5)
    }

89d6992fd98d4005b4076e265302bf16.png

7.其他方法---trim( )方法

trim( ) 方法是用来除去字符串两边的空格的,但并不会出去字符串里面的空格。

代码演示

public static void main(String[] args) {
        String str="    what can I say      ";
        String s=str.trim();
        System.out.println(s);
    }

a87728d3d2a84b209e8201ad7a3ce340.png

8. 字符串的不可变性

首先,我们要清楚,只要涉及到String类型的转变都不是在原字符串上进行的修改,原理是产生一个新的对象。 

 1.string类在设计时就是被设计为无法改变的,在String类中已经具体描述了,如下图:

638bc4671d634698aa2c4220f3779045.jpeg

64ae116509774a869d370285e03d7c9b.jpeg

从该图中还可以看出,字符串的内容是保存在char[ ] value 数组中的。

String类是如何设计成无法改变的呢?

一直有人误认为String类之所以无法被改变是因为String类被final修饰或者string类中的那个数组被final修饰,其实这些都是错误的。

因为一个类被final修饰只能表明这个类无法被继承,一个数组被final修饰,表示数组名存的引用无法被改变。这些都与String类无法被改变有联系。

真正的原因是,存放字符串的那个数组被private修饰了,且String类内没有提供任何方法来让外界去访问和使用该数组,所以就造成了字符串的不可变性。

10.字符串的修改

注意:我们要尽量避开对字符串的直接修改,因为String类是无法被改变的,所有的修改都会创建新的对象,会导致效率非常底下。

如以下代码:

public static void main(String[] args) {
        String s = "hello";
        s += " world";
        System.out.println(s); // 输出:hello world
    }

这段代码看似很简单,有看起来像直接对String类进行了修改。其实不然,

在这段代码的背后做了很多工作,先是创建了一个StringBuilder对象,在原来s中字符串的内容存到StringBuilder对象里面,然后在对StringBuilder对象进行了修改,然后再通过toString()方法转换为String类型,最后再放回一个新的String类的对象。

如下图

a4725defd9bd435ebf9cf06b1b1c59f9.jpeg

这里创建了很多临时变量,就导致了效率低下。

因此我们要尽量避免对String类的直接改变,如果要修改建议尽量 使用StringBuffer或者StringBuilder。

11.StringBuilder和StringBuffer

由于String类型无法直接被改变,再Java中提供了StringBuilder和StringBuffer类,这两个类也是可以存储字符串的,但可以直接对字符串修改的。

public static void main(String[] args) {
        StringBuilder stringBuilder=new StringBuilder("haha ");
        System.out.println(stringBuilder.append("man"));
        StringBuffer stringBuffer=new StringBuffer("what can I say");
        stringBuffer.append("?");
        System.out.println(stringBuffer);
    }

e4eea03714af4b84b299daf7e96a6f78.png

其实 StringBuilder和StringBuffer的用法很相似,就一个区别。

ba97e3bcdcdd49abb92ae467b0b55ce3.png

如上图StringBuffer中多了一个synchronized,这个可以理解为一把锁,在多线程的情况下可以保证安全。

而StringBuilder主要是在单线程情况下使用。

StringBuilder和StringBuffer和String的区别

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

2.StringBuffer与StringBuilder大部分功能是相似的
3.StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安
全操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/668597.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

函数的创建和调用

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 提到函数&#xff0c;大家会想到数学函数吧&#xff0c;函数是数学最重要的一个模块&#xff0c;贯穿整个数学学习过程。在Python中&#xff0c;函数…

Flutter开发效率提升1000%,Flutter Quick教程之对组件进行拖拽与接收

1&#xff0c;首先&#xff0c;所有可以选择的组件&#xff0c;都在左边的组件面板里。从里面点击任何一个&#xff0c;按住左键&#xff0c;向右边的手机面板上进行拖拽即可。 2&#xff0c;拖拽后&#xff0c;我们要选择一个接收组件。什么时候可以接收组件&#xff0c;就是当…

小柴带你学AutoSar系列一、基础知识篇(4)编译

小柴带你学AutoSar总目录https://blog.csdn.net/qianshang52013/article/details/138140235?spm1001.2014.3001.5501 Flechazohttps://www.zhihu.com/people/jiu_sheng 编译真的很重要&#xff01;了解一下机器是如何工作的吧。当然啦&#xff01;通过学习这篇文章还可以学习…

【Go语言精进之路】构建高效Go程序:掌握变量、常量声明法则与iota在枚举中的奥秘

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 引言一、变量1.1 基础知识1.2 包级变量的声明形式深入解析&#x1f4cc; 声明并同时显式初始化&#x1f4cc; 声明但延迟初始化&#x1f4cc; 声明聚类与就近原则 1.3 局部变量的声明形式深入探讨&#x1f4cc; 延迟初始化的…

【原创教程】MES服务器与成品打标机控制说明

1 实现的功能及应用的场合 MES即制造执行系统(manufacturing execution system,简称MES),即在加强MRP计划的执行功能,把MRP计划同车间作业现场控制,通过执行系统联系起来。 MES是一个生产管理智能化的一个系统,是用于生产时记录数据、产量等信息的智能管理系统。 该项…

go语言基于Gin集成后台管理系统开发定时任务管理cron/v3好用又好看

系统目前是支持两种定时类型&#xff0c;一种是函数类型&#xff0c;一种是接口类型&#xff0c;来支持多样的业务&#xff1b;时间周期可视化选择&#xff0c;方便设定执行周期。框架UI漂亮&#xff0c;添加管理定时任务设置简单&#xff0c;客户都可以做自己调整执行时间周期…

LLC开关电源开发:第一节,LLC原理概述

第一节&#xff0c;LLC原理概述文章目录 一、LLC概述二、LLC电路拓扑1.电路拓扑2.电路工作原理3.电路原理分析 总结 一、LLC概述 LLC电路&#xff0c;是一种通过控制开关频率&#xff08;频率调节&#xff09;来实现输出电压恒定的谐振电路&#xff0c;它包括一个电感L、一个电…

transfomer中attention为什么要除以根号d_k

简介 得到矩阵 Q, K, V之后就可以计算出 Self-Attention 的输出了&#xff0c;计算的公式如下: A t t e n t i o n ( Q , K , V ) S o f t m a x ( Q K T d k ) V Attention(Q,K,V)Softmax(\frac{QK^T}{\sqrt{d_k}})V Attention(Q,K,V)Softmax(dk​ ​QKT​)V 好处 除以维…

算法每日一题(python,2024.05.31)

题目来源&#xff08;力扣. - 力扣&#xff08;LeetCode&#xff09;&#xff0c;简单&#xff09; 解题思路&#xff1a; 二次遍历&#xff0c;第一次遍历用哈希表记录每个字母的出现次数&#xff0c;出现一次则将它的value值赋为True&#xff0c;将它的下标赋为key值&#x…

leetcode74搜索二维矩阵

题目 给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非严格递增顺序排列。每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &#xff0c;如果 target 在矩阵中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 fa…

LeetCode-47 全排列Ⅱ

LeetCode-47 全排列Ⅱ 题目描述解题思路代码说明 题目描述 给定一个可包含重复数字的序列 nums &#xff0c;按任意顺序 返回所有不重复的全排列。 示例 &#xff1a; 输入&#xff1a;nums [1,1,2]输出&#xff1a; [[1,1,2], [1,2,1], [2,1,1]] b站题目解读讲的不好&…

充电宝哪个牌子好?怎么选充电宝?压箱底充电宝购买指南大全!

充电宝作为我们日常生活中不可或缺的便携式电源之一&#xff0c;市场上品牌众多、种类繁多。对于消费者来说&#xff0c;如何选择适合自己的充电宝成为一个值得重视的问题。有的充电宝厂家为节省成本“偷工减料”&#xff0c;使用劣质电池&#xff0c;以次充好、参数造假等现象…

Win10安装TensorRT

目录 什么是TensorRT 下载TensorRT 安装TensorRT 拷贝文件 安装whl文件 验证是否安装成功 什么是TensorRT TensorRT是由Nvidia推出的C语言开发的高性能神经网络推理库&#xff0c;是一个用于生成部署的优化器和运行时引擎。和cudnn类似&#xff0c;但它不支持训练&#xff…

Mysql(一)查询Sql是如何执行的

Hello&#xff0c;大家好我是极客涛&#x1f60e;&#xff0c;我最近在整理Mysql相关的知识点&#xff0c;所以准备开启一个Mysql的主线任务&#xff0c;大概耗时3周左右&#xff0c;整个节奏还是由浅入深&#xff0c;主要包括Mysql的架构、事务实现、索引组织形式、SQL优化、日…

kettle 使用动态变量名定义变量

name是变量&#xff0c;value 值也是变量 我需要把name作为变量名&#xff0c;value作为变量值&#xff1b; 在kettle中&#xff0c;使用javascript脚本 key与lastVsxzl都是变量 //Script here setVariable(key,lastVsxzl,r);var rgetVariable(key,r); Demo 1、从记事本里面…

sensitive-word 敏感词 v0.16.1 新特性支持字典内存资源释放

敏感词系列 sensitive-word-admin 敏感词控台 v1.2.0 版本开源 sensitive-word-admin v1.3.0 发布 如何支持分布式部署&#xff1f; 01-开源敏感词工具入门使用 02-如何实现一个敏感词工具&#xff1f;违禁词实现思路梳理 03-敏感词之 StopWord 停止词优化与特殊符号 04-…

【第十三节】C++控制台版本坦克大战小游戏

目录 一、游戏简介 1.1 游戏概述 1.2 知识点应用 1.3 实现功能 1.4 开发环境 二、项目设计 2.1 类的设计 2.2 各类功能 三、程序运行截图 3.1 游戏主菜单 3.2 游戏进行中 3.3 双人作战 3.4 编辑地图 一、游戏简介 1.1 游戏概述 本项目是一款基于C语言开发的控制台…

linux--------线程的同步和互斥

前言 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、线程互斥 &#xff08;1&#xff09;互斥&#xff1a; 任何时刻&#xff0c;互斥保证有且只有一个执行流进入临界区&#xff0c;访问临界资源&#xff0c;通常对临界资源起保护作用 要了解互…

fastjson 泛型转换问题(详解)

系列文章目录 附属文章一&#xff1a;fastjson TypeReference 泛型类型&#xff08;详解&#xff09; 文章目录 系列文章目录前言一、代码演示1. 不存在泛型转换2. 存在泛型转换3. 存在泛型集合转换 二、原因分析三、解决方案1. 方案1&#xff1a;重新执行泛型的 json 转换2. …

使用Python突破网站验证码限制

之前有小伙伴说&#xff0c;在web自动化的过程中&#xff0c;经常会被登录的验证码给卡住&#xff0c;不知道如何去通过验证码的验证&#xff0c;今天专门给大家来聊聊验证码的问题。 常见的验证码一般分为两类&#xff0c;一类是图文验证码&#xff0c;一类是滑块验证码&#…