先看一段代码:

public static void main(String[] args) {
        String a = "a"+"b"+1;
        String b ="ab1";
        System.out.println(a == b);
    }

输出的结果是true.

1.==和equals的区别

(1).基本数据类型,也称原始数据类型。byte,short,char,int,long,float,double,boolean 他们之间的比较,应用双等号(==),比较的是他们的值。

(2).复合数据类型(对象类型),当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址,所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。
JAVA当中所有的类都是继承于Object这个基类的,在Object中的基类中定义了一个equals的方法,这个方法的初始行为是比较对象的内存地
址,但在一些类库当中这个方法被覆盖掉了,如String,Integer,Date在这些类当中equals有其自身的实现,而不再是比较类在堆内存中的存放地址了。
 对于复合数据类型之间进行equals比较,在没有覆写equals方法的情况下,他们之间的比较还是基于他们在内存中的存放位置的地址值的,因为Object的equals方法也是用双等号(==)进行比较的,所以比较后的结果跟双等号(==)的结果相同。

2.编译时优化

当编译器在编译代码String a="a"+"b"+1;时,会将其编译为:String a="ab1";这是为了提升整体工作效率JVM进行的优化。类似的优化还有很多,例如当程序中出现int i=3*4+120时,会在编译时就变成了i=132。
但需要注意的是,JVM只优化可以优化的部分,即在编译阶段就可以确定值的,如果字符串中出现了变量,那么JVM是不会做这样的编译时优化的。例如:

String a="a";

final String c="a";

String b=a+"b";

String c=c+"b";

String e=getA()+"b";

String d="ab";

String f = new String(b);

其中b和e在编译时不会被优化,而c会被优化,因为c是final变量,可认为是常量。所以b==d,e==d为false,c==d为true.

3.常量池

程序在运行的时候会创建一个常量池,它保证同一个值的字符串全局唯一。当使用 String b = "ab1", 这样的表达是创建字符串的时候,程序首先会在这个常良池中寻找相同值的对象,在程序中,a引用的对象先被放到了池中,所以在b被创建的时候,将使b也指向这个对象。所以a==b为true.
String 类有个intern方法,当调用它时,JVM会在常良池中通过equals方法查找是否存在等值的String,如果存在,则直接返回常量池中这个String对象的地址;如果不存在,则会在常良池中创建等值的字符串,然后再返回这个新创建空间的地址。因此,只要是同样的字符串,当调用intern方法时,都会得到常良池中对应String对象的地址。所以上面虽然b==d为false,但是b.intern()==d为true.

4.String类的equals方法实现。

前面说过, 对于复合数据类型之间进行equals比较,在没有覆写equals方法的情况下,他们之间的比较还是基于他们在内存中的存放位置的地址值的,但String,Integer,Date在这些类当中equals有其自身的实现,因此不再是比较类在堆内存中的存放地址了。下面是String类的equals方法实现:

public boolean equals(Object anObject)
{

//1、如果是同一个对象,直接返回true
       
if (this == anObject)
       
{
           
return true;
       
}
       
//2、如果传递进来的参数类型不是String,直接返回false
       
if (anObject instanceof String)
       
{
           
String anotherString = (String)anObject;
           
int n = count;//字符串长度
           
if (n == anotherString.count) //3、如果长度不相等,直接返回false
           
{
               
char v1[] = value;//取每一个位置的字符
               
char v2[] = anotherString.value;
               
int i = offset;
               
int j = anotherString.offset;
               
while (n-- != 0) //4、循环对比两个字符串的char数组,逐个比较字符是否一致,若存在不一致的情况,直接返回false
               
{
                   
if (v1[i++] != v2[j++])
                       
return false;
                }

return true;//5、循环结束都没有找到不匹配的,说明两个字符串相等,返回true.
           
}
       
}
       
return false;
}

在上例中,f==d为false,因为内存地址不一样,但是f.equals(d)为true.

