0
点赞
收藏
分享

微信扫一扫

Java之反射(重要 · 下)

创建对象

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();
		}
	}

}

Java之反射(重要 · 下)_System

案例:依赖注入实现

在一些框架开发中经常将要实例化的类名保存到配置文件中,在运行时从配置文件中读取类名字符串,然后动态创建对象,建立依赖关系。采用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();
		}
	}

}

Java之反射(重要 · 下)_反射_02

调用成员方法

通过反射机制还可以调用成员变量,调用方法需要使用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();
		}
	}

}

Java之反射(重要 · 下)_System_03

通过本章的学习,我们应该清楚什么时候使用反射。

举报

相关推荐

0 条评论