Java之String相关内容详解(字符串和字符串常量池)【面试题】

  • (5)将字符串转为基本类型parseXxx

  • 4、字符串编码

  • 5、`String s = “Hello”;s = s + " world!"`;这两行代码执行后,原始的 String 对象中的内容变了没有?

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,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©; //但是不能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©; //打印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));//equals对比的是两个字符串的内容是否相等

System.out.println(c.equals(d));

System.out.println(c.equalsIgnoreCase(d));//在忽略大小写的情况下对比其字符串的内容

}

}

在这里插入图片描述

(5)将字符串转为基本类型parseXxx

例如转换为double

public class StringTest02 {

public static void main(String[] args) {

String a = “123”;

double a_double = Double.parseDouble(a);//将字符串类型的数据转换为double 类型

System.out.println(“a_double:”+a_double);

}

}

在这里插入图片描述

Double.parseDouble()方法对应的源代码

public static double parseDouble(String s) throws NumberFormatException {

return FloatingDecimal.parseDouble(s);

}

此方法抛出NumberFormatException 数字转换异常,可以看出要想转换为double你的字符串必须要哦符合相应数据类型的格式。

但是有一个例外就是parseBoolean除非是字符串"true"或者"TRUE"(大小写不固定)

等返回true其余的情况都返回false。

也就是说可以不符合格式(这种情况例外)

对应案例代码

package cn.itbluebox;

public class StringTest02 {

public static void main(String[] args) {

String byteStr1 = “127”;

String byteStr2 = “128”;

System.out.println(Byte.parseByte(byteStr1));

try {

System.out.println(Byte.parseByte(byteStr2));

}catch (Exception e){

System.out.println(e);

}

String shortStr = “32767”;

String shortStr2 = “32768”;

System.out.println(Short.parseShort(shortStr));

try {

System.out.println(Short.parseShort(shortStr2));

}catch (Exception e){

System.out.println(e);

}

String intStr1 = “2147483647”;

String intStr2 = “2147483648”;

System.out.println(Integer.parseInt(intStr1));

try {

System.out.println(Integer.parseInt(intStr2));

}catch (Exception e){

System.out.println(e);

}

String floStr1 = “12”;

String floStr2 = “12f”;

String floStr3 = “12.1”;

String floStr4 = “12.121222”;

String floStr5 = “12.12122122121212122”;

System.out.println(Float.parseFloat(floStr1));

System.out.println(Float.parseFloat(floStr2));

System.out.println(Float.parseFloat(floStr3));

System.out.println(Float.parseFloat(floStr4));

System.out.println(Float.parseFloat(floStr5));

String douStr1 = “11”;

String douStr2 = “11d”;

String douStr3 = “11.0”;

System.out.println(Double.parseDouble(douStr1));

System.out.println(Double.parseDouble(douStr2));

System.out.println(Double.parseDouble(douStr3));

String longStr1 = “9223372036854775807”;

String longStr2 = “9223372036854775808”;

System.out.println(Long.parseLong(longStr1));

try {

System.out.println(Long.parseLong(longStr2));

}catch (Exception e){

System.out.println(e);

}

String booleanStr1 = “true”;

String booleanStr2 = “TRUE”;

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

最后

现在其实从大厂招聘需求可见,在招聘要求上有高并发经验优先,包括很多朋友之前都是做传统行业或者外包项目,一直在小公司,技术搞的比较简单,没有怎么搞过分布式系统,但是现在互联网公司一般都是做分布式系统。

所以说,如果你想进大厂,想脱离传统行业,这些技术知识都是你必备的,下面自己手打了一份Java并发体系思维导图,希望对你有所帮助。

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img

效又漫长,而且极易碰到天花板技术停滞不前!**

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-4WuCkR6N-1712942254627)]
[外链图片转存中…(img-9it0RCB7-1712942254628)]
[外链图片转存中…(img-45yUzMBH-1712942254628)]
[外链图片转存中…(img-HPGEJTFZ-1712942254628)]
[外链图片转存中…(img-43Cv6mrJ-1712942254629)]
[外链图片转存中…(img-a96nLJMM-1712942254629)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-JRXxxuYC-1712942254629)]

最后

现在其实从大厂招聘需求可见,在招聘要求上有高并发经验优先,包括很多朋友之前都是做传统行业或者外包项目,一直在小公司,技术搞的比较简单,没有怎么搞过分布式系统,但是现在互联网公司一般都是做分布式系统。

所以说,如果你想进大厂,想脱离传统行业,这些技术知识都是你必备的,下面自己手打了一份Java并发体系思维导图,希望对你有所帮助。

[外链图片转存中…(img-BhYWSNQ8-1712942254630)]

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-H2I14uiD-1712942254630)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值