开发过程中为了方便解析JSON数组数据,所以客户端类属性按照JSON数组数据顺序进行编写,然后通过反射分别给每个属性复制:
新建一个实体类
public class InfoBean {
public String name;
public String url;
public int page;
public boolean isTest;
public AddressDTO address;
public List links;
}
通过Java的反射机制来获取类的字段列表
var obj = InfoBean()
var fields = obj.javaClass.declaredFields
for (field in fields){
Log.i(TAG,"field ${field.name}")
}
打印日志
I/MainActivity: field address
I/MainActivity: field isTest
I/MainActivity: field links
I/MainActivity: field name
I/MainActivity: field page
I/MainActivity: field url
很失望,打印的属性顺序和代码属性的顺序并不一致,因为getDeclaredFields() 方法返回的字段数组并不保证按照代码顺序排序。字段的顺序可能受到多种因素的影响,例如编译器、JVM 实现以及其他因素。
根据 Java 文档,getDeclaredFields() 方法返回的字段数组是以任意顺序返回的,没有特定的排序保证。如果需要按照特定顺序获取字段,可以使用其他方法来实现,比如通过字段名称排序或者自定义排序规则。
我们使用自定义注解来为字段添加排序信息,并根据注解值进行排序。然而,需要注意的是,注解本身并不能直接影响字段的排序顺序,而是需要在代码中编写逻辑来实现按照注解值排序的功能。
自定义注解 FieldOrder
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface FieldOrder {
int value();
}
在 FieldOrder.java 文件中,使用 @interface 关键字来定义注解,并为注解添加所需的元素。在这种情况下,我们需要为注解添加一个整数类型的 value 元素,用于表示字段的排序值。
使用自定义注解
public class InfoBean {
@FieldOrder(1)
public String name;
@FieldOrder(2)
public String url;
@FieldOrder(3)
public int page;
@FieldOrder(4)
public boolean isTest;
@FieldOrder(5)
public AddressDTO address;
@FieldOrder(6)
public List links;
}
排序逻辑来实现字段排序
var obj = InfoBean()
var fields = obj.javaClass.declaredFields
fields.sortWith(compareBy { field -> field.getAnnotation(FieldOrder::class.java).value })
for (field in fields){
Log.i(TAG,"field ${field.name}")
}
打印日志
I/MainActivity: field name
I/MainActivity: field url
I/MainActivity: field page
I/MainActivity: field isTest
I/MainActivity: field address
I/MainActivity: field links
完美
@Retention(RetentionPolicy.RUNTIME) 是一个用于指定注解的保留策略的元注解(meta-annotation)。它用于告诉编译器和运行时环境在何时可以访问注解。
@Retention 元注解有三个预定义的保留策略,分别是:
综合起来,@Retention(RetentionPolicy.RUNTIME) 和 @Target(ElementType.FIELD) 的组合表示该注解在运行时保留,并且可以应用在字段上。这意味着我们可以在运行时通过反射获取字段上的注解信息,并根据注解值进行相应的操作,比如排序。