toString()
源代码:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
默认实现:
类名@对象的内存地址转换为十六进制的形式
作用:
toString()方法是通过调用这个方法可以将一个“Java对象”转换称“字符串表达形式”。
建议所以的子类都重写toString()方法。
总结:
System.out.println(引用);这里会自动调用“引用”的toString()方法。
string 类已经重写了toString()方法。可以直接使用,不用再次重写。
代码演示:
public class Test01
{
public static void main(String[] arg)
{
MyTime my = new MyTime(1000,2,3);
//未改写toString方法之前输出结果为:MyTime@54bedef2
//第一种:
//System.out.println(my.toString());
//第二种:默认会调用toString方法
System.out.println(my);
}
}
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方法
public String toString()
{
return this.year + "年" +this.month + "月" + this.day + "日";
}
}
equals
源代码:
public boolean equals(Object obj) {
return (this == obj);
}
默认实现:
作用:以后编程的过程中,都要通过equals方法来判断两个对象是否相等。equlas方法是判断两个对象是否相等。
总结:
String类已经重写了equals方法,比较两个字符串不能使用==,必须使用equeals。equals是通用的。
Java中基本数据类型比较是否相等,使用“==”
Java中引用数据类型比较是否相等,使用equals。
代码演示:
public class Test02
{
public static void main(String[] arg)
{
MyTime my1 = new MyTime(1000,2,3);
MyTime my2 = new MyTime(1000,2,3);
MyTime my3 = new MyTime(1002,2,31);
//重写Object类中的equals方法之前:比较的地址
//这里的“==”判断的是:my1中保存的对象内存地址和my2中内存的对象内存地址是否相等。
System.out.println(my1 == my2);//输出false.
//重写Object类中的equals方法之后:
//将my2传给了equals方法。
boolean flag = my1.equals(my2);
System.out.println(flag);//true
//将my3传给了equals方法。
System.out.println(my1.equals(my3));//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;
}
/*基础版重写:
//重写Object类的equals方法
//你认为两个对象什么相等的时候表示相等
public boolean equals(Object obj) {
//获取第一个日期的年月日
int year1 = this.year;
int month1 = this.month;
int day1 = this.day;
//向下转型,用instanceof判断类型。
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)
{
//判断日期相等,返回true
return true;
}
//日期不相等返回false
return false;
}
return (this == obj);
}
*/
//改良版:
public boolean equals(Object obj) {
//如果obj为空直接返回false
//如果obj不是一个MyTime,没必要比较了,直接返回false
if(obj == null || !(obj instanceof MyTime))
{
return false;
}
//如果this 和obj保存的内存地址相同,没必要比较了,直接返回true。
//内存地址相同的时候指向的堆内存的对象肯定是同一个。
if(this == obj)
{
return true;
}
//obj向下转型
MyTime t = (MyTime)obj;
//第一种写法:
//return this.year == t.year && this.month == t.month && this.day == t.day
//第二种写法:
if(this.year == t.year && this.month == t.month && this.day == t.day)
{
return true;
}
return false;
}
}
public class Test05
{
public static void main(String[] arg)
{
Address addr1 =new Address("北京","朝阳区");
Address addr2 =new Address("北京","朝阳区");
Address addr3 =new Address("湖北","武汉市");
User use1 = new User("李某",addr1);
User use2 = new User("李某",addr2);
User use3 = new User("李某",addr3);
System.out.println(use1.equals(use2));
System.out.println(use1.equals(use3));
}
}
class User
{
String name;
Address add;
//无参构造
public User()
{
}
//有参构造
public User(String name, Address add)
{
this.name = name;
this.add = add;
}
//重写equals方法
public boolean equals(Object obj)
{
//如果obj为空直接返回false
//如果obj不是一个User,没必要比较了,直接返回false
if(obj == null || !(obj instanceof User))
{
return false;
}
//如果this 和obj保存的内存地址相同,没必要比较了,直接返回true。
//内存地址相同的时候指向的堆内存的对象肯定是同一个。
if(this == obj)
{
return true;
}
//将obj进行向下强转
User u = (User)obj;
//String引用类型比较,用equals方法
//相等返回true;不相等返回false
if (this.name.equals(u.name) && this.add.equals(u.add))
{
return true;
}
return false;
}
}
class Address
{
String city;
String street;
//无参构造
public Address()
{
}
//有参构造
public Address(String city, String street)
{
this.city = city;
this.street = street;
}
//重写equals方法
public boolean equals(Object obj)
{
//如果obj为空直接返回false
//如果obj不是一个Address,没必要比较了,直接返回false
if(obj == null || !(obj instanceof Address))
{
return false;
}
//如果this 和obj保存的内存地址相同,没必要比较了,直接返回true。
//内存地址相同的时候指向的堆内存的对象肯定是同一个。
if(this == obj)
{
return true;
}
//将obj向下强转。
Address add = (Address)obj;
//String引用类型比较,用equals方法
//相等返回true;不相等返回false
if(this.city.equals(add.city) && this.street.equals(add.street))
{
return true;
}
return false;
}
}
finalize()
源代码:
protected void finalize() throws Throwable { }
说明:
- finalize()方法只有一个方法体,里面没有代码,而且这个方法是protected修饰的。
- 这个方法不需要程序员手动调用,jvm的垃圾回收器GC,负责调用这个方法
- 当一个java对象即将被垃圾回收器回收时,垃圾回收器负责调用finalize()方法。
- finalize()方法实际上时SUN公司为Java程序员准备的一个时机,垃圾销毁时机。如果希望在对象销毁时机执行一段代码的话,这段代码要写到finalize()方法中。
代码演示:
public class Test06{
public static void main(String[] args){
/*
// 创建对象
Person p = new Person();
// 怎么把Person对象变成垃圾?
p = null;
*/
// 多造点垃圾
/*
for(int i = 0; i < 100000000; i++){
Person p = new Person();
p = null;
}
*/
for(int i = 0; i < 1000; i++){
Person p = new Person();
p = null;
// 有一段代码可以建议垃圾回收器启动。
if(i % 2 == 0){
System.gc(); // 建议启动垃圾回收器。(只是建议,可能不启动,也可能启动。启动的概率高了一些。)
}
}
}
}
// 项目开发中有这样的业务需求:所有对象在JVM中被释放的时候,请记录一下释放时间!!!
// 记录对象被释放的时间点,这个负责记录的代码写到哪里?
// 写到finalize()方法中。
class Person{
// 重写finalize()方法
// Person类型的对象被垃圾回收器回收的时候,垃圾回收器负责调用:p.finalize();
protected void finalize() throws Throwable {
// this代表当前对象
System.out.println(this + "即将被销毁!");
}
}
hashCode方法:
说明:
在Object中的hashCode方法是怎样的?
public native int hashCode();
这个方法不是抽象方法,带有native关键字,底层调用C++程序。
hashCode()方法返回的是哈希码:
实际上就是一个java对象的内存地址,经过哈希算法,得出的一个值。
所以hashCode()方法的执行结果可以等同看做一个java对象的内存地址。
代码演示:
public class Test07{
public static void main(String[] args){
Object o = new Object();
int hashCodeValue = o.hashCode();
// 对象内存地址经过哈希算法转换的一个数字。可以等同看做内存地址。
System.out.println(hashCodeValue); //798154996
MyClass mc = new MyClass();
int hashCodeValue2 = mc.hashCode();
System.out.println(hashCodeValue2); //1392838282
MyClass mc2 = new MyClass();
System.out.println(mc2.hashCode()); // 523429237
}
}
class MyClass
{
}