Last Updated
Viewed 38 Times
              

How can i create a method that accepts Class and Field as parameters? Like this:

List<SomeClassEntity> list = ...;
// Service to make useful things around a list of objects
UsefulThingsService<SomeClassEntity> usefulThingsService = new UsefulThingsService<>();
// Maybe invoke like this. Did't work 
usefulThingsService.makeUsefulThings(list, SomeClassEntity.class, SomeClassEntity::getFieldOne);
// or like this. Will cause delayed runtime erros
usefulThingsService.makeUsefulThings(list, SomeClassEntity.class, "fieldTwo");



public class SomeClassEntity {

    Integer fieldOne = 10;
    Double fieldThree = 0.123;

    public Integer getFieldOne() {
        return fieldOne;
    }
    public void setFieldOne(Integer fieldOne) {
        this.fieldOne = fieldOne;
    }
    public Double getFieldThree() {
        return fieldThree;
    }
    public void setFieldThree(Double fieldThree) {
        this.fieldThree = fieldThree;
    }
}


public class UsefulThingsService<T> {
    public void makeUsefulThings(Class<T> someClassBClass, String fieldName) {
        // there is some code
    }
}

Want to have correct references on compile stage, not at runtime.

Update: I need code that would look more convenient than this:

    Field fieldOne = null;
    try {
        fieldOne = SomeClassEntity.class.getDeclaredField("fieldOne");
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    }
    usefulThingsService.makeUsefulThings(SomeClassEntity.class, fieldOne);

Let's say we have this class:

public abstract class A {
  int x;
  public int foo();
  public int foo(int x);
}

As we all know, A.class has a distinct advantage over Class.forName("A"): it will still work if the name of A is changed by refactoring or obfuscation.

However, there is no way to get this advantage with fields and methods. Have you ever wished that you could do this: (see a better proposed syntax in the edit below!)

Field xField = A.x.field;
Method fooMethod = A.foo().method;
Method fooIntMethod = A.foo(int).method;

Instead of this?

Field xField = A.getField("x");
Method fooMethod = A.getMethod("foo");
Method fooIntMethod = A.getMethod("foo", int.class);

So here's my question: does anyone know if this feature has been planned or discussed or if Sun/Oracle specifically decided against it for some reason?

EDIT: How about this syntax? It avoids problems people have mentioned:

Field xField = A..x;
Method fooMethod = A..foo();
Method fooIntMethod = A..foo(int);

Example use case

I recently created an AbstractTableModel class called EasyTableModel that allows you to define your own POJO row type. Its getValueAt(...) and setValueAt(...) etc. use reflection to get/set the values of the fields in the POJO.

public class EasyTableModel<T> extends AbstractTableModel {
    private RowFormat<T>                prototypeFormat;

    private final ArrayList<T>          rows                = new ArrayList<T>();

    ...

    public static interface RowFormat<T> {
        Object getValueAt(T row, int columnIndex);

        void setValueAt(T row, Object value, int columnIndex);

        ...
    }

    ...

    public static class ReflectionRowFormat<T> implements RowFormat<T> {
        private Field[]             fields;

        ...

        public Object getValueAt(T row, int column) {
            try {
                return fields[column].get(row);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        public void setValueAt(T row, Object value, Field field) {
            if (!field.getDeclaringClass().isInstance(this)) {
                throw new IllegalArgumentException("field is not a member of this class");
            }
            setValueAt(row, value, getColumnIndex(field));
        }

        ...
    }

    ...

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        return getRowFormat(rowIndex).getValueAt(rows.get(rowIndex), columnIndex);
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        getRowFormat(rowIndex).setValueAt(rows.get(rowIndex), aValue, columnIndex);
        fireTableRowsUpdated(rowIndex, rowIndex);
    }

    public void fireTableCellUpdated(T row, String columnName) {
        fireTableCellUpdated(row, indexOfColumn(columnName));
    }

    public void fireTableCellUpdated(T row, Field field) {
        fireTableCellUpdated(row, indexOfColumn(field));
    }
}

Using this base class, it's extremely easy to create your table:

public abstract class QuoteMonitorTableModel<R extends QuoteMonitorTableModel<R>.Row> extends EasyTableModel<R> {
    ...

