জাভাতে প্রতিফলনের মাধ্যমে ব্যক্তিগত উত্তরাধিকার সূত্রে প্রাপ্ত অ্যাক্সেস


109

আমি উত্তরাধিকার সূত্রে প্রাপ্ত সদস্যদের মাধ্যমে একটি class.getDeclaredFields(); বেসরকারী সদস্যদের মাধ্যমে প্রবেশের একটি উপায় খুঁজে পেয়েছি class.getFields() তবে আমি ব্যক্তিগত উত্তরাধিকার সূত্রে ক্ষেত্রগুলি খুঁজছি। আমি কীভাবে এটি অর্জন করতে পারি?


28
"ব্যক্তিগত উত্তরাধিকার সূত্রে ক্ষেত্রগুলি" বিদ্যমান নেই। যদি ক্ষেত্রটি ব্যক্তিগত হয় তবে তা উত্তরাধিকার সূত্রে প্রাপ্ত হয় না, এবং কেবল পিতামাতার শ্রেণীর অবধি থাকে। প্যারেন্টের ব্যক্তিগত ক্ষেত্রগুলি অ্যাক্সেস করতে আপনাকে প্রথমে পিতামাত্ত শ্রেণীর অ্যাক্সেস করতে হবে (সিএফ। আইওবের প্রতিক্রিয়া)
বেনোইট

6
যা বলেছিল, সুরক্ষিত ক্ষেত্রগুলি উত্তরাধিকার সূত্রে প্রাপ্ত হয়, তবে প্রতিচ্ছবি দ্বারা সেগুলি পেতে আপনাকে একই কাজ করতে হবে।
বোঝো

উত্তর:


128

এটি কীভাবে সমাধান করা যায় তা প্রদর্শন করা উচিত:

import java.lang.reflect.Field;

class Super {
    private int i = 5;
}

public class B extends Super {
    public static void main(String[] args) throws Exception {
        B b = new B();
        Field f = b.getClass().getSuperclass().getDeclaredField("i");
        f.setAccessible(true);
        System.out.println(f.get(b));
    }
}

(বা Class.getDeclaredFieldsসমস্ত ক্ষেত্রের অ্যারের জন্য।)

আউটপুট:

5

এটি কি সমস্ত সুপারক্লাসের ক্ষেত্র বা কেবল প্রত্যক্ষ সুপারক্লাস পায়?
বৃষ্টি

সরাসরি সুপার ক্লাসের ক্ষেত্র। আপনি আরও উপরে যেতে চাইলে getSuperclass()পৌঁছা পর্যন্ত আপনি পুনরাবৃত্তি nullকরতে পারেন।
আইয়ুব

আপনি কেন পরের দুটি বিবৃতিতে অ্যারে অ্যাক্সেসটি ব্যবহার করবেন না getDeclaredFields()[0]বা getDeclaredField("i")বরং পুনরাবৃত্তি করবেন [0]?
হলগার

এই নির্দিষ্ট প্রশ্নটি যেভাবে তৈরি করা হয়েছে তার কারণেই এটি। এটি মূলত কীভাবে ব্যবহার করা যায় তার একটি প্রদর্শন ছিল getDeclaredFields। উত্তর আপডেট করা হয়েছে।
আইয়ুব

44

এখানে সর্বোত্তম পন্থা ভিজিটর প্যাটার্নটি ক্লাসে এবং সমস্ত সুপার ক্লাসের সমস্ত ক্ষেত্র সন্ধান করে এবং তাদের উপর একটি কলব্যাক ক্রিয়া সম্পাদন করে।


বাস্তবায়ন

বসন্তে একটি দুর্দান্ত ইউটিলিটি ক্লাস রয়েছে ReflectionUtilsযা কেবল এটি করে: এটি একটি কলব্যাকের সাহায্যে সমস্ত সুপার ক্লাসের সমস্ত ক্ষেত্রের লুপ করার একটি পদ্ধতি নির্ধারণ করে:ReflectionUtils.doWithFields()

