java中的反射
参考java反射(超详细),写自己实验过程中的一些理解和经验
1.User类(在package test.demo下):
package test.demo;
public class User {
// 姓名
private String name;
// 年龄
private Integer age;
// 身高
public Integer height;
//无参构造函数
public User()
{
}
//构造函数,初始化姓名
public User(String name)
{
this.name = name;
}
//构造函数,初始化姓名和年龄
public User(String name, int age)
{
this.name = name;
this.age = age;
}
//得到对象的姓名
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;
}
}
2.在另一个文件中使用反射方法调用类
与类相关的函数:
1.类的定位
Class.forname("类的全限定名")可以通过类名找到类并返回
//例如:找到test.demo包下的名为User的类,并赋值给userClass
Class userClass = Class.forname("test.demo.User");
2.对象的创建
JAVA9之后废弃newInstance()方法,使用getDeclaredConstructor().newInstance()方法替代
使用getDeclaredConstructor()可以调用构造函数对对象进行初始化
//使用方法如下:使用userClass对obj对象进行实例创建
Class userClass = Class.forName("test.demo.User");
/*
下面三种方式分别调用了userClass的三个构造函数
其中第一个调用了空构造函数
第二个调用了对姓名赋值的构造函数
第三个调用了对姓名和年龄均赋值的函数
*/
Object obj = userClass.getDeclaredConstructor().newInstance();
Object obj1 = userClass.getDeclaredConstructor(String.class).newInstance("Anya");
Object obj2 = userClass.getDeclaredConstructor(String.class, int.class).newInstance("Anya", 6);
分别输出obj1和obj2的姓名和年龄,得到:
这里要注意如果类中没有定义构造函数,那么会默认生成空构造函数,但是如果自己定义了构造函数,就不会有空构造函数了,此时调用空构造函数会报错:
(1).反射方式得到一个类的参数:
关于反射类的函数:
class ReflectTest1{
public static void main(String[] args) throws Exception {
Class userClass = Class.forName("test.demo.User");
Object obj = userClass.getDeclaredConstructor().newInstance();
//返回完整类名带包名
System.out.println(userClass.getName());
//返回类名
System.out.println(userClass.getSimpleName());
//返回类中public修饰的属性
System.out.println(userClass.getFields());
//返回类中所有的属性
System.out.println(userClass.getDeclaredFields());
//根据属性名name获取指定的属性
System.out.println(userClass.getDeclaredField("height"));
//获取属性的修饰符列表,返回的修饰符是一个数字,每个数字是修饰符的代号
System.out.println(userClass.getModifiers());
//返回类中所有的实例方法
System.out.println(userClass.getDeclaredMethods());
//根据方法名name和方法形参获取指定方法
System.out.println(userClass.getDeclaredMethod("getName"));
//返回类中所有的构造方法
System.out.println(userClass.getDeclaredConstructors());
//根据方法形参获取指定的构造方法
System.out.println(userClass.getDeclaredConstructor());
}
}
可以看到第1行输出完整包名+类名,第2行输出类名
第3、4行获得属性列表,第五行获得具体属性
第6行输出修饰符对应的数字
第7行输出方法列表,第8行输出具体方法
第9行输出构造函数列表,第10行输出具体构造函数
(2).使用反射得到属性的情况:
首先还是得到类,并用类初始化一个对象:
Class userClass = Class.forName("test.demo.User");
Object obj = userClass.getDeclaredConstructor().newInstance();
关于反射属性的函数:
Field f = userClass.getDeclaredField("height");
//返回属性名
System.out.println(f.getName());
//返回修饰符
System.out.println(f.getModifiers());
//返回属性类型
System.out.println(f.getType());
//设置属性值
f.set(obj, 97);
//读取属性值
System.out.println(f.get(obj));
这里要注意set只能设置public修饰的属性,如果要设置private属性,则需要通过如下的方式:
class ReflectTest2{
public static void main(String[] args) throws Exception {
Class userClass = Class.forName("test.demo.User");
Object obj = userClass.getDeclaredConstructor().newInstance();
Field nameField = userClass.getDeclaredField("name");
//设置nameField的setAccessible为true
nameField.setAccessible(true);
nameField.set(obj, "Anya");
System.out.println(nameField.get(obj));
}
}
(3).使用反射得到类中函数的情况:
关于反射函数的函数:
使用反射调用User中的setName和getName函数
class ReflectorTest4{
public static void main(String[] args) throws Exception{
//使用反射构造对象
Class userClass = Class.forName("test.demo.User");
Object obj = userClass.getDeclaredConstructor().newInstance();
//分别获得setName和getName两个方法
Method m = userClass.getDeclaredMethod("setName", String.class);
Method m2 = userClass.getDeclaredMethod("getName");
//调用m方法对对象obj进行操作
m.invoke(obj, "Anya");
Object o = m2.invoke(obj);
System.out.println(o);
}
}