Java String建立對象執行個體解析,javastring

來源:互聯網
上載者:User

Java String建立對象執行個體解析,javastring

本文研究的主要是Java String建立對象的問題,具體介紹如下。

首先我們要明白兩個概念,引用變數和對象,對象一般通過new在堆中建立,String只是一個引用變數。

所有的字串都是String對象,由於字串常量的大量使用,java中為了節省時間,在編譯階段,會把所有字串常量放在字串常量池中,字串常量池的一個好處就是可以把相同的字串合并,佔用一個空間。

雖然在Java中無法直接擷取變數的地址,但是可以用==判斷一下兩個引用變數是否指向了一個地址即一個對象。

棧記憶體 堆記憶體
基礎類型,對象引用( 堆記憶體位址 ) 由new 建立的對象和數組
存取速度快 相對於棧記憶體較慢
資料大小在聲明周期必須確定 分配的記憶體由java 虛擬機器自動記憶體回收行程管理。動態分配記憶體大小
共用特性,棧中如果有字串,則直接引用;如果沒有,開闢新的空間存入值 每new一次都在堆記憶體中產生一個新的對象。不存在任何複用

package com.demo.test;import java.lang.reflect.Field;public class StringDemo {  public static void main(String[] args) {    //先在記憶體中尋找有沒有這個字串對象存在,如果存在就指向這個字串對象;    String str1 = "abc";    String str2 = "abc";    /*     public String toString() {      return this;     }     */    String str3 = "abc".toString();    //不論記憶體中是否已經存在這個字串對象,都會建立一個對象。    String str4 = new String("abc");    String str5 = new String("abc");    String str6 = str5;    String str7 = "a" + "b" + "c";    String str8 = "a" + "b" + new String("c");    //String是不可變字串對象,StringBuilder和StringBuffer是可變字串對象(其內部的字元數組長度可變),StringBuffer安全執行緒,StringBuilder非安全執行緒    String str9 = new StringBuilder().append("a").append("b").append("c").toString();    String str10 = new StringBuffer().append("a").append("b").append("c").toString();    System.out.println("--------> ==");    System.out.println("---> 1");    System.out.println(str1==str2);//true    System.out.println("---> 3");    System.out.println(str3==str1);//true    System.out.println("---> 4");    System.out.println(str4==str1);//false    System.out.println(str4==str3);//false    System.out.println(str4==str5);//false    System.out.println(str4==str6);//false    System.out.println("---> 7");    System.out.println(str7==str1);//true    System.out.println(str7==str3);//true    System.out.println(str7==str4);//false    System.out.println("---> 8");    System.out.println(str8==str1);//false    System.out.println(str8==str3);//false    System.out.println(str8==str4);//false    System.out.println(str8==str7);//false    System.out.println("---> 9");    System.out.println(str9==str1);//false    System.out.println(str9==str3);//false    System.out.println(str9==str4);//false    System.out.println(str9==str7);//false    System.out.println(str9==str8);//false    System.out.println("---> 10");    System.out.println(str10==str1);//false    System.out.println(str10==str3);//false    System.out.println(str10==str4);//false    System.out.println(str10==str7);//false    System.out.println(str10==str8);//false    System.out.println(str10==str9);//false    System.out.println("--------> equals");    System.out.println(str1.equals(str4));//true    System.out.println(str1.equals(str7));//true    System.out.println(str1.equals(str8));//true    System.out.println("--------> hashCode");    /*     hashCode計算公式: s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]      因此hashCode都是一樣的,而且是每次運行都一樣     */    System.out.println(str1.hashCode());//96354    System.out.println(str2.hashCode());    System.out.println(str3.hashCode());    System.out.println(str4.hashCode());    System.out.println(str5.hashCode());    System.out.println(str6.hashCode());    System.out.println(str7.hashCode());    System.out.println("--------> normal change value");    //String是不可變類,string只是指向堆記憶體中的引用,儲存的是對象在堆中的地址,而非對象本身,給string賦值只是改變其引用對象而非對象本身    str6 = "123";    System.out.println(str5);//abc    System.out.println(str6);//123    System.out.println("--------> reflect change value");    /*     如果非要改變String的值,也不是不可行。只能使用反射了。     public final class String implements java.io.Serializable, Comparable<String>, CharSequence {       // The value is used for character storage.       private final char value[];       ……     }    */    str6 = str5;    try {      Field field = String.class.getDeclaredField("value");//     Field field = str6.getClass().getDeclaredField("value");      if(!field.isAccessible()) {        field.setAccessible(true);      }      char[] value = (char[])field.get(str6);      value[0] = '0';      System.out.println(str5);//0bc      System.out.println(str6);//0bc    } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {      e.printStackTrace();    }    System.out.println("--------> obj.toString()");    Object obj = new Object();    /*    public String toString() {      return getClass().getName() + "@" + Integer.toHexString(hashCode());    }    */    System.out.println(obj.toString());//java.lang.Object@15db9742    String[] arr1 = {"0"};    String[] arr2 = {"0"};    System.out.println(arr1.equals(arr2));//false  }}

總結

  • 如果String指向的是一個字串常量,那麼會先在字串常量池(棧)中尋找,如果有就直接指向它;沒有則在字串常量池中建立該常量,然後String指向該常量。
  • 如果String使用關鍵字new初始化,則會在堆中開闢固定的空間存放該字串的值,然後String指向該常量。
  • 使用字串常量拼接,由於運算式先計算右值,因此相當於將String指向一個新拼接好的字串常量。同樣會在字串常量池中尋找,如果有就直接指向它;沒有則在字串常量池中建立該常量,然後String指向該常量。但是如果拼接中存在使用new產生的字串,則新的字串就等價於使用new在堆中建立的一樣。
  • 修改String的值,只能改變String的指向,不會改變String指向的對象本身。如果非要改變指向的對象本身,可以使用反射。
  • 如果是數組,由於它是對象,那麼equals只比較其數組指標地址,並不會去比較其中的元素是否相等。

以上就是本文關於Java String建立對象執行個體解析的全部內容,希望對大家有所協助。感興趣的朋友可以繼續參閱本站其他相關專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支援!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.