web-dev-qa-db-ja.com

リフレクションでフィールド値を設定する

私はオープンソースではない1つのプロジェクトで作業しており、1つ以上のクラスを変更する必要があります。

1つのクラスには次のコレクションがあります。

private Map<Integer, TTP> ttp = new HashMap<>(); 

ここで必要なのは、リフレクションを使用して、concurrenthashmapを使用することだけです。次のコードを試してみましたが、うまくいきません。

Field f = ..getClass().getDeclaredField("ttp");
f.setAccessible(true);
f.set(null, new ConcurrentHashMap<>());
31
user2749903

これがあなたがしようとしていることであることを願っています:

import Java.lang.reflect.Field;
import Java.util.HashMap;
import Java.util.Map;
import Java.util.concurrent.ConcurrentHashMap;

public class Test {

    private Map ttp = new HashMap(); 

    public  void test() {
        Field declaredField =  null;
        try {

            declaredField = Test.class.getDeclaredField("ttp");
            boolean accessible = declaredField.isAccessible();

            declaredField.setAccessible(true);

            ConcurrentHashMap<Object, Object> concHashMap = new ConcurrentHashMap<Object, Object>();
            concHashMap.put("key1", "value1");
            declaredField.set(this, concHashMap);
            Object value = ttp.get("key1");

            System.out.println(value);

            declaredField.setAccessible(accessible);

        } catch (NoSuchFieldException 
                | SecurityException
                | IllegalArgumentException 
                | IllegalAccessException e) {
            e.printStackTrace();
        }

    }

    public static void main(String... args) {
        Test test = new Test();
        test.test(); 
    }
}

印刷されます:

value1
34
Visruth

読む価値があります Oracle Javaチュートリアル-フィールド値の取得と設定

Field#set(Object object、Object value) このFieldオブジェクトで表されるフィールドを指定されたオブジェクトに設定します指定された新しい値への引数。

こんな感じ

f.set(objectOfTheClass, new ConcurrentHashMap<>());

null Objectに値を設定することはできません。試してみるとNullPointerExceptionになります


注:リフレクションを介してフィールドの値を設定すると、さまざまな操作が必要になるため、一定量のパフォーマンスオーバーヘッドがありますアクセス許可の検証など。ランタイムの観点から見ると、効果は同じであり、操作はクラスコードで値が直接変更されたかのようにアトミックです。

17
Braj

以下のメソッドは、フィールドがスーパークラスにある場合でもオブジェクトにフィールドを設定します

/**
 * Sets a field value on a given object
 *
 * @param targetObject the object to set the field value on
 * @param fieldName    exact name of the field
 * @param fieldValue   value to set on the field
 * @return true if the value was successfully set, false otherwise
 */
public static boolean setField(Object targetObject, String fieldName, Object fieldValue) {
    Field field;
    try {
        field = targetObject.getClass().getDeclaredField(fieldName);
    } catch (NoSuchFieldException e) {
        field = null;
    }
    Class superClass = targetObject.getClass().getSuperclass();
    while (field == null && superClass != null) {
        try {
            field = superClass.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            superClass = superClass.getSuperclass();
        }
    }
    if (field == null) {
        return false;
    }
    field.setAccessible(true);
    try {
        field.set(targetObject, fieldValue);
        return true;
    } catch (IllegalAccessException e) {
        return false;
    }
}
7
Alex Burdusel

これを試すことができます:

//Your class instance
Publication publication = new Publication();

//Get class with full path(with package name)
Class<?> c = Class.forName("com.example.publication.models.Publication");

//Get method
Method  method = c.getDeclaredMethod ("setTitle", String.class);

//set value
method.invoke (publication,  "Value to want to set here...");
1
VK321