object
- 任何一个类都默认继承Object类
- Object常见的方法:本地查找、查阅java的类库帮助文档
toString()
- 源代码
public String toString(){
return getClass().getName() + ‘@’ + Integer.toHexString(hashCode());
}- 源代码上toString()的默认实现是:类名@对象的内存地址转换为16进制的形式
- system.out.println(引用); 这里会自动调用“引用”的toString()方法
- toString()设计目的:通过该方法,可以将“java对象”转换成“字符串”的表现形式。返回该对象的字符串表示。通常, toString 方法会返回一个“以文本方式表示”此对象的字符串。结果应是一个简明但易于读懂的信息表达式。
建议所有子类都重写此方法
。 ——见例一 - String重写了toString()方法——见例三
例题一
package day3.toString;
public class ToStringTest01 {
public static void main(String[] args) {
//创建对象
Mytime m =new Mytime();
String s = m.toString();
//System.out.println(s);//toString重写之前; 运行结果:day3.toString.Mytime@15db9742
System.out.println(s); //toString重写之后:0年0月0日
}
}
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 String toString() {
return this.year +"年"+this.month+"月"+this.day+"日";
}
}
equals
-
equals源代码
public boolean equals(Object obj){
return (this==obj);
}- 在Object的equals方法中,默认采用“==”判断两个对象是否相等,而当所判断的
对象变成内存地址
时(m1、m2),此时equals不够使用,需要重写equals()
;——见例二
- 在Object的equals方法中,默认采用“==”判断两个对象是否相等,而当所判断的
-
equals 设计目的:指示其他某个对象是否与此对象“相等”。
-
String类已经重写了equals()方法。比较两个字符串,不能使用==,需要使用equals——见例三
-
结论:java中判断两对象是否相等,基本数据类型适用“==”,引用数据类型使用“equals()”
-
深度理解equals,equals方法重写要彻底——见例四
例题二
- 手动重写equals
package day3;
public class EqualsTest {
public static void main(String[] args) {
//判断基本数据类型是否相等,使用== ==判断原理:a中的数值和b中的数值是否相等
int a = 100;
int b = 100;
//System.out.println(a==b); //输出结果true
//判断java的两个对象是否相等?
Mytime m1 = new Mytime(1921,7,1);
Mytime m2 = new Mytime(1921,7,1);
//System.out.println(m1==m2); //不能使用==,==判断的是m1、m2保存的数值(地址)是否相等,m1、m2肯定不一样。
//重写equals之前[比较内存地址]
boolean flag = m1.equals(m2);
//重写之后,【比较内容】
System.out.println(flag);
Mytime m3= new Mytime(2021,7,1);
System.out.println(m1.equals(m3));
Mytime m4= null;
System.out.println(m1.equals(m4)); //可以运行,但是效率低进行改良
//程序执行到if(null instanceof Mytime) 不会进入if语句中,直接return false
}
}
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;
}
//默认equals
/*public boolean equals(Object obj){
return (this==obj);
}*/
/*
//重写equals
public boolean equals(Object obj){
//获得第一个对象 this==obj的this
int year1 = this.year;
int month1 = this.month;
int day1 = this.day;
//获得第二个对象 this==obj的obj
//int year2 = obj.year; //编译错误,obj中没有year属性
//int month2 = obj.month;
//int day2 = obj.day;
//向下转型
if(obj instanceof Mytime) {
Mytime t = (Mytime)obj;
int year2 = t.year;
int month2 =t.month;
int day2 = t.day;
if(year1==year2&&month1==month2&&day1==day2) {
return true;
}
}
//程序执行到此处,表示日期不相等
return false;
}
*/
//equals改良
public boolean equals(Object obj) {
if(obj==null ||!(obj instanceof Mytime)) { //obj为空
return false;
}
//if(!(obj instanceof Mytime)) { //obj不是mytime的一个实例
// return false;
//}
if(this==obj) { //this 和obj的内存地址一样,即指向的堆内存是一个
return true;
}
Mytime t = (Mytime)obj;
return this.year==t.year&&this.month==t.month&&this.day==t.day;
}
}
例题三
- java语言中的字符串String重写了toString、equals方法
package day3.string;
/**
* @author 衣鱼
* java语言中的字符串String重写了toString、equals方法
*/
public class StringTest01 {
public static void main(String[] args) {
String s1 ="123";
String s2="dfgs";
//String是一个类,是引用数据类型,存在构造方法
String s3 = new String("123");
String s4 = new String ("sfjks");
System.out.println(s3==s1); //结果false s3和s1是new了两个对象的内存地址,对象不一样,那么指向它们的内存地址也不一样
System.out.println(s3.equals(s1)); //结果true String重写了equals
System.out.println(s4.toString()); //结果sfjks String重写了toString
}
}
例题四
package day3;
/**
* @author 衣鱼
*
*/
public class EqulasTest02 {
public static void main(String[] args) {
Address addr1 = new Address("沈阳","八经街道","111"); //address是自己写的类,user调用了该类,都需要new
//Address addr2 = new Address("沈州","八经街道","111");
User u1 = new User("辽宁",addr1);
User u2 = new User("辽宁",new Address("沈洲","八经街道","111"));
System.out.println(u1.equals(u2));
}
}
class User{
String name; //name保存的是内存地址
Address addr; //addr保存的是内存地址
public User() {
}
public User(String name, Address addr) {
this.name = name;
this.addr = addr;
}
//重写equals方法
//当用户的名字和家庭住址信息都一致时,表示当前两个用户相等
//思路:判断User对象和User对象是否一样
public boolean equals(Object obj) {
if((obj==null)||!(obj instanceof User)) return false;
if(this==obj) return true;
User u=(User)obj;
if(this.name.equals(u.name)&&this.addr.equals(u.addr)) { //需要重写Address的equals
return true;
}
return false;
}
/*
* public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (addr == null) {
if (other.addr != null)
return false;
} else if (!addr.equals(other.addr))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
*/
}
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;
}
//重写equals:判断Address对象和Address对象是否相等
public boolean equals(Object obj) {
if((obj==null)||!(obj instanceof Address)) return false;
if(this ==obj) return true;
//向下转型
Address a = (Address)obj;
if(this.street.equals(a.street)&&this.city.equals(a.city)&&this.zipcode.equals(a.zipcode)) {
return true;
}
return false;
}
}
finalize
- finalize源代码
protected void finalize()
throws Throwable{}- finalize()方法只有一个方法体,里面没有代码,且该方法使用protected修饰
- 该方法不需要程序员手动调用,jvm的垃圾回收器负责调用这个方法。即finalize()只需要重写,写完之后,程序自动调用。
- finalize()执行时机:当一个java对象即将被垃圾回收器回收的时候,垃圾回收器会调用该方法,即finalize()方法实际上是sun公司为程序员准备的一个时机,垃圾销毁时机。如果希望在对象销毁时机时执行一段代码,这段代码需要写到finalize()方法当中。
- 回顾静态代码块作用 static{} 静态代码块是类加载时刻执行的,且只执行一次
- 提示:java中的垃圾回收器,不一定启动,
例题五
package day3;
/**
* @author 衣鱼
*业务需求:
* 所有对象在jvm被释放的时候,记录对象的释放时间
*/
public class FinalizeTest {
public static void main(String[] args) {
//Person p = new Person();
//p对象变成垃圾 p是引用,p保存的是一个指向Person对象的内存地址
//当p为空的时候,相当于该person对象没有引用指向,会变成垃圾
//堆内存当中的person对象变成垃圾,代码执行就会找到Person类里面的finalize()方法,并执行该方法
//p = null; //jvm垃圾回收器不一定会实时启动
//多造垃圾
/*for(int i =0;i<1000000;i++) {
Person p = new Person();
p=null;
}*/
//使用gc 建议启动垃圾回收器
for(int i =0;i<1000;i++) {
Person p = new Person();
p=null;
System.gc();
}
}
}
class Person{
protected void finalize() throws Throwable{
System.out.println("finalize 执行!person即将被销毁");
}
}
hashCode
- hashCode源代码
public native int hashCode();- 该方法不是抽象方法,带有native关键字,底层调用c++程序
- hashCode()方法返回值是哈希码,实际上假设一个java对象的内存地址,经过哈希运算之后,得到的一个值。由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的)