在Java-8中自动将属性名作为参数进行传递

在Java-8中自动将属性名作为参数进行传递,java,reflection,Java,Reflection,我想有一个方法来验证字段的类型 protected void validate(String field, String fieldName){ if (field==null || field.isEmpty){ throw new IllegalArgumentException("Parameter " + fieldName + " cannot be empty"); } } 比如在我的课堂上 class Foo { private String x; pri

我想有一个方法来验证字段的类型

protected void validate(String field, String fieldName){
  if (field==null || field.isEmpty){
    throw new IllegalArgumentException("Parameter " + fieldName + " cannot be empty");
  }
}
比如在我的课堂上

class Foo {
  private String x;
  private String y;

  ...

  public void validateAll(){
    validate(x, "x");
    validate(y, "y");
  }
}
以这种方式使用将非常好

  public void validateAll(){
    validate(x);
    validate(y);
  }
并让编译器自动将变量名传递给validate(field,fieldName)方法


如何在Java-8中实现这一点?

您可以在Java中实现这一点,方法是放弃使用带有字段的Java类的想法,而是使用一个将
对象映射到值的
映射。从使用角度来看,大致如下所示:

public static final Column<String> X_COLUMN = new Column<>( "x", String.class );
public static final Column<String> Y_COLUMN = new Column<>( "y", String.class );
public static final Table FOO_TABLE = new Table( "Foo", X_COLUMN, Y_COLUMN, ... );
...
Row fooRow = new Row( FOO_TABLE );

fooRow.setFieldValue( X_COLUMN, "x" );
String x = fooRow.getFieldValue( X_COLUMN );

for( Column<?> column : fooRow.getTable().getColumns() )
    doSomethingWithField( fooRow, column );

private static <T> void doSomethingWithField( Row row, Column<T> column )
{
    T value = row.getFieldValue( column );
    ...do something with the field value...
}
public static final Column X_Column=新列(“X”,String.class);
公共静态最终列Y_Column=新列(“Y”,String.class);
公共静态最终表FOO_Table=新表(“FOO”,X_列,Y_列,…);
...
行foorrow=新行(FOO_表);
setFieldValue(X_列,“X”);
字符串x=foorw.getFieldValue(x_列);
for(列:fooRow.getTable().getColumns())
doSomethingWithField(foorw,column);
私有静态void doSomethingWithField(行、行、列)
{
T值=行。getFieldValue(列);
…对字段值执行某些操作。。。
}

您可以在Java中实现这一点,方法是放弃使用带有字段的Java类的想法,而是使用将
对象映射到值的
映射。从使用角度来看,大致如下所示:

public static final Column<String> X_COLUMN = new Column<>( "x", String.class );
public static final Column<String> Y_COLUMN = new Column<>( "y", String.class );
public static final Table FOO_TABLE = new Table( "Foo", X_COLUMN, Y_COLUMN, ... );
...
Row fooRow = new Row( FOO_TABLE );

fooRow.setFieldValue( X_COLUMN, "x" );
String x = fooRow.getFieldValue( X_COLUMN );

for( Column<?> column : fooRow.getTable().getColumns() )
    doSomethingWithField( fooRow, column );

private static <T> void doSomethingWithField( Row row, Column<T> column )
{
    T value = row.getFieldValue( column );
    ...do something with the field value...
}
public static final Column X_Column=新列(“X”,String.class);
公共静态最终列Y_Column=新列(“Y”,String.class);
公共静态最终表FOO_Table=新表(“FOO”,X_列,Y_列,…);
...
行foorrow=新行(FOO_表);
setFieldValue(X_列,“X”);
字符串x=foorw.getFieldValue(x_列);
for(列:fooRow.getTable().getColumns())
doSomethingWithField(foorw,column);
私有静态void doSomethingWithField(行、行、列)
{
T值=行。getFieldValue(列);
…对字段值执行某些操作。。。
}

由于作为参数传递给方法的值不包含有关其来源字段的任何信息,如果它是从字段中读取的,则无法重建此信息。但是,由于您的目的是验证字段,因此在首先处理字段而不是其包含的值时,可以执行所需的操作:

class Foo {
    private String x;
    private String y;

    //...

    public void validateAll() {
        for(Field f: Foo.class.getDeclaredFields()) {
            if(!Modifier.isStatic(f.getModifiers()) && !f.getType().isPrimitive()) try {
                Object o=f.get(this);
                if(o==null || o.equals(""))
                    throw new IllegalArgumentException(f.getName()+" cannot be empty");
            } catch(ReflectiveOperationException ex) { throw new AssertionError(); }
        }
    }
}

这种方法的一般问题是,当
validateAll()
报告问题时,
Foo
实例已经包含非法状态。在尝试为属性设置无效值时,最好正确拒绝这些值。在这种情况下,当名为
setX
的方法抛出
IllegalArgumentException
时,该方法的参数名可能不可用(如堆栈跟踪所示),消息中不需要额外的元信息…

,因为作为参数传递给方法的值不包含有关其来源字段的信息,如果它是从字段读取的,则无法重建此信息。但是,由于您的目的是验证字段,因此在首先处理字段而不是其包含的值时,可以执行所需的操作:

class Foo {
    private String x;
    private String y;

    //...

    public void validateAll() {
        for(Field f: Foo.class.getDeclaredFields()) {
            if(!Modifier.isStatic(f.getModifiers()) && !f.getType().isPrimitive()) try {
                Object o=f.get(this);
                if(o==null || o.equals(""))
                    throw new IllegalArgumentException(f.getName()+" cannot be empty");
            } catch(ReflectiveOperationException ex) { throw new AssertionError(); }
        }
    }
}

这种方法的一般问题是,当
validateAll()
报告问题时,
Foo
实例已经包含非法状态。在尝试为属性设置无效值时,最好正确拒绝这些值。在这种情况下,当名为
setX
的方法抛出
IllegalArgumentException
时,该方法的参数名可能不可用(如堆栈跟踪所示),消息中不需要额外的元信息…

这是不可能的。有关您希望在何处以及为什么这样做的一些上下文将帮助您(例如,您可能不应该尝试这样做,而是使用许多验证框架中的一个)。这是不可能的。有关您希望在何处以及为什么这样做的一些上下文将有助于您(例如,您可能不应该尝试这样做,而是使用许多验证框架中的一个)。这似乎是一种非常复杂的方法:-(您是否更喜欢“这是不可能的”。注释?C-:=这似乎是一种非常复杂的方法:-(您是否更喜欢“这是不可能的。”评论?C-:=