新闻类网站备案,自己设计小程序,番禺区建站服务商,wordpress成品图String 在Java中String是作为引用对象存在的一种数据类型#xff0c;用来保存字符串。 实例化和赋值 //直接声明
String s1 Hello world!;
//通过构造函数创建, 提供了 11 种不同参数创建的方法
char[] c { h, e, l, l, o, .};
String s2 new String(c); Strin…String 在Java中String是作为引用对象存在的一种数据类型用来保存字符串。 实例化和赋值 //直接声明
String s1 Hello world!;
//通过构造函数创建, 提供了 11 种不同参数创建的方法
char[] c { h, e, l, l, o, .};
String s2 new String(c); String类是不可改变的所以你一旦创建了String对象那它的值就无法改变了。如果需要对字符串做很多修改那么应该选择使用StringBuffer或StringBuilder类。 我们来看下面的另一种创建方法 使用这种方式来创建字符串在堆内存中会创建两个字符串对象因为当使用符号是就表示创建了一个新的字符串而str只指向了第二个对象导致第一个对象没有引用处于等待回收的状态除了加大内存使用外还增加了GC的负担所以直接使用来创建字符串是更好的方式。 连接字符串 String类提供了连接两个字符串的方法 string1.concat(string2); 返回string2连接string1的新字符串。也可以对字符串常量使用concat()方法如 My name is .concat(Zara); 更常用的是使用操作符来连接字符串如 Hello, world ! 结果如下: Hello, world! 下面是一个例子: 1 public class StringDemo {
2 public static void main(String args[]) {
3 String string1 saw I was ;
4 System.out.println(Dot string1 Tod);
5 }
6 } 以上实例编译运行结果如下 Dot saw I was Tod 比较字符串 判断字符串内容是否相等Java和大部分语言不一样Java中是比较两个字符串引用的地址是否相同即是否指向同一个对象而equals方法则比较字符串的内容是否相同。 String a abc;
String b new String(abc); a b返回falsea.equals(b)返回true。这时创建b时不管abc是否存在都会new一个新的abc从而a和b指向的字符创对象是不同的因此返回false。 我们来看下面的情况容易混淆 String a abc;
String b abc; a b返回truea.equals(b)同样返回true这是为什么呢 原来程序在运行时有一个字符串池创建字符串时会先查找池中是否有相应的字符串如果已经存在的话只需把引用指向它即可如果没有则新建一个。 上例中创建a时会在字符串池中首先创建一个abc然后a指向它创建b时由于abc已经存在b直接指向它即可。 格式化字符串 String类的format()方法用于创建格式化的字符串以及连接多个字符串对象 format()方法有两种重载形式 format(String format, Object... args) 新字符串使用本地语言环境制定字符串格式和参数生成格式化的新字符串。format(Locale locale, String format, Object... args) 使用指定的语言环境制定字符串格式和参数生成格式化的字符串。显示不同转换符实现不同数据类型到字符串的转换如图所示 转 换 符 说 明 示 例 %s 字符串类型 mingrisoft %c 字符类型 m %b 布尔类型 true %d 整数类型十进制 99 %x 整数类型十六进制 FF %o 整数类型八进制 77 %f 浮点类型 99.99 %a 十六进制浮点类型 FF.35AE %e 指数类型 9.38e5 %g 通用浮点类型f和e类型中较短的 %h 散列码 %% 百分比类型 %n 换行符 %tx 日期与时间类型x代表不同的日期与时间转换符 测试用例 1 public static void main(String[] args) { 2 String strnull; 3 strString.format(Hi,%s, 王力); 4 System.out.println(str); 5 strString.format(Hi,%s:%s.%s, 王南,王力,王张); 6 System.out.println(str); 7 System.out.printf(字母a的大写是%c %n, A); 8 System.out.printf(37的结果是%b %n, 37); 9 System.out.printf(100的一半是%d %n, 100/2);
10 System.out.printf(100的16进制数是%x %n, 100);
11 System.out.printf(100的8进制数是%o %n, 100);
12 System.out.printf(50元的书打8.5折扣是%f 元%n, 50*0.85);
13 System.out.printf(上面价格的16进制数是%a %n, 50*0.85);
14 System.out.printf(上面价格的指数表示%e %n, 50*0.85);
15 System.out.printf(上面价格的指数和浮点数结果的长度较短的是%g %n, 50*0.85);
16 System.out.printf(上面的折扣是%d%% %n, 85);
17 System.out.printf(字母A的散列码是%h %n, A);
18 } 输出结果 1 Hi,王力 2 Hi,王南:王力.王张 3 字母a的大写是A 4 37的结果是false 5 100的一半是50 6 100的16进制数是64 7 100的8进制数是144 8 50元的书打8.5折扣是42.500000 元 9 上面价格的16进制数是0x1.54p5
10 上面价格的指数表示4.250000e01
11 上面价格的指数和浮点数结果的长度较短的是42.5000
12 上面的折扣是85%
13 字母A的散列码是41 String、StringBuffer和StringBuider 首先通过阅读Java源码我们可以发现String类是被final标记为不能继承的类其内部是使用一个char数组来记录整个字符串的值而String类的大部分改变数据的方法如substring、concat和replace等都是直接创建一个新的String对象改变后返回所以我们说String的数据是不能更改的实际上Java也没有为String设计更改其内部char数组的方法。 在这里要永远记住一点“对String对象的任何改变都不影响到原对象相关的任何change操作都会生成新的对象”。 看个例子 1 public class Main {2 3 public static void main(String[] args) {4 String str1 hello world;5 String str2 new String(hello world);6 String str3 hello world;7 String str4 new String(hello world);8 9 System.out.println(str1str2);
10 System.out.println(str1str3);
11 System.out.println(str2str4);
12 }
13 } 输出的结果是 1 false
2 true
3 false 为什么会出现这样的结果下面解释一下原因 对于JVM内存机制在class文件中有一部分 来存储编译期间生成的 字面常量以及符号引用这部分叫做class文件常量池在运行期间对应着方法区的运行时常量池。 因此在上述代码中String str1 hello world;和String str3 hello world; 都在编译期间生成了字面常量和符号引用运行期间字面常量hello world被存储在运行时常量池当然只保存了一份。通过这种方式来将String对象跟引用绑定的话JVM执行引擎会先在运行时常量池查找是否存在相同的字面常量如果存在则直接将引用指向已经存在的字面常量否则在运行时常量池开辟一个空间来存储该字面常量并将引用指向该字面常量。 总所周知通过new关键字来生成对象是在堆区进行的而在堆区进行对象生成的过程是不会去检测该对象是否已经存在的。因此通过new来创建对象创建出的一定是不同的对象即使字符串的内容是相同的。 StringBuilder 我们看一下下面的例子 1 public class Main {
2 public static void main(String[] args) {
3 String string ;
4 for(int i0;i10000;i){
5 string hello;
6 }
7 }
8 } 我们知道每次对String进行连接操作都是重新生成一个新的String那么这段代码运行后会创建10001个String对象而存在引用的仅1个String对象其他对象会被当做垃圾回收造成了内存和CPU的浪费。 Java为了解决这种情况设计了StringBuilderStringBuilder可以直接修改其内部记录的char数组在改变字符串时不会生成多余的对象如下 1 public class Main {
2 public static void main(String[] args) {
3 StringBuilder stringBuilder new StringBuilder();
4 for(int i0;i10000;i){
5 stringBuilder.append(hello);
6 }
7 }
8 } 得到的结果和上面使用String的方法一致但避免了内存和CPU资源的浪费。 StringBuffer 实际上StringBuffer提供的功能和StringBuilder是一样的唯一的不同就是StringBuilder是线程不安全的只能在单线程中使用而StringBuffer是线程安全的可以在多线程中使用。