使用Java反射访问类的字段

时间:2016-06-30 00:50:01

标签: java

我试图访问具有ID,名称,文本和单词列表的文档类。我尝试将id与id进行比较,并在找到时获取附加到此id的单词列表以找到确切的单词。我正在尝试使用java反射,但我无法使其正常工作? 任何帮助都非常感谢。

public class Doc {
    private static int documentID;
    private static Doc docInstance = null;
    private String documentText;
    private ArrayList<String> listOfTokens;
    static int docCount = 0;

    public Doc() {
        documentID = 0;
        listOfTokens = new ArrayList<String>();
        tokFreq = 0;
        docCount++;
    }

    public static Doc getDocInstance() { 
        if (docInstance == null) {
            docInstance = new Doc();
        }
        return docInstance;
    }

    public ArrayList<String> getListOfTokens() { 
        return listOfTokens;
    }
}

我正在尝试这个

public static void createDocumentVector(TreeMap<Integer,Integer> 
documentVector, TreeMap<String, ArrayList<Integer>>qm, int N) throws 
NoSuchFieldException, SecurityException, IllegalArgumentException, 
IllegalAccessException, InstantiationException, NoSuchMethodException, 
InvocationTargetException 
{
    int eachDoc = 0;

    Collection<String> allKeys = qm.keySet();
    ArrayList<Integer> l1 = new ArrayList<Integer>();
    boolean addedTerm = false;

    /**
    Obtain an Iterator for Collection
    */
    Iterator<String> itr = allKeys.iterator();
    String key;
    int termFrequency = 0;
    int documentFrequency = 0;

    /**
     Iterate through TreeMap values iterator
     */
    while(itr.hasNext()) 
    {
        key = (String)itr.next();
        Integer LL = 0;
        l1 = qm.get(key); // Returns value of that key
        for (int k = 0; k < l1.size(); k++) 
        {
            LL = l2.get(k);

            Doc obj = new Doc();
            Class<? extends Doc> docOb = obj.getClass();
            Field field1 = docOb.getDeclaredField("documentID");
            field1.setAccessible(true);
            Field field2 = docOb.getDeclaredField("listOfTokens");
            field1.setAccessible(true);

            if (field1.isAccessible()) {
                Method setID = docOb.getDeclaredMethod("setDocumentID", new Class[]{int.class});
                setID.setAccessible(true);
                setID.invoke(docOb, LL);
            }

            Method listTock = docOb.getMethod("getListOfTokens");
            ArrayList<String> per = (ArrayList<String>) listTock.invoke(docOb, null);
            for (String tock : per) {
                if(tock.equals(key)) {
                    termFrequency++;
                }
            }

            documentFrequency = l1.size();
            eachDoc.add(getTFIDF(termFrequency, documentFrequency, N));
            documentVector.put(eachDoc, LL);
            addedTerm = true;
        }


    }
}

我收到此错误

Exception in thread "main" java.lang.IllegalArgumentException: object is not an instance of declaring class
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)

2 个答案:

答案 0 :(得分:3)

由于 javadoc 中的这种解释,

TreeMap<List<Integer>,Integer>会导致错误。

  

地图根据{@linkplain Comparable natural进行排序   订购其密钥

但是List没有实现Comparable接口。因此,您无法将List<Integer>用作TreeMap中的密钥。

我的英语很差,希望你能理解!

答案 1 :(得分:0)

您是否发布了Doc的完整定义?它错过了setDocumentID方法。

无论如何,我能够使用以下代码重现您的错误:

public class DocReflection {

    private static int documentId; // static field

    private void setDocumentId(int docId) { // but setter is not static.
        documentId = docId;
    }


    public static void main(String [] args) throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        DocReflection docReflection = new DocReflection();
        Class<? extends DocReflection> cls = docReflection.getClass();
        Field docId = cls.getDeclaredField("documentId");
        docId.setAccessible(true);

        if (docId.isAccessible()) {
            Method setId = cls.getDeclaredMethod("setDocumentId", new Class[]{int.class});
            setId.setAccessible(true);
            setId.invoke(cls, 1); // <-- Invoking non-static method with class object.
        }
    }
}

输出:

Exception in thread "main" java.lang.IllegalArgumentException: object is not an instance of declaring class
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.company.DocReflection.main(DocReflection.java:28)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

解决方案是使setDocumentId成为静态。