java String对象总结

来源:互联网 发布:北理莫斯科大学知乎 编辑:程序博客网 时间:2024/06/05 10:10

String是一个对象,不是一个基本数据类型,默认值是null(因为对象的默认值是null)
String实际上是用字符数组存储的,这一点可以在源码中体现
1. String 创建方式

String ok1 = new String("ok");String ok2 = "ok"

这里写图片描述
第一种方式String ok1=new String(“ok”):首先会在堆内存申请一块内存存储字符串ok,ok1指向其内存块对象。同时还会检查字符串常量池中是否含有ok字符串,若没有则添加ok到字符串常量池中。所以 new String()可能会创建两个对象.
第二种方式`String ok2=“ok”: 先检查字符串常量池中是否含有ok字符串,如果有则直接指向, 没有则在字符串常量池添加ok字符串并指向它.所以这种方法最多创建一个对象,有可能不创建对象

2. 匹配方式
常量池是在java用于保存在编译时已经确定的,已经编译的class文件的一份数据
字符串对比,看是否相等,有两种方式:==和equals
比较类中的数值是否相等使用equals(),比较两个包装类的引用是否指向同一个对象时用==
第一种方式:==
1)java代码:
String ok = "ok"; String ok1 = new String("ok"); ok == ok1 (false)
原因:ok指向的是常量池中的对象,ok1指向的是堆内存中的对象,而且new的字符串在编译器是无法确定的
2)java代码:
String ok = "apple1"; String ok1 = "apple" + 1; ok == ok1 (true)
原因:编译期ok1和ok都是确定的,ok和ok1都指向的是常量池里面的字符串apple1
3)java代码:
String ok = "apple1"; int temp = 1;String ok1 = "apple" + temp;ok==ok1(false)
原因:编译期间ok1不是确定的(ok1含有变量),ok是确定的(指向常量池中的对象),所以不是指向同一个对象
4) java代码:
String ok = "apple1"; final int temp = 1; String ok1 = "apple"+temp; ok == ok1 (true)
原因:ok1是确定的了,因为temp能在编译器确定
5) java代码:

public static void main(String[] args) {        String ok="apple1";      final int temp=getTemp();      String ok1="apple"+temp;      System.out.println(ok==ok1);//false       }public static int getTemp()  {    return 1;  } 

原因:ok1编译时无法确定,需要运行代码获得temp

3. 扩展常量池方式:intern()
intern()是扩充常量池的一个方法,当一个String实例str调用intern()方法时,java会检查常量池中是否有相同的字符串,如果有则返回其引用,如果没有则在常量池中增加一个str字符串并返回它的引用。

String ok="apple";  String ok1=new String("apple");  System.out.println(ok==ok1);//false  ok1=ok.intern();//获取常量池ok的引用  System.out.println(ok==ok1);//true--指向同一个对象

4. 常量池
字符串:其对象的引用都是存储在栈中的,如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才能确定的就存储在堆中。对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份。
java代码:

String s1 = "china";  String s2 = "china";  String s3 = "china";  String ss1 = new String("china");  String ss2 = new String("china");  String ss3 = new String("china"); 

这里写图片描述
对于基础类型的变量和常量:变量和引用存储在栈中,常量存储在常量池中。

int i1 = 9;  int i2 = 9;  int i3 = 9;   public static final int INT1 = 9;  public static final int INT2 = 9;  public static final int INT3 = 9;  

这里写图片描述
对于成员变量和局部变量:成员变量就是方法外部,类的内部定义的变量;局部变量就是方法或语句块内部定义的变量。局部变量必须初始化。
形式参数是局部变量,局部变量的数据存在于栈内存中。栈内存中的局部变量随着方法的消失而消失。
成员变量存储在堆中的对象里面,由垃圾回收器负责回收。

class BirthDate {      private int day;      private int month;      private int year;          public BirthDate(int d, int m, int y) {          day = d;           month = m;           year = y;      }      省略get,set方法………  }  public class Test{      public static void main(String args[]){  int date = 9;          Test test = new Test();                   test.change(date);           BirthDate d1= new BirthDate(7,7,1970);             }        public void change1(int i){          i = 1234;      }  

这里写图片描述
对于以上这段代码,date为局部变量,i,d,m,y都是形参为局部变量,day,month,year为成员变量。下面分析一下代码执行时候的变化:
(1). main方法开始执行:int date = 9;
date局部变量,基础类型,引用和值都存在栈中。
2). Test test = new Test();
test为对象引用,存在栈中,对象(new Test())存在堆中。
3). test.change(date);
i为局部变量,引用和值存在栈中。当方法change执行完成后,i就会从栈中消失。
4). BirthDate d1= new BirthDate(7,7,1970);
d1为对象引用,存在栈中,对象(new BirthDate())存在堆中,其中d,m,y为局部变量存储在栈中,且它们的类型为基础类型,因此它们的数据也存储在栈中。day,month,year为成员变量,它们存储在堆中(new BirthDate()里面)。当BirthDate构造方法执行完之后,d,m,y将从栈中消失。
5).main方法执行完之后,date变量,test,d1引用将从栈中消失,new Test(),new BirthDate()将等待垃圾回收。

6. String 的常用方法

String类具有immutable(不可改变)性质,当String变量需要经常变化的时候,会产生很多变量值,应该考虑使用StringBuffer提高效率,在开发的时候,注意String的创建方法。

7. == 与 equals
String 是个对象,要对比两个不同的String对象的值是否相同明显的要用到 equals() 这个方法可是如果程序里面有那么多的String对象,有那么多次的要用到 equals ,哦,天哪,真慢啊更好的办法:把所有的String都intern()到缓冲池去吧最好在用到new的时候就进行这个操作String s2 = new String(“Monday”).intern();嗯,大家都在水池里泡着了吗?哈哈现在我可以无所顾忌的用 == 来比较 String 对象的值了真是爽啊,又快又方便!

例程1:class Str {     public static void main(String[] args) {         String s = "Hi!";         String t = "Hi!";         if (s == t)             System.out.println("equals");         else              System.out.println("not equals");     } } //equals例程2:class Str {     public static void main(String[] args) {         String s = "HELLO";         String t = s.toUpperCase();         if (s == t)             System.out.println("equals");         else             System.out.println("not equals");     } } //equalsclass Str2 {     public static void main(String[] args) {         String s = "Hello";         String t = s.toUpperCase();         if (s == t)             System.out.println("equals");         else             System.out.println("not equals");     } } // not equals

你了解 String 吗?解读 String 的 API ,可以看到:toUpperCase() 和 toLowerCase() 方法返回一个新的String对象,它将原字符串表示字符串的大写或小写形势;但是要注意:如果原字符串本身就是大写形式或小写形式,那么返回原始对象。
(1) charAt(int n) 返回字符串内n位置的字符,第一个字符位置为0,最后一个字符的位置为length()-1,访 问错误的位置会扔出一块大砖头:StringIndexOutOfBoundsException 真够大的
(2) concat(String str) 在原对象之后连接一个 str ,但是返回一个新的 String 对象
(3) EqualsIgnoreCase(String str) 忽略大小写的 equals 方法这个方法的实质是首先调用静态字符方法toUpperCase() 或者 toLowerCase() 将对比的两个字符转换,然后进行 == 运算
(4) trim() 返回一个新的对象,它将原对象的开头和结尾的空白字符切掉同样的,如果结果与原对象没有差别,则返回原对象
(5) toString() String 类也有 toString() 方法吗?真是一个有趣的问题,可是如果没有它,你的 String 对象说不定真的不能用在System.out.println() 里面啊小心,它返回对象自己String 类还有很多其他方法,掌握他们会带来很多方便也会有很多困惑,所以坚持原则,是最关键的。
目前String看到的就是这些了,之后会再更新的

原创粉丝点击