Как мне найти то, к чему относится объект? - PullRequest
3 голосов
/ 06 декабря 2011

Я пытаюсь найти способ перечисления объектов, на которые ссылается объект времени выполнения. Я знаю, что есть способ запросить jvm с помощью oql, но я хотел бы запросить его изнутри программы. Могу ли я использовать какой-либо API?

Ответы [ 2 ]

3 голосов
/ 06 декабря 2011

Вы можете сделать это с помощью Reflection (java.lang.reflect).

Как описано в этой статье . В основном, учитывая этот класс, который имеет частных членов:

public class Secret {

    private String secretCode = "It's a secret";

    private String getSecretCode(){
        return secretCode;     
    }
}

С помощью Reflection вы можете получить доступ ко всем его членам (включая частных), включая их значения. И поэтому вы просматриваете все элементы данных, чтобы увидеть, на что они ссылаются (и, конечно, вы можете повторить процесс, если они также ссылаются на другие объекты). Вот как получить доступ к их членам (в этом коде также показаны методы, которые вам, вероятно, не понадобятся, если вы просто заинтересованы в данных, но я не видел веских причин для того, чтобы вытащить эту часть):

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

public class Hacker {

    private static final Object[] EMPTY = {};

    public void reflect(Object instance)
    throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        Class secretClass = instance.getClass();

        // Print all the method names & execution result
        Method methods[] = secretClass.getDeclaredMethods(); 
        System.out.println("Access all the methods"); 
        for (int i = 0; i < methods.length; i++) { 
            System.out.println("Method Name: " + methods[i].getName());
            System.out.println("Return type: " + methods[i].getReturnType());
            methods[i].setAccessible(true);
            System.out.println(methods[i].invoke(instance, EMPTY) + "\n");
        }

        //  Print all the field names & values
        Field fields[] = secretClass.getDeclaredFields();
        System.out.println("Access all the fields");
        for (int i = 0; i < fields.length; i++){ 
            System.out.println("Field Name: " + fields[i].getName()); 
            fields[i].setAccessible(true); 
            System.out.println(fields[i].get(instance) + "\n"); 
        }
    }

    public static void main(String[] args){

        Hacker newHacker = new Hacker();

        try { 
            newHacker.reflect(new Secret());
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Я исправил ошибку в их исходном коде и сделал небольшое изменение, чтобы сделать более ясным, что Hacker никоим образом не привязан к Secret (кроме как в main).

Обновление : Перескажите ниже свой вопрос о полях из базовых классов, вот обновленный Hacker, который делает это (я предположил, что вы не хотите пытаться перечислять поля на Object вот я и остановился):

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

public class Hacker {

    private static final Object[] EMPTY = {};

    public void reflect(Object instance)
    throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        Class cls = instance.getClass();

        while (cls != null && cls != Object.class) {
            System.out.println("From class: " + cls.getName());

            // Print all the method names & execution result
            Method methods[] = cls.getDeclaredMethods(); 
            System.out.println("Access all the methods"); 
            for (int i = 0; i < methods.length; i++) { 
                System.out.println("Method Name: " + methods[i].getName());
                System.out.println("Return type: " + methods[i].getReturnType());
                methods[i].setAccessible(true);
                System.out.println(methods[i].invoke(instance, EMPTY) + "\n");
            }

            //  Print all the field names & values
            Field fields[] = cls.getDeclaredFields();
            System.out.println("Access all the fields");
            for (int i = 0; i < fields.length; i++){ 
                System.out.println("Field Name: " + fields[i].getName()); 
                fields[i].setAccessible(true); 
                System.out.println(fields[i].get(instance) + "\n"); 
            }

            // Go to the base class
            cls = cls.getSuperclass();
        }
    }

    public static void main(String[] args){

        Hacker newHacker = new Hacker();

        try { 
            newHacker.reflect(new Secret());
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

В сочетании с

public class BaseSecret {

  private String baseSecretCode = "It's a base secret";

}

и

public class Secret extends BaseSecret {

    private String secretCode = "It's a secret";

    private String getSecretCode(){
        return secretCode;     
    }
}

вы получите:

$ java Hacker 
From class: Secret
Access all the methods
Method Name: getSecretCode
Return type: class java.lang.String
It's a secret

Access all the fields
Field Name: secretCode
It's a secret

From class: BaseSecret
Access all the methods
Access all the fields
Field Name: baseSecretCode
It's a base secret
0 голосов
/ 06 декабря 2011

Вы можете использовать метод getClass () класса Object, чтобы получить класс времени выполнения объекта.

...