تجاوز طريقة "يساوي":كيفية معرفة نوع المعلمة؟

StackOverflow https://stackoverflow.com/questions/1628718

  •  06-07-2019
  •  | 
  •  

سؤال

أحاول التجاوز equals طريقة لفئة ذات معلمات.

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (!(obj instanceof Tuple))
        return false;

    Tuple<E> other = (Tuple<E>) obj; //unchecked cast
    if (!a0.equals(other.a0) && !a0.equals(other.a1)) {
        return false;
    }
    if (!a1.equals(other.a1) && !a1.equals(other.a0)) {
        return false;
    }

    return true;
}

كيف يمكنني التأكد من ذلك <E> التابع other الكائن هو نفسه this?

هل كانت مفيدة؟

المحلول

ويمكنك القيام بذلك عن طريق الاحتفاظ إشارة إلى نوع Class<E>. ومع ذلك، في رأيي، يجب أن يكون <م> الاختبارات المساواة حول القيم الكائنات تمثل بدلا من أنواع ملموسة الحصول أعرب القيم .

والمثال الكلاسيكي على ذلك هو API مجموعات على سبيل المثال. new ArrayList<String>().equals(new LinkedList<Object>()) يعود true. في حين أن هذه لديها أنواع مختلفة تماما، إلا أنها تمثل نفس القيمة، وهي "مجموعة فارغة".

وشخصيا، ينبغي اثنين Tuples التي تمثل نفس البيانات (مثل ("a", "b")) لا يكون على قدم المساواة، لأنه واحد من نوع Tuple<String> حين أن الآخر هو Tuple<Object>؟

نصائح أخرى

ولأن المحو لا يمكنك. حول أفضل ما يمكن القيام به هو مخزن في فئة الصفوف (tuple) نوع كنت تخطط لالصفوف (tuple) إلى عقد في عضو الميدان "java.lang.Class". ثم هل يمكن مقارنة تلك المجالات للتأكد من الطبقة الصفوف (tuple) تحتجز نفس أنواع.

وانظر أيضا هذا الموضوع: ما يعادل ++ C زوج في جافا؟

وسيكون من المفيد لو قمت بنشر المزيد عن صفك. أنا أفكر المدلى بها دون رادع أو رقمك من الحقول التي تساوي يعني أنه ينبغي أن يكون الصفوف (tuple) لا؟

وتحرير: هنا هي فئة زوج مفيدة يمكنني استخدام بانتظام (يمكنك التكيف مع الطبقة الصفوف (tuple) إذا لزم الأمر). ملاحظة مشابهة إلى اقتراحات من قبل الآخرين هذه الفئة يتيح فقط أعضاء احتواء تبت في مسألة المساواة. حالة استخدامك هو ما يجب تحديد ما إذا كانت المساواة ويستند حقا على نوع من أعضاء احتواء.

/**
 * Adapted from http://forums.sun.com/thread.jspa?threadID=5132045
 * 
 * 
 * @author Tim Harsch
 *
 * @param <L>
 * @param <R>
 */
public class Pair<L, R> {

    private final L left;
    private final R right;

    public R getRight() {
        return right;
    } // end getter

    public L getLeft() {
        return left;
    } // end getter

    public Pair(final L left, final R right) {
        this.left = left;
        this.right = right;
    } // end constructor

    public static <A, B> Pair<A, B> create(A left, B right) {
        return new Pair<A, B>(left, right);
    } // end factory method

    @Override
    public final boolean equals(Object o) {
        if (!(o instanceof Pair<?,?>))
            return false;

        final Pair<?, ?> other = (Pair<?, ?>) o;
        return equal(getLeft(), other.getLeft()) && equal(getRight(), other.getRight());
    } // end method

    public static final boolean equal(Object o1, Object o2) {
        if (o1 == null) {
            return o2 == null;
        }
        return o1.equals(o2);
    } // end method

    @Override
    public int hashCode() {
        int hLeft = getLeft() == null ? 0 : getLeft().hashCode();
        int hRight = getRight() == null ? 0 : getRight().hashCode();

        return hLeft + (37 * hRight);
    } // end method

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append('<');
        if( left == null ) {
            sb.append("null");
        } else {
            sb.append(left.toString());
        } // end if
        sb.append(',');
        if( right == null ) {
            sb.append("null");
        } else {
            sb.append(right.toString());
        } // end if
        sb.append('>');
        return sb.toString();
    } // end method
} // end class

وركضت للتو في هذه المشكلة بنفسي، وفي حالتي -particular-، لم أكن بحاجة إلى معرفة نوع E.

وعلى سبيل المثال:

public class Example<E> {
    E value;

    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Example<?> other = (Example<?>) obj;
        if (value == null) {
            if (other.value != null)
                return false;
        } else if (!value.equals(other.value))
            return false;
        return true;
    }
}

في رمز أعلاه، لا يوجد يلقي دون رادع بسبب استخدام Example<?>. نوع البدل المعلمة '؟ ينقذ اليوم.

للأسف، لا يمكنك القيام بذلك في وقت الترجمة؛لقد اختفت المعلومات.هذه هي عواقب نوع المحو.البديل هو تخزين المعلمة كـ a Class المثال، ثم ابحث عنه لاحقًا.

يتم مسح الأدوية في وقت الترجمة ، كنت في الأساس لا يمكن. في وقت التشغيل، وذهب أي معلمة نوع، وبقدر ما يتعلق الأمر JVM، فإنها هي نفسها تماما من جميع النواحي.

والطريقة للتغلب على ذلك هو لتخزين حقل Class الذي يمثل نوع، وإنشاء الكائن مع هذا النوع في منشئ.

وعينة المنشئ:

public class Tuple < E > {

    public Tuple(Class<E> c) {
        //store the class
    }

}

وأو هل يمكن استخدام المصنع:

public static <E> Tuple <E> getTuple(Class<E> type) {
    // Create and return the tuple, 
    // just store that type variable in it 
    // for future use in equals.
}

والاقتراحات للاحتفاظ إشارة إلى نوع E مع كائن Class يبدو <م> غير فعال (وهذا هو الكثير من إشارات لا معنى لها لClass تناول الذاكرة) والعبث لمشكلتك.

وانها ليست عموما صحيح أن Foo<Bar> andFoo<Baz> يجب أن يكون غير متكافئ. لذلك لا تحتاج E. و، في رمز كتبته، حتى أنك لا تحتاج إلى ترجمة. ببساطة يلقي إلى Tuple<?>، لأن ذلك هو حقا كل ما تعرفه عن Tuple في تلك المرحلة. لا يزال يجمع وجميع.

إذا تم تمريرها لك Tuples مع البيانات من نوعين مختلفين بعنف، لن equals تلك العناصر، وسوف طريقتك عودة false، كما تريد. (تأمل واحدة - يعتمد على تلك الأنواع تنفيذ equals عاقل)

خارج الموضوع - هل تدرك أنه وفقًا لتطبيقك، فإن Tuple(a0, a1) يساوي Tuple(a1, a1)؟أظن أن هذا ليس ما تريده ...

وفيما يتعلق بالموضوع، كما قال آخرون، فإن المحو يجعل هذا الأمر مستحيلاً.ولكن يجب عليك إعادة النظر في سبب رغبتك في ذلك - فالتحقق من المساواة يحدث فقط في وقت التشغيل، و الأدوية العامة هي وقت الترجمة فقط.من الناحية المفاهيمية، أ عامل لديه معلمات عامة، ولكن هدف لا.وبالتالي، عند مقارنة تساوي الكائنات، فإن المعلمات العامة لا تهم على الإطلاق؛لا يمكنك اتخاذ أي إجراء مناسب بناءً عليها في وقت التشغيل على أي حال.

تعد المساواة في الكائنات، والتباين المشترك/المتغير للمعلمة العامة، من الاهتمامات المتعامدة.

وأنا أتفق مع التعليقات الواردة أعلاه، لماذا الطبقة E تحتاج إلى أن تكون على قدم المساواة؟ وكيف تريد لعلاج الفئات الفرعية من E؟

وعلى أي حال، بالنظر إلى أن هنا هو نموذج التعليمات البرمجية التي قد تساعدك:

public class Example<T> {

  T t;

  public Example(T t) {
    this.t = t;
  }

  public static void main(String[] args) {
    final String s = "string";
    final Integer i = 1;
    final Number n = 1;

    final Example<String> exampleString = new Example<String>(s);
    final Example<Integer> exampleInteger = new Example<Integer>(i);
    final Example<Number> exampleNumber = new Example<Number>(n);

    System.out.println("exampleString subclass "  + exampleString.t.getClass());
    System.out.println("exmapleIntger subclass " + exampleInteger.t.getClass());
    System.out.println("exmapleNumber subclass " + exampleNumber.t.getClass());
    System.out.println("Integer equals Number = " + 
        exampleInteger.t.equals(exampleNumber.t));
  }
}

ويمكنك الاتصال t.getClass () للحصول على معلومات فئة عن نوع T (على افتراض أنه ليس لاغيا، بالطبع).

وآمل أن يساعد هذا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top