String类的一些细节的更多相关文章

  1. Java之String类的使用细节

    String类的特点:     字符串对象一旦被初始化就不会被改变,字符串存储在字符串常量池中(字符串缓冲区).如果池中没有就创建,如果有就直接拿过来用.  代码验证如下:     String s ...

  2. 关于String类和String[]数组的获取长度方法细节

    一.在Java中,以下代码段有错误的是第(  )行 public static void main(String[] args) { String name = "小新";     ...

  3. Java中是否可以继承String类,为什么

    Java中,是否可以继承String类?为什么? 答案: 不可以,因为String类有final修饰符,而final修饰的类是不能被继承的,实现细节不允许改变. public final class ...

  4. C/C++关于string.h头文件和string类

    学习C语言时,用字符串的函数例如stpcpy().strcat().strcmp()等,要包含头文件string.h 学习C++后,C++有字符串的标准类string,string类也有很多方法,用s ...

  5. (转)C++——std::string类的引用计数

    1.概念 Scott Meyers在<More Effective C++>中举了个例子,不知你是否还记得?在你还在上学的时候,你的父母要你不要看电视,而去复习功课,于是你把自己关在房间里 ...

  6. Java学习笔记21(String类补充:正则表达式)

    正如python的re模块,不过Java和Python的正则表达式有一些区别,这里做简单介绍,具体的细节可以参考网上其他的文章: 功能:可以用于检验一个字符串,比如验证用户名,验证密码格式,验证是否是 ...

  7. String类的深入理解

    String不是基本数据类型,String和8种包装类型是不可变类.String和8种基本数据类型采用值传递. 关于方法区中的常量区和class文件中的常量区的关系,参考:https://www.cn ...

  8. 转载:C/C++关于string.h头文件和string类

    学习C语言时,用字符串的函数例如stpcpy().strcat().strcmp()等,要包含头文件string.h 学习C++后,C++有字符串的标准类string,string类也有很多方法,用s ...

  9. 逐步解读String类(一)

    一句题外话 面试刚入行的Java新手,侧重基础知识:面试有多年工作经验的老鸟,多侧重对具体问题的解决策略. 从一类面试题说起 考察刚入行菜鸟对基础知识的掌握程度,面试官提出关于String类的内容挺常 ...

随机推荐

  1. Arduino入门笔记(4):用蜂鸣器演奏音乐并配有LED闪烁

    转载请注明:@小五义 http://www.cnblogs.com/xiaowuyi 欢迎加入讨论群 64770604 一.本次实验所需器材 1.Arduino板 https://item.taoba ...

  2. P1522 牛的旅行 Cow Tours

    题目描述 农民 John的农场里有很多牧区.有的路径连接一些特定的牧区.一片所有连通的牧区称为一个牧场.但是就目前而言,你能看到至少有两个牧区通过任何路径都不连通.这样,Farmer John就有多个 ...

  3. Java面试题,Java三大特性之一——多态的理解

    首先我们知道Java是一门面向对象的语言 面向对象三大特性,封装.继承.多态. 封装.继承.多态 ↓ 无论是学习路线,还是众人的口语习惯,都是按照这个这样进行排序,这是有原因的.因为封装好了才能继承, ...

  4. 从0开始学golang--2.1--如何去爬园子的数据

    20天过去了,才开始写...主要还是因为自己懒吧.之前一边上班一边也有挤时间练习golang,可是写博客却老是不能行动,跑步也没跑了.突然的就懈怠了快一个月.可能也和开始玩the elder scro ...

  5. c# Findwindow sendMessage

    using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServi ...

  6. Django Rest Framework源码剖析(一)-----认证

    一.简介 Django REST Framework(简称DRF),是一个用于构建Web API的强大且灵活的工具包. 先说说REST:REST是一种Web API设计标准,是目前比较成熟的一套互联网 ...

  7. 20155311高梓云《网络对抗》逆向及Bof基础

    20155311高梓云<网络对抗>逆向及Bof基础 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任 ...

  8. 20155327 2017-2018-2《Java程序设计》课程总结

    20155327 2017-2018-2<Java程序设计>课程总结 每周作业链接汇总 预备作业1:我期望的师生关系,对课程的展望:https://www.cnblogs.com/l97- ...

  9. Voronoi图与Delaunay三角剖分

    详情请见[ZJOI2018]保镖 题解随笔 - 99 文章 - 0 评论 - 112

  10. 【Java框架型项目从入门到装逼】第十三节 用户新增功能完结篇

    这一节,我们把用户新增的功能继续做一个完善.首先,新增成功后,需要给前台返回一个信息,就是告诉浏览器,这次用户新增的操作到底是成功了呢,还是失败了呢?为此,我们需要专门引入一个结果类,里面只有两个属性 ...