关于网站建设新闻/广西百度seo
概述
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;
}
/*打印结果:intintclass com.demo.bean.demo.Animalclass com.demo.bean.demo.Animalclass [Ljava.lang.String;class [Ljava.lang.String;doubledoubleinterface java.util.Listjava.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);*/
参考链接:
- Java反射 Field类详解