Java剖析String类

String类对象的两种实例化方法

String并不是一个基本数据类型,它本身属于一个类。但是这个类在设计的过程之中加入了属于Java的特殊支持,所以对于这个类的对象实例化方式有两种形式

  • 直接赋值:String 对象名称 = "内容";
  • 构造方法:String 对象名称 = new String("内容");

String的相等比较

如果说现在有两个int型的变量,要进行相等的判断,则直接使用“==”即可;如果进行String的比较,我们可先用“=="尝试:

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

发现结果并不相等,此时我们发现问题,字符串的内容实际上都是一样的,而在使用“==”比较结果是\color{red}{flase},具体原因如下图所示:

String内存关系图

  • 发现在程序中如果使用“==”比较的只是两个对象(任意的引用类型)\color{red}{堆内存的地址数值},并不是对堆内存中保存的内容进行比较
  • 如果想要在String类中进行比较,那么可以利用String类中提供的public boolean equals(String str);方法进行比较
代码如下:
class StringDemo{
    public static void main(String[] args){
        String strA = "hello";
        String strB = new String("hello") ;
        String strC = strB;
        System.out.println(strA.equals(strB));//true
        System.out.println(strB.equals(strC));//true
        System.out.println(strA.equals(strC));//true
    }
}

\color{red}{由于内容是可控的因素而地址是不可控的因素,因此只要是字符串的比较都使用equals()完成}

面试题:请解释在String比较中”==“与"equals()"的区别
  • "=="是java的一种关系运算符,可以进行数值比较,如果用在String上时则是对堆内存地址数值进行比较,使得结果错误
  • "equals()"是String类的一个方法,用于进行字符串内容的比较

String匿名对象

任何的编程语言都不会提供有字符串这一数据类型,字符串的描述在很多语言之中都是用字符数组表示,而在Java的设计之初为了解决这样的问题,专门提供了一个String类来进行描述。但是随着发展,为了能够让程序变得更加的易于开发,所以在Java里面也提供双引号声明的数据,而这些数据,在Java中并不是普通的变量,而是String类的匿名对象

String 字符串对象 = "字符串";本质:就是为一个字符串的匿名对象起了一个名字


String类两种实例化对象的区别(核心)

此时对于String类的声明方式有两种,那么这两种方式到底应该使用哪一种,以及每种方式的区别

分析String类对象直接实例化的形式

开辟一块堆内存空间,并且开辟一块栈内存空间将直接指向该堆内存

观察以下代码:

class StringDemo{
    public static void main(String[] args){
        String strA = "hello";
        String strB = "hello";
        String strC = "nihao";
        System.out.println(strA == strB);//true
        System.out.println(strB == strC);//false
        System.out.println(strA == strC);//false
    }
}

\color{red}{此时我们可能有疑问,为何使用"=="运算关系符strA仍然与strB相等,在接下来我们会得到这个答案}
内存关系图如下:

内存关系图

关于对象池的概念(Object Pool):

  • 为了更方便用户的代码编写开发,针对于几个特殊的类使用了共享设计的思路,其中String类属于这其中的一员。这种设计思路是Java自己的支持,而且只针对于直接赋值的情况

  • 在使用直接赋值实例化String类对象的操作之中,字符串的内容定义之后实际上会自动将其保存在一个对象池之中,而后如果现在有其他的字符串对象也采用了直接赋值的形式,并且内容与之前的字符串内容完全相同,那么不会开辟新的堆内存空间,而是会通过对象池找到已有的堆内存空间地址,直接引用即可

回到上方的疑问:由于对象池的存在,当若干个字符内容相同时,地址是完全相同的,所以“==“的结果也是相同的,这样的设计就是共享设计模式

分析String类利用构造方法实例化对象的形式

代码如下:

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

内存关系图如下:

内存关系图

分析以上情况:

  • 通过此时的内存分析可以发现,如果采用了构造方法进行String类对象的实例化操作,那么最终会产生两块堆内存,其中一块是垃圾空间

  • 如果使用了构造方法进行String类对象实例化,那么所产生的的对象将不会保存在对象池之中(此对象无法重用),如果用户需要其入池,只能通过public String intern();手工入池

面试题:请解释String类两种对象实例化的区别
  • 直接赋值String str = "字符串";:只会开辟一块堆内存,且对象可以自动入池以供重复使用

  • 构造方法String str = new String("字符串");:会开辟两块堆内存,且其中一块为垃圾空间,由构造方法声明的实例化对象不能自动入池,需要调用intern()方法手动入池


字符串一旦声明不可改变

观察以下代码:

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

分析内存关系:

内存关系图

可以发现整个的操作流程之中,都是String类对象的引用发生着改变,而字符串本身的内容并没有改变,这样的操作会产生大量垃圾,因此杜绝使用


总结

  • String类开发中都使用直接赋值,并且不要频繁修改

  • 字符串内容比较时使用equals()方法

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,193评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,306评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,130评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,110评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,118评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,085评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,007评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,844评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,283评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,508评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,395评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,985评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,630评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,797评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,653评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,553评论 2 352

推荐阅读更多精彩内容