Object类
JDK类库的根类:Object
类中方法所有子类通用,所有类默认继承Object,
1. 常用方法
查询所有方法:
- 查源代码(C:\Program Files\Java\jdk1.8.0_301\src\java\lang\object.java):麻烦、代码难懂
- 查阅Java类库帮助文档
什么是API?
API = Application Program Interface 应用程序编程接口
SUN公司提前写好的,整个JDK的类库,就是一个JavaSE的API
每个API都配置帮助文档(https://docs.oracle.com/javase/8/docs/api/)
常用方法:
protected Object clone() //负责对象克隆
boolean equals(Object obj) //判断两对象是否相等
protected void finalize() //负责调用垃圾回收器
int hashCode() //获取对象哈希值
String toString() //讲对象换成字符串形式
2. toString()方法
源码
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
//类名@对象的内存地址转换为十六进制的形式
作用
将一个Java对象转换成字符串表示形式,建议所有子类都重写toString()方法。
练习
package com.comclass;
import com.comclass.demo01.MyTime;
public class Application {
public static void main(String[] args) {
MyTime myTime = new MyTime(1990,11,1);
String s1 = myTime.toString();
//重写前,不简洁,不容易阅读,日期对象转换成字符串后还希望看见日期
System.out.println(s1); //com.comclass.demo01.MyTime@1b6d3586
}
}
/*
package com.comclass.demo01;
public class MyTime {
int year;
int month;
int day;
public MyTime(){
}
public MyTime(int year, int month, int day){
this.year = year;
this.month = month;
this.day = day;
}
}
*/
重写前,toString()方法不简洁,不容易阅读,日期对象转换成字符串后还希望看见日期。
所以需要重写,原则要简洁、翔实、易阅读
package com.comclass;
import com.comclass.demo01.MyTime;
public class Application {
public static void main(String[] args) {
MyTime myTime = new MyTime(1990,11,1);
String s1 = myTime.toString();
System.out.println(s1); //1990年11月1日
}
}
/*
package com.comclass.demo01;
public class MyTime {
int year;
int month;
int day;
public MyTime(){
}
public MyTime(int year, int month, int day){
this.year = year;
this.month = month;
this.day = day;
}
//重写
@Override
public String toString() {
return this.year+"年"+this.month+"月"+this.day+"日";
}
}
*/
注意:输出引用的时候,会自动调用该引用的toString()方法。
System.out.println(s1); //1990年11月1日
以后toString()都自己重写
3. equals()方法
源码
public boolean equals(Object obj) {
return (this == obj);
}
作用
判断两个对象是否相等
Object类中默认使用“==”判断两个对象是否相等,而双等号判断的是对象内存地址,所以要判断对象内容,需要子类重写equsals();
package com.comclass;
import com.comclass.demo02.MyTime;
import sun.security.mscapi.CPublicKey;
public abstract class Application {
public static void main(String[] args) {
//判断基本数据,双等号判断a,b中的100是否相等
int a = 100;
int b = 100;
System.out.println(a == b); //true
//判断引用类型(对象),双等号比较的是对象内存地址
MyTime myTime1 = new MyTime(2008,8,8); //MyTime myTime1 = 0x1234
MyTime myTime2 = new MyTime(2008,8,8); //MyTime myTime2 = 0x3456
MyTime myTime3 = new MyTime(2008,8,9);
System.out.println(myTime1 == myTime2); //false
//Object类给的equals方法不够用
//重写前
//System.out.println(myTime1.equals(myTime2)); //false
//重写后
String s = "hhhh";
System.out.println(myTime1.equals(myTime2)); //true
System.out.println(myTime1.equals(s)); //false对象类型不同
System.out.println(myTime1.equals(myTime3)); //false
}
}
/*
package com.comclass.demo02;
public class MyTime {
int year;
int month;
int day;
public MyTime(){
}
public MyTime(int year, int month, int day){
this.year = year;
this.month = month;
this.day = day;
}
//重写
public boolean equals(Object obj){
if(obj instanceof MyTime){
MyTime mt = (MyTime)obj;
if(this.year == mt.year && this.month == mt.month && this.day == mt.day){
return true;
}
}
return false;
}
}
*/
改良的equals()方法
//改良
public boolean equals(Object obj){
if(obj == null){
return false;
}
if(!(obj instanceof MyTime)){
return false;
}
if(this == obj){ //内存地址相同指向同一对象
return true;
}
MyTime mt = (MyTime)obj;
if(this.year == mt.year && this.month == mt.month && this.day == mt.day){
return true;
}
return false;
}
package com.comclass;
import com.comclass.demo02.MyTime;
import sun.security.mscapi.CPublicKey;
public abstract class Application {
public static void main(String[] args) {
//判断基本数据,双等号判断a,b中的100是否相等
int a = 100;
int b = 100;
System.out.println(a == b); //true
//判断引用类型(对象),双等号比较的是对象内存地址
MyTime myTime1 = new MyTime(2008,8,8); //MyTime myTime1 = 0x1234
MyTime myTime2 = new MyTime(2008,8,8); //MyTime myTime2 = 0x3456
MyTime myTime3 = new MyTime(2008,8,9);
MyTime myTime4 = null;
System.out.println(myTime1 == myTime2); //false
//Object类给的equals方法不够用
//重写前
//System.out.println(myTime1.equals(myTime2)); //false
//重写后
String s = "hhhh";
System.out.println(myTime1.equals(myTime2)); //true
System.out.println(myTime1.equals(s)); //false对象类型不同
System.out.println(myTime1.equals(myTime3)); //false
System.out.println(myTime1.equals(myTime4)); //false
}
}
超级改良
//超级改良
public boolean equals(Object obj){
if(obj == null || !(obj instanceof MyTime)){
return false;
}
if(this == obj){ //内存地址相同指向同一对象
return true;
}
MyTime mt = (MyTime)obj;
return this.year == mt.year && this.month == mt.month && this.day == mt.day;
}
String类有没有重写toString()方法和equals()方法?
重写了
比较两个字符串不能使用双等号,必须用equals()方法
String类有没有重写toString方法?
重写了
Java中基本数据类型使用""=="判断相等
Java中引用数据类型使用equals判断相等
练习
package com.comclass;
import java.util.Locale;
public abstract class Application {
public static void main(String[] args) {
//一般创建字符串
String s1 = "hello";
String s2 = "abc";
//实际上String作为一个类
//存在构造方法
String s3 = new String("Test1");
String s4 = new String("Test1");
//new两次,内存地址不同
System.out.println(s3 == s4); //false
//比较字符串,不能使用双等号,必须用equals()
//String重写了equals()方法
System.out.println(s3.equals(s4)); //true
//String有没有重写toString
String x = new String("动力节点");
//没重写结果为:类名@十六进制地址
//重写结果为:字符串
System.out.println(x.toString()); //动力节点
System.out.println(x); //动力节点
//输出字符串x,默认调用toString,.toSting可以不写
}
}
package com.comclass.demo04;
public class Student {
int id;
String school;
public Student(){
}
public Student(int id, String school) {
this.id = id;
this.school = school;
}
//重写toString
@Override
public String toString() {
return "学号:" + id +", 所在学校:" + school;
}
//重写equals
public boolean equals(Object obj){
if(obj == null || !(obj instanceof Student)){
return false;
}
if(this == obj){
return true;
}
Student st = (Student) obj;
return st.id == this.id && this.school.equals(st.school);
}
}
/*
package com.comclass;
import com.comclass.demo04.Student;
import java.util.Locale;
public abstract class Application {
public static void main(String[] args) {
Student s1 = new Student(203,"TJ");
Student s2 = new Student(203,"SJ");
Student s3 = new Student(203,"TJ");
System.out.println(s1.toString());
System.out.println(s2.toString());
System.out.println(s1.equals(s2)); //false
System.out.println(s1 == s3); //false
System.out.println(s1.equals(s3)); //true
}
}
*/
new出来的字符串不可以用双等号判断,但是直接赋值的字符串可以用双等号判断。
package com.comclass.demo04;
public class Student {
int id;
String school;
public Student(){
}
public Student(int id, String school) {
this.id = id;
this.school = school;
}
//重写toString
@Override
public String toString() {
return "学号:" + id +", 所在学校:" + school;
}
//重写equals
public boolean equals(Object obj){
if(obj == null || !(obj instanceof Student)){
return false;
}
if(this == obj){
return true;
}
Student st = (Student) obj;
//return st.id == this.id && this.school.equals(st.school);
return st.id == this.id && this.school == st.school;
}
}
/*
package com.comclass;
import com.comclass.demo04.Student;
public abstract class Application {
public static void main(String[] args) {
Student s1 = new Student(203,"TJ");
Student s2 = new Student(203,"SJ");
Student s3 = new Student(203,"TJ");
Student s4 = new Student(203,new String("TJ"));
System.out.println(s1.toString());
System.out.println(s2.toString());
System.out.println(s1.equals(s2)); //false
System.out.println(s1 == s3); //false
System.out.println(s1.equals(s3)); //true
System.out.println(s1.equals(s4)); //false
}
}
*/
package com.comclass;
import com.comclass.demo04.Student;
import com.comclass.demo05.Address;
import com.comclass.demo05.User;
public abstract class Application {
public static void main(String[] args) {
//Address addr = new Address("上海", "四平路", "200092");
//User u = new User("GY",addr);
User u1 = new User("GY", new Address("上海", "四平路", "200092"));
User u2 = new User("GY",new Address("上海", "四平路", "200092"));
User u3 = new User("GY",new Address("上海", "彰武路", "200093"));
System.out.println(u1.equals(u2)); //true
System.out.println(u1.equals(u3)); //false
}
}
/*
package com.comclass.demo05;
public class User {
String name; //保存的内存地址
Address addr;
public User(){ }
public User(String name, Address addr){
this.addr = addr;
this.name = name;
}
public boolean equals(Object obj){
if(obj == null || !(obj instanceof User)) return false;
if(obj == this){
return true;
}
User u = (User) obj;
return this.name.equals(u.name) && this.addr.equals(u.addr);
}
}
*/
/*
package com.comclass.demo05;
public class Address {
String city;
String street;
String zipcode;
public Address(){
}
public Address(String city, String street, String zipcode) {
this.city = city;
this.street = street;
this.zipcode = zipcode;
}
@Override
public boolean equals(Object obj) {
if(obj == null || !(obj instanceof Address)) return false;
if(obj == this){
return true;
}
Address addr = (Address) obj;
return this.city.equals(addr.city) &&
this.street.equals(addr.street) &&
this.zipcode.equals(addr.zipcode);
}
}
*/
4. finalize()方法
源码
protected void finalize() throws Throwable{
}
protected修饰的,只有方法体
无需手动调用
JVM的垃圾回收器回收垃圾时自动调用,GC负责调用
执行时机:一个Java对象即将被垃圾回收器回收时
是SUN为程序员准备的垃圾销毁时机,想在垃圾销毁时执行代码可以写在finalize内
类似于静态代码块,在类加载时执行,且执行一次,是类加载时机。
Java的垃圾回收器不是轻易启动的,垃圾少,时间不到等不启动,可以多造点垃圾(for循环),或者建议垃圾回收器启动代码
System.gc();
-----建议归建议,人家并不一定会启动,只是启动的概率高了一些
作用
是SUN为程序员准备的垃圾销毁时机,想在垃圾销毁时执行代码可以写在finalize内。
练习
package com.comclass;
import com.comclass.demo06.Person;
public abstract class Application {
public static void main(String[] args) {
// Person p = new Person();
// //把p变成垃圾
// p = null;
// for (int i = 0; i < 10000000; i++) {
// Person q = new Person();
// q = null;
// }
//把p变成垃圾
for (int i = 0; i < 10; i++) {
Person q = new Person();
q = null;
}
System.gc();
}
}
/*
package com.comclass.demo06;
public class Person {
@Override
protected void finalize() throws Throwable {
System.out.println(this+"即将被销毁");
}
}
*/
5. hashCode() 方法
源码
public native int hashCode();
不是抽象方法,带有native关键字,底层调用C++程序,返回int类型值
作用
返回哈希值:一个Java对象的内存地址,经过哈希算法得出的哈希值,所以结果可以等同看作一个对象的内存地址。
package com.comclass;
import com.comclass.demo07.MyClass;
public abstract class Application {
public static void main(String[] args) {
Object o = new Object();
int hashCodeValue = o.hashCode();
System.out.println(hashCodeValue); //460141958
MyClass mc = new MyClass();
int h2 = mc.hashCode();
System.out.println(h2); //1163157884
System.out.println(new MyClass().hashCode()); //1956725890
}
}
/*
package com.comclass.demo07;
public class MyClass {
}
*/
6. clone()方法
源码
protected Object clone()
throws CloneNotSupportedException
底层调用C++,深克隆,浅克隆
作用
创建并返回一个对象的克隆
for any object
x
, the expression:x.clone() != x
will be
true
, and that the expression:x.clone().getClass() == x.getClass()
will be
true
, but these are not absolute requirements. While it is typically the case that:x.clone().equals(x)
will be
true
, this is not an absolute requirement.