سؤال

أنا معجب حقًا بميزات جافا ولا أريد التخلي عن استخدامها للمشكلة التالية:

لدي فئة قد تكون موروثة ، وداخلها private ArrayList arr; لذا فإن وظيفة setter على ما يرام ، ولكن وظيفة getter return arr; إرجاع الإشارة إلى هذا المتغير الذي قادر على تحرير هذا الصفيف بأكمله الذي لا أريده ولن يكون له أي معنى!

في C ++ أود فقط return const arr; وسيعود إشارة ثابتة إلى المتغير.

أنا بحاجة كثيرًا إلى المتغير ألا يتم استنساخه أو نسخه يدويًا لأن هناك العديد من الحسابات التي تتطلب (قراءة المتغير فقط) لماذا لا يوجد عودة في Java ؟؟؟؟ هل هناك أي طريقة يمكنني من خلالها الهروب من النسخ؟

ملاحظة (final ArrayList<Integer> arr;) ليس خيارًا يتسبب في أن الصفيف يغير دائمًا الحجم أو قيم العناصر.

إذا لم أتمكن


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

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

المحلول

لف قيمة الإرجاع مع java.util.collections.unmodifiablelist. لا يقوم بإنشاء نسخة من البيانات ، ولكنه يلف القائمة الأصلية ، ومندوب عمليات القراءة فقط إلى القائمة الأساسية. يتم رفض العمليات التي من شأنها تعديل القائمة في وقت التشغيل عبر UnsupportedOperationException.

لك

return arrayList;

يصبح

return Collections.unmodifiableList(arrayList);

لسوء الحظ ، لن يتم تنفيذ القيود للقراءة فقط من قبل المترجم. ومع ذلك ، سيتم فرضها في وقت التشغيل.

لديك أيضا متاح لك: unmodifiableset, UnmodiFiableAP, unmodifiableCollection, unmodifiablesortedset, ، و unmodifiablesortedMap. وإذا لم تكن هذه كافية ، فلا يزال بإمكانك الإلهام من نهج التصميم العام هذا ، وإنشاء فصول غلاف مخصصة للقراءة فقط.

نصائح أخرى

:) لديك عدة خيارات:

  • لا تكشف getter ، وتوفير الأساليب المسموح بها فقط بالاتصال ، على سبيل المثال

    public void addToList(Object arg) { this.arr.add(arg);}

  • إرجاع الكائن غير القابل للتغيير:

    public List getArr() { return Collections.unmodifiableList(this.arr); }

يمكنك أيضا استخدام Google Guavaغير قابل للتغيير مجموعات. في هذه الحالة ، ستخزن IMMUTABLELIST في مجالك.

بالطبع ، إذا احتاج فصلك إلى تعديل هذه القائمة داخليًا ، باستخدام Immutablist قد تتحول إلى فكرة سيئة ، حيث ستحتاج إلى إنشاء مثيل Immutablist جديد وإعادة تعيينه في الحقل في كل مرة ...

لكنها مثالية عندما تعرف أن القائمة لن تتغير بعد بناء الكائن.

مثال غير قابل للتغيير (لن تتغير القائمة بعد بناء الكائنات)

@Immutable
public final class Foo {

    @Nonnull
    private final ImmutableList<String> list;

    public Foo(@Nonnull List<String> list) {
        // you could also compute the appropriate list here
        // before assigning it to the field
        this.list = ImmutableList.copyOf(list);
    }


    public ImmutableList<String> getList() {
        return list;
    }
}

مثال قابل للتغيير (لا يمكن تعديل القائمة إلا باستخدام Setter)

public class Foo {

    @Nonnull
    private ImmutableList<String> list = ImmutableList.of();

    public ImmutableList<String> getList() {
        return list;
    }

    public void setList(@Nonnull List<String> list) {
        this.list = ImmutableList.copyOf(list);
    }
}

ملاحظات

  • أعلم أنه يُنصح غالبًا بإرجاع الأساليب إلى النوع الأكثر أهمية ممكنة (List في هذه الحالة) ، لكني أفضل إعلان نوع عودة getter الخاص بي باعتباره ImmutableList, ، لأنه بمثابة وثائق (لا حاجة لتوثيق قابلية التأثير القائمة التي تم إرجاعها في Javadoc) وكمواجرة API. إنه مثل قول "أنا ضمان هذه القائمة غير قابلة للتغيير ، لا داعي للقلق أو نسخها بشكل دفاعي ". وهي موجزة للغاية.
  • ImmutableList.copyOf() رائع ، لأنه يرفض تلقائيًا قوائم فارغة (عن طريق الرمي NullPointerException). كما يرفض العناصر الفارغة. ولن يقوم بنسخ قائمة المصدر إذا كانت بالفعل محفوظًا ، مما يتجنب إنشاء مثيل للكائنات غير المجدية.
  • في المثال الثاني ، أقوم بتهيئة الحقل إلى عازف Immutablelet الفارغ باستخدام ImmutableList.of(), ، لأنه من الممارسات الجيدة إعادة مجموعات فارغة بدلاً من القيم الخالية (نمط الكائن الفارغ). قد تعتقد أن هذا يخلق مثيلًا لا داعي له ، ولكن ImmutableList.of() في الواقع يعيد المفرد.

هناك بديل للطريقة غير المودعة. يمكنك فقط إعادة نسخة من هذه المجموعة الخاصة. فمثلا،

    return your_private_array.clone();

حسنًا ، يمكن أن يكون هناك عقوبة أداء لهذا الغرض. لكن لديك واجهة دون تغيير (لا تزال تُرجع صفيفًا).

unmodifiablelist هو بالتأكيد الجواب.

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