java之string相关内容详解(字符串和字符串常量池)面试题(代码片段)

蓝盒子itbluebox 蓝盒子itbluebox     2023-01-14     792

关键词:

1、String可以被继承吗?

String类在声明时使用final关键字修饰,被final关键字修饰的类无法被继承。

Cannot inherit from final "java.lang.String’
无法从最终的“java.lang.String”继承

接下来我们可以看一下String类的源代码片段:

public final class String
    implements java.io.Serializable, Comparable<String>,CharSequence 
    /** The value is used for character storage. */
    private final char value[];

    /** Cache the hash code for the string */
    private int hash; // Default to 0

    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = -6849794470754667710L;

2、为什么Java语言的开发者,把String类定义为final的呢?

1 主要是为了“效率” 和 “安全性” 的缘故。
若 String允许被继承, 由于它的高度被使用率, 可能会降低程序的性能,所以String被定义成final。

2、 String类中的成员属性也几乎都设计成了private final的,这样String就被设计成一个不变类,这样有助于共享,提高性能。
可以将字符串对象保存在字符串常量池中以供与字面值相同字符串对象共 享。
如果String对象是可变的,那就不能这样共享,因为一旦对某一个String类型变量引用的对象值改变,将同时改变一起共享字符串对象的其他 String类型变量所引用的对象的值。

3、String被设计为不变类,其中的offset,value[]都被设计成private final的,这样在多线程时,对String对象的访问是可以保证安全的。
java程序语言的许多特性依赖于不可变的String对象。

3、字符串和字符串池

(1)字符串

1、字符串的创建

(1)直接创建:String s = “Hello”;
(2)new 创建:String s = new String(“Hello”)

要注意空字符串和null是不同的

public class StringTest
    public static void main(String[] args) 
        String s1 = "";
        String s2 = new String("");
        String s3 = new String();
        String s4 = null;
        System.out.println("s1.equals(s2)="+s1.equals(s2));
        System.out.println("s2.equals(s3)="+s2.equals(s3));
        System.out.println("s3.equals(s4)="+s3.equals(s4));
        System.out.println("s1.equals(s4)="+s1.equals(s4));
    

(3)除了new (“Hello”)中的类型之外,还能有如下方式:
public class StringTest
    public static void main(String[] args) 
        String s1 = "Hello1";
        String s2 = new String(s1);
        char []c = 'H','e','l','l','o','2';
        String s3 = new String(c);  //但是不能String s3 = new String('H','e','l','l','o','2')
        byte []b = 'H','e','l','l','o','2';
        String s4 = new String(b);
        StringBuffer sb = new StringBuffer(new String("Hello4"));
        String s5 = new String(sb);
        StringBuilder sbu = new StringBuilder(new StringBuffer("Hello5"));
        String s6 = new String(sbu);
        System.out.println("s1:"+s1+" s2:"+s2+" s3:"+s3+" s4:"+s4+" s5:"+s5+" s6:"+s6);
    


可以看出还可以以byte[]、char[]、String、StringBuffer、StringBuilder均可作为String构造函数的参数。

(4)vauleOf()创建

普通数据类型 String s1=String.vauleOf(true);
或者是int bl=54;String s1=String.vauleOf(bl);直接将其转换为String.

public class StringTest
    public static void main(String[] args) 
       String s1 = String.valueOf(true);
       System.out.println("s1:"+s1);
       int bl = 54;
       String s2 = String.valueOf(bl);
       System.out.println("s2:"+s2);
    


(5)toString()

引用数据类型通过调用成员方法toString()来将对象转换为字符串。对与System.out.println(obj);若obj = null返回null

public class StringTest
    public static void main(String[] args) 
        Object obj = null;
        System.out.println(obj);
    


继续探讨toString()方法,如果调用它的是一个字符串对象包括String,StringBuffer、StringBuilder则返回当前字符串,如果是基础数据的引用、例如Integer,Character,Boolean则会返回对应的int,char,boolean等对应的数据字符串。如果是其他类型对象,重写toString()方法就不说了,但是未重写方法就会输出“包名.类名@哈希码十六进制”(此处包含数组)

package cn.itbluebox;

class A


