জাভা প্রতিবিম্বে গেটফিল্ড এবং getDeclaredFields মধ্যে পার্থক্য কি


195

আমি জাভা প্রতিবিম্ব ব্যবহার করার সময় getFieldsপদ্ধতি এবং পদ্ধতির মধ্যে পার্থক্য সম্পর্কে কিছুটা বিভ্রান্ত হয়ে পড়েছি getDeclaredFields

আমি পড়েছি যা getDeclaredFieldsআপনাকে ক্লাসের সমস্ত ক্ষেত্রে অ্যাক্সেস দেয় এবং এটি getFieldsকেবল সর্বজনীন ক্ষেত্রগুলি দেয়। যদি এটি হয় তবে আপনি কেবল সর্বদা ব্যবহার করবেন না কেন getDeclaredFields?

কেউ কি দয়া করে এ সম্পর্কে বিশদভাবে বর্ণনা করতে পারেন এবং দুটি পদ্ধতির মধ্যে পার্থক্যটি ব্যাখ্যা করতে পারেন এবং কখন / কেন আপনি অন্যটির মধ্যে একটি ব্যবহার করতে চান?


3
getFieldএকটি সুপারক্লাস থেকে উত্তরাধিকার সূত্রে ক্ষেত্র পেতে পারে তবে তা getDeclaredFieldপারে না। getDeclaredFieldআপনি যে ক্লাসটিতে কল করেন তার মধ্যে নিজেকে সীমাবদ্ধ করুন।
ব্যবহারকারী 2336315

@ ইউজার 2336315 এটি সঠিক, তবে getFieldব্যক্তিগত সদস্যদের অ্যাক্সেস করতে পারবেন না
ম্যাডব্রেকস

উত্তর:


258

getFields ()

সমস্ত publicক্ষেত্র পুরো শ্রেণিবদ্ধ শ্রেণিবদ্ধ।

getDeclaredFields ()

সমস্ত ক্ষেত্রগুলি তাদের অ্যাক্সেসযোগ্যতা নির্বিশেষে কেবলমাত্র বর্তমান শ্রেণীর জন্য, বর্তমান শ্রেণিটি উত্তরাধিকার সূত্রে প্রাপ্ত কোনও বেস ক্লাস নয়।

সমস্ত ক্ষেত্রকে শ্রেণিবদ্ধ করতে, আমি নিম্নলিখিত ফাংশনটি লিখেছি:

public static Iterable<Field> getFieldsUpTo(@Nonnull Class<?> startClass, 
                                   @Nullable Class<?> exclusiveParent) {

   List<Field> currentClassFields = Lists.newArrayList(startClass.getDeclaredFields());
   Class<?> parentClass = startClass.getSuperclass();

   if (parentClass != null && 
          (exclusiveParent == null || !(parentClass.equals(exclusiveParent)))) {
     List<Field> parentClassFields = 
         (List<Field>) getFieldsUpTo(parentClass, exclusiveParent);
     currentClassFields.addAll(parentClassFields);
   }

   return currentClassFields;
}

exclusiveParentক্লাস থেকে ক্ষেত্র আহরণ প্রতিরোধ প্রদান করা হয় Objectnullআপনি যদি Objectক্ষেত্র চান তবে এটি হতে পারে ।

স্পষ্ট করতে, Lists.newArrayListপেয়ারা থেকে আসে।

হালনাগাদ

এফওয়াইআই, উপরের কোডটি আমার লিবিএক্স প্রকল্পের প্রতিচ্ছবিগুলিতে গিটহাবে প্রকাশিত হয়েছে ।


8
দুর্দান্ত উত্তর, তবে এটি লক্ষ করা উচিত যে সুপারক্লাসে ব্যক্তিগত ক্ষেত্রগুলি বর্তমান শ্রেণীর উদাহরণ Field#getএবং অনুরূপ পদ্ধতির দ্বারা ব্যবহার করা যায় না । অন্য কথায়, এই পদ্ধতির বর্তমান ক্লাসটিকে তার সুপারক্লাসের ব্যক্তিগত ইন্টারফেসে অ্যাক্সেসের অনুমতি দেয় না , একইভাবে সাধারণত সংকলনটি করে না।
এফটিহম্পসন

4
@ ভ্যালকান ট্রু না হলে কোডটি স্কোপ পরিবর্তন করার জন্য প্রতিবিম্বটি ব্যবহার করতে লেখা setAccessibleনা হয় এবং কোনও সুরক্ষা ব্যবস্থাপক নেই
জন বি

সামান্য নিট, হওয়া উচিত "(অ্যাক্সেসযোগ্যতার কোনও ব্যাপার নয়)" না "(কোনও সুযোগ নেই)"। সমস্ত ক্ষেত্রের একই স্কোপ থাকে, যথা, শ্রেণীর শরীর
ysavit

ধন্যবাদ আপডেট করা হয়েছে।
জন বি

1
এটা হবে না। যেহেতু শ্রেণি-নির্দিষ্ট privateকেবল ক্ষেত্রগুলিতে কেবল অ্যাক্সেস করা যায় getDeclaredFields। প্রতিটি ক্ষেত্র (এমনকি একই ধরণের এবং নাম সহ) পৃথক Fieldদৃষ্টান্ত।
জন বি

7

