补坑:Java的字符串String类(1)

news2024/10/5 23:26:29

常用方法

字符串构造

来看看源码里面String的构造方法

普通字符串

        //"hello" 是字符串常量,没有\0标记结尾
        String str = "hello";
        System.out.println(str);//hello

        String str2 = new String();
        System.out.println(str2);//没有输出

        String str3 = new String("pppp");
        System.out.println(str3);//pppp

字符串数组

        char[] array = {'a','b','c'};
        String str4 = new String(array);
        System.out.println(str4);//abc

        char[] array1 = {'a','b','c'};
        String str5 = new String(array1,1,2);
        System.out.println(str5);//bc

⚠String是引用类型,内部并不存储字符串本身,String类实例变量

也就是说,一个String其实是长这样的

我们来尝试分析这段代码

String s1 = new String("hello");
String s2 = new String("world");
String s3 = s1;

假设s1的地址是0x9,new String之后在堆中创建一个新的String,value是0x8,把"hello"扔给这个String,那这个"hello"的地址也是0x8,s1根据value的地址找到"hello"对象

字符串长度 

辨析

        String str4 = "";
        System.out.println(str4.length());
        String str5 = null;
        System.out.println(str5.length());

str4指向的是一个空的字符串,空的字符串也是字符串,也是有长度的,只不过长度为0

str5不指向任何一个字符串,那它怎么可能会有长度呢

我们也可以用isEmpty()来检验

        String str4 = "";
        System.out.println(str4.isEmpty());
        String str5 = null;
        System.out.println(str5.isEmpty());

因为str4是空的字符串,那必然返回true,而str5什么都不指向,那就会返回空指针异常 


字符串比较

equals()

辨析:这个打印的结果是true吗?

        String s1 = new String("hello");
        String s2 = new String("hello");
        System.out.println(s1 == s2);

答案是false,== 比较的是s1和s2的地址,因为s1和s2本来在申请内存空间的时候,地址就不一样,怎么可能相等

那我们就要邀请String里面的一个方法.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;
    }

从代码我们可以看出来,equals是按照字符串里的字符一个一个进行比较的,返回值是布尔类型

compareTo()

假设我有两个字符串,我想要比较这两个字符串谁大谁小

        String s1 = new String("abc");
        String s2 = new String("acd");

String里面实现了Comparable接口,那就可以调用compareTo方法轻松帮助我们解决问题

     System.out.println(s1.compareTo(s2));

该方法返回类型是int类型,如果s1>s2返回正数;s1=s2返回0;s1<s2返回负数

所以我们一般用>0或=0或<0来进行字符串比较

平时我们在输入验证码的时候,系统在比较两个字符串是否相等的时候是忽略大小写的

其实就是调用compareToIgnoreCase方法


字符串查找

charAt()

如果数字给大了,下标越界

indexOf()

从头到后查找字符第一次出现的下标

 也可以找子串在主串的位置

从指定位置开始查找

lastIndexOf()

倒着往回找

这就能延伸到BF算法和KMP算法,我后续会出博客,欢迎大家关注


字符串转化

1.数值和字符串转化

valueOf()方法,支持多种形式的数值,都能将其转化成字符串

        String s = String.valueOf(19.9);
        System.out.println(s);

那字符串怎么转成数字呢?

        int data = Integer.parseInt("198");
        System.out.println(data);

哪种数据类型对应哪种parsexx,假如给parseInt传入19.8,程序会报错数值格式错误

2.字符串大小写转化

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

        String s1 = "hello";
        //转变为大写不是在原来的基础上转变
        //转变成大写后是一个新的对象
        //如果只打印s1的话还只是小写
        String ret = s1.toUpperCase();
        System.out.println(ret);

3.字符串转数组

上面我们提到了数组怎么转成字符串(直接new String(array)暴力转换), 其实字符串也可以转数组(使用toCharArray())

toCharArray() 方法返回值是一个char类型的数组,所以我们要用一个新的array来接收它

4.格式化

        String s = String.format("%d-%d-%d",2023,11,9);
        System.out.println(s);


字符串替换

先来看看replace方法

比如这个,字符串里面所有的ab都被99代替了

