জাভা সমান () পদ্ধতির ওভাররাইডিং - কাজ করছে না?


150

আমি equals()আজ সেই পদ্ধতিটি নিয়ে একটি আকর্ষণীয় (এবং খুব হতাশাব্যঞ্জক) ইস্যুতে ছড়িয়ে পড়েছি যার কারণে আমি যা মনে করি যা ভাল পরীক্ষিত শ্রেণি হিসাবে ক্র্যাশ হয়ে পড়েছিল এবং একটি ত্রুটি সৃষ্টি করেছিল যা আমাকে ট্র্যাক করতে খুব দীর্ঘ সময় নিয়েছিল।

কেবল সম্পূর্ণতার জন্য, আমি কোনও আইডিই বা ডিবাগার ব্যবহার করছিলাম না - কেবলমাত্র ভাল পুরানো ফ্যাশন সম্পাদক এবং সিস্টেম.আউট's সময় খুব সীমিত ছিল এবং এটি একটি স্কুল প্রকল্প ছিল।

যাইহোক -

আমি একটি মৌলিক শপিং কার্ট যা থাকতে পারে উন্নয়নশীল ছিল ArrayListএর Bookবস্তু । কার্টের ,, এবং পদ্ধতিগুলি বাস্তবায়নের জন্য addBook(), আমি আগে থেকেই এর মধ্যে বিদ্যমান কিনা তা খতিয়ে দেখতে চেয়েছিলাম । তাই আমি যাই -removeBook()hasBook()BookCart

public boolean equals(Book b) {
    ... // More code here - null checks
    if (b.getID() == this.getID()) return true;
    else return false;
}

সমস্ত পরীক্ষায় সূক্ষ্ম কাজ করে। আমি 6 টি অবজেক্ট তৈরি করি এবং সেগুলিতে ডেটা পূরণ করি। অনেকগুলি যুক্ত করে, মুছে ফেলে, () অপারেশন করে Cartএবং সবকিছু ঠিকঠাক কাজ করে। আমি পড়েছি আপনি হয় equals(TYPE var)বা থাকতেequals(Object o) { (CAST) var } পারেন তবে ধরে নিয়েছিলেন যেহেতু এটি কাজ করছে তাই এটি খুব বেশি গুরুত্ব দেয় না।

তারপর আমি একটি সমস্যাতে পড়েছি - আমি একটি তৈরি করতে প্রয়োজন Bookসঙ্গে বস্তুর শুধুমাত্রID বইয়ের বর্গ মধ্যে থেকে এটা হবে। এটিতে অন্য কোনও ডেটা প্রবেশ করা হবে না। মূলত নিম্নলিখিত:

public boolean hasBook(int i) {
    Book b = new Book(i);
    return hasBook(b);
}

public boolean hasBook(Book b) {
    // .. more code here
    return this.books.contains(b);
}

হঠাৎ করেই, equals(Book b)পদ্ধতিটি আর কাজ করে না। কোনও ভাল ডিবাগার ছাড়াই এবং Cartক্লাসটি সঠিকভাবে পরীক্ষিত এবং সঠিক হয়েছে তা ধরে নিলে এটি বেশ দীর্ঘ সময় নিয়েছে । equals()নিম্নলিখিতটিতে পদ্ধতিটি অদলবদলের পরে :

public boolean equals(Object o) {
    Book b = (Book) o;
    ... // The rest goes here   
}

সবকিছু আবার কাজ শুরু। পদ্ধতিটি বুকের প্যারামিটারটি গ্রহণ না করার সিদ্ধান্ত নেওয়ার কোনও কারণ আছে কি না এটি স্পষ্টভাবে একটি বস্তু ছিলBook ? পার্থক্যটি কেবল একই শ্রেণীর মধ্যে থেকেই ইনস্ট্যান্ট করা হয়েছিল বলে মনে হয়েছিল এবং কেবলমাত্র একজন ডেটা সদস্য দ্বারা পূর্ণ। আমি খুব বিভ্রান্ত প্লিজ, কিছুটা আলোকপাত করবেন?


1
আমি সচেতন যে প্রতিফলিত হয়ে সমান পদ্ধতিগুলিকে ওভাররাইড করা সম্পর্কে আমি 'চুক্তি' লঙ্ঘন করেছি - তবে জেনেরিক ব্যবহার না করে অ্যারেলিস্টে বস্তুটির অস্তিত্ব আছে কিনা তা যাচাই করার জন্য আমার দ্রুত উপায় প্রয়োজন।
জোশ স্মিটন

1
এটি জাভা এবং সমান সম্পর্কে শেখার জন্য একটি ভাল পাঠ
jjnguy

উত্তর:


329

জাভাতে, যে equals()পদ্ধতি থেকে উত্তরাধিকার সূত্রে প্রাপ্ত Objectতা হ'ল:

public boolean equals(Object other);

অন্য কথায়, প্যারামিটারটি অবশ্যই টাইপের হতে হবে Object। একে ওভাররাইডিং বলা হয় ; আপনার পদ্ধতি public boolean equals(Book other)কি বলা হয় না ওভারলোডিং থেকে equals()পদ্ধতি।