    protected static final String   NUM_QUOTES_RECEIVED = "# Quotes Received";
    protected static final String   LAST_QUOTE_TIME     = "Last Quote Time";

    public class Row {
        public Row() {

        }

        @ColumnName(NUM_QUOTES_RECEIVED)
        private Integer numQuotesReceived;

        @ColumnName(LAST_QUOTE_TIME)
        private Long    lastQuoteTimeMillis;

        public Integer getNumQuotesReceived() {
            return numQuotesReceived;
        }

        public void setNumQuotesReceived(Integer numQuotesReceived) {
            this.numQuotesReceived = numQuotesReceived;
            fireTableCellUpdated((R) this, NUM_QUOTES_RECEIVED);
        }

        public Long getLastQuoteTimeMillis() {
            return lastQuoteTimeMillis;
        }

        public void setLastQuoteTimeMillis(Long lastQuoteTimeMillis) {
            this.lastQuoteTimeMillis = lastQuoteTimeMillis;
            fireTableCellUpdated((R) this, LAST_QUOTE_TIME);
        }
    }
}

What are the advantages of all this?

  • You can set contents of the table through your own POJO row class without having to worry about column indices
  • Using your own POJO row class to set values is type-safe, unlike getValueAt(...) and setValueAt(...)
  • You could easily create a table using some prexisting POJO class for the row format

If you think this is an abuse of reflection, then you would consider many well-used libraries like Google GSON as an abuse of reflection as well.

Now, notice how the derived class indicates which field has changed when firing events by a String, rather than the Field:

    public void setNumQuotesReceived(Integer numQuotesReceived) {
        this.numQuotesReceived = numQuotesReceived;
        fireTableCellUpdated((R) this, NUM_QUOTES_RECEIVED);
    }

It would be nice if we could just use the fields. But doing it with getDeclaredField() would suck:

public void setNumQuotesReceived(Integer numQuotesReceived) {
    this.numQuotesReceived = numQuotesReceived;
    try {
        // what if obfuscation changes the name of the numQuotesReceived field?
        fireTableCellUpdated((R) this, getClass().getDeclaredField("numQuotesReceived"));
    } catch (NoSuchFieldException e) {
    }
}

However, with the feature I am proposing, it would be easy as cake:

public void setNumQuotesReceived(Integer numQuotesReceived) {
    this.numQuotesReceived = numQuotesReceived;
    // if obfuscation changes the name of the numQuotesReceived it will
    // not break the compiled form of this code
    fireTableCellUpdated((R) this, QuoteMonitorTableModel..numQuotesReceived);
}

If you think this feature wouldn't open up a world of possibilities for useful programming tools, you're lacking imagination ;)

This question already has an answer here:

Where does "class" method/field come from? I don't find any information about it in the API.

Code example:

public class SomeClass{
    public static void main(String[] args){

        System.out.println(SomeClass.class);
    }    
}

Output: class SomeClass

I'm pretty new to Java, as the nature of my post will give away

I need to create a class which contains a set of methods which can easily be extended by a programmer, should it be needed. I thought about having two classes: Commands and Command. Commands contains an array of Command objects, and is where the programmer can add new commands. The Command class has two fields. The name of the class, and a method signature. I'm not sure how this can be done. In C, I think you can have a struct of functions, so can we have a class where the instances of the class are methods? Or am I completely on the wrong track?

I thought about trying to do something like this:

public class Commands
{
    private ArrayList<Command> commands;

    /**
     * Constructor for objects of class Command
     */
    public Commands()
    {
        createCommands();
    }

    /**
     * This is where a programmer can add new commands
     */
    public void createCommands()
    {
        commands.add(new Command("move", public void move()));
    }

    /**
     * This is where the programmer can define the move command
     */
    public void move()
    {
        ....
    }
}

public class Command
{
    private String command_name;
    private Method command;

    public Command(String command_name, Method command)
    {
        this.command_name = command_name;
        this.command = command;
    }
}

I know there are a lot of things wrong with this, but I'm stuck on finding the right way. Hints/help would be fantastic.

Similar Question 4 (2 solutions) : How to get class from field?

Similar Question 5 (2 solutions) : Get value of unknown class field

Similar Question 6 (2 solutions) : Get (access) class from its field

Similar Question 8 (1 solutions) : java - cannot get field with different initialize

cc