ডকুমেন্টেশন:

টার্গেট ক্লাসের সমস্ত ক্ষেত্রে প্রদত্ত কলব্যাকটি আহ্বান করুন, সমস্ত ঘোষিত ক্ষেত্রগুলি পেতে ক্লাসের শ্রেণিবিন্যাসে উঠে যান।

পরামিতি:
- ক্লজ - বিশ্লেষণের লক্ষ্য শ্রেণি
- এফসি - প্রতিটি ক্ষেত্রের জন্য কলব্যাক
- এফএফ - ফিল্টার যা কলব্যাক প্রয়োগ করতে ক্ষেত্রগুলি নির্ধারণ করে

কোডের উদাহরণ:

ReflectionUtils.doWithFields(RoleUnresolvedList.class,
    new FieldCallback(){

        @Override
        public void doWith(final Field field) throws IllegalArgumentException,
            IllegalAccessException{

            System.out.println("Found field " + field + " in type "
                + field.getDeclaringClass());

        }
    },
    new FieldFilter(){

        @Override
        public boolean matches(final Field field){
            final int modifiers = field.getModifiers();
            // no static fields please
            return !Modifier.isStatic(modifiers);
        }
    });

আউটপুট:

পাওয়া ক্ষেত্র ব্যক্তিগত অস্থায়ী javax.management.relation.RoleUnresolvedList.typeSafe বুলিয়ান টাইপ বর্গ javax.management.relation.RoleUnresolvedList মধ্যে
javax.management.relation.RoleUnresolvedList.tainted বুলিয়ান পাওয়া ক্ষেত্র ব্যক্তিগত অস্থায়ী টাইপ বর্গ javax.management.relation.RoleUnresolvedList মধ্যে
পাওয়া ক্ষেত্র প্রাইভেট ট্রান্সিয়েন্ট জাভা.আলং.অবজেক্ট [] java.util.ArrayList.elementData টাইপ ক্লাসে java.util.ArrayList
ফিল্ড প্রাইভেট ইন্ট java.util.ArrayList.size টাইপ শ্রেণিতে java.util.ArrayList
পাওয়া ক্ষেত্র সুরক্ষিত ক্ষণস্থায়ী জাভা জাভা। java.util.AbstractList টাইপ শ্রেণিতে use.AbstractList.modCount


3
এটি "দর্শনার্থী বিন্যাস" নয়, তবে আপনার কোডটিতে স্প্রিং ভাইরাস থাকলে এটি এখনও খুব সুন্দর একটি সরঞ্জাম tool ভাগ করার জন্য :) ধন্যবাদ
thinlizzy

2
@ জোস.ডিয়েগো আমি নিশ্চিত যে আপনি সে সম্পর্কে তর্ক করতে পারেন। এটি কোনও বস্তু গাছের চেয়ে শ্রেণি শ্রেণিবিন্যাস পরিদর্শন করে তবে নীতিটি একই থাকে
সান প্যাট্রিক ফ্লয়েড

এই মন্তব্যটির কোনও প্রতিক্রিয়া পাওয়া যায় কিনা তা নিশ্চিত নয়, তবে আপনি এই সমাধানটি নিয়ে কেবলমাত্র কোনও নির্দিষ্ট ক্ষেত্রে ঘুরে দেখছেন। যদি একই সাথে আমার অন্যান্য ক্ষেত্রগুলির দিকে নজর দেওয়া দরকার - যেমন, অন্য ক্ষেত্রটি যদি শূন্য হয় তবে এই ক্ষেত্রটি "অ্যাবসি" তে সেট করুন - আমার কাছে সামগ্রিকভাবে উপলব্ধ অবজেক্টটি নেই।
জিন খ।

