一、想对你说
(1)之前一直有小伙伴让我总结下Java相关的知识点,这里我针对有一定Java基础的同学做了一个系列的总结,感兴趣的同学可以看看顶部的【Java专栏】希望对大家有所帮助。
(2)要是对您有所帮助的话,可以给 “大大大钢琴” 点个赞,这是我继续下去的动力,谢谢大家了!废话不多说了,直接上干货。
二、反射API:Field类
(一)获取Field类对象属性
Field是一个类,位于Java.lang.reflect包下,在Java反射中Field用于获取某个类的属性或该属性的属性值。
Field类中最常用的是get(Object obj)和set(Object obj, Object value)这两个方法,所以这两个方法是最重要的。
获取Field类对象:4种方法
(1)Class.getDeclaredField(String name);
返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段(包括私有成员)。
(2)Class.getDeclaredFields();
返回 Field 对象的一个数组,该数组包含此 Class 对象所表示的类或接口所声明的所有字段(包括私有成员)。
(3) Class.getField(String name);
返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
(4)Class.getFields();
返回一个包含某些 Field 对象的数组,该数组包含此 Class 对象所表示的类或接口的所有可访问公共字段。
import java.lang.reflect.*;
public class test_demo {
public static void main(String[] args) throws Exception {
//获取Field类对象
//1. Class.getDeclaredField(String name);
//返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段(包括私有成员)。
//2. Class.getDeclaredFields();
//返回 Field 对象的一个数组,该数组包含此 Class 对象所表示的类或接口所声明的所有字段(包括私有成员)。
//3. Class.getField(String name);
//返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
//4. Class.getFields();
//返回一个包含某些 Field 对象的数组,该数组包含此 Class 对象所表示的类或接口的所有可访问公共字段。
Person person =new Person();
//(1)通过Class.getDeclaredField(String name)获取类或接口的指定已声明字段。
Field f1=person.getClass().getDeclaredField("name");
System.out.println("getDeclaredFields(String name)用法:"+f1);
//(2)通过Class.getDeclaredFields()获取类或接口的指定已声明字段。
Field []f2=person.getClass().getDeclaredFields();
for(Field field:f2){
System.out.println("getDeclaredFields()用法:"+field);
}
//(3)通过Class.getField(String name)返回一个类或接口的指定公共成员字段,私有成员报错。
Field f3=person.getClass().getField("name");//(private私有成员) 则会报错
System.out.println("Class.getField(String name)用法:"+f3);
//(4)通过Class.getField(),返回 Class 对象所表示的类或接口的所有可访问公共字段。
Field []f4=person.getClass().getFields();
for(Field fields:f4){
//因为只有name属性为共有,因此只能遍历出name属性
System.out.println("Class.getFields()用法:"+fields);
}
}
}
//定义一个类,用于反射中的调用
class Person {
public String name;
public int age;
public Person() {}
public Person(String name) { this.name = name;}
public Person(int age) { this.age = age; }
}
//主要方法【后面会单独介绍】
//(单独介绍)getType(): 获取属性声明时类型对象(返回class对象)
//(单独介绍)getGenericType() : 返回属性声的Type类型
//getName() : 获取属性声明时名字
//getAnnotations() : 获得这个属性上所有的注释
//getModifiers() : 获取属性的修饰
//isEnumConstant() : 判断这个属性是否是枚举类
//isSynthetic() : 判断这个属性是否是 复合类
//(单独介绍)get(Object obj) : 取得obj对象这个Field上的值
//(单独介绍)set(Object obj, Object value) : 向obj对象的这个Field设置新值value
(二)Field.getType()返回一个Class对象
介绍:Java Field.getType()获取属性声明时类型对象,Field对象所表示字段的声明类型。如果属性是一个泛型,从getType()只能得到这个属性的接口类型。
定义:public Class<?>getType() 返回一个Class 对象。
返回:标识此对象所表示字段的声明类型的 Class 对象
import java.lang.reflect.*;
public class test_demo {
public boolean[][] b = {{true, true}, {false, false}};
public String name = "大大大钢琴";
public Integer age = 23;
public static void main(String[] args) throws Exception {
//getType()返回一个Class对象(放回类中的字段类型)
try {
Class<?> aClass = Class.forName("test_demo");
Field[] fields = aClass.getFields();
for (Field field : fields) {
System.out.println("Field:"+field.getName());
System.out.println("Type:"+field.getType().getCanonicalName());
System.out.println("GenericType:"+field.getGenericType().toString() +"\n");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
(三)Field.getGenericType()返回属性类型
getType(): 获取属性声明时类型对象(返回class对象)
getGenericType() : 返回属性声明的Type类型
getType() 和 getGenericType()的区别 :
(1)首先是返回的类型不一样,一个是Class对象一个是Type接口。
(2)如果属性是一个泛型,从getType()只能得到这个属性的接口类型。但从getGenericType()还能得到这个泛型的参数类型。
(3)getGenericType()如果当前属性有签名属性类型就返回,否则就返回 Field.getType()。
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
public class test_demo {
public static void main(String[] args) throws Exception {
Person person = new Person();
Field[] field = person.getClass().getDeclaredFields(); // 获取实体类的所有属性,返回Field数组
try {
// 遍历所有属性
for (int j = 0; j < field.length; j++) {
// 获取属性的名字
String name = field[j].getName();
// 将属性的首字符大写,方便构造get,set方法
name = name.substring(0, 1).toUpperCase() + name.substring(1);
// 获取属性的类型
String type = field[j].getGenericType().toString();
// 如果type是类类型,则前面包含"class ",后面跟类名
if (type.equals("class java.lang.String")) {
Method method = person.getClass().getMethod("get" + name);
String value = (String) method.invoke(person); // 调用getter方法获取属性值
if (value == null) {
method = person.getClass().getMethod("set" + name, String.class);
method.invoke(person, "大大大钢琴");
method = person.getClass().getMethod("Person1", String.class);
method.invoke(person, "大大大钢琴");
}
}
if (type.equals("class java.lang.Integer")) {
Method method = person.getClass().getMethod("get" + name);
Integer value = (Integer) method.invoke(person);
if (value == null) {
method = person.getClass().getMethod("set" + name, Integer.class);
method.invoke(person, 0);
}
}
if (type.equals("class java.lang.Boolean")) {
Method method = person.getClass().getMethod("get" + name);
Boolean value = (Boolean) method.invoke(person);
if (value == null) {
method = person.getClass().getMethod("set" + name, Boolean.class);
method.invoke(person, false);
}
}
if (type.equals("class java.util.Date")) {
Method method = person.getClass().getMethod("get" + name);
Date value = (Date) method.invoke(person);
if (value == null) {
method = person.getClass().getMethod("set" + name, Date.class);
method.invoke(person, new Date());
}
}
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
//定义一个类,用于反射中的调用
class Person {
public String name;
public Integer age;
public Person() {
System.out.println("hello!");
}
public void Person1(String name) {
System.out.println("hello my name is :" + name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
(四)Field.set()设置新值value
将指定对象变量上此 Field 对象表示的字段设置为指定的新值.
import java.lang.reflect.Field;
public class test_demo {
public static void main(String[] args) throws Exception {
Person person = new Person();
person.setName("大大大钢琴");
person.setAge(24);
person.setSex("男");
//(1)通过Class.getDeclaredField(String name)获取类或接口的指定属性值。
Field f1 = person.getClass().getDeclaredField("name");
System.out.println("Class.getDeclaredField(String name)用法:"+f1.get(person));
//(2)通过Class.getDeclaredFields()获取类或接口的指定属性值。
Field[] f2 = person.getClass().getDeclaredFields();
for (Field field: f2) {
field.setAccessible(true);
System.out.println("Class.getDeclaredFields()用法:"+field.get(person));
}
//(3)使用set修改属性值,再遍历各属性的值*************
f1.set(person, "钢琴");
Field[] f3 = person.getClass().getDeclaredFields();
for (Field fields: f3) {
fields.setAccessible(true);
System.out.println("修改name属性:"+fields.get(person));
}
}
}
//定义一个类,用于反射中的调用
class Person {
public String name;
public Integer age;
public String sex;
public Person() {
System.out.println("hello!");
}
public void Person1(String name) {
System.out.println("hello my name is :" + name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
(五)Field.get()取得对象的Field属性值
1. 如果字段不是静态字段的话,要传入反射类的对象.如果传null是会报java.lang.NullPointerException
2. 如果字段是静态字段的话,传入任何对象都是可以的,包括null
import java.lang.reflect.Field;
public class test_demo {
public static void main(String[] args) throws Exception {
//(1)获取执行class类的field字段属性
Field field=number.class.getDeclaredField("field");
int a= (Integer)field.get(new number()) ;
//int c= (Integer)field.get(null) ; //不是静态字段不能传null
System.out.println(a);
//(2)获取执行class类的staticField字段属性(静态字段)
Field staticfield=number.class.getDeclaredField("staticField");
int b= (Integer)staticfield.get("") ;
int d= (Integer)staticfield.get(null) ;
System.out.println(b);
System.out.println(d);
}
}
class number{
int field=3;
static int staticField=4;//static静态属性
}