java - কিভাবে জাভা একটি ভিন্ন ক্লাস থেকে একটি ব্যক্তিগত ক্ষেত্র মান পড়তে?




class reflection (8)

Apache commons- FieldUtils থেকে FieldUtils ব্যবহার করে দেখুন:

FieldUtils.readField(object, fieldName, true);

আমি একটি তৃতীয় পক্ষের JAR মধ্যে একটি দুর্বল পরিকল্পিত বর্গ আছে এবং আমি তার ব্যক্তিগত ক্ষেত্র এক অ্যাক্সেস করতে হবে। উদাহরণস্বরূপ, কেন আমার ব্যক্তিগত ক্ষেত্র বেছে নেওয়ার প্রয়োজন হয়?

class IWasDesignedPoorly {
    private Hashtable stuffIWant;
}

IWasDesignedPoorly obj = ...;

stuffIWant মূল্য পেতে আমি কিভাবে প্রতিফলন ব্যবহার করতে পারি?


Oxbow_lakes উল্লেখ হিসাবে, আপনি অ্যাক্সেস সীমাবদ্ধতা কাছাকাছি পেতে প্রতিফলন ব্যবহার করতে পারেন (আপনার SecurityManager আপনাকে দেবে বলে মনে করা)।

যে বলেন, এই ক্লাস এত খারাপভাবে ডিজাইন করা হয়েছে যে এটি আপনাকে এই হ্যাকারের জন্য অবলম্বন করে, সম্ভবত আপনার একটি বিকল্প সন্ধান করা উচিত। নিশ্চিত এই সামান্য হ্যাক আপনি কয়েক ঘন্টা এখন সংরক্ষণ করা হতে পারে, কিন্তু এটা রাস্তা নিচে কত খরচ হবে?


আপনি Manifold's @ জাইলব্রিক সরাসরি, টাইপ-নিরাপদ জাভা প্রতিফলনের জন্য ব্যবহার করতে পারেন:

@JailBreak Foo foo = new Foo();
foo.stuffIWant = "123;

public class Foo {
    private String stuffIWant;
}

@JailBreak Foo এর আধিপত্যের সকল সদস্যের সরাসরি অ্যাক্সেসের জন্য কম্পাইলারের foo স্থানীয় পরিবর্তনটি আনলক করে।

একইভাবে আপনি একত্রে ব্যবহারের জন্য জেল ব্রেক () এক্সটেনশন পদ্ধতিটি ব্যবহার করতে পারেন:

foo.jailbreak().stuffIWant = "123";

jailbreak() পদ্ধতির মাধ্যমে আপনি Foo এর অনুক্রমের যেকোনো সদস্য অ্যাক্সেস করতে পারেন।

উভয় ক্ষেত্রেই কম্পাইলার আপনার জন্য টাইপ-নিরাপদে টাইপ করার জন্য ক্ষেত্রের অ্যাক্সেস সংশোধন করে, যেমন একটি পাবলিক ক্ষেত্র, যখন ম্যানিফোল আপনার জন্য হুডের অধীনে দক্ষ প্রতিফলন কোড জেনারেট করে।

Manifold সম্পর্কে আরও জানুন।


আপনি নিম্নলিখিত কাজ করতে হবে:

private static Field getField(Class<?> cls, String fieldName) {
    for (Class<?> c = cls; c != null; c = c.getSuperclass()) {
        try {
            final Field field = c.getDeclaredField(fieldName);
            field.setAccessible(true);
            return field;
        } catch (final NoSuchFieldException e) {
            // Try parent
        } catch (Exception e) {
            throw new IllegalArgumentException(
                    "Cannot access field " + cls.getName() + "." + fieldName, e);
        }
    }
    throw new IllegalArgumentException(
            "Cannot find field " + cls.getName() + "." + fieldName);
}

প্রতিফলন সম্পর্কে শুধু একটি অতিরিক্ত নোট: আমি কিছু বিশেষ ক্ষেত্রে পর্যবেক্ষণ করেছি, যখন বিভিন্ন নামের মধ্যে একই নামের একই নাম রয়েছে, উপরের উত্তর হিসাবে ব্যবহৃত প্রতিফলনটি বস্তুর সঠিক শ্রেণী বেছে নিতে ব্যর্থ হতে পারে। সুতরাং যদি আপনি জানেন বস্তুর প্যাকেজ.ক্ল্যাস কি, তাহলে তার ব্যক্তিগত ক্ষেত্রের মানগুলি নিম্নরূপঃ অ্যাক্সেস করা ভাল:

org.deeplearning4j.nn.layers.BaseOutputLayer ll = (org.deeplearning4j.nn.layers.BaseOutputLayer) model.getLayer(0);
Field f = Class.forName("org.deeplearning4j.nn.layers.BaseOutputLayer").getDeclaredField("solver");
f.setAccessible(true);
Solver s = (Solver) f.get(ll);

(এটি উদাহরণ শ্রেণী যা আমার জন্য কাজ করে না)


ব্যক্তিগত ক্ষেত্রগুলি অ্যাক্সেস করার জন্য, আপনাকে অবশ্যই ক্লাসের ঘোষিত ক্ষেত্রগুলি থেকে তাদের পেতে হবে এবং তারপরে তাদের অ্যাক্সেসযোগ্য করতে হবে:

Field f = obj.getClass().getDeclaredField("stuffIWant"); //NoSuchFieldException
f.setAccessible(true);
Hashtable iWantThis = (Hashtable) f.get(obj); //IllegalAccessException

সম্পাদন করুন : অ্যাপারকিনস দ্বারা মন্তব্য করা হয়েছে, উভয় ক্ষেত্রেই অ্যাক্সেস করা, এটি অ্যাক্সেসযোগ্য হিসাবে এবং মান পুনরুদ্ধার করা সমস্ত Exception ফেলে দেবে, যদিও কেবলমাত্র চেক করা ব্যতিক্রমগুলি আপনাকে সতর্ক হতে হবে তবে উপরে মন্তব্য করা হয়েছে।

যদি আপনি কোনও ক্ষেত্রের জন্য এমন একটি নাম জিজ্ঞাসা করেন যা ঘোষিত ক্ষেত্রের সাথে সম্পর্কিত না থাকে তবে NoSuchFieldException হবে।

obj.getClass().getDeclaredField("misspelled"); //will throw NoSuchFieldException

যদি ক্ষেত্রটি অ্যাক্সেসযোগ্য না হয় তবে IllegalAccessException হবে (উদাহরণস্বরূপ, এটি ব্যক্তিগত এবং যদি f.setAccessible(true) লাইন অনুপস্থিতির মাধ্যমে অ্যাক্সেসযোগ্য হয় না।

RuntimeException গুলি যা সরিয়ে দেওয়া যেতে পারে সেগুলি হয় SecurityException গুলি (যদি JVM এর SecurityManager IllegalArgumentException আপনাকে ক্ষেত্রের অ্যাক্সেসিবিলিটি পরিবর্তন করতে দেয় না), বা IllegalArgumentException গুলি, যদি ক্ষেত্রের ক্লাসের কোনও বস্তুর ক্ষেত্রে কোনও বস্তুর ক্ষেত্রটি চেষ্টা করে এবং অ্যাক্সেস করেন তবে:

f.get("BOB"); //will throw IllegalArgumentException, as String is of the wrong type

স্প্রিং ব্যবহার করে, ReflectionTestUtils কিছু সহজ সরঞ্জাম সরবরাহ করে যা সর্বনিম্ন প্রচেষ্টায় এখানে সহায়তা করে। এটি "ইউনিট এবং ইন্টিগ্রেশন টেস্টিং পরিস্থিতিতে ব্যবহারের জন্য" হিসাবে বর্ণনা করা হয়েছে। ReflectionUtils নামেও একই শ্রেণী রয়েছে কিন্তু এটি "অভ্যন্তরীণ ব্যবহারের জন্য কেবলমাত্র উদ্দেশ্যে" হিসাবে বর্ণনা করা হয়েছে - এই অর্থটির অর্থ ব্যাখ্যা করার জন্য এই উত্তরটি দেখুন।

পোস্ট উদাহরণ ঠিকানা:

Hashtable iWantThis = (Hashtable)ReflectionTestUtils.getField(obj, "stuffIWant");

জাভাতে প্রতিফলন ব্যবহার করে আপনি সমস্ত private/public ক্ষেত্র এবং অন্য শ্রেণীতে অন্য কোনও পদ্ধতিতে অ্যাক্সেস করতে পারেন। তবে বিভাগের ত্রুটিগুলির মধ্যে ওরাকলের documentation তারা সুপারিশ করেছে যে:

"প্রতিফলন কোডগুলি এমন কার্য সম্পাদন করার অনুমতি দেয় যা বেসরকারী ক্ষেত্রগুলি এবং পদ্ধতিগুলিতে অ্যাক্সেস করার মতো নন-প্রতিফলিত কোডে অবৈধ হতে পারে, প্রতিফলনের ব্যবহার অপ্রত্যাশিত পার্শ্ব প্রতিক্রিয়া হতে পারে যা কোডকে ত্রুটিযুক্ত করে এবং পোর্টেবিলিটি ধ্বংস করতে পারে। প্রতিক্রিয়াশীল কোড বিভাজন বিরতি এবং তাই প্ল্যাটফর্মের আপগ্রেড সঙ্গে আচরণ পরিবর্তন করতে পারে "

এখানে প্রতিফলনের মৌলিক ধারণাগুলি প্রদর্শনের জন্য কোড স্ন্যাপগুলি অনুসরণ করা হচ্ছে

Reflection1.java

public class Reflection1{

    private int i = 10;

    public void methoda()
    {

        System.out.println("method1");
    }
    public void methodb()
    {

        System.out.println("method2");
    }
    public void methodc()
    {

        System.out.println("method3");
    }

}

Reflection2.java

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;


public class Reflection2{

    public static void main(String ar[]) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
    {
        Method[] mthd = Reflection1.class.getMethods(); // for axis the methods 

        Field[] fld = Reflection1.class.getDeclaredFields();  // for axis the fields  

        // Loop for get all the methods in class
        for(Method mthd1:mthd)
        {

            System.out.println("method :"+mthd1.getName());
            System.out.println("parametes :"+mthd1.getReturnType());
        }

        // Loop for get all the Field in class
        for(Field fld1:fld)
        {
            fld1.setAccessible(true);
            System.out.println("field :"+fld1.getName());
            System.out.println("type :"+fld1.getType());
            System.out.println("value :"+fld1.getInt(new Reflaction1()));
        }
    }

}

এটা সাহায্য করবে আশা করি।





private