এটি অত্যন্ত খারাপ যে এই শ্রেণীর জন্য জাভাডোক নির্দেশ করে যে "এটি কেবল অভ্যন্তরীণ ব্যবহারের উদ্দেশ্যেই করা হয়েছে", সুতরাং এটি যে কেউ এটি ব্যবহার করতে চান তাদের পক্ষে এটি সম্ভাব্য ঝুঁকি।
স্পেসম্যান

1
@ স্পেসম্যানস্পিফ আপনি প্রযুক্তিগতভাবে সঠিক, তবে এই শ্রেণিটি প্রায় 15 বছর ধরে রয়েছে (4 টি বড় রিলিজ সংস্করণ সহ) এবং বহু স্প্রিং গ্রাহকরা ব্যাপকভাবে ব্যবহার করেছেন। আমি সন্দেহ করি তারা এখন এটিকে আবার টানবে।
সান প্যাট্রিক ফ্লয়েড

34

এটি এটি করবে:

private List<Field> getInheritedPrivateFields(Class<?> type) {
    List<Field> result = new ArrayList<Field>();

    Class<?> i = type;
    while (i != null && i != Object.class) {
        Collections.addAll(result, i.getDeclaredFields());
        i = i.getSuperclass();
    }

    return result;
}

আপনি যদি EclEmma এর মতো কোনও কোড কভারেজ সরঞ্জাম ব্যবহার করেন তবে আপনাকে নজরদারি করতে হবে: তারা আপনার প্রতিটি ক্লাসে একটি লুকানো ক্ষেত্র যুক্ত করে। EclEmma এর ক্ষেত্রে, এই ক্ষেত্রগুলি সিন্থেটিক হিসাবে চিহ্নিত হয়েছে এবং আপনি এগুলি তাদের মতো ফিল্টার করতে পারেন:

private List<Field> getInheritedPrivateFields(Class<?> type) {
    List<Field> result = new ArrayList<Field>();

    Class<?> i = type;
    while (i != null && i != Object.class) {
        for (Field field : i.getDeclaredFields()) {
            if (!field.isSynthetic()) {
                result.add(field);
            }
        }
        i = i.getSuperclass();
    }

    return result;
}

সিন্থেটিক ক্ষেত্র সম্পর্কে আপনার মন্তব্যের জন্য ধন্যবাদ, EMMA একই কাজ করে।
আনাতোলি

এটি আর্গুমেন্ট শ্রেণীর ঘোষিত এবং উত্তরাধিকার সূত্রে প্রাপ্ত ক্ষেত্রগুলির সুতরাং getDeclaredAndInherisedPrivateFields নামকরণ করা উচিত। ধন্যবাদ যদিও ধন্যবাদ!
পিটার হকিন্স

1
আইস সিনথেটিকের উপর দুর্দান্ত ক্যাচ :)
লুকাস ক্রাফোর্ড

চমত্কার উত্তরের জন্য ধন্যবাদ ~
বৃষ্টি

19
public static Field getField(Class<?> clazz, String fieldName) {
    Class<?> tmpClass = clazz;
    do {
        try {
            Field f = tmpClass.getDeclaredField(fieldName);
            return f;
        } catch (NoSuchFieldException e) {
            tmpClass = tmpClass.getSuperclass();
        }
    } while (tmpClass != null);

    throw new RuntimeException("Field '" + fieldName
            + "' not found on class " + clazz);
}

( এই উত্তরের ভিত্তিতে )


15

আসলে আমি একটি জটিল ধরণের হাইরাচি ব্যবহার করি যাতে আপনার সমাধানটি সম্পূর্ণ হয় না। সমস্ত ব্যক্তিগত উত্তরাধিকার সূত্রে প্রাপ্ত ক্ষেত্রগুলি পেতে আমার পুনরাবৃত্তি কল করতে হবে। এখানে আমার সমাধান

 /**
 * Return the set of fields declared at all level of class hierachy
 */
public Vector<Field> getAllFields(Class clazz) {
    return getAllFieldsRec(clazz, new Vector<Field>());
}

