Findbugs تحذير:يساوي الأسلوب لا ينبغي أن نفترض أي شيء عن نوع من الحجة

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

  •  21-08-2019
  •  | 
  •  

سؤال

عند تشغيل FindBugs على المشروع ، لدي بعض حالات الخطأ المذكورة أعلاه.

وهي بلدي تجاوز إصدارات يساوي يلقي RHS الكائن في نفس نوع الكائن الذي تجاوز نسخة محددة.

ولكن لست متأكدا ما إذا كان أفضل تصميم ممكن ، منذ AFAIK جافا لا تسمح الفرق في طريقة المعلمات ، لذلك فإنه ليس من الممكن تحديد أي نوع يساوي المعلمة.

أفعل شيء خاطئ جدا ، أو هو FindBugs حريصة جدا?

طريقة مختلفة للتعبير عن هذا السؤال هو:ما هو السلوك الصحيح إذا كان الكائن الذي تم تمريره إلى تساوي ليس من نفس النوع كما LHS:هذا كاذب ، أو ينبغي أن يكون هناك استثناء ؟

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

public boolean equals(Object rhs)
{
    MyType rhsMyType = (MyType)rhs; // Should throw exception
    if(this.field1().equals(rhsMyType.field1())... // Or whatever
}
هل كانت مفيدة؟

المحلول

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

if (getClass() != obj.getClass())
    return false;
MyObj myObj = (MyObj) obj;

بهذه الطريقة سوف تمنع FindBugs تحذير.

ملاحظة جانبية إلى عنوان التعليق:
ويزعم بعض الناس أن استخدام instanceof بدلا من getClass للتحقق من نوع الأمان.هناك نقاش كبير و هذا ما كنت أحاول أن لا ندخل في حين لاحظت أن يمكنك التحقق من الدرجة المساواة أو التوافق, ولكن أعتقد أنني لا أستطيع الهروب منه.يتلخص هذا - إذا كنت تستخدم instanceof يمكنك دعم المساواة بين مثيلات فئة الحالات من فئة فرعية ، ولكن هل خطر كسر متماثل عقد equals.عموما أنصح بعدم استخدام instanceof إلا إذا كنت تعرف كنت في حاجة إليها و أنت تعرف ما تقومون به.لمزيد من المعلومات انظر:

نصائح أخرى

وكنت تفعل ربما شيء من هذا القبيل:

public class Foo {
  // some code

  public void equals(Object o) {
    Foo other = (Foo) o;
    // the real equals code
  }
}

في هذا المثال كنت على افتراض شيئا عن حجة يساوي (): أنت على افتراض انها من نوع فو. هذا يحتاج لا يكون الأمر كذلك! يمكنك أيضا الحصول على سلسلة (في هذه الحالة يجب عليك تقريبا بالتأكيد سيعود كاذبة).

وهكذا التعليمات البرمجية الخاصة بك ينبغي أن تبدو هذه:

public void equals(Object o) {
  if (!(o instanceof Foo)) {
    return false;
  }
  Foo other = (Foo) o;
  // the real equals code
}

و(أو استخدام getClass() != o.getClass() أكثر صرامة من قبل ديف L المذكورة.

ويمكنك أيضا أن ننظر في الأمر بهذه الطريقة:

Integer i = new Integer(42);
String s = "fourtytwo";
boolean b = i.equals(s);

هل هناك أي سبب أن هذا الرمز يجب رمي ClassCastException بدلا من الانتهاء بشكل طبيعي ووضع b إلى false؟

ورمي ClassCastException كرد على .equals() لن يكون من المعقول. لأنه حتى لو كان هو سؤال غبي ( "وبالطبع سلسلة أبدا تساوي فو!") ما زال ساري المفعول واحد مع إجابة ما يرام تماما ( "لا" == false).

وأنصح تجاهل findbugs قال التحذير. في الواقع، إذا كان يتم استدعاء مع كائن من فئة غير متوقعة قدم المساواة، فإنه يكاد يكون من المؤكد أن علة، وتريد أن تفشل بسرعة على البق.

وعلى سبيل المثال، إذا كان لديك "ملفات ArrayList"، وندعو files.contains ( "على Myfile.txt")، فإنه سيكون من الرائع إذا كنت حصلت على ClassCastException. بدلا من ذلك، جافا يعود فقط كاذبة، وأنه من المرجح يستغرق وقتا طويلا حتى تكتشف هذا الخطأ.

وأبدأ متساوين بلدي (كائن) تطبيقات مثل هذا:

if ((object == null) || !(object instaceof ThisClass)) {
    return false;
}

وهذا من شأنه أيضا منع التحذير FindBugs ولكن لن يعود false تلقائيا عندما يتم تسليم فئة فرعية من ThisClass في. يمكن النظر أيضا على قدم المساواة، وخاصة إذا لم يتم تجاوز أسلوب equals(Object) لها.

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