标签:new 特殊 方式 tac 不同的 span rgs build 关键字
1、字符串操作可以说是我们在java中使用最频繁的操作之一,String不是基本类型,而是一个引用类型,查看jdk源码可以知道String这个类是被final修饰的,这就意味着String是不能被继承的,类中的方法默认是final方法。这或许是对字符串String的一种保护。字符串使用非常简单,如下:
1 public class Demo { 2 public static void main(String[] args) { 3 String str0 = null; 4 String str1 = "test"; 5 String str2 = new String("test"); 6 System.out.println(str1.substring(1)); 7 System.out.println(str2.concat("hi")); 8 } 9 10 }
2、字符串的特殊之处
1 public class Demo { 2 public static void main(String[] args) { 3 String str0 = "demo"; 4 String str1 = new String("demo"); 5 String str2 = "demo"; 6 String str3 = new String("demo"); 7 8 System.out.println(str0==str1); 9 System.out.println(str0==str2); 10 System.out.println(str1==str3); 11 } 12 13 }
输出结果:
false true false
为什么有上面结果的差异呢?String str1 = "test"和String str2 = new String("test")的区别在哪里呢?在字符串中存在一个非常特殊的地方,一般推荐使用String str1 = "test"的形式。
String str0 = "demo";和String str2 = "demo";在编译期间生成字面常量和符号引用,运行期间字面常量"hello world"被存储在运行时常量池,当我们通过这个方式创建一个字符串的时候,首先会检查常量池中检查字面常量"demo"是否已经存在,如果存在,则直接将str0指向已经存在的字面常量,否则在运行时常量池开辟一个空间来存储该字面常量,并将引用指向该字面常量。而通过new的方式创建字符串对象,则是在堆区进行,通过new关键字每次都是新创建一个对象。因此通过new来创建对象,创建出的一定是不同的对象,即使字符串的内容是相同的。
3、字符串的连接操作
字符串的拼接的方式主要是有如下几种:+,+=,String的concat方法,以及借助StringBuild类的append方法。+,+=是java中仅有的两个被重载了的操作符,java中不允许程序员自己重载操作符。
1 public class Demo { 2 public static void main(String[] args) { 3 String str0 = "demo"; 4 str0+="--next"; 5 System.out.println(str0); 6 String str1 = "--next"; 7 String str3 = str0+str1; 8 System.out.println(str3); 9 10 String str4 = str3.concat("--next"); 11 System.out.println(str3); 12 System.out.println(str4); 13 14 StringBuilder sb = new StringBuilder(); 15 String str5 = sb.append(str4).append("--last").toString(); 16 System.out.println(str5); 17 } 18 19 }
输出结果:
demo--next demo--next--next demo--next--next demo--next--next--next demo--next--next--next--last
字符串可以通过上面三种方式拼接,那么他们之间除了用法的区别外,还有上面其他的不同之处?处理字符串的速度不同。通过一个测试类就能知道
1 public class StringTest { 2 public static void main(String[] args) { 3 //1、+连接符 4 long start1 = System.currentTimeMillis(); 5 String str1 = "hi"; 6 for(int i=0;i<10000;i++){ 7 str1+="hi"; 8 } 9 long end1 = System.currentTimeMillis(); 10 System.out.println("+ 消耗时间:"+(end1-start1)+"毫秒"); 11 12 //2、contact() 13 long start2 = System.currentTimeMillis(); 14 String str2 = "hi"; 15 for(int i=0;i<10000;i++){ 16 str2=str2.concat("hi"); 17 } 18 long end2 = System.currentTimeMillis(); 19 System.out.println("+ 消耗时间:"+(end2-start2)+"毫秒"); 20 21 //2、contact() 22 long start3 = System.currentTimeMillis(); 23 String str3 = "hi"; 24 StringBuilder sb = new StringBuilder(str3); 25 for(int i=0;i<10000;i++){ 26 sb.append("hi"); 27 } 28 str3 = sb.toString(); 29 long end3 = System.currentTimeMillis(); 30 System.out.println("+ 消耗时间:"+(end3-start3)+"毫秒"); 31 } 32 33 }
输出结果:
+ 消耗时间:95毫秒
concat 消耗时间:35毫秒
append 消耗时间:1毫秒
出现上述结果的原因:
1)字符串的直接相加,效率非常高,例如:String str="hell"+"o",在编译期间优化成String str="hello",而String str="hell",str=str+"o"等同于str = new StringBuilder(str).append("b").toString();
2)concat方法是借助字符数组拷贝的形式操作字符串,数组的处理速度非常之快
3)append方法同样是借助字符数组进行字符串处理的,加长,然后拷贝。而上述结果差异是因为concat涉及的对象个数远大于append,对象的创建需要时间。
StringBuffer和String一样都是用来存储字符串的,是一个可变的字符串对象,在内存使用方面优于String,通过它操作字符串的时候,不会产生新的字符串对象,使用比较简单。
1 public class Demo { 2 public static void main(String[] args) { 3 StringBuffer sb = new StringBuffer("hello"); 4 sb.append("sss"); 5 System.out.println(sb); 6 sb.insert(2, ‘A‘); 7 System.out.println(sb); 8 sb.delete(0, 2); 9 System.out.println(sb); 10 } 11 12 }
输出结果:
hellosss
heAllosss
Allosss
StringBuilder也是一个可变的字符串对象,他与StringBuffer不同之处就在于它是线程不安全的,基于这点,它的速度一般都比StringBuffer快。与StringBuffer一样,StringBuider的主要操作也是append与insert方法。这两个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符添加或插入到字符串生成器中。与String和StringBuilder的使用场景不同。
标签:new 特殊 方式 tac 不同的 span rgs build 关键字
原文地址:https://www.cnblogs.com/liupiao/p/9256381.html