public class StringTest

    public static void main(String[] args) 

        A a = new A();
        A a0 = new A();
        System.out.println(a.toString());
        System.out.println(a0);

    


(6)System.out.println()方法

我们常用的System.out.println()方法其实就是将参数转换为字符串,而主要方法,如果是基本类型,就使用valueOf(),若是非null引用就调用toString(),若是null类型数据就是返回null(null不能直接作为参数,只能是某些对象指向null,然后打印此对象的形式)

class A

class B
    @Override
    public String toString() 
        return "BB";
    

public class StringTest
    public static void main(String[] args) 
        char []c = 'H','e','l','l','o','2';//数组
        StringBuffer sb = new StringBuffer(new String("Hello4"));//字符串对象
        Integer i = 9;//基本类型的包装类
        boolean b1 = false;//基本数据类型
        Object o = null;//null
        A a = new A();      //非null无重写
        B b = new B();      //非null有重写
        System.out.println("c:"+c);  //打印Hello2
        System.out.println("c.toString():"+c.toString());//打印地址
        System.out.println("i:"+i);
        System.out.println("b1:"+b1);
        System.out.println("o:"+o);
        System.out.println("a:"+a);
        System.out.println("b.toString():"+b.toString());
    

(7)直接+

两个字符串相加
例如:

String s1 = "123"+"456";

字符串和其他相加时会采用和println相同的策略

public class StringTest02 
    public static void main(String[] args) 
        byte []b = 'H','e','l','l','o','3';
        Object o = null;
        String s1 = "123"+new Integer(456);
        String s2 = "123"+o;//o对象没有实例化返回null
        String s3 = "123"+false;
        String s4 = "123"+b;
        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);
        System.out.println(s4);
    


任然来重点看一下字符数组,在+连接符下,会直接调用toString()从而返回其地址,不会访问其内容,编程与其他类型数组一样。

2、字符串的操作

(1)public String concat(String str)进行拼接操作,若str是空字符串,则还返回原理的引用
public class StringTest02 
    public static void main(String[] args) 
        String s1 = "123";
        String s2 = "456";
        System.out.println("s1:"+s1);
        System.out.println("s1.hashCode():"+s1.hashCode());
        s1 = s1.concat(s2);
        System.out.println("s1:"+s1);
        System.out.println("s1.hashCode():"+s1.hashCode());
    


s1.hashCode():1450575459 可以看出str不为空就会返回一个新的引用

(2)String replace(char oldChar,char newChar)将所有的oldChar字符替换为newChar,String toLowerCase()String toUpperCase()转换大小写,String trim()去空白符,对于这些方法来说若不会改变原有字符串(如果需要改变需要对原有字符串重新赋值),例如toLowerCase()不含oldChar,转换为小写的不含小写字符串,或不含空白符等就不会修改原引用,String substring(int beginIndex)String substring(int beginIndex,int endIndex)是截取第beginIndex+1到结束的字符串和从第beginIndex+1到nedIndex的子字符串
package cn.itbluebox;

import javax.swing.*;

public class StringTest02 
    public static void main(String[] args) 

        System.out.println("replace↓");
        String s1 = "123123123";
        s1.replace("1","a");
        System.out.println(s1);
        s1 =  s1.replace("1","a");
        System.out.println(s1);

        System.out.println("toUpperCase↓");
        s1.toUpperCase();
        System.out.println(s1);
        s1 = s1.toUpperCase();
        System.out.println(s1);

        System.out.println("toLowerCase↓");
        s1.toLowerCase();
        System.out.println(s1);
        s1 = s1.toLowerCase();
        System.out.println(s1);

        System.out.println("trim↓");
        s1 = "  "+s1+"   "+s1+"    ";
        s1.trim();
        System.out.println(s1);
        s1= s1.trim();
        System.out.println(s1);

        System.out.println("substring↓");
        s1.substring(5);
        System.out.println(s1);
        s1 = s1.substring(5);
        System.out.println(s1);

        s1.substring(2,4);
        System.out.println(s1);
        s1 = s1.substring(2,4);
        System.out.println(s1);

    


