18-Java-核心类库1-常用类库介绍及Object类的equals()、hashCode()、toString()方法
一、java中常用的类库包,以JDK1.8目录截图为例,把java的jdk1.8全部背住就牛逼了(我能背目录)
主要常用的包有(把所有包记住才是强者)
java.lang包:这个包是java语言的核心包,该包中的所有内容由java虚拟机自动导入。该包下常用的类有java.lang.String/Double/.../System等类。
java.util包:这个包java语言的工具包,提供了大量的工具类和集合类等内容。该包下常用的类有java.util.Scanner/Random/.../Arrays等类。
java.io包:这个包是java语言的输入输出包,里面提供了大量的读写文件的相关类。该包下常用的类有java.io.PrintStream/.../InputStream等类。
java.net包:这个包是java语言的网络包,里面提供了大量网络通信相关的类的内容。该包下常用的类有java.net.ServerSocket类/Socket类等。
java.lang.reflect包:这个包是java语言的反射包,里面提供了一些反射相关的类。通过反射可以写一些封装类,写一些框架等。
二、Object类(java.lang.Object)
public class Object
简述:Object
类是类层次结构的根。每个类都有 Object
作为超类。所有对象,包括数组,实现这个类的方法。
Object类中包含的方法:(这些方法是所有类都可调用的)
protected Object clone() throws CloneNotSupportedException 用于创建并返回此对象的副本。
public boolean equals(Object obj) 用于指示是否有其他对象“等于”这一个对象(对象之间的比较)。
protected void finalize() throws Throwable 当垃圾收集确定没有对对象的引用时,由对象上的垃圾收集器调用。
public final 类<?> getClass() 返回该 Object
运行时类。
public int hashCode() 返回一个对象的哈希代码值。
public final void notify() 唤醒一个在这个对象的监视器上等待的单个线程。
public final void notifyAll() 唤醒正在等待此对象监视器上的所有线程。
public String toString() 返回对象的字符串表示形式。
public final void wait() throws InterruptedException 使当前线程等待另一个线程调用此对象的方法或 notify()
notifyAll()
方法。
public final void wait(long timeout) throws InterruptedException 同wait(),或一个指定的时间流逝。
public final void wait(long timeout, int nanos) throws InterruptedException。同wait(),或者其他某个线程中断当前线程,或一定量的实际时间已经过去了。
重点总结一下equals()、hashCode()、toString()方法:
public boolean equals(Object obj):指示是否有其他对象“等于”这一个。
equals
方法实现了对非空对象引用的一个等价关系:
1.它是空的自反:对于任何非空的参考价值x
,x.equals(x)
应该返回true
。
2.它是空的对称的:对于任何非空的参考值x
和y
,x.equals(y)
应该返回true
当且仅当y.equals(x)
返回true
。
3.它是空的传递:对于任何非空的参考值x
,y
,和z
,如果x.equals(y)
返回true
和y.equals(z)
返回true
,然后x.equals(z)
应该返回true
。
4.它是空的一致的:对于任何非空的参考值x
和y
,多次调用x.equals(y)
始终返回true
或始终返回false
,没有提供信息用于equals
比较对象被修改。
5.对于任何非空的参考价值x
,x.equals(null)
应该返回false
。
注意:这类Object
equals
方法实现对象上差别可能性最大的等价关系;
就是说,对于任何非空的参考值x
和y
,此方法返回true
当且仅当x
和y
引用同一个对象(x == y
有价值true
)。
请注意它一般是必要覆盖hashCode
方法重写此方法,以保持对hashCode
方法的一般合同,即平等的对象必须具有相等的散列码
下面是人话翻译:
1.该方法默认比较两个对象的地址,与“ == ”效果等效
2.如需要比较对象的内容,则需要进行方法的重写
3.若该方法重写了,则应该去重写hashCode()方法,目的是为了满足hashCode常规协定
public int hashCode():返回一个对象的哈希代码值(内存地址和编号等)。这种方法对于hash表,如所提供的 HashMap
利益支持。
对hashCode
一般合同:
1.不管是调用同一对象的多一个java应用程序执行期间,该hashCode
方法总是返回相同的整数,没有提供信息用于equals
比较的对象被修改。
这个整数不需要保持一致,从一个应用程序的一个执行到另一个执行相同的应用程序。
2.如果根据equals(Object)
法两个对象是相等的,那么调用hashCode
方法每一个对象必须产生相同的整数结果。
3.它不是必需的,如果按照equals(java.lang.Object)
法两个对象是不平等的,然后调用hashCode
方法每一个对象必须产生不同的整数结果。
然而,程序员应该意识到,产生不同的整数结果的不平等的对象可能会提高哈希表的性能。
4.尽合理的切实可行,由类Object
定义hashCode方法返回不同的对象不同的整数。
(这通常是通过将该对象的内部地址转换成一个整数,但这不是实现实现技术的™java编程语言。要求)
下面人话翻译:
1.若两个对象调用的equals()方法相等,则各自调用hashCode()方法得到的哈希码值必须相同。
2.若两个对象调用的equals()方法不相等,则各自调用hashCode()方法得到的结果相同。
public string toString() :返回对象的字符串表示形式。
总的来说,这 toString
方法返回一个字符串,“以文本方式表示”这个对象。
其结果应该是一个简洁,但翔实的代表性,是一个容易阅读的人。建议所有子类都重写此方法。
Object
类的toString
方法返回一个包含该类的对象是一个实例的名称字符串的符号' @
',和符号进制表示的对象的哈希码。
换句话说,此方法返回一个等于值的字符串:
getClass().getName() + '@' + Integer.toHexString(hashCode())
(1)没任何重写的两个对象的比较(代码演示):
第一部分:一个学生类
1 public class student { 2 private int id; 3 private String name; 4 5 public int getId() { 6 return id; 7 } 8 public void setId(int id) { 9 this.id = id; 10 } 11 public String getName() { 12 return name; 13 } 14 public void setName(String name) { 15 this.name = name; 16 } 17 18 public student(int id, String name) { 19 super(); 20 this.id = id; 21 this.name = name; 22 } 23 public student() { 24 super(); 26 } 27 }
第二部分:调用部分
1 public class TestObjectEquals { 2 public static void main(String[] args){ 3 student s1 = new student(1001,"张三"); 4 student s2 = new student(1001,"张三");//都为张三,突出相同 5 6 System.out.println("s1的地址:"+s1+" "+"s2的地址:"+s2); 7 boolean check1 = s1.equals(s2); 8 System.out.println("check1:"+check1);//check1 == false,两个对象地址不同 9 System.out.println("check2:"+(s1 == s2));//check1 == false,原因同上
10
11 System.out.println("s1的hashCode:"+s1.hashCode()+" "+"s2的hashCode:"+s2.hashCode()); 12 } 13 }
第三部分:运行结果
(2)倘若想比较两个学生的学号相等,则两个对象相等,需在第一部分中的学生类中重写equals()方法和hashCode()方法
第一部分:重写equals()方法和hashCode()方法后的学生类
1 public class student { 2 private int id; 3 private String name; 4 5 public int getId() { 6 return id; 7 } 8 public void setId(int id) { 9 this.id = id; 10 } 11 public String getName() { 12 return name; 13 } 14 public void setName(String name) { 15 this.name = name; 16 } 17 18 public student(int id, String name) { 19 super(); 20 this.id = id; 21 this.name = name; 22 } 23 public student() { 24 super(); 26 } 27 28 @Override 29 public boolean equals(Object obj){//子类重写object类的方法,子类调用该方法则执行子类重写后的该方法 30 //1.若调用对象不为空,参数对象为空,则不相等 31 if(obj == null) 32 return false; 33 //2.若调用对象与参数对象的地址相同,则相等 34 if(this == obj) 35 return true; 36 //3.若调用调用对象与参数对象的类型一致,由对象内容中的学号来决定两个对象是否相等(取代Object类默认的比较地址) 37 if(obj instanceof student){ 38 student s = (student)obj; 39 return s.getId() == this.getId();//此处判断int型的学号 40 } 41 //4.若调用对象与参数对象的类型不一致,则不相等 42 else 43 return false; 44 }
45 @Override
46 public int hashCode(){//重写后若两个对象学号相等,则这两个对象的信息则相等,若重写hashCode(),两个对象的信息还是不一样。
47 return this.getId();
48 } 49 }
第二部分:重写equals()方法和hashCode()方法后的调用部分
1 public class TestObjectEquals { 2 public static void main(String[] args){ 3 student s1 = new student(1001,"张三"); 4 student s2 = new student(1001,"李四");//修改为的李四,突出不同 5 6 System.out.println("s1的地址:"+s1+" "+"s2的地址:"+s2); 7 boolean check1 = s1.equals(s2); 8 System.out.println("check1:"+check1);//两个对象学号相同check1 == true 9 System.out.println("check2:"+(s1 == s2));//两个对象地址不同check2 == false
10
11 System.out.println("s1的hashCode:"+s1.hashCode()+" "+"s2的hashCode:"+s2.hashCode()); 12 } 13 }
第三部分:重写equals()方法和hashCode()方法后的执行结果
(3)倘若想直接输出两个对象的信息,而不是输出"包.类名称@符号进制表示的对象的hashCode"的形式,需在第一部分中的学生类中重写toString()方法
第一部分:重写toString()方法后的学生类
1 public class student { 2 private int id; 3 private String name; 4 5 public int getId() { 6 return id; 7 } 8 public void setId(int id) { 9 this.id = id; 10 } 11 public String getName() { 12 return name; 13 } 14 public void setName(String name) { 15 this.name = name; 16 } 17 18 public student(int id, String name) { 19 super(); 20 this.id = id; 21 this.name = name; 22 } 23 public student() { 24 super(); 25 // TODO Auto-generated constructor stub 26 } 27 28 @Override 29 public boolean equals(Object obj){//子类重写object类的方法,子类调用该方法则执行重写后子类的该方法 30 //1.若调用对象不为空,参数对象为空,则不相等 31 if(obj == null) 32 return false; 33 //2.若调用对象与参数对象的地址相同,则相等 34 if(this == obj) 35 return true; 36 //3.若调用调用对象与参数对象的类型一致,由对象内容中的学号来决定两个对象是否相等(取代Object类默认的比较地址) 37 if(obj instanceof student){ 38 student s = (student)obj; 39 return s.getId() == this.getId();//此处判断int型的学号 40 } 41 //4.若调用对象与参数对象的类型不一致,则不相等 42 else 43 return false; 44 } 45 @Override 46 public int hashCode(){ 47 return this.getId(); 48 } 49 @Override 50 public String toString(){ 51 return " 学号:"+this.getId()+"姓名:"+this.getName(); 52 } 53 }
第二部分:重写toString()方法后的调用部分
1 public class TestObjectEquals { 2 public static void main(String[] args){ 3 student s1 = new student(1001,"张三"); 4 student s2 = new student(1001,"李四");//修改为的李四,突出不同 5 6 System.out.println("s1的信息:"+s1+" "+"s2的信息:"+s2);//自动调用了toString()方法 7 boolean check1 = s1.equals(s2); 8 System.out.println("check1:"+check1);//两个对象学号相同check1 == true 9 System.out.println("check2:"+(s1 == s2));//两个对象地址不同check2 == false 10 11 System.out.println("s1的hashCode:"+s1.hashCode()+" "+"s2的hashCode:"+s2.hashCode()); 12 13 System.out.println(s1);//自动调用了toString()方法 14 System.out.println(s2); 15 } 16 }
第三部分:重写toString()方法后的执行结果
面试字符串String比较相等的坑题:
代码:
1 public class TestStringEquals { 2 public static void main(String[] args){ 3 //String类重写了equals()、hashCode()、toString()方法 4 String t1 = "123"; 5 String t2 = "123"; 6 String s1 = new String("123"); 7 String s2 = new String("123"); 8 9 boolean check1 = (t1 == t2); 10 boolean check2 = (t1.equals(t2)); 11 boolean check3 = (t1 == s1); 12 boolean check4 = (t1.equals(s1)); 13 boolean check5 = (s1 == s2); 14 boolean check6 = (s1.equals(s2)); 15 boolean check7 = (s1.hashCode() == s2.hashCode()); 16 17 System.out.println("check1 = "+check1);//true,原因如下(涉及常量池)。 18 //出于性能的考虑,JVM会将字面量对象缓存在常量池中; 19 //对于重复出现的字符串直接量,JVM会先在常量池中查找,不会重复创建一个新对象,直接返回之前的对象地址。 20 21 System.out.println("check2 = "+check2);//true,String类重写了equals()方法,并且此时两个对象的地址、hashCode都是相同的 22 23 System.out.println("check3 = "+check3);//false,对象地址不相等 24 25 System.out.println("check4 = "+check4);//true,String类重写了equals()方法,并且此时两个对象的hashCode都是相同的 26 27 System.out.println("check5 = "+check5);//false,对象地址不相等 28 29 System.out.println("check6 = "+check6);//true,String类重写了equals()方法,并且此时两个对象的hashCode都是相同的 30 31 System.out.println("check7 = "+check7);//true,String类重写了hashCode()方法 32 } 33 }
运行结果:
以上内容有不对或是不懂的地方请评论区留言哟,我会及时回复的。谢谢耐心阅读。