replaceFirst():将首个内容进行替换

这里只对第一个ab进行了替换,其他ab都不动


字符串拆分

split():分割字符串

        String str = "hello abc world";
        String[] ret = str.split(" ");//将上面的字符串按照空格拆分
        for (int i = 0; i < ret.length; i++) {
            System.out.println(ret[i]);
        }

问题:

为什么用"."号分割字符串后打印出来没结果呢?

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

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

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

给你这个字符串,把每个单词拆分出来

String str = "name=zhangsan&age=18" ;

第一种写法,用|把两个分割判断符号分开来

        String[] ret = str.split("=|&");
        for (int i = 0; i < ret.length; i++) {
            System.out.println(ret[i]);
        }

第二种写法:多次分割法

        String[] ret = str.split("&");
        for (int i = 0; i < ret.length; i++) {
            System.out.println(ret[i]);
            String x = ret[i];
            //在第一次分割的基础上按照"="进行第二次分割
            String[] ret2 = x.split("=");
            for (int j = 0; j < ret2.length; j++) {
                System.out.println(ret2[j]);
            }
        }

字符串截取

substring(): 两个参数代表区间,一个参数代表从哪里开始截

        String str = "ababc";
        String ret = str.substring(0,3);//截取字符串范围[0,3)
        System.out.println(ret);

        String ret1 = str.substring(2);
        System.out.println(ret1);

其他的方法


字符串的不可变性

String类在设计时就是不可变的

String被final修饰,表示这个类不能被继承

而String的两个实例变量均被private修饰,外部根本拿不到这两个值,也无法修改

⚠String的不可变不是因为value被final修饰了,final修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象的内容是可以修改的,接下来我们就来讲讲具体是怎么修改的。


String的修改

看看下面的例子

        String str = "hello";
        //System.out.println(str);//hello
        str = str + "abc";
        System.out.println(str);//helloabc

hello加上一个abc变成helloabc的过程,不是说把str的值进行修改(因为被private修饰根本拿不到value),而是创建了一个新的对象“helloabc",再让str指向这个新对象

但是如果单纯采用String产生新对象的方法来修改字符串,这样的效率是十分低下的,因为会创建一堆新对象。其实java编辑器采用了另一种方法

我们拿上面的代码去窥探它的底层 

底层看不懂?我用代码来翻译一下

    public static void main(String[] args) {
        String str = "hello";
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(str);
        stringBuilder.append("abc");
        str = stringBuilder.toString();
        System.out.println(str);
    }

底层代码构造了一个新的对象stringBuilder,传统的String对象是不可变的,但是有了StringBuilder这个可变对象,字符串就可以被修改了,而且效率很高(原因看下面)。那我们接下来就来讲讲StringBuilder这个对象


StringBuilder和StringBuffer

我们首先来比较一下String自创新String对象和采用StringBuilder或StringBuffer的效率

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        String s = "";
        for(int i = 0; i < 10000; ++i){
            s += i;
        }
        long end = System.currentTimeMillis();
        System.out.println("String: "+(end - start));

        start = System.currentTimeMillis();
        StringBuffer sbf = new StringBuffer("");
        for(int i = 0; i < 10000; ++i){
            sbf.append(i);
        }
        end = System.currentTimeMillis();
        System.out.println("StringBuffer: "+(end - start));
        
        start = System.currentTimeMillis();
        StringBuilder sbd = new StringBuilder();
        for(int i = 0; i < 10000; ++i){
            sbd.append(i);
        }
        end = System.currentTimeMillis();
        System.out.println("StringBuilder: "+(end - start));
    }

看看内层

内层里面每一次循环StringBuilder一直存在,说明这个对象在创建之后就一直靠它来修改字符串,相比起String那种不断创建新对象再销毁旧对象的方法,这种方式显然效率更高。

StringBuffer也是这个道理

StringBuilder和StringBuffer的区别

StringBuilder的append方法底层

Stringbuffer的append方法底层

StringBuffer多了一个synchronized,表示保证线程安全,也就是说StringBuffer是一个线程安全的类

线程安全是什么?

可以参考这篇文章什么是线程安全,你真的了解吗? - 知乎

