Rumah  >  Artikel  >  Java  >  Bagaimana untuk mengatasi kaedah yang sama dengan betul di Jawa

Bagaimana untuk mengatasi kaedah yang sama dengan betul di Jawa

WBOY
WBOYke hadapan
2023-05-09 11:19:261322semak imbas

1. Apakah kaedah yang sama?

Pertama sekali kita perlu tahu bahawa Object类 ialah kelas induk (kelas super/kelas asas) bagi semua kelas dalam Java Maksudnya, dalam Java, semua kelas mewarisi daripada Object类, dengan kata lain, kita boleh menggunakan semua kaedah yang dilaksanakan dalam Object类 secara langsung. Kaedah equals ialah salah satu daripada banyak kaedah yang dilaksanakan oleh Object类.

Tangkapan skrin berikut adalah daripada Java11 API

Bagaimana untuk mengatasi kaedah yang sama dengan betul di Jawa

Semua kaedah kelas Objek:

Bagaimana untuk mengatasi kaedah yang sama dengan betul di Jawa

1.1 sama dengan Kaedah:

  • equals: Ia adalah kaedah dalam Object类 Saya hanya boleh menunjukkan kepada anda jdk kod sumber kemudian

  • Pertimbangan lalai ialah sama ada alamat adalah sama (kerana intipati asas pembolehubah jenis rujukan adalah untuk menyimpan alamat objek, rakan dengan pengetahuan C/C++ harus mengetahuinya dengan baik), kaedah ini sering ditindih dalam subkelas, Digunakan untuk menentukan sama ada kandungan objek adalah sama. Contohnya, Integer dan String, yang akan anda pelajari secara ringkas kemudian (lihat pelaksanaan kod sumber dalam IDEA)

2. Mengapakah kita perlu menulis semula kaedah sama?

Bolehkah kita menggunakan kaedah Object类 yang telah equals kami laksanakan? Mengapakah kita perlu mengatasi kaedah equals? Ini bergantung pada mekanisme pelaksanaan kaedah Object类 equals.

Bagaimana untuk mengatasi kaedah yang sama dengan betul di Jawa

Kita dapat melihat dengan jelas bahawa lapisan bawah kaedah Object类 equals dilaksanakan menggunakan ==, yang bermaksud penggunaannya sama dengan apa yang kita biasanya menggunakan Penggunaan == adalah konsisten apabila membandingkan jenis data asas. Mari kita lihat sintaks ==:

  • == hanya boleh digunakan untuk membandingkan jenis data asas untuk kesaksamaan, iaitu perbandingan nilai mudah; >

  • == Mungkin juga terdapat kegagalan semasa membandingkan nombor titik terapung Ini kerana mekanisme penyimpanan nombor titik terapung adalah berbeza daripada keluarga integer Nombor titik terapung itu sendiri tidak boleh mewakili nilai yang tepat (. anda boleh menyemak sendiri sebab-sebab tertentu peraturan IEEE 754, tidak akan dikembangkan di sini)
  • Jadi kita boleh gunakan == apabila hanya membandingkan nilai jenis data asas, tetapi kita tidak boleh lakukan ini apabila membandingkan jenis data rujukan, seperti yang dinyatakan di atas Telah disebutkan bahawa jenis data rujukan pada dasarnya digunakan untuk merujuk/menyimpan alamat objek, jadi anda boleh menganggapnya sebagai penunjuk
(di sini dikatakan bahawa Java tidak mempunyai penunjuk, tetapi saya secara peribadi berpendapat ia hanya dipanggil secara berbeza )

Nota: Jangan mengelirukan C/C++ rujukan dengan rujukan C++ sebenarnya adalah pemalar penunjuk, iaitu,
. Inilah sebabnya mengapa rujukan Java hanya boleh digunakan sebagai alias untuk pembolehubah. C++int* const2.1 Contohnya~C++

Apabila membandingkan dua int, anda boleh terus menggunakan == Apabila ia sama, hasilnya adalah

dan apabila

kedua-dua atribut itu betul-betul. yang sama. Apabila menggunakan

untuk perbandingan, ralat akan berlaku, seperti yang kita lihat, kita pasti ingin mendapatkan true, tetapi hasilnya adalah new== > truefalse
Keputusan larian:

Bagaimana untuk mengatasi kaedah yang sama dengan betul di Jawa

Pada ketika ini, kita sepatutnya mempunyai idea kasar mengapa kita perlu mengatasi

kaedah apabila membandingkan objek, kerana

Yang diberikan kepada kita tidak berfungsi~~Bagaimana untuk mengatasi kaedah yang sama dengan betul di Jawa

3 Analisis kod sumber yang sama:

equalsSebelum menulis semula, mari kita lihat pada definisi dalam Object类:

Fungsi: Menunjukkan sama ada beberapa objek lain adalah "sama" dengan objek ini. Kaedah

Java APIequals melaksanakan kesetaraan pada rujukan objek bukan nol:
public boolean equals(Object obj)

