string()

前言类字符串的重要性不用多说,可以说是我们后端开发中用的最多的类了,有必要好好讲一下。本文的主要内容如下:String简介先说java里的八种数据类型,再说St

前言

类字符串的重要性不用多说,可以说是我们后端开发中用的最多的类了,有必要好好讲一下。

本文的主要内容如下:

string()

String简介

先说java里的八种数据类型,再说String。

八大基本数据类型

Byte: 8位,存储数据量最大为255,存储数据范围为-128~127。

简称:16位,最大数据存储容量为65536,数据范围为-32768~32767。

Int: 32位,最大数据存储容量为2的32次方减1,数据范围为-2到正2的31次方减1。

Long: 64位,最大数据存储容量为2的64次方减1,数据范围为-2到正2的63次方减1。

Float: 32位,数据范围为3.4e-45~1.4e38,直接赋值时数字后面必须加F或F。

Double: 64位,数据范围为4.9e-324~1.8e308,赋值时可以加D或不加D。

Boolean:只有true和false两个值。

CHAR: 16位,存储Unicode代码,用单引号赋值。

除了这八种数据类型(这八种数据类型也有对应的封装类型,相信你也知道),Java中还有一种特殊的类型:String,字面意思是字符串。

String官方介绍英文版

string()

地址:https://docs . Oracle . com/en/Java/Java se/11/docs/API/Java . base/Java/lang/string . html

你不明白吗?没关系。我们可以借用浏览器自带的翻译工具。更重要的是,我希望你能理解原版英语。

String存在于我们安装它的JDK目录下的rt.ar包中。完整的路径名是:java.lang.String我们java代码中的String是用来表示字符串的,比如:

String str = & # 34中国梦,我的梦& # 34;;字符串名称= & # 34;张三& # 34;;暂时知道这些还可以。

String使用定义类型

在日常开发中,使用String的地方太多了,尤其是定义变量和常量的类型。基本上只要你编码,总能看到。

例如,用户信息由实体类User表示。

公共类用户{私有长id;私有字符串用户名;私有字符串地址;私有字符串密码;...}常用方法演示了String类中有20多个方法。下面举例说明如何使用(这里演示了大部分方法,剩下的可以自己尝试)。

