补充:
1.定义的位置不一样【重点】
- 局部变量:在方法的内部
- 成员变量:在方法的外部,直接写在类当中
2.作用范围不一样【重点】
- 局部变量:只有方法当中才可以使用,出了方法就不能再用了
- 成员变量:整个类都可以通用
3.默认值不一样【重点】
- 局部变量:没有默认值,如果要想使用,必须手动进行赋值
- 成员变量:如果没有赋值,会有默认值,规则和数组一样
4.内存的位置不一样(了解)
- 局部变量:位于栈内存
如果是基本类型,会把值直接存储在栈; 如果是引用类型,比如String s = new String("william");会把其对象存储在堆,而把这个对象的引用(指针)存储在栈。
-
String s1 = new String(“william”); String s2 = s1; s1和s2同为这个字符串对象的实例,但是对象只有一个,存储在堆,而这两个引用存储在栈中。
- 成员变量:位于堆内存
-
在不同对象中各不相同,都有自己的存储空间(成员变量在堆中的对象中),基本类型和引用类型的成员变量都在这个对象的空间中,作为一个整体存储在堆。 而类的方法却是该类的所有对象共享的,只有一套,对象使用方法的时候方法才被压入栈,方法不使用则不占用内存。
5.生命周期不一样(了解)
- 局部变量:随着方法进栈而诞生,随着方法出栈而消失
- 成员变量:随着对象的创建而诞生,随着对象被垃而消失
在Java学习和面试中经常遇到这个问题,虽然想着简单,但还是决定记录下来,毕竟菜嘛..
==:
==是直接比较的两个对象的堆内存地址,如果相等,则说明这两个引用实际是指向同一个对象地址的。但是我们又常常碰到这样一个问题
最终结果是 true,true,false,那既然==是比较的地址,那么int数据的地址是怎样的呢,String又是怎样的呢?
对于基本数据类型(byte,short,char,int,float,double,long,boolean)来说,他们是作为常量在方法区中的常量池里面以HashSet策略存储起来的,对于这样的字符串 "123" 也是相同的道理,在常量池中,一个常量只会对应一个地址,因此不管是再多的 123,"123" 这样的数据都只会存储一个地址,所以所有他们的引用都是指向的同一块地址,因此基本数据类型和String常量是可以直接通过==来直接比较的。
另外,对于基本数据的包装类型(Byte, Short, Character,Integer,Float, Double,Long, Boolean)除了Float和Double之外,其他的六种都是实现了常量池的,因此对于这些数据类型而言,一般我们也可以直接通过==来判断是否相等。那么再出一个问题考考大家 ↓
结果是 true,false。没想到吧!其实是因为 Integer 在常量池中的存储范围为[-128,127],127在这范围内,因此是直接存储于常量池的,而128不在这范围内,所以会在堆内存中创建一个新的对象来保存这个值,所以m,n分别指向了两个不同的对象地址,故而导致了不相等。
equals方法:
之前在网上也搜了很多相关的问题,但给出的答案却不尽人意,很多网友都说equals比较的是对象的内容,这样的说法是不准确的。首先我们来看看在Object类中定义的equals方法 ↓
可以看到,在Object类型的equals方法是直接通过==来比较的,和==是没有任何区别的。
那么为什么又要说equlas和==的区别呢?是因为equals方法是可以由我们自己重写的。
众所周知,我们所有的类都直接或间接地继承自java.lang.Object类,因此我们可以通过重写equals方法来实现我们自己想要的比较方法。来看看eclipse为我们自动生成的equals方法 ↓
。
可以看出,eclipse还是很智能的,它首先是判断两个对象的地址是否相等,若不相等再进行下面的成员变量判断。
但这个方法体是完全可以由我们自己实现的,即便是我们直接 return true 都是可以的,只要能满足我们的业务需求,怎样写都是无所谓的,因此,equals比较的并不一定是对象的内容,它还可以由其他的信息来指导比较
背景介绍
== 比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,即是否是指相同一个对象。比较的是真正意义上的指针操作。
equals用来比较的是两个对象的内容是否相等,由于所有的类都是继承自java.lang.Object类的,所以适用于所有对象,如果没有对该方法进行覆盖的话,调用的仍然是Object类中的方法,而Object中的equals方法返回的却是==的判断。