这里可以简单用个厕所的例子来解释。假设有一个人要上厕所,一个厕所只能容纳一个人,这个人可以当成一个线程。厕所得有门锁才能保证里面的人的安全吧,诶这个锁就是所谓的保障线程安全,能够保证外面的人(其他线程)进不来。当这个人上完厕所后出来锁打开,换下一个人进去锁又闭上

 

上面的synchronized其实可以当成一个锁,阻止别的线程进入

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

摊位展示预约小程序的作用有哪些

无论市场还是街边&#xff0c;小摊小贩往往很多&#xff0c;组成了丰富多彩的线下购物环境&#xff0c;而在实际发展中&#xff0c;摊位的需求度很高&#xff0c;但由于种种原因&#xff0c;导致在实际发展中&#xff0c;也有一定难题&#xff1a; 1、摊位预约难、信息查看难 …

IDEA的优化配置教程

前言 IDEA 全称 IntelliJ IDEA&#xff0c;是java编程语言开发的集成环境。IntelliJ在业界被公认为最好的java开发工具&#xff0c;尤其在智能代码助手、代码自动提示、重构、JavaEE支持、各类版本工具(git、svn等)、JUnit、CVS整合、代码分析、 创新的GUI设计等方面的功能可以…

多门店民宿预定系统酒店预订管理系统源码/公寓/农家乐小程序源码

技术栈&#xff1a; thinkphpuniappmysql 支持H5APP小程序 主要功能介绍&#xff1a; 在线预订 支持在线支付或到店付&#xff0c;支持配置免费取消订单时长&#xff0c;支持到店付保留时长设置 房间搜索 支持按日期搜索房间状态&#xff0c;支持按日期区间搜索房间状态…

Python tkinter库利用Scrollbar对象实现Text组件右侧滚动条

在Python的Tkinter中&#xff0c;可以使用Scrollbar来实现Text组件的上下滑动。首先&#xff0c;需要创建一个Scrollbar对象并将其与Text组件绑定&#xff0c;然后将Scrollbar放置在Text组件的右侧&#xff0c;使其能够控制Text组件的上下滑动。 运行结果 以下是一个简单的示例…

Postman常见报错与解决方法,持续更新~

postman中文文档 基本操作&#xff1a;从控制台查看请求报错 如果 Postman 无法发送你的请求&#xff0c;或者如果它没有收到你发送请求的 API 的响应&#xff0c;你将收到一条错误消息。此消息将包含问题概述和指向控制台的链接&#xff0c;你可以在其中访问有关请求的详细信…

SmargGBD(GB28181设备接入模块)如何对接wvp-gb28181-pro

技术背景 我们在对接SmartGBD&#xff08;GB28181设备接入模块&#xff09;的时候&#xff0c;除了常规的海康大华宇视等国标平台外&#xff0c;有些公司会选择wvp-gb28181-pro。 众所周知&#xff0c;WEB VIDEO PLATFORM是一个基于GB28181-2016标准实现的开箱即用的网络视频…

SAMBA文件共享与DNS域名服务

一、SAMBA文件共享 1、什么是SAMBA SMB&#xff08;Server Message Block&#xff09;协议实现文件共享&#xff0c;也称为CIFS&#xff08;Common Internet File System &#xff09; 是Windows和类Unix系统之间共享文件的一种协议 客户端主要是Windows&#xff1b;支持多…

openGauss学习笔记-120 openGauss 数据库管理-设置密态等值查询-概述及使用gsql操作密态数据库

文章目录 openGauss学习笔记-120 openGauss 数据库管理-设置密态等值查询-概述及使用gsql操作密态数据库120.1 密态等值查询概述120.2 使用gsql操作密态数据库 openGauss学习笔记-120 openGauss 数据库管理-设置密态等值查询-概述及使用gsql操作密态数据库 120.1 密态等值查询…

【dbeaver】添加mysql高低版本选择驱动

添加mysql高低版本选择驱动 连接到数据库->全部->查询mysql MySQL 版本驱动 8.0 MySQL 5 版本驱动 5.7.x 其他需要就&#xff1a;https://downloads.mysql.com/archives/c-j/ 密码查看 项目设置密码&#xff1a; File -> Project security ->设置密码 It i…

