java的String类


创建String对象的方法

java中的String是一个引用类型,它被用来创建一个字符串。

我们最常使用的创建一个字符串的方法即类似这样:

String s = "java";

但其实也可以这样:

String s = new String("java");

这说明String也是一个类,事实上,String是一个特殊的包装类,在String的早期api官方描述文档中,String被这样定义:

public final class String implements ...
{
    private final char[];
    ......
}

可以看到,String类是一个final类,它无法被继承,String类的所有方法也都默认为final方法。
另外可以看到,在String类的内部定义了一个char数组,它被用来存储String数据,即我们在new一个String时,其实是这样的:

String s = new String(new char[]{});

而较新的JDK版本的String则以byte[]存储:如果String仅包含ASCII字符,则每个byte存储一个字符,否则,每两个byte存储一个字符。这种优化主要是为了节省内存。但我们不必关心String的内部优化,它是不会影响任何已有代码的。


字符串常量池

字符串的分配和其它对象分配一样是很耗时间和空间的,况且字符串又是如此的常用,JVM为了提高性能和减少内存的开销,为String维护了一个字符串常量池,每当有字符串将被创建时,JVM会首先检查字符串常量池中是否有该字符串对象,如果有直接返回常量池中的实例引用,如果字符串不在常量池中,就实例化该字符串并将它放进常量池中。

另外,字符串还有一个非常显著的特性,即不可变性,任何字符串对象的操作方法都会返回一个新的字符串对象,而不会对原字符串进行操作,这点需要牢记。

因此可以确定,字符串常量池中不存在两个一样的字符串

接下来看一些例子:

public static void main(String[] args)
{
    String s1 = "hello";
    String s2 = "hello";
    System.out.println(s1 == s2); //true s1与s2均指向字符串常量池中的hello对象
}
public static void main(String[] args)
{
    String s1 = new String("java");
    String s2 = new String("java");
    System.out.println(s1 == s2); //false s1与s2指向不同的堆中的String对象
}
public static void main(String[] args)
{
    String s1 = "java";
    String s2 = "ja" + "va";
    System.out.println(s1 == s2); //true s1与s2都能在编译期被确定,都指向字符串常量池中的“java”对象
}
public static void main(String[] args)
{
    String s1 = "java";
    String s2 = "ja" + new String("va");
    System.out.println(s1 == s2); //false s2在编译器无法确定,不是常量,需要在堆中存储
}
public static void main(String[] args)
{
    String s1 = "java";
    String s2 = "ja" + new String("va");
    System.out.println(s1 == s2);
}
public static void main(String[] args)
{
    String s1 = "java";
    String s2 = "ja";
    String s3 = "va";
    String s4 = s2 + s3;
    System.out.println(s1 == s4);//false s4在编译器无法确定,因为s4是两个引用变量相加,而不是确切的字符串常量相加
    //s4 = s2 + s3会在堆中创建一个“ja”对象和一个“va”对象,并再在堆中创建一个"java"对象
    //”java“对象引用自字符串池中的”java“对象,并使s4指向堆中该对象
}

.

public static void main(String[] args)
{
    String s1 = "java" + 8;
    String s2 = "java8";
    System.out.println(s1 == s2); //true "java"+8在编译器就会被优化为"java8"
}

例子怎么都说不完,给出以上这些例子好好体会差不多就够了。


String对象的一些常用方法