ArrayListব্যবহারসমূহ উপেক্ষিত equals()পদ্ধতি (তার জন্য যেমন বিষয়বস্তু তুলনা করতে contains()এবং equals(), পদ্ধতি) না ওভারলোড বেশী। আপনার বেশিরভাগ কোডে, সঠিকভাবে Objectসমানভাবে ওভাররাইড না করা কোডটি কল করা ভাল ছিল, তবে এটির সাথে সামঞ্জস্যপূর্ণ নয় ArrayList

সুতরাং, পদ্ধতিটি সঠিকভাবে ওভাররাইড না করা সমস্যার কারণ হতে পারে।

আমি নীচের সময়কালের তুলনায় ওভাররাইড করে:

@Override
public boolean equals(Object other){
    if (other == null) return false;
    if (other == this) return true;
    if (!(other instanceof MyClass)) return false;
    MyClass otherMyClass = (MyClass)other;
    ...test other properties here...
}

@Overrideটীকাগুলির ব্যবহার মূর্খ ভুল সহ এক টনকে সহায়তা করতে পারে।

যখনই আপনি ভাবেন যে আপনি একটি সুপার ক্লাস 'বা ইন্টারফেসের পদ্ধতিটিকে ওভাররাইড করছেন it এইভাবে, আপনি যদি এটি ভুল উপায়ে করেন তবে আপনি একটি সংকলন ত্রুটি পাবেন।


31
এটি @ ওভারাইডের টীকাটির পক্ষে একটি ভাল যুক্তি ... যদি ওপি @ ওভাররাইড ব্যবহার করে থাকে তবে তার সংকলক তাকে বলত যে তিনি আসলে কোনও পিতাম শ্রেণীর পদ্ধতিকে উপেক্ষা করছেন না ...
কোয়ান

1
@ ওভাররাইড সম্পর্কে কখনও সচেতন ছিল না, এর জন্য ধন্যবাদ! আমি আরও যুক্ত করতে চাই যে ওভাররাইডিং হ্যাশকোড () সত্যিই করা উচিত ছিল এবং ত্রুটিটি খুব শীঘ্রই খুঁজে পেয়েছিল।
জোশ স্মিটন

5
কিছু আইডিই (উদাহরণস্বরূপ Eclipse) এমনকি ক্লাস সদস্য ভেরিয়েবলের উপর ভিত্তি করে আপনার জন্য সমান () এবং হ্যাশকোড () পদ্ধতিগুলি স্বয়ংক্রিয়ভাবে তৈরি করতে পারে।
স্ক।

1
if (!(other instanceof MyClass))return false;ফেরৎ falseযদি MyClassঅন্যান্য বর্গ প্রসারিত করে। তবে falseঅন্য শ্রেণি প্রসারিত হলে তা ফিরে আসবে না MyClassequalকম বৈপরীত্য হওয়া উচিত নয় ?
রবার্ট

19
উদাহরণস্বরূপ ব্যবহার করার সময় পূর্বের নালচেকটি অতিরিক্ত।
ম্যাটিউজ ডিমসিজিক

108

আপনি যদি গ্রহনটি ব্যবহার করেন তবে কেবল শীর্ষ মেনুতে যান

উত্স -> সমান উত্পন্ন () এবং হ্যাশকোড ()


আমি রাজী! এটির আগে আমি কখনই জানতাম না এবং এটি তৈরি করা এটিকে কম ত্রুটিযুক্ত করে তোলে
বয়

একই অবস্থা. ধন্যবাদ ফ্রেড!
আনিলা

16
ইন্টেলিজিতে আপনি এটি কোড → উত্পন্ন করুন ... বা নিয়ন্ত্রণ + এন এর অধীনে দেখতে পান। :)
ডানফোল্ড

নেটবিনে আপনি মেনু বার> উত্স (বা ডান ক্লিক)> কোড সন্নিবেশ করুন (বা Ctrl-I) যান, এবং উত্পন্ন সমান () ক্লিক করুন ...
সলোমন

11

আপনার প্রশ্নের বিষয়ে সামান্যভাবে অফ-টপিক, তবে এটি সম্ভবত যাইহোক উল্লেখ করার মতো:

কমন্স ল্যাং কিছু দুর্দান্ত পদ্ধতি পেয়েছে যা আপনি ওভাররাইডিং এর সমান এবং হ্যাশকোডে ব্যবহার করতে পারেন। পরীক্ষা করে দেখুন EqualsBuilder.reflectionEquals (...) এবং HashCodeBuilder.reflectionHashCode (...) । অতীতে আমাকে প্রচুর মাথাব্যাথা বাঁচিয়েছে - যদিও আপনি যদি কেবল আইডিতে "সমান" করতে চান তবে এটি আপনার পরিস্থিতিতে উপযুক্ত নয়।

আমি এও সম্মত হই যে আপনি @Overrideযখনই সমান (বা অন্য কোনও পদ্ধতি) ওভাররাইড করছেন তখন আপনার মন্তব্যটি ব্যবহার করা উচিত ।


4
আপনি একটি অন্ধকার ব্যবহারকারী হন তাহলে আপনার কাছে যেতে পারেন right click -> source -> generate hashCode() and equals(),
tunaranch