//案例代码,来自网络公共类string demo { public static void main(string[]args)throws exception { string str 1 = & # 34;你好世界& # 34;;String str2 = & # 34你好世界& # 34;;String str3 = & # 34你好世界& # 34;;String str4 = & # 34你好世界& # 34;;//返回字符串system . out . println(& # 34;R1:& # 34;+str 1 . length());//比较两个字符串的大小compareTo(返回的是int),0相等,复数小于,正数大于system . out . println(& # 34;R2:& # 34;+str 1 . compare to(str 2));//比较两个字符串的大小compareTo(返回的是int),0相等,复数小于,正数大于system . out . println(& # 34;R3:& # 34;+str 1 . compare to(str 3));//字符串比较compareToIgnoreCase,忽略大小写。0等于,复数小于,正数大于system . out . println(& # 34;R4:& # 34;+str 1 . comparetignorecase(str 3));//String查找indexOf,并返回找到的第一个的位置。如果没有找到,则返回-1。从0开始,system . out . println(& # 34;r5:& # 34;+str 1 . index of(& # 34;o & # 34));//找到字符串lastingdexofsystem . out . println(& # 34;R6:& # 34;+str 1 . lastindexof(& # 34;o & # 34));//删除字符串中的一个字符,substring (a,b)from 0//返回字符串system . out . println(& # 34;r7:& # 34;+ str1.substring(0,5)+str 1 . substring(6));//字符串替换,替换所有system . out . println(& # 34;r8:& # 34;+str 1 . replace(& # 34;o & # 34, "h & # 34));//字符串替换,替换所有system . out . println(& # 34;r9:& # 34;+str 1 . replace all(& # 34;o & # 34, "h & # 34));//字符串替换,替换第一个system . out . println(& # 34;r10:& # 34;+str 1 . replace first(& # 34;o & # 34, "h & # 34));//字符串反转system . out . println(& # 34;r11:& # 34;+ new StringBuffer(str1)。反向());//字符串反转system . out . println(& # 34;r11 ':& # 34;+新的StringBuilder(str1)。反向());//String split String[]temp = str 1 . split(& # 34;\ ");for(String str:temp){ system . out . println(& # 34;R12:& # 34;+str);}//字符串转换为大写的system . out . println(& # 34;r13:& # 34;+str 1 . toupper case());//字符串转换为小写system . out . println(& # 34;R14:& # 34;+str 1 . tolowercase());//删除第一个和最后一个空cases system . out . println(& # 34;r15:& # 34;+str 4 . trim());//无论是否包含,都区分大小写system . out . println(& # 34;r16:& # 34;+str 1 . contains(& # 34;世界& # 34;));//返回字符system . out . println(& # 34;r17:& # 34;+str 1 . charat(4));//测试此字符串是否以指定的后缀system . out . println(& # 34;r18:& # 34;+str 1 . ends with(& # 34;d & # 34));//测试该字符串是否以指定的前缀system . out . println(& # 34;r19:& # 34;+str 1 . starts with(& # 34;H & # 34));//测试此字符串从指定索引开始的子字符串是否以指定前缀system . out . println(& # 34;r20:& # 34;+str 1 . starts with(& # 34;ll & # 34, 2));//将指定的字符串连接到该字符串的末尾。相当于使用“+”system . out . println(& # 34;r21:& # 34;+str 1 . concat(& # 34;哈哈& # 34;));//比较字符串内容是否相同system . out . println(& # 34;R22:& # 34;+str 1 . equals(str 2));//类似于equals方法,忽略system . out . println(& # 34;r23:& # 34;+str 1 . equalsignorecase(str 2));//判断是否为空string system . out . println(& # 34;r24:& # 34;+str 1 . isempty());}}我们在开发中差不多就是这么用的,但是如果你只是用的很好,似乎还是会在面试中失败。所以学习知识不能停留在使用的层面,而是需要更深层次的学习。

让我们深入学习弦乐。希望你能以平常心学习,不要怕什么。灯笼就是一张纸,捅破了也不值钱。

String核心部分源码分析

注:JDK版本是1.8+,因为JDK9版本和老版本略有差异。

String类源码注释

/** *类{@code String}表示字符串。Java程序中的所有*字符串文字,如{ @ code & # 34abc & # 34},被*实现为这个类的实例。*这个String类代表一个字符串。java编程中的所有字符串常量。*例如:& # 34;abc & # 34是该字符串类的实例*

String类定义

public final类String实现java.io.Serializable,Comparable & lt字符串& gt,CharSequence {....}类图

string()

类字符串用final修饰,这意味着该字符串不能被继承。让我们来谈谈使用String实现三个接口:

实现Serializable,可以被序列化实现Comparable,可以用于比较大小(按顺序比较单个字符的ASCII码)实现CharSequence,表示是一个有序字符的序列,(因为String的本质是一个char类型数组)

简要介绍final

装饰:类不能继承,也就是字符串类不能继承。

装饰方法:锁定方法,防止任何继承的类修改其含义。

装饰遍历:初始化后不能更改。

重要成员

/* *该值用于字符存储。*//使用存储字符串内容的私有final char value[];//存储字符串哈希值,默认值为0private int hash//默认为0//实现序列化的ID,Private Static Final Long SerialVersionUID =-684979470754667710 l;CHAR []由final修饰,表示value[]数组是不可变的。

构造方法

