Method.invoke不使用package-private类

时间:2017-07-27 10:35:58

标签: java reflection

我有一个扩展AbstractTableModel的类TableModelBase。在那里我覆盖了getValueAt方法,以便它返回行类的getter结果。

TableModelBase.java

@Log
@AllArgsConstructor
public abstract class TableModelBase<T> extends AbstractTableModel{
    @NonNull private final String[] columns;
    @NonNull protected final transient List<T> rows;

    //...

    /**
     * Default getValue method.<br>
     * The row type fields must be in the same sequence that the columns.<br>
     * Getter methods must follow the getter convention.
     * @param rowIndex The row index.
     * @param columnIndex The column index matches the field index of the row type.
     * @return Object
     */
    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        final T row = rows.get(rowIndex);
        if(row.getClass().getDeclaredFields().length != getColumnCount()) {
            for (Field field : row.getClass().getDeclaredFields()) {
                System.out.println(field.getName());
            }
            log.severe("Fields number and table columns number are different in: " + row.getClass().getSimpleName());
            System.exit(1);
        }
        final Field field = row.getClass().getDeclaredFields()[columnIndex];

        String getter;
        if(field.getType().equals(boolean.class)) {
            getter = field.getName();
        }
        else {
            getter = "get" + Character.toUpperCase(field.getName().charAt(0)) + field.getName().substring(1);
        }

        try {
            Method method = row.getClass().getMethod(getter);
            return method.invoke(row);
        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            log.severe(e.getMessage());
            System.exit(1);
            return null;
        }
    }
}

我在包tablemodel中有一个测试类TableModelTest。在这个包中还有类Data和DataModel。

Data.java

@Value
class Data {
    String text = "text";
    boolean isSuccessful = true;
}

DataModel.java

class DataModel extends TableModelBase<Data> {
    DataModel() {
        super(new String[]{"Text", "Is Successful"}, new ArrayList<>());
        rows.add(new Data());
    }
}

TableModelBaseTest

public class TableModelBaseTest {
        @org.junit.Test
        public void getValueAt() {    
            final DataModel dataModel = new DataModel();
            assertEquals("text",dataModel.getValueAt(0, 0));
            assertEquals(true, dataModel.getValueAt(0, 1));
        }
}

测试给出IllegalAccessException:

  

类com.dsidesoftware.tablemodel.TableModelBase无法访问   类tablemodel.Data的成员,带有修饰符“public”

吸气剂是公开的,为什么我无法访问它们? 奇怪的是,当我公开Data时,异常就消失了。

知道发生了什么事吗?

感谢。

1 个答案:

答案 0 :(得分:0)

我怀疑这与Data类中的字段是package-private有关。如果您想避开此问题,请在获得后立即在setAccessible(true);个实例(即您的案例中为字段和方法)上调用java.lang.reflect.AccessibleObject。这将使对get()的调用忽略安全检查。