Field类的使用
Posted 二木成林
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Field类的使用相关的知识,希望对你有一定的参考价值。
概述
Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。
Field类中提供了对反射获取的类中成员变量进行操作的方法。
类中每个成员变量都有数据类型和数据值。
在Java中数据类型分为基本数据类型和引用数据类型。
基本数据类型分为四类八种:
- 整数:byte、short、int、long
- 浮点数:float、double
- 字符:char
- 布尔值:boolean
引用数据类型:
- 所有引用数据类型都继承自java.lang.Object,如String就是引用数据类型
- 而自定义的类、枚举、数组、接口都是引用数据类型。
- java.io.Serializable接口,基本数据类型的包装类(如Integer、Character等)都是引用数据类型。
获取Field
可以通过如下方法来获取Field类对象,但必须是Class类型的对象来调用下面的方法。
方法 | 说明 |
---|---|
Field[] getFields() | 获取类中的字段Field,getFields()获取某个类中所有公共(public)的字段,包括父类中的公共(public)字段。 |
Field getField(String name) | 获取指定name的字段Field,可以获取某个类中所有公共(public)的字段,包括父类中的公共(public)字段。 |
Field[] getDeclaredFields() | 获取某个类中所有声明的字段,包括public、private、protected和(default),但是不包括父类的声明字段。 |
Field getDeclaredField(String name) | 获取某个类中指定name的字段,包括public、private、protected和(default),但是不包括父类的声明字段。 |
实例如下:
public class Test {
public static void main(String[] args) throws IOException, IllegalAccessException, NoSuchFieldException {
Class<Bird> personClass = Bird.class;
// 获取类中的字段Field,getFields()获取某个类中所有公共(public)的字段,包括父类中的字段
// getDeclaredFields()获取某个类中所有声明的字段,包括public、private、protected和(default),但是不包括父类的声明字段
// 同样类似的还有getConstructors()和getDeclaredConstructors()、getMethods()和getDeclaredMethods(),这两者分别表示获取某个类的方法、构造函数
Field[] fields = personClass.getFields();
Field heightField = personClass.getField("height");
Field[] declaredFields = personClass.getDeclaredFields();
Field idDeclaredField = personClass.getDeclaredField("id");
// 打印结果
for (Field field : fields) {
System.out.println(field.getName());
}
System.out.println("==================================");
System.out.println(heightField.getName());
System.out.println("==================================");
for (Field declaredField : declaredFields) {
System.out.println(declaredField.getName());
}
System.out.println("==================================");
System.out.println(idDeclaredField.getName());
}
}
class Animal {
public String name;
}
class Bird extends Animal {
private int id;
protected Animal son;
String[] masters;
public double height;
}
常用方法
Field类对象可以有如下方法:
获取变量的数据类型
方法说明如下:
成员方法 | 说明 |
---|---|
Class<?> getType() | 返回一个Class对象,它标识了此 Field 对象所表示字段的数据类型。 |
Type getGenericType() | 返回一个Type对象,它表示此Field对象所表示字段的数据类型,一般情况二者返回相同的结果,但如果当前Field的数据类型是泛型则返回泛型类型,反之返回getType()的值。 |
实例如下:
public class Test {
public static void main(String[] args) throws IOException, IllegalAccessException, NoSuchFieldException {
Class<Bird> personClass = Bird.class;
Field[] declaredFields = personClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
// getType(),返回一个Class对象,它标识了此 Field 对象所表示字段的数据类型。
// getGenericType(),返回一个Type对象,它表示此Field对象所表示字段的数据类型,一般情况二者返回相同的结果,但如果当前Field的数据类型是泛型则返回泛型类型,反之返回getType()的值
Class<?> type = declaredField.getType();
Type genericType = declaredField.getGenericType();
System.out.println(type);
System.out.println(genericType);
}
}
}
class Animal {
public String name;
}
class Bird extends Animal {
private int id;
protected Animal son;
String[] masters;
public double height;
public List<String> hobbies;
}
/*打印结果:
int
int
class com.demo.bean.demo.Animal
class com.demo.bean.demo.Animal
class [Ljava.lang.String;
class [Ljava.lang.String;
double
double
interface java.util.List
java.util.List<java.lang.String>
*/
获取变量的修饰符
成员变量可以被如下修饰符修饰,这些修饰符也可以被下面的方法获取到
- 访问权限控制符:public、protected和private。注意,默认不写权限修饰符调用方法返回的是0但不会打印出任何字符串。
- 静态修饰符:static。
- 常量修饰符:final。
- 序列化相关修饰符:transient。
- 线程相关修饰符:volatile。
方法说明如下:
成员方法 | 说明 |
---|---|
int getModifiers() | 获取当前成员变量的修饰符,但是返回的是java.lang.reflect.Modifier 中定义的整形值,需要使用Modifier.toString(int mod) 解码成字符串。 |
实例如下:
public class Test {
public static void main(String[] args) throws IOException, IllegalAccessException, NoSuchFieldException {
Class<Bird> personClass = Bird.class;
Field[] declaredFields = personClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
// getModifiers(),获取当前成员变量的修饰符,但是返回的是java.lang.reflect.Modifier中定义的整形值,需要使用Modifier.toString(int mod)解码成字符串
int modifiers = declaredField.getModifiers();
System.out.println("变量名:" + declaredField.getName() + ", 修饰符:" + Modifier.toString(modifiers));
}
}
}
class Animal {
public String name;
}
class Bird extends Animal {
private int id;
protected Animal son;
String[] masters;
public double height;
public volatile List<String> hobbies;
public final static transient String COMMENT = "XXX";
}
/*打印结果:
变量名:id, 修饰符:private
变量名:son, 修饰符:protected
变量名:masters, 修饰符:
变量名:height, 修饰符:public
变量名:hobbies, 修饰符:public volatile
变量名:COMMENT, 修饰符:public static final transient
*/
获取成员变量的值
可以分别获取八大基本数据类型和引用数据类型的值。其API方法如下,注意每个方法内的参数obj其实是类对象。
成员方法 | 说明 |
---|---|
byte getByte(Object obj) | 获取一个静态或实例的byte字段的值。 |
int getInt(Object obj) | 获取int类型的静态或实例字段的值,或通过扩展转换可转换为int类型的其他基本类型的值。 |
short getShort(Object obj) | 获取short类型的静态或实例字段的值,或通过扩展转换可转换为short类型的其他基本类型的值。 |
long getLong(Object obj) | 获取long类型的静态或实例字段的值,或通过扩展转换可转换为long类型的其他基本类型的值。 |
float getFloat(Object obj) | 获取float类型的静态或实例字段的值,或通过扩展转换可转换为float类型的其他基本类型的值。 |
double getDouble(Object obj) | 获取double类型的静态或实例字段的值,或通过扩展转换可转换为double类型的其他基本类型的值。 |
boolean getBoolean(Object obj) | 获取一个静态或实例boolean字段的值。 |
char getChar(Object obj) | 获取char类型的静态或实例字段的值,或通过扩展转换可转换为char类型的其他基本类型的值。 |
Object get(Object obj) | 获取指定对象上此Field表示的字段是引用数据类型所表示的值。 |
实例代码如下:
public class Test {
public static void main(String[] args) throws IllegalAccessException {
Bird bird = new Bird((byte) 1, 2, (short) 3, 4L, 5.0F, 6.0, false, 'X', "text");
Class<? extends Bird> birdClass = bird.getClass();
Field[] fields = birdClass.getFields();
for (Field field : fields) {
switch (field.getGenericType().getTypeName()) {
case "byte":
byte b = field.getByte(bird);
System.out.println("字段名:" + field.getName() + ", 字段值:" + b);
break;
case "short":
short s = field.getShort(bird);
System.out.println("字段名:" + field.getName() + ", 字段值:" + s);
break;
case "int":
int i = field.getInt(bird);
System.out.println("字段名:" + field.getName() + ", 字段值:" + i);
break;
case "long":
long l = field.getLong(bird);
System.out.println("字段名:" + field.getName() + ", 字段值:" + l);
break;
case "float":
float f = field.getFloat(bird);
System.out.println("字段名:" + field.getName() + ", 字段值:" + f);
break;
case "double":
double d = field.getDouble(bird);
System.out.println("字段名:" + field.getName() + ", 字段值:" + d);
break;
case "boolean":
boolean bool = field.getBoolean(bird);
System.out.println("字段名:" + field.getName() + ", 字段值:" + bool);
break;
case "char":
char c = field.getChar(bird);
System.out.println("字段名:" + field.getName() + ", 字段值:" + c);
break;
default:
Object obj = field.get(bird);
System.out.println("字段名:" + field.getName() + ", 字段值:" + obj);
}
}
}
}
class Animal {
public String name;
}
class Bird extends Animal {
public byte b;
public int i;
public short s;
public long l;
public float f;
public double d;
public boolean bool;
public char c;
public String str;
// 无参构造器、全参构造器、get和set方法
}
/*打印结果:
字段名:b, 字段值:1
字段名:i, 字段值:2
字段名:s, 字段值:3
字段名:l, 字段值:4
字段名:f, 字段值:5.0
字段名:d, 字段值:6.0
字段名:bool, 字段值:false
字段名:c, 字段值:X
字段名:str, 字段值:text
字段名:name, 字段值:null
*/
设置成员变量的值
为Field所表示的成员变量设置值的方法如下:
成员方法 | 说明 |
---|---|
void setByte(Object obj, byte b) | 将字段的值设置为指定对象上的一个 byte 值。 |
void setShort(Object obj, short s) | 将字段的值设置为指定对象上的一个 short 值。 |
void setInt(Object obj, int i) | 将字段的值设置为指定对象上的一个 int 值。 |
void setLong(Object obj, long l) | 将字段的值设置为指定对象上的一个 long 值。 |
void setFloat(Object obj, float f) | 将字段的值设置为指定对象上的一个 float 值。 |
void setDouble(Object obj, double d) | 将字段的值设置为指定对象上的一个 double 值。 |
void setBoolean(Object obj, boolean z) | 将字段的值设置为指定对象上的一个 boolean 值。 |
void setChar(Object obj, char c) | 将字段的值设置为指定对象上的一个 char 值。 |
void set(Object obj, Object value) | 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。 |
实例如下:
public class Test {
public static void main(String[] args) throws IllegalAccessException {
Bird bird = new Bird((byte) 1, 2, (short) 3, 4L, 5.0F, 6.0, false, 'X', "text");
Class<? extends Bird> birdClass = bird.getClass();
Field[] fields = birdClass.getFields();
for (Field field : fields) {
switch (field.getGenericType().getTypeName()) {
case "byte":
// 设置byte类型的值
field.setByte(bird, (byte) 127);
break;
case "short":
// 设置short类型的值
field.setShort(bird, (short) 128);
break;
case "int":
// 设置int类型的值
field.setInt(bird, 999);
break;
case "long":
// 设置long类型的值
field.setLong(bird, 1000L);
break;
case "float":
// 设置float类型的值
field.setFloat(bird, 95.5F);
break;
case "double":
// 设置double类型的值
field.setDouble(bird, 99.99);
break;
case "boolean":
// 设置boolean类型的值
field.setBoolean(bird, true);
break;
case "char":
// 设置char类型的值
field.setChar(bird, '中');
break;
default:
// 以上八种都是基本数据类型的设置,这个方法表示是对引用数据类型值的设置
field.set(bird, "引用数据类型值");
}
}
System.out.println(bird);
}
}
class Animal {
public String name;
}
class Bird extends Animal {
public byte b;
public int i;
public short s;
public long l;
public float f;
public double d;
public boolean bool;
public char c;
public String str;
// 无参构造器、全参构造器、get和set方法、toString方法
}
/*打印结果:
Bird{name='引用数据类型值', b=127, i=999, s=128, l=1000, f=95.5, d=99.99, bool=true, c=中, str='引用数据类型值'}
*/
其他方法
其他还有一些方法,最常用的就是setAccessible和getName方法:
成员方法 | 说明 |
---|---|
void setAccessible(boolean flag) | 使用该方法会取消访问控制检查,一般来说,我们不能对私有字段(private修饰)进行操作,但有的时候我们必须对私有字段进行操作,所以就需要调用该方法。设置为true表示可以访问私有字段。 |
boolean equals(Object obj) | 将此Field与指定的对象进行比较。 如果对象相同,则返回 true。 如果两个Field对象由同一个类声明并且具有相同的名称和类型,则它们是相同的。 |
boolean isEnumConstant() | 如果此字段表示枚举类型的元素,则返回true ; 否则返回false 。 |
boolean isSynthetic() | 如果此字段是合成字段,则返回true ; 否则返回false 。 |
String getName() | 返回由此Field对象表示的字段的名称。 |
String toGenericString() | 返回描述此Field的字符串,包括其泛型类型。 格式是字段的访问修饰符(如果有),后跟通用字段类型,后跟一个空格,后跟声明该字段的类的完全限定名称,后跟一个句点,然后是该字段的名称。 |
String toString() | 返回描述此Field的字符串。 格式是字段的访问修饰符(如果有),后跟字段类型,后跟一个空格,后跟声明该字段的类的完全限定名称,后跟一个句点,后跟该字段的名称。 |
Annotation[] getAnnotations() | 获取直接存在此Field上的所有注解。 |
<T extends Annotation> T getAnnotation(Class<T> annotationClass) | 如果存在该元素的指定类型的注解,则返回这些注解,否则返回null。 |
Class<?> getDeclaringClass() | 返回表示类或接口的Class对象,该类或接口声明了由此Field对象表示的Field 。 |
实例
下面是一个简单的Field实例,利用实体类对象生成一条插入SQL语句。
public class Test {
public static void main(String[] args) throws IllegalAccessException {
User user = new User(3, "王五", "wangwu", "10086", "10086@qq.com", "描述", new Date());
System.out.println(insertSql(user));
}
/**
* 将一个实体类对象生成插入SQL语句
*
* @param obj 实体类对象
* @return 返回插入SQL语句
* @throws IllegalAccessException
*/
public static String insertSql(Object obj) throws IllegalAccessException {
// 获取实体类对象的Class类对象
Class<?> aClass = obj.getClass();
// 获取所有的字段(包括私有字段等)
Field[] fields = aClass.getDeclaredFields();
StringBuilder sql = new StringBuilder();
sql.append("insert into ");
sql.append(aClass.getSimpleName().toLowerCase());// 获取类名,并且转换为小写字母
sql.append("(");
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
field.setAccessible(true);
sql.append(field.getName().toLowerCase());
if (i != fields.length - 1) {
sql.append(",");
}
}
sql.append(") values(");
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
// 设置允许访问私有字段
field.setAccessible(true);
// 添加值
if ("java.lang.String".equals(field.getGenericType().getTypeName())) {
// 对于String类型的值则需要添加单引号
sql.append("'");
sql.append(field.get(obj));
sql.append("'");
} else {
sql.append(field.get(obj));
}
if (i != fields.length - 1) {
sql.append(",");
}
}
sql.append(");");
return sql.toString();
}
}
class User {
public int id;
public String username;
public String password;
public String phone;
private String email;
public String desc;
public Date insert_time;
public User() {
}
public User(int id, String username, String password, String phone, String email, String desc, Date insert_time) {
this.id = id;
this.username = username;
this.password = password;
this.phone = phone;
this.email = email;
this.desc = desc;
this.insert_time = insert_time;
}
}
/*打印结果:
insert into user(id,username,password,phone,email,desc,insert_time) values(3,'王五','wangwu','10086','10086@qq.com','描述',Sun Aug 08 19:03:26 CST 2021);
*/
参考链接:
以上是关于Field类的使用的主要内容,如果未能解决你的问题,请参考以下文章