سؤال

في Java، أحتاج إلى إرجاع Iterator من طريقتي.تأتي بياناتي من كائن آخر والذي عادةً ما يمكن أن يمنحني مكررًا حتى أتمكن من إرجاعه، ولكن في بعض الظروف تكون البيانات الأساسية فارغة.من أجل الاتساق، أريد إرجاع مكرر "فارغ" في هذه الحالة حتى لا يضطر المتصلون بي إلى اختبار القيمة الفارغة.

أردت أن أكتب شيئا مثل:

public Iterator<Foo> iterator() {
   if (underlyingData != null) {
      return underlyingData.iterator();  // works
   } else {
      return Collections.emptyList().iterator();  // compiler error
   }
}

لكن مترجم Java يشكو من العودة Iterator<Object> بدلاً من Iterator<Foo>.الصب ل (Iterator<Foo>) لا يعمل أيضا.

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

المحلول

ويمكنك الحصول على قائمة فارغة من نوع فو من خلال بناء الجملة التالي:

return Collections.<Foo>emptyList().iterator();

نصائح أخرى

لقد كان جافا 7 من لفترة طويلة الآن. إلا إذا كنت مطورا للحصول على إصدار جافا السابق، هل يعود مكرر فارغ مثل هذا:

return Collections.emptyIterator();

وكنت أذهب أكثر على غرار

public Iterator<Foo> iterator() {
    if (underlyingData == null)
        return Collections.<Foo> emptyList().iterator();
    return underlyingData.iterator();
}

وفقط، والتعامل مع الحالة الخاصة والعودة، ثم التعامل مع الحالة الطبيعية. ولكن النقطة الرئيسية بلدي هو أنه يمكنك تجنب الاحالة مع

Collections.<Foo> emptyList().iterator();

والانزعاج من Collections.<Foo>emptyList().iterator() هو السبب الرئيسي لتوفير Iterators.emptyIterator() في جوجل-مجموعات . لا نوع معلمة اللازمة، في حالات مثل لك.

أعتقد أن هذا يوضح أن استدلال نوع Java لا يعمل في كل حالة وأن العامل الثلاثي لا يعادل دائمًا بنية if-else المكافئة على ما يبدو.

أريد أيضا أن أقول يتجنب null.تجنب أيضا المرور Iteratorيتعلق الأمر، لأن لديهم سلوكًا غريبًا (يفضل Iterable).ومع ذلك، بافتراض أن لديك سببًا مشروعًا وغير سابق لأوانه للقيام بذلك، فإن طريقتي المفضلة لكتابته ستكون

public Iterator<Foo> iterator() {
    return getUnderlyingData().iterator();
}
private List<Foo> getUnderlyingData() {
    if (underlyingData == null) {
        return Collections.emptyList();
    } else {
        return underlyingData;
    }
}

IMO، من الأفضل عدم إدراج معلومات النوع التي يمكن استنتاجها إذا كان من الممكن استنتاجها (حتى لو كانت تجعل التعليمات البرمجية الخاصة بك أطول).

من المؤكد أنك ستفعل ذلك أكثر من مرة، لذا أدخل أ getUnderlyingData الطريقة بدلاً من مجرد الإعلان عن متغير محلي.

انت تتصل iterator على كلا النتيجتين، فلا تكرر نفسك.

وعذرا، وأنا أحسب من ذلك. تحتاج إلى استخدام واجب بحيث مترجم يمكن معرفة نوع معلمات.

public Iterator<Foo> iterator() {
   if (underlyingData != null) {
      return underlyingData.iterator();
   } else {
      List<Foo> empty = Collections.emptyList();  // param type inference
      return empty.iterator();
   }
}
public  final class EmptyIterator{

    public static Iterator iterator(){
        return new Empty();
    }

    private static class Empty implements Iterator {
        public boolean hasNext(){
            return false;
        }
        public Object next(){
            throw new NoSuchElementException();
        }
        public void remove(){
        }
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top