先看几个例子
int a=1;
int b=1;
System.out.println(a==b);
这个大家都知道吧,结果是true,那下面的呢
String a="1";
String b="1";
System.out.println(a==b); [color=#FF0000]true[/color]
System.out.println(a.equals(b)); [color=#FF0000]true[/color]
String a=new String("1");
String b="1";
System.out.println(a==b); [color=#FF0000]false[/color]
System.out.println(a.equals(b)); [color=#FF0000]true[/color]
StringBuffer a=new StringBuffer("1");
StringBuffer b=new StringBuffer("1");
System.out.println(a==b); [color=#FF0000]false[/color]
System.out.println(a.equals(b)); [color=#FF0000]false[/color]
List a=new ArrayList();
a.add("0");
List b=new ArrayList();
b.add(new String("0"));
System.out.println(a1==b1); [color=#FF0000]false[/color]
System.out.println(a1.equals(b1)); [color=#FF0000]true[/color]
大家知道为什么结果为是这样吗,知道的就不必往下看了
预备知识:
Java中把存储区分为6类。
分别为寄存器(register)、栈(stack)、堆(heap)、静态存储区(static storage)、常量存储区(constant storage)以及非随机存取存储区(Non-RAM)。
1. 寄存器(register).寄存器与其他的存储区不同,它位于CPU中,所以它是存取速度最快的存储区.但是由于CPU中寄存器的数量是非常有限的,所以寄存器的使用是由CPU按需进行分配.编程的时候我们没有必要去对它进行直接控制.并且在程序中也没办法找到到底什么时候使用了寄存器的依据.
2. 栈(stack).它位于随机存取存储器(RAM)中,并通过由CPU直接支持的栈指针(stack pointer)来进行操作.栈指针通过向下移动来分配新的存储空间,并通过向上移动来释放存储空间.这是仅次于寄存器的另一种高速有效地分配存储空间的方式.在创建程序期间,Java编译器必须知道存储在栈上的所有数据的准确大小和它们的生命周期.这样它才能够产生代码来让栈指针上下地移动.但这种约束限制了代码的灵活性,所以当某些Java存储区在栈上的时候——非凡是,对象引用(object reference)――而Java对象本身并不被存储在栈上.
3. 堆(heap).这是存储Java所有对象的内存池(同样在RAM区域中).堆的优点是,它不像栈一样,编译器并不需要知道它应该从堆中分配多大的存储空间,或者存储空间应该在堆上存在多久.因此,在堆上分配多大的存储空间具有很大的灵活性.无论你何时需要创建对象,你只需要简单的在代码中使用关键字new来创建它就行了.在这段代码被执行时候就在堆(heap)上面分配相应的存储空间.当然,为这样的灵活性也需要付出一定的代价:在堆上分配存储空间比在栈上分配存储空间要更加耗时(假如你能够在Java中像在C++一样,在stack上创建对象的话).
4. 静态存储区(static storage).”静态(static)”在这里表示”在一个固定的位置”(尽管它同样在RAM中).静态存储区包括:对于程序的整个运行期间都有效的数据.你能够使用关键字static来指定非凡的对象为静态的.但是Java对象自身却从来不放置在静态存储区中. 5. 常量存储区(constant storage).常量通常被直接放置在程序代码当中.这是安全的,因为它们永远不能被改变.在某些时候多个常量能够自己分隔开,这样在嵌入式系统中可以被任意地放置在只读存储器(ROM)中.
6. 非RAM存储区(non-RAM storage).假如数据完全存在于程序之外,在程序未被运行时数据也能存在,而不受程序的控制.对于此类情况,有两个主要的例子来说明:一,对象流(streamed objects),这种对象通常以字节流的形式被送到其他的机器去.二,持久化对象(persistent objects),这种对象存放在磁盘上,即便是程序中止以后它们仍然保持原有状态.这些存储器都是将对象以某种形式保存在其他的介质中,然后在需要的时候再把它恢复为常规的基于RAM的对象.Java提供了对轻量级持久性的支持.在未来的Java版本中,Java将提供更加完备的持久性的支持.
先从对象的创建说起
int a=1;在编译时就创建了变量a存储在stack中,1就是它的值,它在内存中存在唯一的地址。
Integer a=new Integer(1);编译时创建了变量a,类型是Integer,存储在stack中,有一个唯一地址,而1则是在运行时创建存储在heap中,也有一个唯一地址,类型是Integer,并且变量a指向1的内存地址,a里面放的就是1的内存地址。
八大基本数据类型boolean,byte,char,short,int,long,float,double只能用==,比较的就是值,直接从stack中取出来比就是了。
引用类型的比较有==和equals(),==比较的是两个对象所指向的内存地址,equals()比较两个对象所指向的内存地址的值,比如说
Java codeString a=new String("1");
String b=new String("1");
System.out.println(a==b); [color=#FF0000]false[/color]
System.out.println(a.equals(b)); [color=#FF0000]true[/color]
a.equals(b)比的就是a的值(相当于"1"的内存地址)和b,a本身也占有一个地址的。
你不用new它就在编译时创建,存储在stack、静态存储区、常量存储区中
一旦你new了,new后面的东西要等到运行时在heap中创建,new前面的东西还是在编译时创建存储在stack中
所以a和b是指向不同的内存地址的,==就返回false,equals就返回true
Java codeStringBuffer a=new StringBuffer("1");
StringBuffer b=new StringBuffer("1");
System.out.println(a==b); [color=#FF0000]false[/color]
System.out.println(a.equals(b)); [color=#FF0000]false[/color]
而StringBuffer为什么会不行呢?
因为StringBuffer没有重写equals()方法,所以它的equals还是Object.equals(Object o),比较的还是他们所指向的对象的内存地址,也就是他们是否指向同一个对象,与==号一样。
大多数类都重写了equals()方法,Integer、Float、Date、String、ArrayList、HashMap等,没有重写equals()的方法也有很多,比如StringBuffer、StringBuilder等。
哪个类有没有重写equals(),API上都有,看它的方法中有没有equals()就是了。
还有个比较特殊的String,有着值类型的特征,但是本身却是引用类型
JVM专门为String在内存中分配了一个String常量池,每次创建String类型的变量时申明部分在stack中创建,只要你不new,=号后面的它会从String常量池中查找是否已经存在要创建的值,存在就直接指向它,否则就在stack中创建一个新的对象,如果new了那就跟引用类型一样。那下面的例子也不难理解了。
Java codeString a="1";
String b="1";
System.out.println(a==b); [color=#FF0000]true[/color]
System.out.println(a.equals(b)); [color=#FF0000]true[/color]
申明部分a首先在stack中创建,不存在"1",在String常量池中创建"1",b再次创建时发现String常量池中有了"1",直接指向它,所以他们指向同一个对象,也就是指向的对象的地址相同。
常量前置的优点:
在许多代码中都能见到比较对象/变量是否为空,代码如下:
但是常常我们可以看到这样的代码:
if (null != obj)
...
把null写在前面有什么样的好处呢?
这个习惯是这样来的。最早学C编程的时候,像if(a=b)这样的条件是编译通过的,尽管你的意思是if(a==b)。
为了避免出现这种低级错误,写判断的时候习惯把常量写在前边,因为即使出现了if(null=a)这样的错误,也会被编译器提示错误,因为你不能给常量再赋值。
另外,我们知道equals方法判断的时候把常量放在前面可以防止空指针异常:
if ("".equals(obj))
相关推荐
6. **字符串比较**:使用`equals()`或`compareTo()`方法进行字符串内容的比较,注意区分字面量和引用的比较。 7. **正则表达式**:强大的字符串匹配工具,能进行复杂的查找、替换和验证操作。 此外,字符串处理还...
JavaSE专题-Set集合 Set集合是JavaSE中的一种重要数据结构,主要包括HashSet、TreeSet和LinkedHashSet三个子类。下面我们将对Set集合的原理、特点、使用场景等进行详细的探索和分析。 HashSet HashSet是Set集合中...
6. **安全验证**:使用了`equals`方法进行字符串比较,这可能是对用户输入的密码或登录信息进行验证的过程。 7. **代码逻辑控制**:通过`boolean`类型的变量进行条件判断,例如登录成功后进行界面跳转,不成功则提示...
"equals"在大多数情况下也是比较对象的值,但默认行为是对引用的比较,除非被重写,如String、Integer等类中,"equals"已重写为比较对象的内容。 3. **hashCode()与equals()的关系**: 两个对象的hashCode()相同并...
而equals方法通常用于比较对象的内容,大多数类默认实现与==相同,但像String、Integer等类重写了equals方法以比较对象内容。 3. **hashCode()与equals()的关系**: 两个对象的hashCode()相同,并不意味着它们的...
Java基础知识点面试专题涵盖了许多Java编程的核心概念,这些知识点经常在面试中被考察。下面将逐一解析这些关键点。 1. `==`与`equals()`和`hashCode()`的区别: - `==`:用于比较基本类型时,直接比较值;对于...
首先,我们来看`==`、`equals`和`hashCode`的区别。`==`在Java中用于比较基本数据类型时,直接比较数值是否相等;对于引用类型,它比较的是两个引用是否指向内存中的同一位置,即对象的地址。`equals`是`Object`类中...
`Object`是所有Java类的顶级父类,包含所有对象共有的方法,如`equals()`、`hashCode()`和`toString()`。 12. **Math类**: `Math`类提供了一系列用于执行基础数学运算的方法,如`Math.pow()`(指数运算)、`Math...
【Java基础面试专题1】 Java 是一种面向对象的编程语言,其核心概念包括封装、继承和多态。封装是将数据和操作数据的方法绑定在一起,保护数据不被随意访问;继承则是子类继承父类的属性和方法,使得代码复用更加...
### JAVA 专题课程-Cookies入门知识点总结 #### 1. 什么是Cookie? - **定义**:Cookie是一种由服务器端产生的小文本文件,用于记录用户的相关信息,并存储在客户端(通常是浏览器)。当用户再次访问该网站时,...
JAVA集合框架专题 JAVA集合框架是JAVA编程语言中的一种常用的数据结构,用于存储和操作对象信息。下面是JAVA集合框架的主要知识点: 一、集合框架概述 JAVA集合框架是一种容器,用于存储对象信息。所有集合类都...
- 错误使用`==`与`equals()`方法比较非原始类型对象。 - 不熟悉不同平台上的线程调度机制,如抢占式调度。 - 不清楚新线程和本地线程的差异。 - 对Hotspot虚拟机优化技术及JIT编译器的工作原理理解不深。 - API使用...
if (x.equals(BigInteger.ZERO)) break; sum = sum.add(x); } System.out.println(sum); ``` B - Product 类似地,第二个问题要求我们计算两个大整数的乘积。同样使用 `BigInteger` 类,我们读取两个输入值并使用...
Scala 函数式编程专题 -- Scala 基础语法介绍 本文主要介绍 Scala 基础语法的相关知识点,旨在帮助读者更好地理解和学习 Scala 编程语言。 一、Scala 语言简介 Scala 是一种现代化的、多范式的编程语言,运行于 ...
4. **Object类**:学习equals(), hashCode(), clone()等方法的默认实现和重写规则。 **JVM相关** JVM(Java虚拟机)是Java程序运行的基础,掌握JVM的工作原理对于优化程序性能至关重要: 1. **内存模型**:理解堆...
Java作为一门广泛使用的编程语言,其面试题涵盖了众多的知识领域,包括基础概念、核心特性、高级专题以及与其他技术的交互。以下将详细解读标题、描述中提到的重点知识点,并结合JavaSE的基础内容进行深入探讨。 ...
4. "A widely held belief, as proved by practice, that a fun-filled, pain-free life equals happiness actually reduces people’s chances of attaining real happiness.","that"引导的同位语从句解释"belief...
例如,对象创建和初始化过程中的细微差别,如何正确实现`Cloneable`和`Serializable`接口,以及`equals`方法的正确重写,确保对象的平等性判断。不可变性(Immutability)和多线程环境下的同步(Synchronization)...