Refleksitiviti: Untuk sebarang nilai rujukan bukan nol

,

hendaklah Kembali
    .
  • xx.equals(x) Simetri: Untuk sebarang nilai rujukan bukan nol true dan

    ,
  • hendaklah mengembalikan
  • jika dan hanya jika

    mengembalikan x . yx.equals(y)truey.equals(x) Transitiviti: Untuk sebarang nilai rujukan bukan nol true ,

    dan
  • , jika
  • mengembalikan

    x mengembalikan y , Kemudian z sepatutnya kembali x.equals(y). true

  • Ketekalan: Untuk sebarang nilai rujukan bukan nol x dan y, berbilang panggilan ke x.equals(y) sentiasa kembali sama ada true atau sentiasa kembali false, dengan syarat objek itu tidak diubahsuai Maklumat equals yang digunakan dalam perbandingan.

  • Untuk sebarang nilai rujukan bukan kosong x, x.equals(null) hendaklah mengembalikan false.

Kaedah sama dengan Objek kelas melaksanakan perhubungan kesetaraan yang paling mendiskriminasikan pada objek, iaitu, untuk sebarang nilai rujukan bukan nol x dan y, jika dan hanya jika x dan Kaedah ini mengembalikan benar apabila y merujuk kepada objek yang sama (x == y mempunyai nilai benar).

Nota: Biasanya perlu untuk mengatasi kaedah Kod cincang apabila mengatasi kaedah ini untuk mengekalkan kontrak biasa kaedah hashCode, yang menyatakan bahawa objek yang sama mesti mempunyai kod cincang yang sama.

Bagaimana untuk mengatasi kaedah yang sama dengan betul di Jawa

Seterusnya, lihat kaedah String类 yang ditindih dalam equals dan kaedah Integer yang ditindih dalam kelas equals:

Bagaimana untuk mengatasi kaedah yang sama dengan betul di Jawa

//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;
    }

Penjelasan mudah ialah apabila membandingkan objek yang sama, kembalikan true terus untuk meningkatkan kecekapan. Apabila objek yang dilalui adalah contoh kelas semasa, pertimbangan selanjutnya dimasukkan A for gelung melintasi setiap aksara rentetan secara bergilir-gilir dan mengembalikan false selagi satu aksara berbeza.

Mari kita teruskan melihat Integer kod sumber kelas equals:

Bagaimana untuk mengatasi kaedah yang sama dengan betul di Jawa

//Integer类的equals源代码:
 public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }

Integer类kod sumber equals adalah lebih mudah, cuma muat naiknya Jika objek yang dimasukkan ialah contoh kelas semasa, pertimbangan selanjutnya akan dibuat: apabila nilainya adalah sama, true akan dikembalikan, dan jika mereka tidak sama, false akan dikembalikan.

Berikut ialah demonstrasi praktikal⑧, mengambil Integer类 sebagai contoh:

Bagaimana untuk mengatasi kaedah yang sama dengan betul di Jawa

Jelas sekali, kita tahu bahawa Integer类 menulis semula equalsKaedah dan adalah jenis rujukan. Apabila == digunakan secara langsung untuk membandingkan pembolehubah jenis rujukan, hasilnya ialah false, dan apabila equals digunakan untuk membandingkan pembolehubah jenis rujukan, hasilnya ialah true. Ini dengan baik menggambarkan keperluan untuk mengatasi kaedah equals. String类Sahkan sendiri⑧.

4. Tulis semula kaedah yang sama dengan betul:

(Mari kita bincangkan kesimpulannya dahulu, getClass() lebih selamat daripada instanceof)

Pada ketika ini, pada asasnya kita letakkan equals Pelbagai kod sumber kaedah telah dianalisis, dan langkah seterusnya ialah melaksanakan kaedah equals sendiri.

Berikut ialah dua equals kaedah penulisan semula biasa:

  • Gunakan instanceof untuk melaksanakan penulisan semula kaedah equals

  • Gunakan getClass untuk melaksanakan kaedah equals mengatasi

Andaikan terdapat senario ini:

Tulis semula dalam kelas segi empat tepat yang telah dibuatObjec kaedah dalam kelas 🎜>t mengembalikan equals apabila panjang dan lebar segi empat tepat adalah sama, dan mengatasi kaedah TRUE untuk memaparkan maklumat panjang dan lebar segi empat tepat. dan menguji kelas. hashCode

package com.test10_04;

import java.util.Objects;

class Rectangle {
    private double length;
    private double wide;

    public Rectangle() {
        //空实现
    }
    public Rectangle(double length, double wide) {
        setLength(length);
        setWide(wide);
    }

    public double getLength() {
        return length;
    }

    public void setLength(double length) {
        assert length > 0.0 : "您的输入有误,长方形的长不能小于0";
        this.length = length;
    }

    public double getWide() {
        return wide;
    }

    public void setWide(double wide) {
        assert wide > 0.0 : "您的输入有误,长方形的宽不能小于0";
        this.wide = wide;
    }

