(一) ==
java中数据类型分为两类:
(1)基本数据类型:byte,char,short,int,float,double,long,boolean。当比较基本数据类型的时候用 == 比较的是他们的值。
(2)引用类型(类,数组,接口):当用等号比较这三种类型的时候比较的是内存中存放的地址。
对象是存放在堆中的,栈中存放的是对象的引用地址,所以用 == 比较时比较的时栈中存放的值。
实例1:
public static void main(String[] args) {
int int1 = 12;
int int2 = 12;
Integer Integer1 = new Integer(12);
Integer Integer2 = new Integer(12);
Integer Integer3 = new Integer(127);
Integer a1 = 127;
Integer b1 = 127;
Integer a = 128;
Integer b = 128;
String s1 = "str";
String s2 = "str";
String str1 = new String("str");
String str2 = new String("str");
//int1==int2:true
System.out.println("int1==int2:" + (int1 == int2));
//int1==Integer1:true 这里Integer1自动拆箱成int,所以为true
System.out.println("int1==Integer1:" + (int1 == Integer1));
//Integer1==Integer2:false 这是两个不同的对象,在内存中存放的地址不同
System.out.println("Integer1==Integer2:" + (Integer1 == Integer2));
//Integer3==b1:false Integer3指向new的对象地址,b1只想缓存中的127地址,地址不同
System.out.println("Integer3==b1:" + (Integer3 == b1));
//a1==b1:true Integer查看源码就知道对于-128 -- 127之间的数会进行直接缓存,
//当Integer a1时会将127进行缓存,在写Integer b1时会去缓存中直接读取,不会new,所以相等
System.out.println("a1==b1:" + (a1 == b1));
//a==b:false 同a1,b1不同他每次都会new
System.out.println("a==b:" + (a == b));
//s1==s2:true 这两个都是String字符串常量,存在静态区
System.out.println("s1==s2:" + (s1 == s2));
//s1==str1:false
System.out.println("s1==str1:" + (s1 == str1));
//str1==str2:false
System.out.println("str1==str2:" + (str1 == str2));
}
补充:
JVM内存分四种:1、栈区(stacksegment)—由编译器自动分配释放,存放函数的参数值,局部变量的值等,具体方法执行结束之后,系统自动释放JVM内存资源2、堆区(heapsegment)—一般由程序员分配释放,存放由new创建的对象和数组,jvm不定时查看这个对象,如果没有引用指向这个对象就回收3、静态区(datasegment)—存放全局变量,静态变量和字符串常量,不释放
4、代码区(codesegment)—存放程序中方法的二进制代码,而且是多个对象共享一个代码空间区域
(二):equals()
JAVA当中所有的类都是继承于Object这个超类的,在Object类中定义了一个equals的方法,这个方法的初始行为是比较对象的内存地址,但在一些类库当中这个方法被复写了,如String、Integer、Date。在这些类当中equals有其自身的实现,而不再是比较类在堆内存中的存放地址了。
所以说,对于复合数据类型之间进行equals比较,在没有覆写equals方法的情况下,他们之间的比较还是内存中的存放位置的地址值,跟双等号(==)的结果相同;如果被复写,按照复写的要求来。
【特别注意】Object类中的equals方法和“==”是一样的,没有区别,而String类,Integer类等等一些类,是重写了equals方法,才使得equals和“==不同”,所以,当自己创建类时,自动继承了Object的equals方法,要想实现不同的等于比较,必须重写equals方法。
"=="比"equal"运行速度快,因为"=="只是比较引用.
注意规范:"".equals(str);而不是str.equals("");因为str可能为空,这容易出错,所以一般将需要被比较的常量写在前面。
补充: equals 方法实现的规则
自反性:对于任何非空引用值 x,x.equals(x) 都应返回 true。对称性:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应返回 true。
传递性:对于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 应返回 true。
一致性:对于任何非空引用值 x 和 y,多次调用 x.equals(y) 始终返回 true 或始终返回 false,前提是对象上 equals 比较中所用的信息没有被修改。
对于任何非空引用值 x,x.equals(null) 都应返回 false。(三):hashcode()
关于Object 类中hashCode() 方法的实现。。对象的Object类的哈希码的值 是一个和该对象内存地址有关的一个int值。
不同对象的内存地址是不同的。
返回该对象的哈希码值。支持此方法是为了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。
hashCode 的常规协定是:
在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。
如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不 要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。
实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)
哈希码,又叫做散列码。
得到对象的哈希码:要求对象的哈希码均匀的散列在正数 的取值范围内。可以让对象均匀的散列在哈希表的线性表中。
hashCode 方法 用来确定对象在线性表中的位置。和高速访问元素。
equals 用来保证set中的元素的唯一性
对于两个对象来说,如果对象对应的类型中没有重写hashCode方法。如果两个对象的哈希码值相同,说明了什么?说明两个对象是同一个对象,指向了同一个内存区域。