ইতিমধ্যে উল্লিখিত হিসাবে, Class.getDeclaredField(String)শুধুমাত্র আপনি যে ক্ষেত্রটিতে Classকল করেছেন সেখান থেকে কেবল ক্ষেত্রগুলি দেখবে ।

আপনি যদি একটি অনুসন্ধান করতে চান তাহলে FieldClassঅনুক্রমের, আপনি এই সহজ ফাংশন ব্যবহার করতে পারেন:

/**
 * Returns the first {@link Field} in the hierarchy for the specified name
 */
public static Field getField(Class<?> clazz, String name) {
    Field field = null;
    while (clazz != null && field == null) {
        try {
            field = clazz.getDeclaredField(name);
        } catch (Exception e) {
        }
        clazz = clazz.getSuperclass();
    }
    return field;
}

privateউদাহরণস্বরূপ, একটি সুপারক্লাস থেকে একটি ক্ষেত্র সন্ধান করতে এটি দরকারী । এছাড়াও, আপনি যদি এর মানটি পরিবর্তন করতে চান তবে আপনি এটি ব্যবহার করতে পারেন:

/**
 * Sets {@code value} to the first {@link Field} in the {@code object} hierarchy, for the specified name
 */
public static void setField(Object object, String fieldName, Object value) throws Exception {
    Field field = getField(object.getClass(), fieldName);
    field.setAccessible(true);
    field.set(object, value);
}

কিছু না পাওয়া try try { field = clazz.getDeclaredField(name); } catch (NoSuchFieldException e) { clazz = clazz.getSuperclass(); if(clazz==null){ throw e; } }
গেলেও

5

public Field[] getFields() throws SecurityException

সমস্ত অ্যাক্সেসযোগ্য পাবলিক ক্ষেত্রগুলিকে প্রতিফলিত করে এমন ক্ষেত্রের অবজেক্টযুক্ত একটি অ্যারে ফেরত দেয়এই শ্রেণীর অবজেক্ট দ্বারা প্রতিনিধিত্ব করা শ্রেণি বা ইন্টারফেসের প্রদান করে। ফিরে আসা অ্যারের উপাদানগুলি বাছাই করা হয় না এবং কোনও নির্দিষ্ট ক্রমে হয় না। শ্রেণি বা ইন্টারফেসের অ্যাক্সেসযোগ্য পাবলিক ফিল্ড না থাকলে বা এটি কোনও অ্যারে শ্রেণি, একটি আদিম ধরণের বা শূন্যতার প্রতিনিধিত্ব করে তবে এই পদ্ধতিটি দৈর্ঘ্যের 0 টি অ্যারে প্রদান করে।

বিশেষত, যদি এই শ্রেণীর অবজেক্টটি কোনও শ্রেণীর প্রতিনিধিত্ব করে, এই পদ্ধতিটি এই শ্রেণীর সর্বজনীন ক্ষেত্রগুলি এবং এর সমস্ত সুপারক্লাসগুলি প্রদান করে। যদি এই শ্রেণি অবজেক্টটি একটি ইন্টারফেসের প্রতিনিধিত্ব করে, এই পদ্ধতিটি এই ইন্টারফেসের ক্ষেত্রগুলি এবং এর সমস্ত সুপারিনটারফেসগুলি প্রদান করে।

অ্যারে শ্রেণীর জন্য অন্তর্ভুক্ত দৈর্ঘ্যের ক্ষেত্রটি এই পদ্ধতি দ্বারা প্রতিফলিত হয় না। ব্যবহারকারীর কোডে অ্যারে হেরফের করতে শ্রেণীর অ্যারের পদ্ধতিগুলি ব্যবহার করা উচিত।


public Field[] getDeclaredFields() throws SecurityException

এই শ্রেণীর অবজেক্ট দ্বারা প্রতিনিধিত্ব করা শ্রেণি বা ইন্টারফেস দ্বারা ঘোষিত সমস্ত ক্ষেত্রকে প্রতিফলিত করে এমন ফিল্ড অবজেক্টগুলির একটি অ্যারে প্রদান করে। এর মধ্যে সর্বজনীন, সুরক্ষিত, ডিফল্ট (প্যাকেজ) অ্যাক্সেস এবং ব্যক্তিগত ক্ষেত্র অন্তর্ভুক্ত রয়েছে তবে উত্তরাধিকারসূত্রে প্রাপ্ত ক্ষেত্রগুলি বাদ দেয় । ফিরে আসা অ্যারের উপাদানগুলি বাছাই করা হয় না এবং কোনও নির্দিষ্ট ক্রমে হয় না। শ্রেণি বা ইন্টারফেসটি কোনও ক্ষেত্র ঘোষণা না করে বা এই শ্রেণি অবজেক্টটি যদি কোনও আদিম প্রকার, একটি অ্যারে শ্রেণি বা শূন্যতার প্রতিনিধিত্ব করে তবে এই পদ্ধতিটি দৈর্ঘ্যের 0 টি অ্যারে প্রদান করে।


এবং যদি আমার সমস্ত অভিভাবক শ্রেণীর সমস্ত ক্ষেত্রের প্রয়োজন হয়? কিছু কোড প্রয়োজন, যেমন https://stackoverflow.com/a/35103361/755804 থেকে :

public static List<Field> getAllModelFields(Class aClass) {
    List<Field> fields = new ArrayList<>();
    do {
        Collections.addAll(fields, aClass.getDeclaredFields());
        aClass = aClass.getSuperclass();
    } while (aClass != null);
    return fields;
}

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.