public static void main(String[] args){
    	String s = "hello,java!";
    	String[] ss = {"j","a","v","a"};
    	System.out.println(s.substring(4)); //拆分字符串,获得索引4之后的全部数据
    	System.out.println(s.substring(2,8)); //拆分字符串,获得索引2到8之间的数据
    	System.out.println(s.trim()); //去除首尾空白字符,包括空格、\t、\r、\n。
    	System.out.println(s.strip()); //去除首尾空白字符,包括空格、\t、\r、\n及\u3000。
    	System.out.println(s.isEmpty()); //判断字符串是否为空
    	System.out.println(s.isBlank()); //判断字符串是否是空白字符串
    	System.out.println(s.replace("ll", "gg")); //替换子串
    	System.out.println(s.split("\\,")); //分割字符串
    	System.out.println(String.join("**",ss)); //连接字符串
    	int a = 100;
    	boolean f = true;
    	System.out.println(String.valueOf(a)); //把其它类型强制转换为String
    	System.out.println(String.valueOf(f));
    	System.out.println(Integer.parseInt("123456")); //把String转换为Integer
    	System.out.println(Integer.parseInt("ff",16));
    	System.out.println(Boolean.parseBoolean("true")); //把String转换为Boolean
    	System.out.println("hello".toCharArray());  //把字符串转换为字符数组	
    } 

output:

o,java!
llo,ja
hello,java!
hello,java!
false
false
heggo,java!
[Ljava.lang.String;@5b6f7412
j**a**v**a
100
true
123456
255
true
hello

另外,还用一个较为特殊的方法,即String.intern(),它可被用来动态扩充字符串常量池。调用该方法,如果字符串常量池中存在该String对象则返回它的引用,如果不存在,则创建了之后再返回它的引用。

字符编码

ASCII编码:适用于英文字母、数字和常用符号的编码,一个字符一个字节。

GB2313编码:汉字编码,两个字符表示一个汉字。

Unicode编码:全球统一编码。需要两个或更多字节来表示一个字符。英文字符被表示为高位00字节加低位ASCII字节,即两个字节。

UTF-8编码:Unicode编码对英文较多的文本不友好,因为它会浪费很多空间。UTF-8是一种变长编码,长度不固定,为1~4个字节,节省空间,容错能力强。常被用于作为传输编码。

java内部编码:java内部的char类型与String类型都采用了Unicode编码,如果要把它们转换为其它编码,方法如下:

byte[] b1 = "Hello".getBytes(); // 按ISO8859-1编码转换,不推荐
byte[] b2 = "Hello".getBytes("UTF-8"); // 按UTF-8编码转换
byte[] b2 = "Hello".getBytes("GBK"); // 按GBK编码转换
byte[] b3 = "Hello".getBytes(StandardCharsets.UTF_8); // 按UTF-8编码转换

如果要把byte[]转换回来,采用如下方法:

String s1 = new String(b, "GBK"); // 按GBK转换
String s2 = new String(b, StandardCharsets.UTF_8); // 按UTF-8转换

理解String的+操作

String可以直接用+进行拼接,这个过程具体是如何实现的呢?

如果让s1与s2直接用+拼接,从最左边的s1开始,java内部会创建一个StringBuilder对象,然后依次对右边进行append操作,最后通过StringBuilder的toString()返回拼接完成后的字符串。

对于多个字符串连加,每加一个就会创建一次StringBuilder对象,这会大幅度拖慢程序的允许效率,因此对于需要连加很多次的时候,合适的做法是先创建一个StringBuilder对象,连接完了之后手动调用toString()方法得到我们的结果。

StringBuffer是与StringBuilder功能相同的线程安全版本。


StringJoiner

如果需要用连接符连接字符串,可以这么做:

 public static void main(String[] args)
 {
     String[] ssr = {"java","Python","C++"};
     var sb = new StringBuilder();
     sb.append("<");
     for(String s:ssr)
         sb.append(s).append(",");
     System.out.println(sb.toString().replace("+,","+>")); //<java,Python,C++>
 }

也可以使用StringJoiner,使用StringJoiner的一个好处就是可以指定开头和结尾,如下:

 public static void main(String[] args)
 {
     String ssr = {"java","Python","C++"};
     var sj = new StringJoiner(",","<",">");
     for(String s:ssr)
         sj.add(s);
     System.out.println(sj.toString()); //<java,Python,C++>
 }

参考链接:
https://www.liaoxuefeng.com/wiki/1252599548343744/1260469698963456
https://www.cnblogs.com/zyy1688/p/9269493.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值