(3)int indexOf(int ch),查询第一次出现的位置,若不含此字符串,返回-1,不要误以为写错了,确实是参数为int类型,这里指的是Unicode码,int indexOf(int ch,int fromIndex)功能相同但要从大于等于fromIndex的下标(注意和第几个分区)开始查询,int indexOf(String str)提前是str是子字符串,返回第一个字符的下标,int index(String str,int fromIndex)类似。
package cn.itbluebox;

public class StringTest02 
    public static void main(String[] args) 
        String s = "abcabcdabcde";
        System.out.println("s.indexOf('b'):"+s.indexOf('b'));
        System.out.println("s.indexOf('b',1):"+s.indexOf('b',1));//返回当前字符串当中b从下角标为1的位置(从第0号位开始)
        System.out.println("s.indexOf('b',2):"+s.indexOf('b',2));//返回当前字符串当中b从下角标为2的位置(从第0号位开始)
        System.out.println("s.indexOf(\\"abc\\"):"+s.indexOf("abc"));//返回当前字符串当中abc从下角标为0的位置(从第0号位开始)
        System.out.println("s.indexOf(\\"abc\\",1):"+s.indexOf("abc",1));//返回当前字符串当中abc从下角标为1的位置(从第0号位开始)
        System.out.println("s.indexOf(\\"ab\\",-1):"+s.indexOf("ab",-1));//返回当前字符串当中ab从下角标为-1的位置(从第0号位开始)
        System.out.println("s.lastIndexOf(\\"ab\\"):"+s.lastIndexOf("ab"));//s.length-1号下角标的相当于最后一个元素,往前第一次ab出现对应的下角标的值
        System.out.println("s.lastIndexOf(\\"c\\",8):"+s.lastIndexOf("c",8));//8号下角标的相当于最后一个元素,往前第一次c出现对应的下角标的值
        System.out.println("s.lastIndexOf(\\"abc\\",7):"+s.lastIndexOf("abc",7));//7号下角标的相当于最后一个元素,往前第一次abc出现对应的下角标的值
        System.out.println("s.lastIndexOf(\\"abc\\",29):"+s.lastIndexOf("abc",29));//29号下角标的相当于最后一个元素,往前第一次abc出现对应的下角标的值
    


(4)字符串的比较int compareTo(String another);(参数不能是null???),返回值第一个不相同字符unicode码差值,若两一个字符串是另外一个字符串字串,返回字符串长度差值,若两串相同则返回0,此外还有int compareToIgnoreCase(String another);比较方法与其类似,但是忽略大小写。

判断两个字符串相等不能用等号==,要用boolean equals(Object anObj)你看到的没错正是Object类型的参数,
但是你用其他对象做参数,参数的值为null的返回值返回false,即使是StringBuffer对象也一样,null可以作为参数但是永远返回false。

boolean equalsIgnoreCase(String another)忽略大小写。

具体案例

public class StringTest02 
    public static void main(String[] args) 

        String a = "123";
        String b = "123";
        String c = "abc";
        String d = "ABC";
        System.out.println(a==b);//相同的字符串在字符串常量池当中是同一个引用/地址   == 对比的是引用/地址
        System.out.println(a.equals(b));查看详情  

java之io知识详解(代码片段)

常见类使用常见类使用IO常见类的使用File相关字节流相关实现逐行输出文本文件的内容Java中的网络支持InetAddressURLSocketsJava7文件操作介绍文件路径文件操作文件属性文件列表流文件监视常见类使用本文主要介绍JavaIO常见类的使用... 查看详情

java基础之string字符串的底层原理,面试常见问题(代码片段)

前言在之前的两篇文章中,给大家介绍了String字符串及其常用的API方法、常用编码、正则表达式等内容,但这些内容都是停留在”如何用“的阶段,没有涉及到”为什么“的层面。实际上,我们在求职时,面试官很喜欢问我们关... 查看详情

c++stl详解——string类的模拟实现(代码片段)

...和end容量和大小相关函数size和capacityreserve和resizeempty修改字符串相关函数push_backappendoperator+=inserteraseclearswapc_str访问字符串相关函数operator[]find和rfind 查看详情

java之io知识详解(代码片段)

常见类使用常见类使用IO常见类的使用File相关字节流相关实现逐行输出文本文件的内容Java中的网络支持InetAddressURLSocketsJava7文件操作介绍文件路径文件操作文件属性文件列表流文件监视常见类使用本文主要介绍JavaIO常见类的使用... 查看详情

