当前位置: 首页 > 知识库问答 >
问题:

如何解决这个反射误差?java.lang.reflect.field.get(Field.java:393)

锺离霖
2023-03-14
List<Field> fields = Arrays.asList(User.class.getDeclaredFields());
for(Field field:fields)
{
    if(field.toString().endsWith("secretfield"))
    {
        System.out.println(field);
        List<Annotation> annotations = Arrays.asList(field.getDeclaredAnnotations());
        for(Annotation annotation : annotations)
        {
            if(annotation.annotationType().toString().endsWith("ColumnTransformer"))
            {
                Annotation newAnnotation = new ColumnTransformer(){
                    @Override
                    public String forColumn() {
                        return "secretfield";
                    }

                    @Override
                    public String read(){
                        return "This is Sparta";
                    }

                    @Override
                    public String write(){
                        return "This is also sparta";
                    }

                    @Override
                    public Class<? extends Annotation> annotationType() {
                        return annotation.annotationType();
                    }
                };
                Field field1 = User.class.getDeclaredField("secretfield");
                field1.setAccessible(true);
                Map<Class<? extends Annotation>, Annotation> annotations1 = (Map<Class<? extends Annotation>, Annotation>) field1.get(User.class);
                annotations1.put(ColumnTransformer.class, newAnnotation);
            }
        }
    }
}

下面是我的POJO:

package Model;

import org.hibernate.annotations.ColumnTransformer;


import javax.persistence.*;
import javax.sql.rowset.serial.SerialBlob;
import java.sql.Blob;
import java.io.Serializable;

@Entity(name = "user")
@Table(name = "user")
public class User implements Serializable {

    @Column(name = "secretfield", nullable = true)
    @ColumnTransformer(read = "TEST")
    private String secretfield;

    public String getSecretfield() {
        return secretfield;
    }

    public void setSecretfield(String secretfield) {
        this.secretfield = secretfield;
    }
}

我得到这个错误:

Exception in thread "main" java.lang.IllegalArgumentException: Can not set java.lang.String field Model.User.secretfield to null value
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
    at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
    at sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:36)
    at java.lang.reflect.Field.get(Field.java:393)
    at Runner.main(Runner.java:65)

共有1个答案

须衡虑
2023-03-14

这条线

Map<Class<? extends Annotation>, Annotation> annotations1 = (Map<Class<? extends Annotation>, Annotation>) field1.get(User.class);

是不正确的。field1.get检索字段值,而不是注释映射。

因为您只需要修改注释中的参数,所以实际上不需要创建ColumnTransformers的新实例。有关详细信息,请参阅在运行时修改类定义的注释字符串参数。

import org.hibernate.annotations.ColumnTransformer;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.util.Map;

public class FieldGetAnnotation {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        Field field = User.class.getDeclaredField("secretfield");
        field.setAccessible(true);
        final ColumnTransformer fieldAnnotation = field.getAnnotation(ColumnTransformer.class);
        System.out.println("old FieldAnnotation = " + fieldAnnotation.forColumn());
        changeAnnotationValue(fieldAnnotation, "forColumn", "secretfield");
        System.out.println("modified FieldAnnotation = " + fieldAnnotation.forColumn());
        System.out.println("old FieldAnnotation = " + fieldAnnotation.read());
        changeAnnotationValue(fieldAnnotation, "read", "This is Sparta");
        System.out.println("modified FieldAnnotation = " + fieldAnnotation.read());
        System.out.println("old FieldAnnotation = " + fieldAnnotation.write());
        changeAnnotationValue(fieldAnnotation, "write", "This is also sparta");
        System.out.println("modified FieldAnnotation = " + fieldAnnotation.write());
    }

    @SuppressWarnings("unchecked")
    public static Object changeAnnotationValue(Annotation annotation, String key, Object newValue) {
        Object handler = Proxy.getInvocationHandler(annotation);
        Field f;
        try {
            f = handler.getClass().getDeclaredField("memberValues");
        } catch (NoSuchFieldException | SecurityException e) {
            throw new IllegalStateException(e);
        }
        f.setAccessible(true);
        Map<String, Object> memberValues;
        try {
            memberValues = (Map<String, Object>) f.get(handler);
        } catch (IllegalArgumentException | IllegalAccessException e) {
            throw new IllegalStateException(e);
        }
        Object oldValue = memberValues.get(key);
        if (oldValue != null && oldValue.getClass() != newValue.getClass()) {
            throw new IllegalArgumentException();
        }
        memberValues.put(key, newValue);
        return oldValue;
    }
}
 类似资料:
  • 我在Gradle控制台得到这个错误 错误:配置根项目“QuakeReport”时出现问题。 无法解析配置“:classpath”的所有文件。找不到com.android.tools.build:gradle:3.0.0。在以下位置搜索:文件:/applications/Android Studio.app/contents/gradle/m2repository/com/android/tools

  • 配置根项目“我的应用程序”时出现问题。 未能解析配置“:classpath”的所有工件。无法解析com.android.tools.build:gradle:3.6.2。project:脱机模式下没有com.android.tools.build:gradle:3.6.2的缓存版本。脱机模式下没有com.android.tools.build:gradle:3.6.2的缓存版本。 这是我的错误,我

  • 我是Springboot的新手,我通过Sping的教程和“https://spring.io/guides”指南来学习。 现在我试图理解并重做教程:“使用MySQL访问数据” 不幸的是,我在Mavenbuild期间出错: 启动ApplicationContext时出错。要显示自动配置报告,请在启用“调试”的情况下重新运行应用程序。2017-12-07 10:26:42.708错误8100---[m

  • 在我的MergeSort程序的这一部分中,我递归地划分一个名为“arr”的未排序数组。为此,我创建了两个子数组,“leftArr”和“rightArr”,然后我分别用“arr”的前半部分和“arr”的后半部分填充“leftArr”和和“right arr”。然后,我将使用递归来划分/排序leftArr和rightArr。 只是想澄清一下:中=长度; 要初始化rightArr,我执行以下操作: 当我

  • 给定一个整数数组和一个整数目标,返回两个数字的索引,使它们相加为目标。 警告:命令行选项已启用安全管理器警告:安全管理器已弃用,将在将来的版本中删除 JAVAlang.ArrayIndexOutOfBoundsException:索引3超出第6行的长度3的界限,解决方案。twoSum 在第54行,驾驶员解决方案。帮手 第87行Driver.main