可视化 | echarts饼图改编

echarts模板来源 &#x1f4da;改编点 &#x1f407;基本样式 去掉legend、label&#xff1a;show: false背景透明&#xff1a;backgroundColor: "transparent"去除功能标签添加载入动态animationEasing: elasticOut, animationDelay: function (idx) {return Mat…

Mac安装与配置eclipse

目录 一、安装Java&#xff1a;Mac环境配置&#xff08;Java&#xff09;----使用bash_profile进行配置&#xff08;附下载地址&#xff09; 二、下载和安装eclipse 1、进入eclipse的官网 (1)、点击“Download Packages ”​编辑 (2)、找到macOS选择符合自己电脑的框架选项…

安全框架SpringSecurity-1(认证入门数据库授权)

一、Spring Security ①&#xff1a;什么是Spring Security Spring Security是一个能够为基于Spring的企业应用系统提供声明式&#xff08;注解&#xff09;的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean&#xff0c;充分利用了Spring …

Linux-vi/vim命令

1.vim/vi编辑器的三种工作模式 ①命令模式 ②输入模式 i打开 ③底线命令模式 :打开 2.命令模式 vi 文件路径 vim 文件路径 如果文件不存在则创建新的文件&#xff0c;存在则使用vi/vim打开 3.快捷键 模式命令描述命令模式i在当前光标位置进入输入模式命令模式a在当前光标位置之…

【2】Gradle-快速入门使用【Gradle项目结构概念】

目录 【2】Gradle-快速入门使用【Gradle项目结构概念】安装本地安装先决条件 官网安装教程 Gradle 快速指南初始化项目查看Gradle的项目结构了解Gradle Wrapper调用Gradle包装器了解Gradle的项目结构了解settings文件了解构建脚本 IDEA中使用Gradle创建一个新项目创建一个Sprin…

环形处理习题,举例:约瑟夫环,魔方阵

目录 约瑟夫环 魔方阵 约瑟夫环 题目描述&#xff1a;有n 个人围成一圈,顺序排号。从第1个人开始报数从1到3报数凡是报到3 的人退出圈子,问最后留下的是原来的第几号? 环形处理:依次遍历数据集的每个元素&#xff08;每个人依次报号&#xff09;&#xff0c;直到遍历到最后…

【Linux】编译Linux内核

之所以编译内核&#xff0c;是因为gem5全系统仿真需要vmlinux文件&#xff0c;在此记录一下以备后面需要。 此过程编译之后会获得vmlinux和bzImage两个文件&#xff1b; 主要参考知行大佬的编译内核与gem5官方教程 文章目录 一、Linux源码下载二、安装编译依赖三、编译1. 内核编…

5种常用Web安全扫描工具,快来查漏补缺吧!

漏洞扫描是一种安全检测行为&#xff0c;更是一类重要的网络安全技术&#xff0c;它能够有效提高网络的安全性&#xff0c;而且漏洞扫描属于主动的防范措施&#xff0c;可以很好地避免黑客攻击行为&#xff0c;做到防患于未然。那么好用的漏洞扫描工具有哪些&#xff1f; 答案…

抖音小程序开发实战:打造独特品牌体验的代码之旅

抖音小程序的崛起为品牌提供了一个全新的数字化平台&#xff0c;而通过深入的抖音小程序开发&#xff0c;品牌不仅能够提升曝光度&#xff0c;更能打造独特的用户体验。在本文中&#xff0c;我们将深入研究抖音小程序开发的关键技术要点&#xff0c;并通过实际代码演示&#xf…

互联网医院牌照|互联网医院牌照办理合法经营医疗服务

在当今数字化医疗的快速发展中&#xff0c;互联网医院牌照不仅是对公司医疗业务的认可&#xff0c;也是开启线上医疗服务的关键。我们的服务旨在帮助您快速、顺利地获得互联网医院牌照&#xff0c;以便您可以及时开展线上医疗服务。 互联网医院牌照申请流程&#xff1a; 1、首…

栈 和 队列

什么是栈? 一种特殊的线性表&#xff0c;只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出&#xff08;LIFO - Last In First Out&#xff09;的原则。   从数据结构的角度来看&…