java疯狂作图之剖释string类之妈见夸之作(代码片段)

前言字符串类型广泛应用在Java编程当中,在之前【Java】数据类型和运算符这一小节里面有简单介绍过一点String类型,但是那不过是String类型的相关内容的九牛一毛在本小节当中将向大家深刻剖析String类,了解其创建... 查看详情

java核心之字符串与编码

...g​​有特殊处理,即可以直接用​​"..."​​来表示一个字符串:Strings1="Hello!";实际上字符串在​​String​​内部是通过一个​​char[]​​数组表示的,因此,按下面的写法也是可以的:Strings2=newString(newchar[]H,e,l,l,o,!);因为​​S... 查看详情

java之运算符相关内容详解面试题(代码片段)

1、Java运算符计算机的基本用途之一就是执行数学运算,作为一门计算机语言,Java也提供了一套丰富运算符来操作变量,我们可以把运算符分成以下几组?算术运算符关系运算符位运算符逻辑运算符赋值运算符其... 查看详情

constantpool和stringconstantpool详解

...节.关于String类的说明1.String使用privatefinalcharvalue[]来实现字符串的存储,也就是说String对象创建之后,就不能再修改此对象中存储的字符串内容,就是因为如此,才说String类型是不可变的(immutable).2.String类有一个特殊的创建方法,就是使... 查看详情

java之string类总结

String类概述:1.String类代表字符串。Java程序中的所有字符串字面值(如"abc")都作为此类的实例实现。2.String是一个final类,代表不可变的字符序列。3.字符串是常量,用双引号引起来表示。它们的值在创建之后不能更改。4.String对象... 查看详情

java之final相关内容详解面试题(代码片段)

1、final关键字除了修饰类之外,还有哪些用法呢?(1)final修饰的变量,一旦赋值,不可重新赋值;(2)如果引用为引用数据类型,比如对象、数组,则该对象、数组本身可以修改,... 查看详情

java之final相关内容详解面试题(代码片段)

1、final关键字除了修饰类之外,还有哪些用法呢?(1)final修饰的变量,一旦赋值,不可重新赋值;(2)如果引用为引用数据类型,比如对象、数组,则该对象、数组本身可以修改,... 查看详情

序列之列表详解(代码片段)

列表是python中常用的重要数据结构,它与字符串,元组都属于序列,支持序列相关操作;本文主要内容如下:1>列表定义方式与基本用法;2>列表遍历;2>字符串,元组与列表区别;3>列表常用函数介绍。1.列表定义方式... 查看详情

java字符串相关类(代码片段)

String类String是一个final类,代表不可变的字符序列。String对象的字符内容是存储在一个字符数组value[]中的。publicfinalclassStringimplementsjava.io.Serializable,Comparable<String>,CharSequence/**Thevalueisusedforcharacterstorage 查看详情

「java」-string字符串详解(代码片段)

目录认识字符串1.创建字符串2.字符串比较相等3.字符串常量池intern()方法4.字符串不可变特性字符串常用操作1.字符串比较2.字符串查找3.字符串替换4.字符串拆分5.字符串截取6.字符串其它方法​ StringBuilder&StringBuffer类构造方法... 查看详情

java-string之寻根问底

...=/equals)说明一、Immutable特性Java设计人员为了方便大家对字符串的各种操作,抽象出String类,该类封装了对字符串的查找、拼接、替换、截取等一系列操作 查看详情

string包含在java哪个包里

...在Java哪个包里java的String类在lang包里。java.lang.String是java字符串类,包含了字符串的值和实现字符串相关操作的一些方法。常用方法包括:1、publicbooleanequals(Objectobj)判断当前字符串与obj的内容是否相同2、publicbooleanequalsIgnoreCase(St... 查看详情

java中关于string类详解(代码片段)

目录一、创建字符串二、字符串常量池三、字符串比较相等四、字符串不可变五、字符、字节与字符串5.1字符与字符串5.1.1将字符数组变为字符串5.1.2取得指定索引位置的字符charAt()5.1.3将字符串对象变成字符数组toCharArray()5.2字节... 查看详情