java基础 --- Java String类

简介: java基础 --- Java String类

1. 创建字符串

 1.1 String s1 = "hello world" 与 String s3 = new String("hello world") 的区别

1. String s1 = "hello world";                //String直接创建
2. String s2 = "hello world";                //String直接创建
3. String s3 = s1;                           //相同引用
4. String s4 = new String("hello world");    //String对象创建
5. String s5 = new String("hello world");    //String对象创建

String创建的字符串存储在class常量池中,new创建的字符串对象在堆上。

String str1 = "hello world";和String str3 = "hello world"; 都在编译期间生成了字面常量和符号引用,运行期间字面常量"hello world"被存储在运行时常量池(当然只保存了一份)。JVM在运行时会先查找常量池是否存在相同的字面常量,如果存在,则直接引用指向已经存在的字面常量;否则在运行时常量池开辟一个空间来存储该字面常量,并将引用指向该字面常量。

new关键字来生成对象是在堆区进行的,而在堆区进行对象生成的过程是不会去检测该对象是否已经存在的。因此通过new来创建对象,创建出的一定是不同的对象,即使字符串的内容是相同的。

1.2 String对象一旦创建就无法改变

  \jdk1.6.0_14\src\java\lang\String.java   文件中。

  打开这个类文件就会发现String类是被final修饰的:

1. public final class String
2.     implements java.io.Serializable, Comparable<String>, CharSequence
3. {
4. /** The value is used for character storage. */
5.     private final char value[];
6. 
7. /** The offset is the first index of the storage that is used. */
8.     private final int offset;
9. 
10. /** The count is the number of characters in the String. */
11.     private final int count;
12. 
13. /** Cache the hash code for the string */
14.     private int hash; // Default to 0
15. 
16. /** use serialVersionUID from JDK 1.0.2 for interoperability */
17.     private static final long serialVersionUID = -6849794470754667710L;
18. 
19.     ......
20. 
21. }

从上面的源码可以看出:

1)String类是final类,也就是说String类不能被继承,并且它的成员方法默认都是final方法。【在java中,被final修饰的类是不允许被继承的,并且该类中的成员方法默认都是final方法】

2)上面的源码列举了String类中所有的成员属性,从上面可以看出String类其实是通过char数组来保存字符串的。

下面继续看String类的一些方法实现:

1. public String substring(int beginIndex, int endIndex) {
2. if (beginIndex < 0) {
3.         throw new StringIndexOutOfBoundsException(beginIndex);
4.     }
5. if (endIndex > count) {
6.         throw new StringIndexOutOfBoundsException(endIndex);
7.     }
8. if (beginIndex > endIndex) {
9.         throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
10.     }
11. return ((beginIndex == 0) && (endIndex == count)) ? this :
12.         new String(offset + beginIndex, endIndex - beginIndex, value);
13.     }
14. 
15.  public String concat(String str) {
16.     int otherLen = str.length();
17. if (otherLen == 0) {
18. return this;
19.     }
20.     char buf[] = new char[count + otherLen];
21.     getChars(0, count, buf, 0);
22.     str.getChars(0, otherLen, buf, count);
23. return new String(0, count + otherLen, buf);
24.     }
25. 
26.  public String replace(char oldChar, char newChar) {
27. if (oldChar != newChar) {
28.         int len = count;
29.         int i = -1;
30.         char[] val = value; /* avoid getfield opcode */
31.         int off = offset;   /* avoid getfield opcode */
32. 
33.         while (++i < len) {
34. if (val[off + i] == oldChar) {
35.             break;
36.         }
37.         }
38. if (i < len) {
39.         char buf[] = new char[len];
40. for (int j = 0 ; j < i ; j++) {
41.             buf[j] = val[off+j];
42.         }
43.         while (i < len) {
44.             char c = val[off + i];
45.             buf[i] = (c == oldChar) ? newChar : c;
46.             i++;
47.         }
48. return new String(0, len, buf);
49.         }
50.     }
51. return this;

从上面可以看到,String的方法包括sub, concat, replace操作都是重新生成一个新的字符串,原始的字符串并没有被改变。对String对象的任何改变都不影响到原对象,相关的任何change操作都会生成新对象。

String类是不可改变的,所以一旦创建String对象,那么它的值就无法改变了。如果需要对字符串做很多修改,可以选择使用StringBuffer和StringBuilder类。

2. 字符串长度

用于获取有关对象的信息的方法称为访问器方法。String类的一个访问器方法是length()方法,它返回字符串对象包含的字符数。

1. public class StaticTest{
2.  public static void main(String args[]){
3.    String site = "www.baidu.com";
4.    int len = site.length;
5.    System.out.println(+len);
6.  }
7. }

输出结果是:13

3. 连接字符串

String类提供了两个连接字符串的方法

1)string1.concat(string2);

2) string1 + string2

4. StringBuffer和StringBuilder类

当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。

在使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,所以如果需要对字符串进行修改推荐使用 StringBuffer。

StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。下面摘了2段代码分别来自StringBuffer和StringBuilder,insert方法的具体实现:

StringBuilder的insert方法:

1. public StringBuilder insert(int index, char str[], int offset,
2. int len)
3.   {
4. super.insert(index, str, offset, len);
5. return this;
6.   }

StringBuffer的insert方法:

1. public synchronized StringBuffer insert(int index, char str[], int offset,
2. int len)
3.     {
4. super.insert(index, str, offset, len);
5. return this;
6.     }

 

由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。

 

相关文章
|
14天前
|
存储 安全 Java
java.util的Collections类
Collections 类位于 java.util 包下,提供了许多有用的对象和方法,来简化java中集合的创建、处理和多线程管理。掌握此类将非常有助于提升开发效率和维护代码的简洁性,同时对于程序的稳定性和安全性有大有帮助。
37 17
|
6天前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
10天前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
50 4
|
10天前
|
Java 大数据 API
14天Java基础学习——第1天:Java入门和环境搭建
本文介绍了Java的基础知识,包括Java的简介、历史和应用领域。详细讲解了如何安装JDK并配置环境变量,以及如何使用IntelliJ IDEA创建和运行Java项目。通过示例代码“HelloWorld.java”,展示了从编写到运行的全过程。适合初学者快速入门Java编程。
|
11天前
|
Java 编译器 开发者
Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面
本文探讨了Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面,帮助开发者提高代码质量和程序的健壮性。
26 2
|
15天前
|
存储 安全 Java
如何保证 Java 类文件的安全性?
Java类文件的安全性可以通过多种方式保障,如使用数字签名验证类文件的完整性和来源,利用安全管理器和安全策略限制类文件的权限,以及通过加密技术保护类文件在传输过程中的安全。
|
19天前
|
Java 数据格式 索引
使用 Java 字节码工具检查类文件完整性的原理是什么
Java字节码工具通过解析和分析类文件的字节码,检查其结构和内容是否符合Java虚拟机规范,确保类文件的完整性和合法性,防止恶意代码或损坏的类文件影响程序运行。
|
19天前
|
存储 Java 编译器
java wrapper是什么类
【10月更文挑战第16天】
22 3
|
8天前
|
安全 Java 测试技术
Java并行流陷阱:为什么指定线程池可能是个坏主意
本文探讨了Java并行流的使用陷阱,尤其是指定线程池的问题。文章分析了并行流的设计思想,指出了指定线程池的弊端,并提供了使用CompletableFuture等替代方案。同时,介绍了Parallel Collector库在处理阻塞任务时的优势和特点。
|
4天前
|
安全 Java 开发者
深入解读JAVA多线程:wait()、notify()、notifyAll()的奥秘
在Java多线程编程中,`wait()`、`notify()`和`notifyAll()`方法是实现线程间通信和同步的关键机制。这些方法定义在`java.lang.Object`类中,每个Java对象都可以作为线程间通信的媒介。本文将详细解析这三个方法的使用方法和最佳实践,帮助开发者更高效地进行多线程编程。 示例代码展示了如何在同步方法中使用这些方法,确保线程安全和高效的通信。
23 9