    public double area() {
        return this.length * this.wide;

    }
    public double circumference() {
        return 2 * (this.wide + this.length);
    }

    public boolean equals(Object obj) {
        if (this == obj) { //判断一下如果是同一个对象直接返回true,提高效率
            return true;
        }
        if (obj == null || obj.getClass() != this.getClass()) { //如果传进来的对象为null或者二者为不同类,直接返回false
            return false;
        }
        //也可以以下方法:
//        if (obj == null || !(obj instanceof Rectangle)) { //如果传进来的对象为null或者二者为不同类,直接返回false
//            return false;
//        }
        Rectangle rectangle = (Rectangle) obj; //向下转型
        //比较长宽是否相等,注意:浮点数的比较不能简单地用==,会有精度的误差,用Math.abs或者Double.compare
        return Double.compare(rectangle.length, length) == 0 && Double.compare(rectangle.wide, wide) == 0;
    }

    public int hashCode() { //重写equals的同时也要重写hashCode,因为同一对象的hashCode永远相等
        return Objects.hash(length, wide); //调用Objects类,这是Object类的子类
    }

    public String toString() {
        return "Rectangle{" + "length=" + length + ", wide=" + wide + '}';
    }
}

public class TestDemo {
    public static void main(String[] args) {

        Rectangle rectangle1 = new Rectangle(3.0, 2.0);
        Rectangle rectangle2 = new Rectangle(3.0, 2.0);
        
        System.out.println(rectangle1.equals(rectangle2));
        System.out.println("rectangle1哈希码:" + rectangle1.hashCode() +
                "\nrectangle2哈希码:" + rectangle2.hashCode());
        System.out.println("toString打印信息:" + rectangle1.toString());
    }
}
toStringIdea pelaksanaan khusus diterangkan dengan sangat jelas dalam kod Di sini kami menumpukan pada menganalisis kelebihan dan kekurangan dua kaedah pelaksanaan

dan

: getClassinstanceof

.

Bagaimana untuk mengatasi kaedah yang sama dengan betul di JawaRingkaskan logik kod:

Mari fokus pada kod ringkas ini

//getClass()版本
public class Student {
	private String name;
	
    public void setName(String name) {
        this.name = name;
    }
	@Override
	public boolean equals(Object object){
		if (object == this)
			return true;
		// 使用getClass()判断对象是否属于该类
		if (object == null || object.getClass() != getClass())
			return false;
		Student student = (Student)object;
		return name != null && name.equals(student.name);
}
rrree
Malah, kedua-dua penyelesaian adalah sah, perbezaannya ialah

mengehadkan objek kepada hanya kelas yang sama , tetapi

membenarkan objek menjadi kelas yang sama atau subkelasnya, jadi kaedah yang sama menjadi kelas induk dan subkelas juga boleh melakukan operasi yang sama Pada masa ini, jika subkelas mentakrifkan semula kaedah yang sama, Maka ia mungkin menjadi objek kelas induk menyamai objek subkelas adalah benar, tetapi objek subkelas menyamai objek kelas induk adalah palsu, seperti yang ditunjukkan di bawah: getClass()

//instanceof版本
public class Student {
	private String name;
	
    public void setName(String name) {
       this.name = name;
   }
	@Override
	public boolean equals(Object object){
		if (object == this)
			return true;
		// 通过instanceof来判断对象是否属于类
		if (object == null || !(object instanceof Student))
			return false;
		Student student = (Student)object;
		return name!=null && name.equals(student.name);
	}
}
instanceofPerhatikan bahawa

getClass()

Kedua-dua nilai pulangan adalah Bagaimana untuk mengatasi kaedah yang sama dengan betul di Jawa, yang selaras dengan jangkaan kami (walaupun kelasnya berbeza, jadi mesti

)

false false

dengan

: Bagaimana untuk mengatasi kaedah yang sama dengan betul di Jawa

instanceof

Keputusan larian: Satu adalah true dan satu lagi adalah false Jelas sekali terdapat masalah.

Bagaimana untuk mengatasi kaedah yang sama dengan betul di Jawa

Sebabnya di sini adalah seperti berikut: Sintaks
instanceof adalah seperti ini:
Apabila objek ialah contoh kelas, hasilnya ialah true. Tetapi satu lagi cirinya ialah jika objek ini adalah contoh subkelasnya, hasilnya juga akan menjadi true. Ini membawa kepada pepijat di atas. Maksudnya, apabila kedua-dua objek yang dibandingkan mempunyai hubungan ibu bapa-anak, instanceof boleh menyebabkan masalah. **Rakan-rakan yang perlu belajar lebih lanjut boleh mempelajarinya sendiri, jadi disyorkan untuk menggunakan equals sebanyak mungkin semasa melaksanakan kaedah penulisan semula getClass.

perlu mengatasi kaedah equals sambil mengatasi kaedah hashCode.

Atas ialah kandungan terperinci Bagaimana untuk mengatasi kaedah yang sama dengan betul di Jawa. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam