Java中equals和“==””的区别,String特殊
public class TestString {
/*
* java中的数据类型,可分为两类:
* 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方法也是用双等号(==)进行比较的,所以比较后的结果跟双等号(==)的结果相同。
*
*/
//method_1编译运行结果为s1==s2
//说明:s1和s2引用同一个Sring对象---"Monday"
public static void method_1(){
String s1 = "Monday";
String s2 = "Monday";
if(s1==s2){
System.out.println("s1==s2");
}else{
System.out.println("s1!=s2");
}
if(s1.equals(s2)){
System.out.println("s1 equals s2"+s1.hashCode()+":::"+s2.hashCode());
}else{
System.out.println("s1 ont equals s2");
}
}
/* 将s2用new操作符创建,程序输出结果为;
* s1!=s2
* s1 equals s2
* 说明s1和s2分别引用了两个“Monday”的String对象
*/
public static void method_2(){
String s1 = "Monday";
String s2 = new String("Monday");
if(s1==s2){
System.out.println("s1==s2");
}else{
System.out.println("s2!=s2");
}
if(s1.equals(s2)){
System.out.println("s1 equals s2");
}else{
System.out.println("s1 not equals s2");
}
}
/*字符串缓冲池
* 原来,程序在运行的时候会创建一个字符串缓冲池,当使用s2="Monday"这样的表达是创建字符串的时候,
* 程序首先会在这个String缓冲池中寻找相同值得对象,在第一个程序中,s1先被放到了池中,
* 所以在s2被创建的时候,程序找到了具有相同值的s1,将s2引用s1所引用的对象“Monday”。
*
* 在第二段程序中,使用了new操作符,他明白的告诉程序:“我要一个新的,不要旧的”,
* 于是一个新的“Monday”String对象被创建在内存中。他们的值相同,但是位置不同,
* 一个在池中有用一个在岸边休息,真是资源浪费,明明是一样的非要分开做什么呢?
*
* 再次修改程序如下:
*/
public static void method_3(){
String s1 = "Monday";
String s2 = new String("Monday");
s2 = s2.intern();
if(s1==s2){
System.out.println("s1==s2");
}else{
System.out.println("s1!=s2");
}
if(s1.equals(s2)){
System.out.println("s1 equals s2");
}else{
System.out.println("s1 not equals s2");
}
}
/*加入s2 = s2.intern();程序的输出结果为:
* s1==s2
* s1 equals s2
* 原来,(java.lang.String)的intern()方法
* "abc".intern()方法的返回值还是字符串"abc",表面上看起来好像这个方法没什么用处。
* 但是实际上,它做了一个小动作:检查字符串池里是否存在"abc"这么一个字符串,
* 如果存在,就返回池里的字符串;如果不存在,该方法会把"abc"添加到字符串池中,然后再返回它的引用。
*
*
*
*
*
*一、java中内存分配策略及堆和栈的比较
*
*1、内存分配策略
* a、按照编译原理的观点,程序运行时的内存分配有三种策略,分别是静态的,栈式的,和堆式的
* 静态存储分配是指在编译时就能确定每个数据目标在运行时刻的存储空间需求,因而在编译时就可以给他们分配固定的内存空间。
* 这种分配策要求程序代码中不允许有可变数据结构(比如可变数组)的存在,也不允许有嵌套或者递归的结构出现,
* 因为他们都会导致编译程序无法计算准确的存储空间需求。
* b、栈式存储分配也可称为动态存储分配,是由一个类似于堆栈的运行栈来实现的。和静态存储分配相反,在栈式存储方案中,
* 程序对数据区的需求在编译时是完全未知的,只有到运行的时候才能够知道,但是规定在运行中进入一个程序模块时,
* 必须知道该程序模块所需的数据区大小才能够为其分配内存。和我们在数据结构所熟知的栈一样,
* 栈式存储分配按照先进后出的原则进行分配。
* c、静态存储分配要求在编译时能知道所有变量的存储要求,栈式存储分配要求在过程的入口处必须知道所有的存储要求,
* 而堆式存储分配则专门负责在编译时或运行时模块入口处都无法确定存储要求的数据结构的内存分配,
* 比如可变长度串和对象实例。堆由大片的可利用块或空闲块组成,堆中的内存可以按照任意顺序分配和释放。
*2、堆和栈的比较
* 上面的定义从编译原理的教材中总结而来,除静态存储分配之外,都显得很呆板和难以理解,下面撇开静态存储分配,集中比较堆和栈:
* 从堆和栈的功能和作用来通俗的比较,堆主要用来存放对象的,栈主要是用来执行程序的,而这种不同又主要是由于堆和栈的特点决定的:
* a、在编译中,例如C/C++中,所有的方法条用都通过栈来进行的,所有的局部变量,形式参数都是从栈中分配内存空间的。
* 实际上也不是什么分配,只是从栈顶向上用就行,就好像工厂中的传送带(conveyor belt)一样,Stack Pointer会自动指引你到放东西的位置,
* 你所要做的只是把东西放下来就行。退出函数的时候,修改栈指针就可以把栈中的内容销毁,这样的模式速度最快,当然要用来运行程序了。
* 需要注意的是,在分配的时候,比如为一个即将要调用的程序模块的分配数据区时,应事先知道这个数据区的大小,
* 也就是说虽然分配是在程序运行时进行的,但是分配的的大小多少是确定的,不变的,而这个“大小多少”是在编译时确定的,不是在运行时。
* b、堆是应用程序在运行的时候请求操作系统分配给自己内存,由于从操作系统管理的内存分配,所以在分配和销毁时都要占用时间,
* 因此用堆的效率非常低。但是堆得优点在于,编译器不必知道要从堆里分配多少存储空间,也不必知道存储的数据要在堆里停留多长时间,
* 因此,用堆保存数据时会得到更大的灵活性。事实上,面向对象的多态性,堆内存分配是必不可少的。
* 因为多态变量所需的存储空间只有在运行时创建了对象之后才能确定。在C++中,要求创建一个对象时,只需用new命令编制相关的代码即可。
* 执行这些代码时,会在堆里自动进行数据的保存,当然,为达到这种灵活性,必然会付出一定的代码:在堆里分配存储空间时会花掉更长的时间!
* 这也正是导致我们刚才所说的效率低得原因。
*
*3、JVM中的堆和栈
* a、JVM是基于堆栈的虚拟机。JVM为每个新创建的线程都分配一个堆栈。也就是说,对于一个java程序来说,它的运行就是通过对堆栈的操作来完成的。
* 堆栈以帧为单位保存线程的状态。JVM对堆栈只进行两种操作:以帧为单位的压栈和出栈操作。
* b、我们知道,某个线程正在执行的方法称为此线程的当前方法。我们可能不知道,当前方法使用的帧称为当前帧。
* 当线程激活一个java方法,JVM就会在线程的java堆栈里新压入一个帧。这个帧自然称为了当前帧。在此方法期间,这个帧将用来保存参数,局部变量,中间计算过程和其他数据
* 这个帧在这个和编译原理中的活动记录的概念是差不多的。
* c、从java的这种分配机制来看,堆栈又可以这样理解:(stack)是操作系统在建立某个进程时或者线程(在支持多线程的操作系统中是线程)
* 为这个线程建立的存储区域,该区域具有先进后出的特性。
* d、每一个java应用都唯一对应一个JVM实例,每一个实例唯一对应一个堆。应用程序在运行中所创建的所有类实例或者数组都放在这个堆中,
* 病由应用所有的线程共享。跟C/C++不同,java中分配堆内存是自动初始化。java中所有对象的存储空间都是在堆中分配的。
* 但是这个对象的引用却是在堆栈中分配的,也就是说在建立一个对象时从两个地方都分配内存,
* 在堆中分配内存实际建立这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的指针(引用)而已。
* e、堆中存放的是创建的对象,java字符串对象内存实现时,在堆中开辟了一块很小的内存,叫字符串常量池,用来存放特定的字符串对象。
* f、通俗来讲java堆栈
* java堆:
* 1、程序运行中动态分配内存大小
* 2、java的垃圾回收器自动回收不再使用的数据
* java栈:
* 1、栈数据可以共享
* 2、存在栈中的数据大小与生存期必须是确定的。
* 3、栈中主要存放一些基本类型的变量(int,short,char,long,byte,float,doubel,boolean)和对象引用。
*
*
*二、String是一个特殊的包装类数据。可以用:
* String str = new String("abc");
* 使用new创建字符串对象的步骤如下,每调用一次就会创建一个新的对象。
* 1、首先在堆(不是常量池)中创建一个包含指定内容的字符串对象,并将字符串引用指向该对象。
* 2、去字符串常量池中查看,是否有包含该内容的对象。
* 3、若有,则将new出来的字符串对象与字符串常量池中内容相同的对象联系起来。
* 4、若没有,则在字符串常量池中再创建一个包含该内容的字符串对象,并将堆中的对象与字符串常量池中新创建出来的对象联系起来。
*
* 字符串特殊的内存机制带来的好处,即是:只比较两个字符串联系的常量池中对象是否为同一个即可,无论字符串大小,比较速度一样。
* String str = "abc";
* 1、先在栈中创建一个堆String类的对象引用变量str
* 2、然后查找堆中常量池里有没有存放"abc"
* 3、如果没有,则将"abc"存放进常量池,并令str指向"abc"
* 4、如果已经有"abc"则直接令str指向"abc"
*
*
*三、特殊情况
*127以下的整数是相等。
* Integer i = 100;
* Integer j = 100;
* System.out.println(i==j);//打印true
*128以上的就作为不同对象处理了
* Integer i = 200;
* Integer j = 200;
* System.out.println(i==j);//打印false
*/
}
Java中equals和“==””的区别,String特殊的更多相关文章
- java中equals和==的区别 (转)
java中equals和==的区别 值类型是存储在内存中的堆栈(以后简称栈),而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其本身则存储在堆中. ==操作比较的是两个变量的值是否相等,对于引 ...
- 【转】Java中equals和==的区别
[转]Java中equals和==的区别 java中的数据类型,可分为两类: 1.基本数据类型,也称原始数据类型.byte,short,char,int,long,float,double,boole ...
- 关于java中equals与==的区别的小实验
java中equals与==经常容易混淆,简单一点说就是equals比较的是值是否相等,是一种方法,==比较的两个对象在JVM中的地址,是一种操作符. 做了几个小实验比较结果. 实验一: String ...
- java中.equals和==的区别?
Java中的equals是十分重要的,和= =要区别开来,孙卫琴的JAVA面向对象编程一书对这个做了阐述,现在小结其主要内容,而且要将 = =和 equals列为重要的对比概念来学习 1.声明格式 ...
- (转)Java中equals和==的区别
java中的数据类型,可分为两类: 1.基本数据类型,也称原始数据类型.byte,short,char,int,long,float,double,boolean 他们之间的比较,应用双等号( ...
- Java 中 Equals和==的区别(转)
另外一篇参考: https://blog.csdn.net/striverli/article/details/52997927 在谈论equals和==的区别前,我们先简单介绍一下JVM中内存分配的 ...
- Java中equals和==的区别?为什么重写equals方法后,一定要重写hashCode方法?
首先明确一点,equals是方法,==是操作符. 1. 如果比较的是基本数据类型: 只讨论==,因为equals是不存在的,因为java中基本数据类型不能调用method的. 2. 如果比较的是引用类 ...
- java中equals和==的区别详解
java中的数据类型,可分为两类: 1.基本数据类型. byte,short,char,int,long,float,double,boolean这八大原始数据类型他们之间的比较,使用“==”,比较的 ...
- java中equals和"=="的区别
"=="号,它比较的是一个对象在内存中的地址值, 比如2个字符串对象String s1 = new String("str");String s2 = new ...
随机推荐
- jquery图片轮播代码
自己写的轮播代码 来张样式效果图 先贴HTML样式 <body> <div id = "wrap"> <div id="lunbo-img& ...
- JavaScript设计模式之建造者模式
一.建造者模式模式概念 建造者模式可以将一个复杂的对象的构建与其表示相分离,使得同样的构建过程可以创建不同的表示.也就是说如果我们用了建造者模式,那么用户就需要指定需要建造的类型就可以得到它们,而具体 ...
- 19 Remove Nth Node From End of List(去掉链表中倒数第n个节点Easy)
题目意思:去掉链表中倒数第n个节点 思路:1.两次遍历,没什么技术含量,第一次遍历计算长度,第二次遍历找到倒数第k个,代码不写了 2.一次遍历,两个指针,用指针间的距离去计算. ps:特别注意删掉 ...
- ActiveX控件资料
Visual Studio 2008(c#)开发ActiveX控件及制作CAB包总结(1) 分类: C#2011-05-27 15:50 403人阅读 评论(0) 收藏 举报 c#stringhook ...
- 插入数据前设置字符编码为utf8
xxx.php保存时选择utf8编码,页头最好加上 header('conten-type:text/html;charset=utf-8'); 在执行CRUD操作前先执行一下 mysql_query ...
- Sample rate 理解
在Gnuradio中,我们可以看到很多模块中都有Sample rate 这个概念 然后看到一个说明 Any processing block's 'Sample Rate' parameter is ...
- 12100 Printer Queue(优先队列)
12100 Printer Queue12 The only printer in the computer science students’ union is experiencing an ex ...
- 在动态引用DLL-A中,当参数是个实体,而实体的属性在另一个DLL-B中。。我们需要得到A这个实体并将其赋值,并将赋值的实体传人DLL-A的方法中。
string strPath = HttpContext.Current.Server.MapPath("/开放式DLL"); DirectoryInfo df = new Dir ...
- UART RS232 的CTS与RTS
目前较为常用的串口有9针串口(DB9)和25针串口(DB25),通信距离较近时(<12m),可以用电缆线直接连接标准RS232端口(RS422,RS485较远),若距离较远,需附加调制解调器(M ...
- java中利用RandomAccessFile读取超大文件
超大文件我们使用普通的文件读取方式都很慢很卡,在java中为我提供了RandomAccessFile函数,可以快速的读取超大文件并且不会感觉到卡哦,下面看我的一个演示实例. 服务器的日志文件往往达到4 ...