JavaAPI-反射

反射

java反射机制:

  1. 反射是一种动态机制,允许java程序运行期间再确定对象的实例化,方法的调用,属性的操作等。

  2. 反射可以提高代码的灵活性,但是会有更多的性能开销和较低的运行效率。因此不能过度依赖反射

Class类

  • 称为类的类对象
  • JVM中每个被加载的类都有且只有一个Class的实例与之对应,通过获取一个类的类对象我们可以得知
    这个类的一切信息,比如类名,有哪些方法,属性,构造器等,并且可以动态的操作它们。

反射的第一步就是获取类对象,而获取一个类的类对象有三种方式

  1. 类名.class
    Class cls = String.class;
    Class cls = int.class
    常用方法:
// 测试String
Class cls = String.class;
String name = cls.getName(); // 获取类对象的名称
System.out.println(name); // java.lang.String
// 通过类对象获取所有的方法(返回Method[])
Method[] methods = cls.getMethods();
for(Method method : methods) {
	System.out.println(method.getName());
}
  1. Class.forName(String className)
    Class cls = Class.forName(“java.lang.String”); // java.lang是包名,String是类名
    示例:
    Class cls = Class.forName(“raflect.Person”); // 自己定义的类,raflect是包名
    // 获取当前类自己定义的所有方法(不含有继承的)
    Method[] methods = cls.getDeclaredMethods(); // 自己定义的类用getDeclaredMethods()方法

3.类加载器ClassLoader

  
第二步:实例化

  • 反射实例化:要求必须有无参构造器
    示例:
// 1.获取类对象
Class cls = Class.forName("raflect.Person");
// 2.实例化(此种方式实例化要求必须有无参构造器)(这里不能用Person去接收的)
Object obj = cls.newInstance();
System.out.println(obj);

  
第三步:利用反射机制调用方法(有参数/无参数)(反射可以调用外部私有方法,不推荐这么做)
示例:

// 1.获取类对象
Class cls = Class.forName("raflect.Person");
// 2.实例化
Object o = cls.newInstance();
// 3.1调用方法(无参数)
Method method = cls.getMethod("sayHi");
method.invoke(o); // 把o这个对象传过去
// 3.2调用有参构造方法
Method m1 = cls.getMethod("sayHi",String.class);
m1.invoke(o, "张三");
Method m2 = cls.getMethod("sayHi", String.class,int.class);
m2.invoke(o, "李四",22);
// 利用反射在类的外部调用其私有方法
Method m3 = cls.getDeclaredMethod("dosome");
m3.setAccessible(true); // 强制访问(不推荐这么做)
m3.invoke(o);


    
示例:
reflect包下的A

package reflect;

public class A {
	public void f1() {
		System.out.println("A.f1()");
	}
	
	public String f2() {
		System.out.println("A.f2()");
		return "Hello f2";
	}
	
	public String bala(String msg, int qty) {
		System.out.println("A.bala()");
		return "bala" + msg + " " + qty;
	}
}

reflect包下的B

package reflect;

public class B {
	public void f1() {
		System.out.println("B's f1()");
	}
	
	public void  testF2() {
		System.out.println("B's testF2()");
	}
	
	public void hello() {
		System.out.println("B's hello()");
	}
}

reflect包下的ReflectTest

package reflect;

import java.lang.reflect.Method;
import java.util.Scanner;

public class ReflectTest {
	public static void main(String[] args) throws Exception {
		// 通过控制台读取类名
		Scanner scanner = new Scanner(System.in);
		String className = scanner.nextLine();
		System.out.println("className:" + className);

		// 加载类
		Class clazz = Class.forName(className);
		// 实例化
		Object obj = clazz.newInstance();
		System.out.println("obj:" + obj);

		/*
		 * 获得该类的所有方法。
		 *  Method用来描述一个方法(包括方法名、参数类型、返回类型,加在方法前的注解等等)
		 */
		Method[] methods = clazz.getDeclaredMethods();
		// 遍历所有方法
		for (Method mh : methods) {
			/*
			 * 我们把要调用的方法称之为目标方法。
			 *  目标不带参: mh.invoke(obj) 
			 *  目标方法带参:mh.invoke(obj,params),params是一个对象数组,里面存放有实际参数值。
			 */

			// 先获得目标方法的参数类型信息
			Class[] types = mh.getParameterTypes();
			// rv是目标方法的返回值。
			Object rv = null;
			if (types.length == 0) {
				// 目标方法不带参
				rv = mh.invoke(obj);
			} else {
				// params用于存放实际参数值
				Object[] params = new Object[types.length];
				// 依据目标方法的参数类型进行赋值
				for (int i = 0; i < types.length; i++) {
					if (types[i] == String.class) {
						params[i] = "阿里巴巴";
					}
					if (types[i] == int.class) {
						params[i] = 100;
					}
				}
				// 调用目标方法(带参)
				rv = mh.invoke(obj, params);
			}

			System.out.println("rv:" + rv);
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值