Java中equal和==区别及String创建过程
Java中equal和==区别
1.起因
在一段Java代码中,使用了两种实现方式。
//第一种命令行输入
int main (String[] args) {
if(args[0] == "-logdb"){
System.out.println("args==-logdb");
} else {
System.out.println("args!=-logdb");
}
}
//第二种
int main (String[] args) {
String[] args1 = {"-logdb"};
if(args1[0] == "-logdb"){
System.out.println("args==-logdb");
} else {
System.out.println("args!=-logdb");
}
}
结果发现,第一种显示的是args!=-logdb,而第二种显示的却是args!=-logdb。
2.原因
1.首先,在Java中,和equal是不一样的。对于基本类型,如int,char之类的,比较的是他们的值。而对于复合类型(类),当使用比较的就不是他们的值,而是他们的地址,的意思可以看成是参与比较的两个对象是不是同一个对象,即是否具有相同的地址。而equal的初始行为是比较地址,但在一些类中被重写覆盖,如String类中的equal方法:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
我们可以很明白地看出,在开始比较地址如果相同就返回true,后续则是比较String的内容。所以,当我们需要比较两个字符串是否相同的时候,最好使用equal来进行比较。
2.创建字符串对象原理
在创建一个字符串对象str = X时,jvm会拿着X去字符串缓存池中找到是否有内容相同的字符串,若有,则将str与其联系起来,若没有,则在池中创建。
使用new创建对象时,会在堆栈区中创建一个对象。
如果直接指定,如第二个例子,则会去字符串缓存池中检查是否存在字符串,不存在则创建,不会在堆栈区创建。
例子
String str1 = "abc";
System.out.println(str1 == "abc"); //true
步骤:
栈中开辟一块空间存放引用str1;
字符串缓存池中开辟一块空间,存放String常量"abc";
引用str1指向池中字符串缓存池"abc";
str1所指代的地址即常量"abc"所在地址,输出为true;
String str2 = new String("abc");
System.out.println(str2 == "abc"); //false
步骤:
栈中开辟一块空间存放引用str2;
检查维护串池,若串池中有"abc",copy到堆中,若没有,在堆中创建,并添加到串池中
引用str2指向堆中的新建的String对象"abc";
str2所指代的对象地址为堆中地址,而常量"abc"地址在池中,输出为false;
String str3 = new String("abc");
System.out.println(str3 == str2); //false
步骤:
3.字符串缓存池
在程序运行过程中,会创建一个字符串缓存池。下面,让我们来看一看第一个例子。int main (String[] args) {
if(args[0] == "-logdb"){
System.out.println("args==-logdb");
} else {
System.out.println("args!=-logdb");
}
}
我们可以看到,在new出一个args字符串数组的时候,在字符串缓存池中,并没有存在着"-logdb"。
所以,这两个字符串进行比较时,比较的是他们的地址,一个位于堆中,一个位于缓存池中,地址当然是不同的,所以返回的是不等于。
int main (String[] args) {
String[] args1 = {"-logdb"};
if(args1[0] == "-logdb"){
System.out.println("args==-logdb");
} else {
System.out.println("args!=-logdb");
}
}
而在第二个例子中,我们先示例化了一个字符串数组,其中存在着"-logdb",所以,当后续比较时,程序先在String缓存池中寻找相同值的对象,即这两比较对象的地址其实是一样的,都是缓存池中的地址,所以返回等于。
Java中equal和==区别及String创建过程的更多相关文章
- Java 中>>和>>>的区别
Java 中>>和>>>的区别 Java中的位运算符: >>表示右移,如果该数为正,则高位补0,若为负数,则高位补1: >>>表示无符号右移 ...
- Java中new一个对象是一个怎样的过程?JVM中发生了什么?
Java中new一个对象的步骤: 1. 当虚拟机遇到一条new指令时候,首先去检查这个指令的参数是否能 在常量池中能否定位到一个类的符号引用 (即类的带路径全名),并且检查这个符号引用代表的类是否已被 ...
- 关于Java中equal函数和==的一些区别
equal函数比较的到底是什么,很明显是比较的值,但是什么值?与==比较的堆中的内存地址不同,其比较的是对象的值,包括各个属性的值.我们在重新overriding此方法时首先要判断是否为同一对象,如果 ...
- 关于Java中equal 和 == 的区别
在对Java开发还不熟练的时候,往往很多人都喜欢用==去比较两个对象是否相等,有时候就会出现很奇葩的问题. 其实这类问题并不是奇葩问题,只是我们不够细心而已,在Java中“==”比较两个变量本身的值, ...
- JAVA中Integer.valueOf, parsetInt() String.valueOf的区别和结果
先来看段代码 public class IntegerDemo { public static void main(String[] args) { String num = null; System ...
- Java中的字符串驻留(String Interning)
1. 首先String不属于8种基本数据类型,String是一个对象. 因为对象的默认值是null,所以String的默认值也是null:但它又是一种特殊的对象,有其它对象没有的一些特性. 2. ne ...
- 全面解释java中StringBuilder、StringBuffer、String类之间的关系
StringBuilder.StringBuffer.String类之间的关系 java中String.StringBuffer.StringBuilder是编程中经常使用的字符串类,在上一篇博文中我 ...
- .NET和JAVA中BYTE的区别以及JAVA中“DES/CBC/PKCS5PADDING” 加密解密在.NET中的实现
场景:java 作为客户端调用已有的一个.net写的server的webservice,输入string,返回字节数组. 问题:返回的值不是自己想要的,跟.net客户端直接调用总是有差距 分析:平台不 ...
- Java中的堆栈区别
在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配. 当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配 ...
随机推荐
- win10汇编如何debug(小白向)
先引用别人的方法 http://blog.csdn.net/lcr_happy/article/details/52491107 按他所说的下完对应软件后,安装其中的dosbox,然后将debug.e ...
- Ipython的安装/ipython notebook的简单使用
安装了pyhton的windows版的shell好久了,今天才听说Ipython这个东西,确实在windows下的python shell很难用,一旦输入错误就要重新来过 了解了下ipython,然后 ...
- Core Animation 文档翻译 (第四篇)
Core Animation 文档翻译(第四篇) 让Layer的content动画起来 核心动画的基础接口以及为拥有Layer的View做的动画扩展接口,使得为Layer制作复杂动画变得简单化.例如改 ...
- DDMS和程序打包过程
1. Android版本对应api级别 2.3~~~~~10 3.0~~~~~11 4.0~~~~~14 4.1.2~~~16 2.3和4.1.2是最稳定的 2.Android手机常见分辨率 320* ...
- slick对超过22个属性的表进行映射的两种办法
版权声明:本文为博主原创文章,未经博主允许不得转载 slick是scala的一个FRM(Functional Relational Mapper)框架,即函数式的关系数据库编程工具库.使用slick不 ...
- Yii 2.0.3 Advanced版控制器不能包含大写字母的Bug
Yii 2.0.3 Advanced版控制器不能包含大写字母的Bug,我是直接下载Archive文件安装的,非Composer方式安装 Yii 框架之前是支持在Url中包含大写字母的 最新的Yii 2 ...
- ABP官方文档翻译 2.6 定时
定时 介绍 时钟 客户端 时区 客户端 Binders和Converters 介绍 一些应用只针对一个时区,而其他的一些已用则有许多不同的时区.为了满足这样的需求和集中的时间操作,Abp提供了时间操作 ...
- Python学习--使用dlib、opencv进行人脸检测标注
参考自https://www.pyimagesearch.com/2017/04/03/facial-landmarks-dlib-opencv-python/ 在原有基础上有一部分的修改(image ...
- 编程岗位电话面试问答Top 50[转]
原文链接:http://blog.jobbole.com/84618/ 1. 从哈希表,二叉树和链表中取元素的时间复杂度?如果你有数百万记录呢? 哈希表的时间复杂度为O(1),二叉树为O(logN) ...
- BZOJ 4516: [Sdoi2016]生成魔咒 [后缀自动机]
4516: [Sdoi2016]生成魔咒 题意:询问一个字符串每个前缀有多少不同的子串 做了一下SDOI2016R1D2,题好水啊随便AK 强行开map上SAM 每个状态的贡献就是\(Max(s)-M ...