zoukankan      html  css  js  c++  java
  • String引用数据类型

    一、String类的第一种方式 (原文地址:https://blog.csdn.net/wangdajiao/article/details/52087302)
    1、直接赋值 
    例:String str = "hello"; 
    直接赋值实际上就是相当于一个匿名对象(“hello”)设置了一个名字(str),String类的匿名对象是由系统自动生成,不在由用户自己创建,产生了匿名对象就一定在堆内存在开辟了一块堆内存空间,并且由一块栈内存指向这块堆内存 
    这里写图片描述

    2、采用直接赋值的String类对象的内存地址完全相同,stra,strb,strc指向同一块内存地址 
    例:

    public class StringDemo {
    
    public static void main(String[] args) {
        String stra = "hello" ;
        String strb = "hello" ;
        String strc = "hello" ;
        System.out.println(stra == strb);//true
        System.out.println(stra == strc);//true
        System.out.println(strb == strc);//true
        }
        }

    这里写图片描述

    原因: 
    共享设计模式:在JVM底层实际上会有一个对象池(不一定保存String对象),当代码之中使用了直接赋值的方式定义了一个String类对象时,会将此字符串对象所使用的匿名对象入池保存,而如果后续还有其他String类对象也采用直接赋值方式,并且设置了同样的内容的时候,将不会开辟新的堆内存空间,而是使用已有的对象进行引用的分配,从而继续使用。(integer同样如此)

    --如下:

    Integer是int的封装对象,两个对象==比较的是栈的值
    Integer a = new Integer(1);
    Integer b = new Integer(1);
    a与b存的是Integer的堆中的地址,而不是值
    a、b指向堆中的地址显然不同所以 a==b 为false

    int c = 1; int为值类型,引用类型Integer与值类型int比较显然比较的是值
    因为int在堆中是不开辟内存的,他在栈中的值则为他本身的值
    所以a==c比较的是他们各自的value, a==c为true

    Integer e=1; 这个比较特殊,直接赋值 它有独立的内存,每次赋值时将检查内存中是否有值跟他匹配的,若有则把此内存地址付给e,若没有,开辟新的内存

    你可以尝试下面的例子:
    Integer t = 1;
    Integer t1 = 1;
    t==t1 为true,如上所说,此时t与t1指向的是同一块内存

    new 一定是开辟新的内存,直接赋值则不一定开辟新的内存
    因为a的引用指向堆,而e指向专门存放他的内存,所以他们的内存地址不一样
    所以a==e为false

    c==e等同于 a==c,一个引用类型一个值类型

    二、String类的第二种方式 
    1、构造方法 
    例:String str = new String("hello")

    这里写图片描述 
    构造方法一定要使用关键字new,一旦使用了关键字new就表示要开辟新的堆内存空间,如果使用的是构造方法的方式产生String类对象,实际上开辟了两块堆内存空间(其中匿名对象产生内存空间将成为垃圾空间)

    public class StringDemo {
    
        public static void main(String[] args) {
            String stra = new String("hello");
            String strb = "hello";
            System.out.println(stra == strb);//false
    
    }
    }

    除了内存浪费以外,如果使用了构造方法产生String类对象,其内容不会保存在对象池之中。因为是使用了关键字new开辟的新内存

    2、手动入池:使用String类定义的public String intern();

    public class StringDemo {
    
        public static void main(String[] args) {
            //使用了构造方法创建对象,而后手动入池
            String stra = new String("hello").intern();
            String strb = "hello";
            System.out.println(stra == strb);//ture
    
    }
    }

    总结 : 
    String类两种实例化的区别 
    1、直接赋值:只会开辟一块堆内存空间,并且会自动保存在对象池之中,以供下次重复使用 
    2、构造方法:会开辟两块堆内存空间,其中有一块空间将成为垃圾,并且不会自动入池,但是用户可以使用intern()自动入池


    在实际工作中,使用直接赋值产生String类对象

    三、字符串一旦定义则不可改变 
    例:

    public class StringDemo {
    
        public static void main(String[] args) {
            String str = "Hello";
            str = str + "World";
            str += "!!!";
            System.out.println(str);
    
    }
    }

    内存分析图: 
    红框内为垃圾内存

    因此,字符串的内容实际上没有改变,而对于字符串对象内容的改变,是利用了引用关系的变化而实现的,但是每一次的改变都会产生垃圾空间,因此String的内容不要过多频繁的修改

  • 相关阅读:
    xps插入图片
    xps文件的基本操作
    大家注意:升级 win8.1 火狐浏览器 谷歌浏览器 搜狗五笔输入法 都不能用啦
    CF4C_Registration system 题解
    CF1B_Spreadsheets 题解
    CSP-J/S 初赛知识点整理
    Nodejs在centos下的安装
    sqlserver2012 表分区
    adb unknown host service 这个问题的解决,转载
    char和nchar,varchar和nvarchar的区别(转载)
  • 原文地址:https://www.cnblogs.com/cherishforchen/p/9987367.html
Copyright © 2011-2022 走看看