欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java String創(chuàng)建對(duì)象實(shí)例解析

 更新時(shí)間:2018年02月01日 11:56:01   作者:司馬懿字仲達(dá)  
這篇文章主要介紹了Java String創(chuàng)建對(duì)象實(shí)例解析,分享了相關(guān)代碼示例,小編覺得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下

本文研究的主要是Java String創(chuàng)建對(duì)象的問題,具體介紹如下。

首先我們要明白兩個(gè)概念,引用變量和對(duì)象,對(duì)象一般通過new在堆中創(chuàng)建,String只是一個(gè)引用變量。

所有的字符串都是String對(duì)象,由于字符串常量的大量使用,java中為了節(jié)省時(shí)間,在編譯階段,會(huì)把所有字符串常量放在字符串常量池中,字符串常量池的一個(gè)好處就是可以把相同的字符串合并,占用一個(gè)空間。

雖然在Java中無法直接獲取變量的地址,但是可以用==判斷一下兩個(gè)引用變量是否指向了一個(gè)地址即一個(gè)對(duì)象。

棧內(nèi)存 堆內(nèi)存
基礎(chǔ)類型,對(duì)象引用( 堆內(nèi)存地址 ) 由new 創(chuàng)建的對(duì)象和數(shù)組
存取速度快 相對(duì)于棧內(nèi)存較慢
數(shù)據(jù)大小在聲明周期必須確定 分配的內(nèi)存由java 虛擬機(jī)自動(dòng)垃圾回收器管理。動(dòng)態(tài)分配內(nèi)存大小
共享特性,棧中如果有字符串,則直接引用;如果沒有,開辟新的空間存入值 每new一次都在堆內(nèi)存中生成一個(gè)新的對(duì)象。不存在任何復(fù)用

package com.demo.test;

import java.lang.reflect.Field;

public class StringDemo {

  public static void main(String[] args) {
    //先在內(nèi)存中查找有沒有這個(gè)字符串對(duì)象存在,如果存在就指向這個(gè)字符串對(duì)象;
    String str1 = "abc";
    String str2 = "abc";
    /*
     public String toString() {
      return this;
     }
     */
    String str3 = "abc".toString();
    //不論內(nèi)存中是否已經(jīng)存在這個(gè)字符串對(duì)象,都會(huì)新建一個(gè)對(duì)象。
    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是不可變字符串對(duì)象,StringBuilder和StringBuffer是可變字符串對(duì)象(其內(nèi)部的字符數(shù)組長度可變),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計(jì)算公式: s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
      因此hashCode都是一樣的,而且是每次運(yùn)行都一樣
     */
    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只是指向堆內(nèi)存中的引用,存儲(chǔ)的是對(duì)象在堆中的地址,而非對(duì)象本身,給string賦值只是改變其引用對(duì)象而非對(duì)象本身
    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
  }
}

總結(jié)

  • 如果String指向的是一個(gè)字符串常量,那么會(huì)先在字符串常量池(棧)中查找,如果有就直接指向它;沒有則在字符串常量池中創(chuàng)建該常量,然后String指向該常量。
  • 如果String使用關(guān)鍵字new初始化,則會(huì)在堆中開辟固定的空間存放該字符串的值,然后String指向該常量。
  • 使用字符串常量拼接,由于表達(dá)式先計(jì)算右值,因此相當(dāng)于將String指向一個(gè)新拼接好的字符串常量。同樣會(huì)在字符串常量池中查找,如果有就直接指向它;沒有則在字符串常量池中創(chuàng)建該常量,然后String指向該常量。但是如果拼接中存在使用new生成的字符串,則新的字符串就等價(jià)于使用new在堆中創(chuàng)建的一樣。
  • 修改String的值,只能改變String的指向,不會(huì)改變String指向的對(duì)象本身。如果非要改變指向的對(duì)象本身,可以使用反射。
  • 如果是數(shù)組,由于它是對(duì)象,那么equals只比較其數(shù)組指針地址,并不會(huì)去比較其中的元素是否相等。

以上就是本文關(guān)于Java String創(chuàng)建對(duì)象實(shí)例解析的全部?jī)?nèi)容,希望對(duì)大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專題,如有不足之處,歡迎留言指出。感謝朋友們對(duì)本站的支持!

相關(guān)文章

  • spring boot如何使用AOP統(tǒng)一處理web請(qǐng)求

    spring boot如何使用AOP統(tǒng)一處理web請(qǐng)求

    這篇文章主要介紹了spring boot如何使用AOP統(tǒng)一處理web請(qǐng)求,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • springboot 監(jiān)控管理模塊搭建的方法

    springboot 監(jiān)控管理模塊搭建的方法

    本篇文章主要介紹了springboot 監(jiān)控管理模塊搭建的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-03-03
  • java substring 截取字符串的方法

    java substring 截取字符串的方法

    這篇文章主要介紹了java substring 截取字符串的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • java的串口通信問題

    java的串口通信問題

    這篇文章主要介紹了java的串口通信問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • SpringBoot集成WebSocket實(shí)現(xiàn)前后端消息互傳的方法

    SpringBoot集成WebSocket實(shí)現(xiàn)前后端消息互傳的方法

    這篇文章主要介紹了SpringBoot集成WebSocket實(shí)現(xiàn)前后端消息互傳的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • Java中集合List、Set和Map的入門詳細(xì)介紹

    Java中集合List、Set和Map的入門詳細(xì)介紹

    Java集合主要分為三種類型:Set(集)、List(列表)和Map(映射),下面這篇文章主要給大家介紹了關(guān)于Java中集合List、Set和Map的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-01-01
  • 詳解Java 中泛型的實(shí)現(xiàn)原理

    詳解Java 中泛型的實(shí)現(xiàn)原理

    這篇文章主要介紹了詳解Java 中泛型的實(shí)現(xiàn)原理,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下
    2021-03-03
  • ShardingJdbc讀寫分離的BUG踩坑解決

    ShardingJdbc讀寫分離的BUG踩坑解決

    這篇文章主要為大家介紹了ShardingJdbc讀寫分離的BUG踩坑解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • java基于socket傳輸zip文件功能示例

    java基于socket傳輸zip文件功能示例

    這篇文章主要介紹了java基于socket傳輸zip文件功能,結(jié)合實(shí)例形式分析了java使用socket進(jìn)行文件傳輸?shù)木唧w操作步驟與服務(wù)器端、客戶端相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2017-07-07
  • 詳解Java-Jackson使用

    詳解Java-Jackson使用

    這篇文章主要介紹了Java-Jackson使用詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03

最新評(píng)論