private Vector<Field> getAllFieldsRec(Class clazz, Vector<Field> vector) {
    Class superClazz = clazz.getSuperclass();
    if(superClazz != null){
        getAllFieldsRec(superClazz, vector);
    }
    vector.addAll(toVector(clazz.getDeclaredFields()));
    return vector;
}

তবে, তার সমাধান আপনাকে সঠিক পথে নিয়েছে, তাই না?
অ্যাপার্কিনস 25:55

1
ভেক্টরটি পুরানো কোডটি খারাপ। দয়া করে সংগ্রহের কাঠামো থেকে একটি বর্তমান ডেটা স্ট্রাকচার ব্যবহার করুন (বেশিরভাগ ক্ষেত্রে অ্যারেলিস্ট পর্যাপ্ত)
সান প্যাট্রিক ফ্লয়েড

@ পেপারকিন্স আইওবের উত্তরটি আমার মতো দেখাচ্ছে তবে আমি এটি খুঁজে পেয়েছি এবং তারপরে আমি উত্তরটি দেখেছি। @ সানাইজার ভেক্টর এত পুরানো নয় এবং এটি সংগ্রহের এপিআইয়ের সদস্য
বেনজেন

"জাভা 2 প্ল্যাটফর্ম v1.2 হিসাবে, এই শ্রেণিটি তালিকা বাস্তবায়নের জন্য পুনরায় প্রেরণ করা হয়েছে, যাতে এটি জাভা সংগ্রহের কাঠামোর অংশ হয়ে যায়।" 1.2 সালে retrofitted? যদি সেই বয়স না হয় তবে কী? সূত্র: download.oracle.com/javase/1.4.2/docs/api/java/util/Vector.html
সান প্যাট্রিক ফ্লয়েড

7
ভেক্টরের একটি বিশাল ওভারহেড রয়েছে কারণ সমস্ত কিছু সিঙ্ক্রোনাইজড। এবং যেখানে আপনার সিঙ্ক্রোনাইজেশন প্রয়োজন, জাভা.ইটি.এল.কন্ট্রন্টে আরও ভাল ক্লাস রয়েছে। ভেক্টর, হ্যাশটেবল এবং স্ট্রিংবাফার বেশিরভাগ ক্ষেত্রে অ্যারেলিস্ট, হ্যাশম্যাপ এবং স্ট্রিংবিল্ডার দ্বারা প্রতিস্থাপন করা উচিত
সান প্যাট্রিক ফ্লয়েড

8

মডেল সিটিজেনের ব্লুপ্রিন্টগুলির জন্য উত্তরাধিকার সূত্রে প্রাপ্ত ক্ষেত্রগুলির জন্য আমার সমর্থন যুক্ত করা দরকার । আমি এই পদ্ধতিটি উত্পন্ন করেছি যা ক্লাসের ক্ষেত্র + উত্তরাধিকার সূত্রে প্রাপ্ত ক্ষেত্রগুলি পুনরুদ্ধারের জন্য কিছুটা সংক্ষিপ্ত।

private List<Field> getAllFields(Class clazz) {
    List<Field> fields = new ArrayList<Field>();

    fields.addAll(Arrays.asList(clazz.getDeclaredFields()));

    Class superClazz = clazz.getSuperclass();
    if(superClazz != null){
        fields.addAll(getAllFields(superClazz));
    }

    return fields;
}

7
private static Field getField(Class<?> clazz, String fieldName) {
    Class<?> tmpClass = clazz;
    do {
        for ( Field field : tmpClass.getDeclaredFields() ) {
            String candidateName = field.getName();
            if ( ! candidateName.equals(fieldName) ) {
                continue;
            }
            field.setAccessible(true);
            return field;
        }
        tmpClass = tmpClass.getSuperclass();
    } while ( clazz != null );
    throw new RuntimeException("Field '" + fieldName +
        "' not found on class " + clazz);
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.