জাভা প্রতিবিম্ব - সেট অ্যাক্সেসযোগ্য (সত্য) এর প্রভাব


105

আমি ক্লাসে ক্ষেত্রের মানগুলি গতিশীলভাবে সেট করতে কিছু টীকাগুলি ব্যবহার করছি। যেহেতু আমি এটি সর্বজনীন, সুরক্ষিত বা ব্যক্তিগত নির্বিশেষে এটি করতে চাই, তাই পদ্ধতিটি setAccessible(true)কল করার আগে প্রতিবারই আমি ফিল্ড অবজেক্টে কল করছি set()। আমার প্রশ্ন হ'ল setAccessible()কলটি মাঠে নিজেই কী ধরনের প্রভাব ফেলে ?

আরও সুনির্দিষ্টভাবে বলুন যে এটি একটি ব্যক্তিগত ক্ষেত্র এবং কোড কলগুলির এই সেট setAccessible(true)। কোডে অন্য কোনও জায়গা যদি প্রতিফলনের মাধ্যমে একই ক্ষেত্রটি পুনরুদ্ধার করা হয় তবে ক্ষেত্রটি ইতিমধ্যে অ্যাক্সেসযোগ্য হবে? অথবা কী getDeclaredFields()এবং getDeclaredField()পদ্ধতিগুলি প্রতিবার কোনও ফিল্ড অবজেক্টের নতুন দৃষ্টান্ত ফেরত দেয় ?

আমি প্রশ্নটি বলার অন্য একটি উপায় অনুমান করি যদি আমি কল setAccessible(true)করি তবে আমার কাজ শেষ হওয়ার পরে এটি মূল মূল্যে সেট করা কতটা গুরুত্বপূর্ণ?

উত্তর:


85

সঙ্গে setAccessible()আপনি আচরণ পরিবর্তন AccessibleObject, অর্থাত্ Fieldউদাহরণস্বরূপ, কিন্তু না বর্গ প্রকৃত ক্ষেত্র। এখানে ডকুমেন্টেশন (অংশ):

একটি মান trueনির্দেশ করে যে প্রতিবিম্বিত অবজেক্টটি জাভা ভাষার অ্যাক্সেস নিয়ন্ত্রণ ব্যবহার করার সময় চেকগুলি দমন করা উচিত

এবং একটি চলমান উদাহরণ:

public class FieldAccessible {
    public static class MyClass {
        private String theField;
    }

    public static void main(String[] args) throws Exception {
        MyClass myClass = new MyClass();
        Field field1 = myClass.getClass().getDeclaredField("theField");
        field1.setAccessible(true);
        System.out.println(field1.get(myClass)); // no exception
        Field field2 = myClass.getClass().getDeclaredField("theField");
        System.out.println(field2.get(myClass)); // IllegalAccessException
    }

}

@ ফিলিপরিগো আপনার নিজের আমদানির ঘোষণাটি লিখতে হবে write আমি আশা করি যে আপনি এটি করতে জানেন।
মরিজ পিটারসেন

সমস্যা পাওয়া গেছে। আপনাকে NoSuchFieldException বা অভিভাবককে ছুঁড়ে ফেলতে হবে বা পরিচালনা করতে হবে।
ফিলিপ রেগো

হ্যাঁ, এটি কেবল নমুনা কোড। মানে throws Exceptionহ্যান্ডলগুলিও NoSuchFieldException, তবে আপনি এটি আরও বিস্তৃত পদ্ধতিতে পরিচালনা করতে চাইতে পারেন।
মরিৎজ পিটারসন

আমি ব্যতিক্রমটি পাচ্ছি: ফিল্ড ফিল্ড 1 = myClass.getClass ()। GetDeclaredField ("দ্য ফিল্ড"); সুতরাং এটি এমনকি সংকলন হয় না, যেমন সেট অ্যাক্সেসিবল এমনকি কোন ব্যাপার না?
ব্যবহারকারী 2796104

32

getDeclaredFieldপদ্ধতি একটি নতুন বস্তু প্রতিটি সময় ফিরে যাওয়ার ঠিক কারণ এই বস্তু চপল করেছে accessibleপতাকা। সুতরাং পতাকাটি পুনরায় সেট করার দরকার নেই। আপনি এই ব্লগ পোস্টে সম্পূর্ণ বিবরণ পেতে পারেন ।


3

যেমন অন্যান্য পোস্টারগুলি ইঙ্গিত করেছে, setAccessibleকেবলমাত্র আপনার সেই ক্ষেত্রে প্রযোজ্য java.lang.reflect.Fieldতাই অ্যাক্সেসিবিলিটিটিকে তার আসল অবস্থায় ফিরিয়ে আনার প্রয়োজন নেই।

যাহোক...

আপনি যদি নিজের কলগুলি field.setAccessible(true)অবিচলিত হতে চান তবে আপনাকে java.lang.Classএবং এর মধ্যে অন্তর্নিহিত পদ্ধতিগুলি ব্যবহার করতে হবে java.lang.reflect.Field। প্রকাশ্য পদ্ধতি মুখোমুখি আপনি পাঠাতে কপি এর Fieldউদাহরণ হিসেবে বলা যায়, তাই এটি "ভুলে" প্রতিটি সময় পরে আপনি ভালো কিছু করতেclass.getField(name)

import java.lang.reflect.*;
import sun.reflect.FieldAccessor;

public class Reflect {
    private static Method privateGetDeclaredFields;
    private static Method getFieldAccessor;

    public static Field[] fields(Class<?> clazz) throws Exception {
        return (Field[]) privateGetDeclaredFields.invoke(clazz, false);
    }

    public static <T> T get(Object instance, Field field) throws Exception {
        return ((FieldAccessor) getFieldAccessor.invoke(field, instance)).get(instance);
    }

    public static void set(Object instance, Field field, Object value) throws Exception {
        ((FieldAccessor) getFieldAccessor.invoke(field, instance)).set(instance, value);
    }

    static {
        try {
            // These are used to access the direct Field instances instead of the copies you normally get through #getDeclaredFields.
            privateGetDeclaredFields = Class.class.getDeclaredMethod("privateGetDeclaredFields", boolean.class);
            privateGetDeclaredFields.setAccessible(true);
            getFieldAccessor = Field.class.getDeclaredMethod("getFieldAccessor", Object.class);
            getFieldAccessor.setAccessible(true);
        } catch (Exception e) {
            // Should only occur if the internals change.
            e.printStackTrace();
        }
    }
}

আপডেট : এই প্রয়োগটি জাভা 8 এর জন্য, ভবিষ্যতের সংস্করণগুলি ব্যাকএন্ড পরিবর্তন করে যা এটি ভেঙে দেয়। আপনি যদি সত্যিই এই কৌশলটি চালিয়ে যেতে চান তবে একই ধারণাটি এখনও প্রযোজ্য।


-1
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class PrivateVariableAcc {

    public static void main(String[] args) throws Exception {
        PrivateVarTest myClass = new PrivateVarTest();
        Field field1 = myClass.getClass().getDeclaredField("a");
        field1.setAccessible(true);
        System.out.println("This is access the private field-"
            + field1.get(myClass));
        Method mm = myClass.getClass().getDeclaredMethod("getA");
        mm.setAccessible(true);
        System.out.println("This is calling the private method-"
            + mm.invoke(myClass, null));
    }

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