JAVA Doc
public final class String extends Object implements Serializable, Comparable, CharSequence
String 类代表字符串Java程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现。 字符串是常量;它们的值在创建之后不能更改。字符串缓冲区支持可变的字符串。因为 String 对象是不可变的,所以可以共享。例如:String str = "abc"; //等效于: char data[] = {'a', 'b', 'c'}; String str = new String(data);
概述:
Java 把内存划分成两种:一种是栈内存,另一种是堆内存。在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用。
堆内存用来存放由new创建的对象和数组,在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或者对象之后,还可以在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或者对象,引用变量就相当于是为数组或者对象起的一个名称。
引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序运行到使用 new 产生数组或者对象的语句所在的代码块之外,数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,才变为垃圾,不能在被使用,但仍然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)。这也是Java比较占内存的原因。
实际上,栈中的变量指向堆内存中的变量,这就是Java中的指针!
String类是一个很特殊的类,它本身是final的,它是不可变的,String类是的本质是字符数组char[], 并且其值不可改变,但StringBuilder也是final,为什么StringBuilder是可变的呢? 究其原因,String类的内部是char[]数组构成,而String的加号(+)运算符的底层是由StringBuilder实现的,一个String每次“+“上一个String,都会创建一个新的StringBuilder,然后调用它的append()方法,该方法返回一个新形成的String。所以字符串的一些合并操作可以使用StringBuilder来提高效率。
用new String()创建的字符串不是常量,不能在编译期就确定,而因为String是类,所以new String()创建的字符串不放入常量池中,它们有自己的地址空间。即Java中,只要使用new关键字来创建对象,则一定会(在堆区或栈区)创建一个新的对象。而直接初始化则会形成字符串常量,分配到运行时常量池中,这会在编译时确定。
JAVA String中null和""的区别String str; String str = null; String str = "";三种定义的区别:1,声明一字符串对象 2,定义一空字符串对象 3,创建一个字符串为空的字符串对象
//定义后在后面程序判断时用if(str == null || str == ""){} public class Test{ static String str1;//成员变量自动赋值 null public static void main(String[] args){ String str;//方法变量 不会赋值,需要显式赋值 System.out.print(str1+" "+str);//str1输出值为null str则会编译不通过 } }
方法:
intern
常量池在运行期被JVM装载后,是可以扩充的。String的intern()方法就是扩充常量池的一个方法;当一个String实例str调用intern()方法时,Java查找常量池中是否有相同Unicode的字符串常量,如果有,则返回其的引用,如果没有,则在常量池中增加一个Unicode等于str的字符串并返回它的引用;看下面的例子就清楚了
String s0= "kvill"; String s1=new String("kvill"); String s2=new String("kvill"); System.out.println( s0==s1 ); System.out.println( "**" ); s1.intern(); s2=s2.intern(); //把常量池中"kvill"的引用赋给s2 System.out.println( s0==s1); System.out.println( s0==s1.intern() ); System.out.println( s0==s2 );结果为:
false
false //虽然执行了s1.intern(),但它的返回值没有赋给s1 true //说明s1.intern()返回的是常量池中"kvill"的引用 true
其他方法:
获取方法
char charAt(int index) //根据位置获取某个字符
char ch="abc";ch.charAt(1);// 返回'b'
int indexOf(int ch) //返回的是ch在字符串中第一次出现的位置
int indexOf(int ch,int fromIndex) //从fromIndex指定位置开始,获取ch在字符串中第一次出现的位置
int indexOf(String str)
int indexOf(String str,int fromIndex)
int lastIndexOf(int ch)
判断方法
boolean contains(String str) //另一种判断方法:
if(str.index(str)!=-1)
boolean startsWith(String str)和boolean endsWith(String str)
bolean isEmpty(String str)
boolean equals(String str)//和==//equals()方法比较字符串对象中的字符,==运算符比较两个对象是否引用同一实例。 String s1="Hello"; String s2=new String(s1); s1.eauals(s2); //true s1==s2;//falseboolean equalsIgnoreCase(String str);忽略大小写的比较
转换方法
•将字符数组转换为字符串
构造函数
String(char[] chs) String(char[] chs,offset,count)将字符数组中的一部分转成字符串。
静态方法
static String copyValueOf(char[] chs)
static String copyValueOf(char[] chs,int offset,int count)
static String valueOf(char[] )
static String valueOf(char[] chs,int offset,int count)
•将字符串转换成字符数组 char[] toCharArray
•将字符数组转换成字符串
•将字符串转换成字节数组 byte[] toBytes
替换方法
String replace(olderStr,newStr)
切割截取方法
String split(regex)
void getChars(int sourceStart,int sourceEnd,char target[],int targetStart)
sourceStart指定了子串开始字符的下标,sourceEnd指定了子串结束后的下一个字符的下标。因此,子串包含从sourceStart到sourceEnd-1的字符。接收字符的数组由target指定,target中开始复制子串的下标值是targetStart。String s="this is a demo of the getChars method."; char buf[]=new char[20];s.getChars(10,14,buf,0);
获取子串
String subString(begin)
String subString(begin,end)包含头不包含尾
将字符串转换成大小写
String toUpperCase()和String toLowerCase()
将字符串两端的空格去除 String trim()
对两个字符串进行自然顺序的比较 int compareTo(String str)
concat() 连接两个字符串
String的乱码解决:
--TODO