1
আমি কি সঠিক যে এই পদ্ধতিটি রানটাইমে কার্যকর করা হয়? প্রতিবিম্বের কারণে আমরা যদি অন্য কোনও আইটেমের সমতার জন্য তাদের আইটেমগুলি পরীক্ষা করে আইটেমগুলি সহ একটি বড় সংগ্রহকে ঘুরিয়ে দিই তবে আমাদের ক্ষেত্রে পারফরম্যান্স সমস্যা থাকবে না?
গেকেট

4

আরেকটি দ্রুত সমাধান যা বয়লারপ্লেট কোডটি সংরক্ষণ করে তা হ'ল লম্বোক ইকুয়ালসএন্ডহ্যাশকোড এনোটোটেশন । এটি সহজ, মার্জিত এবং কাস্টমাইজযোগ্য। এবং IDE উপর নির্ভর করে না । উদাহরণ স্বরূপ;

import lombok.EqualsAndHashCode;

@EqualsAndHashCode(of={"errorNumber","messageCode"}) // Will only use this fields to generate equals.
public class ErrorMessage{

    private long        errorNumber;
    private int         numberOfParameters;
    private Level       loggingLevel;
    private String      messageCode;

সমান ক্ষেত্রগুলিতে কোন ক্ষেত্রটি কাস্টমাইজ করতে বিকল্পগুলি দেখুন । Lombok মধ্যে avalaible হয় ম্যাভেন । এটি কেবল সরবরাহিত সুযোগের সাথে যুক্ত করুন :

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.14.8</version>
    <scope>provided</scope>
</dependency>

1

অ্যান্ড্রয়েড স্টুডিওতে Alt + সন্নিবেশ ---> সমান এবং হ্যাশকোড

উদাহরণ:

    @Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    Proveedor proveedor = (Proveedor) o;

    return getId() == proveedor.getId();

}

@Override
public int hashCode() {
    return getId();
}

1

বিবেচনা:

Object obj = new Book();
obj.equals("hi");
// Oh noes! What happens now? Can't call it with a String that isn't a Book...

1
@ এলাজার কীভাবে? objহিসাবে ঘোষণা করা হয় Object। উত্তরাধিকার সূত্রে প্রাপ্ত পয়েন্ট যে আপনি তারপর একটি ধার্য করতে পারেন হয় Bookকরতে obj। এর পরে, যদি না আপনি প্রস্তাব করেন যে কোনও মাধ্যমে Objectকোনওের সাথে তুলনামূলক না হওয়া উচিত , এই কোডটি পুরোপুরি আইনী হওয়া উচিত এবং ফিরে আসা উচিত । Stringequals()false
বিসিএসবি 1001

আমি ঠিক যে পরামর্শ। আমি বিশ্বাস করি এটি বেশ ব্যাপকভাবে গৃহীত।
এলাজার

0

instanceOfবিবৃতি প্রায়ই সমান বাস্তবায়ন ব্যবহার করা হয়।

এটি একটি জনপ্রিয় ক্ষতি!

সমস্যাটি হ'ল instanceOfপ্রতিযোগিতার বিধি লঙ্ঘন করে:

(object1.equals(object2) == true) যদি এবং কেবল যদি (object2.equals(object1))

প্রথম সমানটি যদি সত্য হয় এবং অবজেক্ট 2 হল শ্রেণীর সাবক্লাসের উদাহরণ যেখানে 1জেক্ট 1 সম্পর্কিত, তবে দ্বিতীয় সমানটি মিথ্যা হিসাবে ফিরে আসবে!

যদি সম্মত শ্রেণি যেখানে ওবি 1 অন্তর্ভুক্ত থাকে তবে তা চূড়ান্ত হিসাবে ঘোষণা করা হয়, তবে এই সমস্যা দেখা দিতে পারে না, তবে সাধারণভাবে আপনাকে নিম্নলিখিত হিসাবে পরীক্ষা করা উচিত:

this.getClass() != otherObject.getClass(); যদি তা না হয় তবে মিথ্যা ফিরুন, অন্যথায় সমতার জন্য তুলনা করার জন্য ক্ষেত্রগুলি পরীক্ষা করুন!


3
ব্লচ, কার্যকর জাভা, আইটেম 8 দেখুন, equals()পদ্ধতিটি ওভাররাইডিংয়ের সাথে সমস্যাগুলি নিয়ে আলোচনা করে একটি বৃহত্ বিভাগ । তিনি ব্যবহার বিরুদ্ধে সুপারিশ getClass()। মূল কারণ হ'ল এটি করা উপক্লাসগুলির জন্য লিসকোভ সাবস্টিটিউশন নীতিমালা ভঙ্গ করে যা সাম্যাকে প্রভাবিত করে না।
স্টুয়ার্ট

-1

রেকর্ডআইডি হ'ল বস্তুর সম্পত্তি property

@Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Nai_record other = (Nai_record) obj;
        if (recordId == null) {
            if (other.recordId != null)
                return false;
        } else if (!recordId.equals(other.recordId))
            return false;
        return true;
    }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.