一、前言
1、String表示字符串类型,属于 引用数据类型,不属于基本数据类型。
2、在java中随便使用 双引号括起来 的都是String对象。
例如:“abc”,“def”,“hello world!”,这是3个String对象。
3、java中规定,双引号括起来的字符串,是 不可变 的,也就是说"abc"自出生到最终死亡,不可变,不能变成"abcd",也不能变成"ab"
4、在JDK当中双引号括起来的字符串,例如:“abc” "def"都是直接存储在“方法区”的“字符串常量池”当中的。
5、为什么SUN公司把字符串存储在一个“字符串常量池”当中呢?
因为字符串在实际的开发中使用太频繁。为了执行效率,所以把字符串放到了方法区的字符串常量池当中。
例:
public class StringTest01 {
public static void main(String[] args) {
// 这两行代码表示底层创建了3个字符串对象,都在字符串常量池当中。
String s1 = "abcdef";
String s2 = "abcdef" + "xy";
// 分析:这是使用new的方式创建的字符串对象。这个代码中的"xy"是从哪里来的?
// 凡是双引号括起来的都在字符串常量池中有一份。
// new对象的时候一定在堆内存当中开辟空间。
String s3 = new String("xy");
}
}
例:
public class StringTest02 {
public static void main(String[] args) {
String s1 = "hello";
// "hello"是存储在方法区的字符串常量池当中
// 所以这个"hello"不会新建。(因为这个对象已经存在了!)
String s2 = "hello";
// == 双等号比较的是变量中保存的内存地址
System.out.println(s1 == s2); // true
String x = new String("xyz");
String y = new String("xyz");
// == 双等号比较的是变量中保存的内存地址
System.out.println(x == y); //false
}
}
注意:
字符串对象之间的比较不能使用“== ”,"=="不保险。应该调用String类的equals方法。
String k = new String("testString");
//String k = null;
// "testString"这个字符串可以后面加"."呢?
// 因为"testString"是一个String字符串对象。只要是对象都能调用方法。
System.out.println("testString".equals(k)); // 建议使用这种方式,因为这个可以避免空指针异常。
System.out.println(k.equals("testString")); // 存在空指针异常的风险。不建议这样写。
二、构造方法
构造方法名
String s = “xxx” 最常用
String(String original) String(“xxx”)
String(char数组)
String(char数组,起始下标,长度)
String(byte数组)
String(byte数组,起始下标,长度)
String(StringBuffer buffer)
String(StringBuilder builder)
}
三、方法
方法名 作用
char charAt(int index) 返回指定位置的字符
int compareTo(String anotherString) 比较两个字符串。相等返回0;前大后小返回1;前小后大返回-1
boolean contains(CharSequence s) 判断字符串是否包含s
boolean endsWith(String suffix) 判断字符串是否以suffix结尾
boolean equals(Object anObject) 判断两个串是否相等
boolean equalsIgnoreCase(String anotherString) 忽略大小写判断两个串是否相等
byte[] getBytes() 将字符串串变成字节数组返回
int indexOf(String str) 返回str在字符串第一次出现的位置
boolean isEmpty() 字符串是否为空
int length() 字符串长度
int lastIndexOf(String str) 返回str最后一次出现的位置
String replace(CharSequence target, CharSequence replacement) 用replacement替换字符串target的字符
String[] split(String regex) 将字符串以regex分割
boolean startsWith(String prefix) 判断字符串是否以prefix开始
String substring(int beginIndex) 从beginIndex开始截取字串
String substring(int beginIndex, int endIndex) 截取beginIndex到endIndex - 1的字符串
char[] toCharArray() 将字符串转换乘char数组
String toLowerCase() 字符串转小写
String toUpperCase() 字符串转大写
String trim() 去除字符串两边空格
静态方法
static String valueOf(int i) 将 i 转换成字符串
eg.
注意:
1.为什么 System.out.println(引用) 会自动调用toString()方法?
因为println()会调用String.valueOf()方法而String.valueOf()会调用toString()方法
2.String byte数组 理解
byte[] b = new byte[1000000000];//有1000000000都是byte类型的
StringBuffer , StringBuilder
StringBuilder 类是 JDK 1.5 新增的类,它也代表可变字符串对象。实际上,StringBuilder 和 StringBuffer 功能基本相似,方法也差不多。不同的是,StringBuffer 是线程安全的,而 StringBuilder 则没有实现线程安全功能,所以性能略高。因此在通常情况下,如果需要创建一个内容可变的字符串对象,则应该优先考虑使用 StringBuilder 类。
StringBuffer、StringBuilder、String 中都实现了 CharSequence 接口。CharSequence 是一个定义字符串操作的接口,它只包括 length()、charAt(int index)、subSequence(int start, int end) 这几个 API。
StringBuffer、StringBuilder、String 对 CharSequence 接口的实现过程不一样,如下图 1 所示:
图 1 对CharSequence接口的实现
可见,String 直接实现了 CharSequence 接口,StringBuilder 和 StringBuffer 都是可变的字符序列,它们都继承于 AbstractStringBuilder,实现了 CharSequence 接口。
总结
String 是 Java 中基础且重要的类,被声明为 final class,是不可变字符串。因为它的不可变性,所以拼接字符串时候会产生很多无用的中间对象,如果频繁的进行这样的操作对性能有所影响。StringBuffer 就是为了解决大量拼接字符串时产生很多中间对象问题而提供的一个类。它提供了 append 和 add 方法,可以将字符串添加到已有序列的末尾或指定位置,它的本质是一个线程安全的可修改的字符序列。
在很多情况下我们的字符串拼接操作不需要线程安全,所以 StringBuilder 登场了。StringBuilder 是 JDK1.5 发布的,它和 StringBuffer 本质上没什么区别,就是去掉了保证线程安全的那部分,减少了开销。
线程安全:
StringBuffer:线程安全StringBuilder:线程不安全
速度:
一般情况下,速度从快到慢为 StringBuilder > StringBuffer > String,当然这是相对的,不是绝对的。使用环境:
操作少量的数据使用 String。
单线程操作大量数据使用 StringBuilder。
多线程操作大量数据使用 StringBuffer