重写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;
    }

}

java的String类重新赋值 java重写string_System


重写之后

/*尝试重写 toString方法*/
    public String toString(){
        return "羊名:"+this.name+",年龄:"+this.age;
    }

java的String类重新赋值 java重写string_System_02

重写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;
    }
}

java的String类重新赋值 java重写string_System_03


为什么要重写呢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;
    }

java的String类重新赋值 java重写string_java_04


而且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是判断堆中的内容是否相等。
    }
}

java的String类重新赋值 java重写string_User_05

原因:
String作为一个基本类型来使用
如果值不相同,对象就不相同,所以"==" 和equals结果一样,
深度解析:
对于直接= =判断时 :
str1==str2因为都是直接赋值实例化对象 ,栈内存中的两个引用都智能的指向了同一个个helloworld 在java上称为:共享设计模式.
str1==str3堆内存中实际内容不等,无需多想。
str1==str4str1是 =直接赋值的实例化对象,str4是new产生的对象,会在堆内存中开辟一个新的空间,所以二者不等。
对于equals判断:
str1.equals(str2)str2与str1是同属于一个类String,采用直接赋值的方式创建的String类型的对象,故判断结果为true
str1.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;
    }