سؤال

في. صافي، يمكنني أن أفعل شيئا مثل هذا:

public static T[] CreateAndFillArray<T>(int size) where T : new()
{
   T[] array = new T[size];
   for (int i = size - 1; i >= 0; i--)
       array[i] = new T();
   return array;
}

يجب علينا تحديد جملة "حيث T: جديد ()".

كيف تفعل ذلك في جاوة؟

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

المحلول

في Java، لا يمكنك إنشاء إنشاء مجموعة عامة. (مثل T جديد [الحجم] لا يمكن أن تعمل) هذا لأنه في وقت التشغيل يتم فقد أنواع الأجواء ("محو") ولا يمكن استردادها.

هل هناك سبب لا يمكنك استخدامه، على سبيل المثال، قائمة صفيف جديدةu003CT> ()؟

نصائح أخرى

لن تتمكن من إنشاء مجموعة من النوع العام "T" في Java إلا إذا قمت بالمرور في المعلمة.

public static <T> T[] createAndFillArray(Class<T> cls, int size) {
  T[] result = (T[]) Array.newInstance(cls, size);
  for (int i=0; i<size; i++) {
    result[i] = cls.newInstance();
  }
  return result;
}

ليس لدى Java بناء ما يعادلها. لا يوجد سلامة تجميع تجميع على فئة تحتوي على منشئ.

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

public static <T> T[] createAndFillArray(T sampleObject, int size) throws Exception {
        Class<T> klass = sampleObject.getClass();
        T[] arr = (T[]) Array.newInstance(klass, size);
        for (int i = 0; i < size; i++) {
            arr[i] = klass.newInstance();
        }
        return arr;
}

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

تحرير: chssply76 تغلبني عليه، لذلك قمت بتعديل الرمز المذكور أعلاه لإعطاء مثال حيث تمر في عينة كائن فعلي، فقط لإظهار كيف يتم ذلك. عادة في مثل هذه الحالة، ستمرك في الفصل لأن الطعما لا ينتهي الأمر في الصفيف.

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

import java.lang.reflect.Array;

public class Main
{
    public static void main(String[] args)
    {
        final String[] array;

        array = createAndFillArray(String.class, 10, new StringCreator());

        for(final String s : array)
        {
            System.out.println(s);
        }
    }

    public static <T> T[] createAndFillArray(final Class<T>   clazz,
                                             final int        size,
                                             final Creator<T> creator)
    {
        T[] result = (T[]) Array.newInstance(clazz, size);

        for (int i=0; i<size; i++)
        {
            result[i] = creator.newInstance();
        }

        return result;
    }
}

interface Creator<T>
{
    T newInstance();
}

class StringCreator
    implements Creator<String>
{
    public String newInstance()
    {
        // not the best example since String is immutable but you get the idea
        // you could even have newInstance take an int which is the index of the 
        // item being created if that could be useful (which it might).
        return ("hello");
    }
}

هذا هو في الواقع أكثر مرونة من طريقة C # التي تصفها لأنك يمكنك التحكم في المنشئ إذا كنت تريد بدلا من مجرد استدعاء No-Arg One.

لا يمكنك القيام بذلك في Java، لأن Java لا يدعم الشيكات من النوع الهيكلية.

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

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