重写toString()
默认实现获取当前对象类的类名+@+(对象的内存地址转化为十六进制)
将java对象转换成“字符串的表示形式,因为有类名+内存地址(十六进制)”
未重写前,对一个类输出
public class Demo01Equals {
public static void main(String[] args) {
Person p1=new Person("喜洋洋",24);
Person p2=new Person("美羊羊",23);
System.out.println(p1);
System.out.println(p2);
}
}
//toString源代码
/*public String toString() {//toString
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}*/
//默认实现获取当前对象类的类名+@+(对象的内存地址转化为十六进制) 将java对象转换成“字符串的表示形式,因为有类名+内存地址(十六进制)”
//所以一般需要重写这个方法
class Person{
private String name;
private int age;
public Person(){
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}
重写之后
/*尝试重写 toString方法*/
public String toString(){
return "羊名:"+this.name+",年龄:"+this.age;
}
重写equals
import java.util.Objects;
public class Demo01Equals {
public static void main(String[] args) {
Person p1=new Person("喜洋洋",24);
Person p2=new Person("美羊羊",23);
Person p3=new Person("喜洋洋",24);
System.out.println(p1);
System.out.println(p2);
boolean b=p1.equals(p3);//直接比较的话是比较这个对象的内存地址
System.out.println(b);
}
}
//toString源代码
/*public String toString() {//toString
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}*/
//默认实现获取当前对象类的类名+@+(对象的内存地址转化为十六进制) 将java对象转换成“字符串的表示形式,因为有类名+内存地址(十六进制)”
//所以一般需要重写这个方法
class Person{
private String name;
private int age;
public Person(){
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
/*尝试重写 toString方法*/
public String toString(){
return "羊名:"+this.name+",年龄:"+this.age;
}
}
为什么要重写呢boolean b=p1.equals(p3);
equals 源代码 直接两个类的对象的地址做比较
public boolean equals(Object obj) {
return (this == obj);
}
而不是类的内容,所以要对他进行重写
这是最基本的重写,但是需要改进
/*尝试重写 equals方法*/
/*public boolean equals(Object obj) {
//return super.equals(obj);
int age1=this.age;
String name1=this.name;
if(obj instanceof Person){//如果是同一个类的话,就进行比较 防止类型转换异常
Person p=(Person) obj;
int age2=p.age;
String name2=p.name;
if(age1==age2&&name1==name2)
return true;
}
return false;
}*/
看看官方的重写
@Override
public boolean equals(Object o) {
if (this == o) return true;//先判断两个对象的地址是否相等,这里虽然比较的是引用地址,但如果相等那也是一致的,不然不一样
if (!(o instanceof Person)) return false;//如果两个都不是同一个类,那更加不能相比 之间返回
Person person = (Person) o;//排除上面两种之后,可以开始转型比较
return getAge() == person.getAge() &&
Objects.equals(getName(), person.getName());//这里最好还僧用equals因为字符串可能是new产生的对象,导致,==比较失败
//return getAge()==person.age&&getName()==person.name;
}
而且sun公司在其他的源码中写会改写这两个方法。
java基本数据类型使用==来判断
java中所有的引用数据类型统一使用equals来进行判断
因为引用数据类型指向对象的地址,而不是实际内容。
练习
import java.util.Objects;
public class Demo02Equals {
public static void main(String[] args) {
Address ad=new Address("杭州","白杨街道","2020");
Address ad2=new Address("杭州","白杨街道","2020");
User u1=new User("张三",ad);
User u2=new User("张三",ad2);
System.out.println(u1.equals(u2));
}
}
//重写规则 :当一个用户的用户名和家庭住址都相等时,表示一个用户
class User{
private String name;
Address add;
public User(){
}
public User(String name, Address add) {
this.name = name;
this.add = add;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof User)) return false;
User user = (User) o;
return Objects.equals(name, user.name) &&
Objects.equals(add, user.add);
}
/* public boolean equals(Object o){
if(this==null||!(o instanceof User))
return false;
User user=(User)o;
return Objects.equals(name,user.name)&&Objects.equals(user.add,add);
}*/
}
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 o) {
if (this == o) return true;
if (!(o instanceof Address)) return false;
Address address = (Address) o;
return Objects.equals(city, address.city) &&
Objects.equals(street, address.street) &&
Objects.equals(zipcode, address.zipcode);
}
}
发现String在使用equals与==的时候发现不一致
import java.util.Objects;
public class StringEquals
{
public static void main(String[] args){
String str1="Hello World!";
String str2="Hello World!";
String str3="Hello World!+++";
String str4=new String("Hello World!");
String str5=new String("Hello World!");
String str6=new String("Hello World!+++");
String str7=str1;
System.out.println(str1==str2);//true 因为都是直接赋值实例化对象 ,栈内存中的两个引用都智能的指向了同一个个helloworld 在java上称为:共享设计模式
System.out.println(str1==str3);//false 堆内存中实际对象不等
System.out.println(str1==str4);//false str1在堆内存中有一个对象。str4是通过new产生了对象,所以二者指向了不同的堆内存中的对象
System.out.println("1和2,两个通过= 赋值的相同实例化变量,结果i-->"+str1.equals(str2));//true
System.out.println("1和3两个通过= 赋值的不相同实例化变量,结果i-->"+str1.equals(str3));//false
System.out.println("4和1,内容一样1是直接赋值实例化,4是new产生,结果i-->"+str1.equals(str4));//ture
System.out.println("4和5,两个new产生的不同对象的相同实例变量,结果i-->"+str5.equals(str4));//ture //equals 在String是判断堆中的内容是否相等。
}
}
原因:
String作为一个基本类型来使用
如果值不相同,对象就不相同,所以"==" 和equals结果一样,
深度解析:
对于直接= =判断时 :str1==str2
因为都是直接赋值实例化对象 ,栈内存中的两个引用都智能的指向了同一个个helloworld 在java上称为:共享设计模式.str1==str3
堆内存中实际内容不等,无需多想。str1==str4
str1是 =直接赋值的实例化对象,str4是new产生的对象,会在堆内存中开辟一个新的空间,所以二者不等。
对于equals判断:str1.equals(str2)
str2与str1是同属于一个类String,采用直接赋值的方式创建的String类型的对象,故判断结果为truestr1.equals(str4)
str4进行下转型,与str1为同类型,再判断其具体内容str5.equals(str4)
4和5类似
具体看源码可以理解,sun公司在String里重写了equals方法,所以equals会判断的是实际的内容
可参考下面是java里String类里关于equals的一个方法,所以String下使用equals时会自动调用这个方法
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}