创建对象
Class类提供了一个实例方法newInstance(),通过该方法可以创建对象,使用起来比较简单。
调用构造方法
package java2023_08_10;
import java.lang.reflect.Constructor;
public class ConstructorReflect {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
@SuppressWarnings("rawtypes")
Class class1 = Class.forName("java.lang.String");
// 调用默认方法
@SuppressWarnings({ "unchecked", "unused" })
String string = (String) class1.getDeclaredConstructor().newInstance();
@SuppressWarnings("rawtypes")
//设置构造方法参数类型
Class[] params = new Class[1];
//第一个参数是string
params[0] = String.class;
@SuppressWarnings({ "unchecked", "rawtypes" })
//获取与参数对应的构造方法
Constructor constructor = class1.getConstructor(params);
//为构造方法传递参数
Object[] objects = new Object[1];
//第一个参数传递“Hello”
objects[0] = "Hello";
//调用非默认构造方法,构造方法第一个参数是String类型
String str = (String) constructor.newInstance(objects);
System.out.println(str);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
案例:依赖注入实现
在一些框架开发中经常将要实例化的类名保存到配置文件中,在运行时从配置文件中读取类名字符串,然后动态创建对象,建立依赖关系。采用new创建对象依赖关系是在编译期建立的,反射机制能够将依赖关系推迟到运行时建立,这种依赖关系动态注入进来称为依赖注入。
package java2023_08_10;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Constructor;
public class DependencyInjection {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
String className = readClassName();
Class class1 = Class.forName(className);
// 指定参数类型
Class[] params = new Class[3];
params[0] = String.class;
params[1] = int.class;
params[2] = String.class;
// 获取对应参数的构造方法
Constructor constructor = class1.getConstructor(params);
Object[] argObjects = new Object[3];
argObjects[0] = "Amy";
argObjects[1] = "15";
argObjects[3] = "奥利萨大学";
// 调用非默认构造方法
Object p = constructor.newInstance(argObjects);
System.out.println(p);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static String readClassName() {
// TODO Auto-generated method stub
FileInputStream fis = null;
InputStreamReader isr = null;
BufferedReader br = null;
try {
fis = new FileInputStream("Configuration.ini");
isr = new InputStreamReader(fis);
br = new BufferedReader(isr);
// 读取文件中的一行数据
String str = br.readLine();
return str;
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("处理IOException...");
e.printStackTrace();
}
return null;
}
}
调用方法
通过反射还可以调用方法,这与调用构造方法类似。调用方法需要使用Method对象,它对应着一个方法。获得Method对象需要使用Class类的如下方法:
- Method[] getMethods()
- Method[] getDeclaredMethods()
- Method getMethod(String name,Class...parameterTypes)
- Method getDeclaredMethod(String name,Class...parameterTypes
)
实例代码如下:
Person.java
package java2023_08_10;
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void setNameAndAge(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
现在编写一个程序通过反射机制调用Person类的setNameAndAge()和getName()方法。
PersonTest.java
package java2023_08_10;
import java.lang.reflect.Method;
public class PersonTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
Class class1 = Class.forName("java2023_08_10.Person");
Person person = (Person) class1.getDeclaredConstructor().newInstance();
System.out.println(person);
Class[] params = new Class[2];
params[0] = String.class;
params[1] = int.class;
// 获取setNameAndAge方法对象
Method method = class1.getMethod("setNameAndAge", params);
Object[] argObjects = new Object[2];
argObjects[0] = "Amy";
argObjects[1] = 18;
// 调用setNameAndAge方法
method.invoke(person, argObjects);
System.out.println(person);
// 获取getName方法对象
method = class1.getMethod("getName");
// 调用getName方法
Object result = method.invoke(person);
System.out.println(result);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
调用成员方法
通过反射机制还可以调用成员变量,调用方法需要使用Field对象,它对应着一个方法。获得Field对象需要使用Class类的如下方法:
- Field[] getFields()
- Field[] getDeclaredFileds()
- Field getField(String name)
- Field getDeclaredField(String name)
实例代码如下:
Person.java
package java2023_08_10;
public class Person {
private String name = "";
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
PersonTestTwo.java
package java2023_08_10;
import java.lang.reflect.Field;
public class PersonTestTwo {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
Class class1 = Class.forName("java2023_08_10.Person");
Person person = (Person) class1.getDeclaredConstructor().newInstance();
Field name = class1.getDeclaredField("name");
name.setAccessible(true);
name.set(person, "Tony");
Field age = class1.getDeclaredField("age");
age.setAccessible(true);
age.set(person, 18);
System.out.printf("[name:%s, age:%d]", name.get(person), age.get(person));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
通过本章的学习,我们应该清楚什么时候使用反射。
标签:反射,重要,String,age,Class,Java,class1,public,name From: https://blog.51cto.com/u_16174658/8760697