/** *初始化一个新创建的{@code String}对象,以便它表示*一个空字符序列。注意,使用这个构造函数是不必要的,因为字符串是不可变的。*初始化新创建的string对象,句点代表空字符串序列。*注意:此构造方法的使用是不必要的,因为字符串是不可变的*/public string(){ this . value = & # 34;"。价值;}在无参数构造方法中,将空字符串的值赋给当前值。

/** *初始化新创建的{@code String}对象,以便它表示*与参数相同的字符序列;换句话说,*新创建的字符串是参数字符串的副本。除非*需要{@code original}的显式副本,否则使用此构造函数是*不必要的字符串是不可估量的。*初始化创建的string对象,句点表示与参数相同的字符串序列。*换句话说:新创建的字符串是参数自粗糙度的副本。*除非,如果需要original的显示副本,就没有必要使用这个构造方法*因为字符串是不可变的* @ param original * a { @ codestring } */public string(string original){ this . value = original . value;this . hash = original . hash;}//Case:String str = new String(& # 34;abc & # 34);将原始值赋给当前值,将原始哈希赋给当前哈希。

/** *分配一个新的{@code String},以便它表示当前包含在字符数组参数中的*字符序列。字符数组的*内容被复制;字符数组的实质修改不影响新创建的字符串。*分配一个新的{@code String},以便它表示当前包含在字符数组参数中的字符。This *复制字符数组的内容;字符数组的后续修改不会影响新创建的字符串。* @ param value * string的初始值*/public string(char value[]){//注意:将传递的char数组复制到值数组this.value = arrays.copyof (value,value.length)中;}//Arrays类中的copyOf方法public static char[]copy of(char[]original,int new length){//创建新的char array char[]copy = new char[new length];//将原数组的内容复制到新创建的char数组System。ArrayCopy(原始,0,副本,0,math.min(原始。长度,新长度));//返回新创建的char数组返回副本;}使用Arrays类的copyOf方法创建一个新的char数组,并将原始内容放入新创建的char数组中。

然后,将新创建的char数组分配给当前的vlaue。

public String(String buffer buffer){ synchronized(buffer){ this . value = arrays . copy of(buffer . getvalue()、buffer . length());}}因为StringBuffer是一个线程安全的类,所以这里添加了一个同步锁来保证线程安全。

public String(StringBuilder builder){ this . value = arrays . copy of(builder . getvalue()、builder . length());}StringBuilder是非线程安全的,所以这里没有线程安全的处理。其他内容同前。

注意:大多数时候,我们不会这样构造,因为StringBuilder和StringBuffer都有toString方法。如果不考虑线程安全,首选StringBuilder。

这里施工方法那么多,其他的都很复杂,基本没必要,知道这些就够了。如果对其他东西感兴趣,可以自己研究。

常用方法分析

在之前的用例中,我们已经演示了String的大部分方法。在这里,我们将选择几个相对重要的方法进行深入分析。

hashCode方法

hashCode()方法是在Object类中定义的,它被String覆盖。

public int hashCode(){ int h = hash;if(h = = 0 & & value . length & gt;0){ char val[]= value;//哈希算法,s [0] * 31 (n-1)+s [1] * 31 (n-2)+...+s[n-1]//使用{@codeint}算法,其中{@codes[i]}是< i & gt我& lt/I & gt;字符串的第一个字符,//{@code n}是一个字符串,{@ code}代表指数运算。for(int I = 0;我& lt值.长度;i++){ h = 31 * h+val[I];} hash = h;}返回h;}一个{ hashCode }的具体实现,因为java系统中的每个对象都可以转换成一个字符串,所以都应该通过这个hash来实现。

接下来,我们来看看equals()方法;

equals()方法

equals()方法也在Object类中定义,它被String类覆盖。

public boolean equals(object an object){//首先是不是同一个对象if(this = = an object){ return true;}//判断是否为字符串类型if(String的一个对象实例){string anotherstring = (string)一个对象;int n = value.length//长度是否相同if(n = = another string . value . length){ char v1[]= value;char v2[]= another string . value;int I = 0;//逐个遍历,判断是否相等。//通过单个字符从后向前判断。如果不相等,则返回false while (n -!= 0) {//不相等,直接返回false if (v1[i]!= v2[i])返回falsei++;}返回true} }返回false}补充:= =对比

= =比较基本数据类型,比较值= =比较引用数据类型,比较地址值子串()方法。substring方法在工作中也被广泛使用,它的作用是截取一个字符串。

公共字符串substring(int begin index){ if(begin index & lt;0){ throw new StringIndexOutOfBoundsException(begin index);} int subLen = value . length-begin index;if(sub len & lt;0){ throw new StringIndexOutOfBoundsException(subLen);}//如果beginIndex==0,则返回当前对象。//否则,这是一个new的新对象。其实String中很多函数都是这样操作的。return (beginIndex == 0)?this : new String(value,beginIndex,sub len);}intern()方法intern()方法是一个本机修饰的方法,表示它是一个局部方法。

/* *调用intern方法时,如果池中已经包含一个* string,该字符串等于由{@link #equals(Object)}方法确定的此{@code String}对象,则返回池中的字符串。否则,这个{@code String}对象被添加到* pool中,并返回对这个{@code String}对象的引用。*/public native String intern();方法注释会被写入,这意味着当方法被调用时,如果常量池有当前的字符串值,它将返回这个值,如果没有,它将被添加并返回这个值的引用。

案例如下

public class String demo { public static void main(String[]args)抛出异常{ String str1 = & # 34一& # 34;;String str2 = & # 34b & # 34;String str3 = & # 34ab & # 34;string str 4 = str 1+str 2;String str5 =新字符串(& # 34;ab & # 34);system . out . println(str 5 = = str 3);//堆内存比较字符串pool //intern如果常量pool有当前字符串的值,则返回该值,如果没有,则添加进去,并返回该值的引用system . out . println(str 5 . intern()= = str 3);//引用同一个字符串池中的system . out . println(str 5 . intern()= = str 4);//变量加一个新值,所以str4引用一个新的system . out . println(str 4 = = str 3);//变量加上新的值,所以str4引用新的}}运行结果。

方法获取字符串的长度,实际上是字符数组的长度。源代码很简单,没什么好说的。

public int length() {返回值.长度;}isEmpty()方法确定字符串是否为空,实际上就是确定字符数组的长度是否为0。源代码也很简单,没什么好说的。

public boolean isEmpty(){ return value . length = = 0;}charAt(int index)方法根据索引参数获取字符。

Public char charAt(int index) {//如果索引小于0或者索引大于字符数组的长度,则出现越界异常,如果((index < 0)| |(index & gt;= value . length)){ throw new StringIndexOutOfBoundsException(index);}//返回字符数组指定位置的字符返回值[index];}getBytes()方法获取字符串的字节数组,根据系统默认的字符编码将字符串解码成字节数组。

public byte[]getBytes(){ return string coding . encode(value,0,value . length);}compareTo()方法这个方法写得很巧妙。首先,从0开始判断字符大小。如果两个对象比较后可以比较字符的地方仍然相等,那么就直接返回自己的长度减去要比较的对象的长度。如果两个字符串的长度相等,则返回0,巧妙地确定了三种情况。

public compare to(string another string){//自身对象字符串len1 int len1 = value.length的长度;//被比较对象的字符串长度len 2 itlen 2 = another string . value . length;//取两个字符串长度的最小值lim int lim = Math.min(len1,le N2);char v1[] =值;char v2[]= another string . value;int k = 0;//从value的第一个字符到最小长度lim,如果字符不相等,//返回自身(对象不相等的地方的字符-对象比较的地方的字符不相等)while(k < lim){ char C1 = v1[k];char C2 = v2[k];如果(c1!= c2) {返回C1-C2;} k++;}//如果前面都相等,return(自身长度-比较对象的长度)返回len 1-len 2;}startsWith()方法public boolean starts with(string prefix,int toffset){ charta[]= value;int to = toffsetchar pa[]= prefix . value;int po = 0;int PC = prefix . value . length;//注意:toffset可能接近-1 & gt;& gt& gt1.//如果起始地址小于0或者(起始地址+被比较对象的长度)大于自身对象的长度,则返回false If((t offset := 0){ if(ta[to++]!= pa[po++]) {返回false} }返回true} public boolean startsWith(字符串前缀){ return startsWith(前缀,0);} public boolean endsWith(字符串后缀){ return startsWith(后缀,value . length-suffix . value . length);}期初比较法和期末比较法是常用的方法。例如,这个方法可以用来比较一个字符串是否是http,或者一个文件是否是mp3。

concat()方法

public String concat(String str){ int other len = str . length();//如果添加的字符串是空,则返回对象本身If(other len = = 0){ return this;} int len = value.lengthchar buf[] = Arrays.copyOf(value,len+other len);str.getChars(buf,len);返回新字符串(buf,true);}concat方法也是常用方法之一。它首先确定添加的字符串是否是空来决定是否创建一个新的对象。

replace()方法

public string replace(char old char,char new char){//用if (oldChar!= new char){ int len = value . length;int I =-1;char[]val = value;//查找旧值第一次出现的位置while(++I < len){ if(val[I]= = old char){ break;} }//从那个位置一直到末尾,替换旧值if(I < len){ char buf[]= new char[len];for(int j = 0;j & lt我;j++){ buf[j]= val[j];} while(I & lt;len){ char c = val[I];buf[i] = (c == oldChar)?new char:c;i++;}返回新字符串(buf,true);} }还这个;}这种方法也有一些窍门,比如先找出旧值出现的地方,这样可以节省一些比较时间。replace (string oldstr,string new str)方法由正则表达式判断。

trim()方法

public String trim(){ int len = value . length;int ST = 0;char[]val = value;/* avoidgetfieldopcode *//查找字符串前面没有空的位置while((ST < len)& &(val[ST]& lt;= '')){ st++;}//在while((ST :0)| |(len & lt;value.length)?substring(st,len):this;}trim方法是从字符串中删除空白字符串。

valueOf()方法

(布尔b)的公共静态字符串值{//如果b为真,则返回& # 34;真& # 34;否则,返回& # 34;假& # 34;返回b?"真& # 34;: "假& # 34;;} public static string value of(char c){//创建一个data[]数组,将c加入char data[]= { c };//创建一个新的String对象,返回新的String(data,true);} public static string value of(int I){//调用Integer对象的toString()方法,返回return Integer . toString(I);}//整数类中的toString(i)方法公共静态字符串toString(int I){//是否为最小整数,直接返回if(I = = Integer . min _ value)return & # 34;-2147483648";//这个I int size = (I < 0)多少位?string size(-I)+1:string size(I);//创建一个char数组char[]buf = new char[size];//将getChars(i,size,buf)放入I content方法的char数组中;//返回一个String对象返回新的String(buf,true);}split()方法public string[]split(strings regex){ return split(regex,0);}//正则表达式公共字符串[] split (string regex,int limit) {//...//源代码有点多。反正里面用的是正则表达式,用split }split()方法把一个字符串拆分成一个字符串数组,返回一个字符串数组。返回数组中的字符串不包括regex本身。可选的“limit”是一个整数,第一个方法中的默认值是0,它允许您指定要返回的最大数组的元素数。

常用方法源代码分析到此为止。让我们回顾一下使用场景,尤其是在面试中。

String在面试中常见问题如何比较字符串相同?

在java中通常有两种方法来比较对象是否相同:

==equals方法

Note = =基本数据类型的比较和引用类型的比较之间的差异。

= =比较基本数据类型,比较值。

= =比较引用数据类型,比较地址值。

另外,String重写了equals方法,所以我们还是要用equals方法来比较字符串。主要是String的equals方法包含了= =(请看前面的源代码分析部分)的判断。

情况

public class String demo { public static void main(String[]args){ String st1 = & # 34;abc & # 34;字符串st2 = & # 34abc & # 34;system . out . println(st1 = = st2);system . out . println(st1 . equals(st2));}}输出

truetrueString str =新字符串(& # 34;abc & # 34);这行代码中创建了多少个对象?请看下面的代码:

String str1 = & # 34abc & # 34;//string str 2 =常量池中的新字符串(& # 34;abc & # 34);//在堆上,关于这段代码,创建了几个对象。网上的回答有很多种,一种,两种,三种。来说说有多少吧。

首先,我们需要明确一点;不管是str1还是str2,都是字符串类型的变量,不是对象。通常,也许我们会称它们为str2对象,这只是为了便于理解。本质上,str2和str1不是对象。

其次,字符串str = & # 34abc & # 34;,字符串“abc”将存储在字符串常量池中,只有一个副本。此时,赋值操作相当于创建0或1个对象。如果常量池中已经存在“abc”,则不再创建对象,引用直接赋给str1;如果常量池中没有“abc ”,那么创建一个对象并将引用分配给str1。

然后,通过新字符串(& # 34;abc & # 34);的形式是什么?

答案是一两个。

当JVM遇到上述代码时,它会首先检索常量池中是否存在“abc”。如果字符串“abc”不存在,它将首先在常量池中创建这个字符串。然后,新操作将创建一个在堆内存中存储“abc”的String对象,该对象的引用将被赋给str2。这个过程创建了两个对象。

当然,如果在搜索常量池时对应的字符串已经存在,那么在堆中只会创建一个新的String对象,在这个过程中只会创建一个对象。

最后,如果你问String str = new String(& # 34;abc & # 34);已经创建了几个对象。记住:不管有没有恒池& # 34;abc & # 34,存在,创建一个对象;没有创建两个对象。

String 和 StringBuilder、StringBuffer 的区别

线程安全性

String中的对象是不可变的,所以可以理解为常量,这是线程安全的。AbstractStringBuilder是StringBuilder和StringBuffer的公共父类,定义了字符串的一些基本操作,如expandCapacity、append、insert、indexOf等公共方法。StringBuffer是线程安全的,因为它向方法或被调用的方法添加了同步锁。StringBuilder不同步锁定该方法,因此它是非线程安全的。

表演

每次更改字符串类型时,都会生成一个新的字符串对象,然后指针指向新的字符串对象。StringBuffer总是对StringBuffer对象本身进行操作,而不是生成一个新对象并更改对象引用。同等情况下,使用StringBuilder相比使用StringBuffer只能获得10%~15%左右的性能提升,但会冒不安全多线程的风险。

三者的使用摘要:

操作少量的数据 ,推荐使用String单线程操作字符串缓冲区下操作大量数据,推荐使用 StringBuilder多线程操作字符串缓冲区下操作大量数据 ,推荐使用 StringBufferString 和 JVM有什么关系?

创建字符串有两种常见的方法:new String()方法和直接赋值方法。在直接赋值方法中,首先要去字符串常量池看看这个值是否已经存在。如果有,你就直接把引用地址指向这个值;否则,您将首先在常量池中创建它,然后将引用指向这个值。new string()方法必须首先在堆上创建一个String对象,然后检查这个String的值是否已经存在于常量池中。如果不存在,它会先在常量池中创建这个字符串,然后将引用的值指向这个字符串。

JVM中的常量池

string()

Literal quantity-text string,也就是我们例子中的public string s = & # 34;abc & # 34;& # 34;abc & # 34。

用final修饰的成员变量包括静态变量、实例变量和局部变量。

请看下面的代码:

字符串s1 =新字符串(& # 34;Java & # 34);string S2 = S1 . intern();字符串s3 = & # 34Java & # 34;system . out . println(S1 = = S2);//false system . out . println(S2 = = S3);// true,它们存储在JVM中,如下图所示:

string()

注意:在JDK 1.7之后,字符串常量池被从method区域移到了meta 空中的Java堆中,在那里永生被替换。

此外,编译器会优化字符串String,如下面的代码:

字符串s1 = & # 34Ja & # 34+ "va & # 34;字符串s2 = & # 34Java & # 34;system . out . println(S1 = = S2);虽然s1拼接了多个字符串,但比较结果为真。我们使用反编译工具,看到了以下结果:

编译自& # 34;StringExample.java & # 34public class com . lagou . interview . string example { public com . lagou . interview . string example();代码:0: aload_0 1: invokespecial #1 //方法java/lang/Object。"& ltinit & gt":()V 4:return line number table:line 3:0 public static void main(Java . lang . string[]);code:0:LDC # 2//String Java 2:astore _ 1 3:LDC # 2//String Java 5:astore _ 2 6:get static # 3//Field Java/lang/system . out:Ljava/io/PrintStream;9:aload _ 1 10:aload _ 2 11:if _ acmpne 18 14:iconst _ 1 15:goto 19 18:iconst _ 0 19:invokevirtual # 4//方法Java/io/printstream . println:(Z)v 22:返回行号表:line5: 0 line6: 3 line7: 6 line8: 22}从编译后的代码#2中可以看出,代码& # 34;Ja & # 34+"va & # 34是直接编译成& # 34;Java & # 34所以s1==s2的结果为真,这是编译器进行字符串优化的结果。

如何判断两个字符串中含有几个相同字符将字符串转化成数组HashMap 方法字符串直接进行比较正则表达式HashSet 方法String有没有长度限制?是多少?为什么?

让我们来看看长度方法源代码:

私有最终字符值[];public int length() {返回值.长度;}length()方法返回的是int类型,所以可以知道String类型的长度一定不能超过整数。MAX_VALUE。

答:首先字符串的内容是由一个字符数组char[]存储的。因为数组的长度和索引都是整数,而string类中方法length()的返回值也是int,所以通过查看java源代码中的类integer,我们可以看到Integer的最大取值范围是2 ^ 31-1。由于数组从0开始,* *数组的最大长度可以是[0 ~ 2]

但是通过翻阅java虚拟机手册中对类文件格式的定义和常量池中对字符串结构的定义可以知道,u2是为index定义的,也就是无符号的2字节,2字节所能代表的最大范围是2 ^ 16-1 = 65535。

但是,由于JVM需要1个字节来表示结束指令,所以这个范围是65534。超过这个范围,编译时会报告错误,但是如果在运行时拼接或赋值,这个范围就是整形的最大范围。

字符串对象能否用在switch表达式中?

从JDK7开始,我们可以在switch条件表达式中使用字符串,这意味着7之前的版本是不允许的。

switch(str . tolowercase()){ case & # 34;田& # 34;:值= 1;打破;案例& # 34;江& # 34;:值= 2;打破;}说说JDK7之前String中intern方法的版本。调用这个方法的时候,我们会去常量池看看这个常量是否已经存在。如果是,我们将直接返回这个常量在常量池中的地址值。如果它不存在,我们将在常量池中创建一个并返回它的地址值。

但是,在JDK7和更高版本中,常量池被从perm区域移到了heap区域。当n检测到常量池中不存在这个常量时,不会直接在常量池中创建对象,而是直接将堆中这个对象的引用存储到常量池中,以减少内存开销。

以下案例

public class intern test { public static void main(String[]args){ String str 1 = new String(& # 34;你好& # 34;)+新字符串(& # 34;世界& # 34;);str 1 . intern();String str2 = & # 34helloworld & # 34;system . out . println(str 1 = = str 2);//true system . out . println(str 1 . intern()= = str 2);//true }}好了,关于Stirng类的分享就到此为止。欢迎来我这里讨论更多的技术问题。原文链接:https://mp.weixin.qq.com/s/rtOO5e0A17EW1CGquLSrQA

作者:Java后端技术全栈

如果你觉得这篇文章对你有帮助,可以转发关注支持。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。

作者:美站资讯,如若转载,请注明出处:https://www.meizw.com/n/44691.html

发表回复

登录后才能评论