Java 反射

1 反射

反射的应用:

public static void main(String[] args) throws ClassNotFoundException, 
				InstantiationException, IllegalAccessException{
		//String类的实例
		String str = new String();
		//String其实也是一个实例对象 它是Class类的实例
		//任何类的Class的实例对象有三种获取方式

		//第一种 每个类都有一个隐含的静态成员变量class
		Class c1 = String.class;
		//第二种 通过该类的getClass方法获取
		Class c2 = str.getClass();
		//第三种 Class.forName()
		Class c3 = Class.forName("java.lang.String");
		System.out.println(c1 == c2 & c2 == c3);
	
		//c1 c2 c3叫做class type 可以通过类类型创建类的实例
		String st = (String) c1.newInstance();
	}

1.1 java.lang.Class

所有的类都是java.lang.Class类的实例

2 类的加载

2.1静态加载

new的对象都是在编译时对类进行加载

String str = new String();

2.2 动态加载

在运行时对类进行加载

String st = (String) c1.newInstance();

2.3 使用场景

在静态加载类的时候如果代码中某一个类不存在,就会报错,如果运用动态加载就会解决这个问题,

1 问题场景 当Word存在Excel不存在的时候 就会报错

public class Office {
	public static void main(String[] args)  {
		if("Word".equals(args[0]))
		{
			Word w = new Word();
			w.start();
		}
		if("Excel".equals(args[0]))
		{
			Excel e = new Excel();
			e.start();
		}
	}
}

2 用动态加载解决该问题

public class OfficeBetter {
	public static void main(String[] args) throws Exception  {
		Class c = Class.forName(args[0]);
		OfficeAble of = (OfficeAble)c.newInstance();
		of.start();
	}
}
//通用接口
public interface OfficeAble {

	public void start();

}
//Word 类
public class Word implements OfficeAble {
	public  void start()
	{
		System.out.println("World is started!");
	}

}

这里写图片描述

3 获取方法信息

/**
	 * 打印类的信息,包括类的成员变量、成员函数
	 * 
	 * @param args
	 */
	public static void printClassInfo(Object obj) {
		// 获取类信息 要先获取类类型
		Class c = obj.getClass();
		// 获取类名称
		System.out.println("c类名称:" + c.getName());

		/*
		 * 获取类方法 Method类是方法类 getMethods()获取的是所有public的方法 包括父类继承而来的
		 * getDeclaredMethods()获取的是该类自己声明的所有方法 不问访问权
		 */
		Method[] m1 = c.getMethods();
		Method[] m2 = c.getDeclaredMethods();
		for (Method m : m1) {
			// 方法的名称
			System.out.println("方法的名称:" + m.getName());
			// 方法的返回类型的类类型
			Class returnType = m.getReturnType();
			System.out.println("返回类型的类类型:" + returnType);
			System.out.println("返回类型的类类型的名字:" + returnType.getName());
			// 获取参数类型的类类型
			Class[] paramTypes = m.getParameterTypes();
			for (Class p : paramTypes) {
				// 参数的名称
				System.out.println("参数名:" + p.getName());
			}
		}
	} 
	

4 获取成员变量&构造函数

	/**
	 * 打印类的信息,包括类的成员变量、成员函数
	 * 
	 * @param args
	 */
	static void printFieldInfo(Object obj) {
		Class c = obj.getClass();
		/*
		 * 成员变量也是对象
		 * java.lang.reflect.Field
		 * Field封装了了关于成员变量的操作
		 * getFields() 获取所有public的成员变量
		 * getDeclaredFields() 获取所有该类声明的成员变量
		 */
		Field[] fList =  c.getDeclaredFields();
		for(Field f : fList)
		{
			//得到成员变量的类型的类类型
			Class fType = f.getType();
			System.out.println("成员变量类型的类类型:" + fType.getName());
			//得到成员变量的名称
			String fName =f.getName();
			System.out.println("成员变量名:" + fName);
		}
	}
	/**
	 * 打印类的信息,包括类的构造函数
	 * 
	 * @param args
	 */
	static void printConInfo(Object obj) {
		Class c = obj.getClass();
		/*
		 * 构造函数也是对象
		 * java.lang.Constructor 封装了了关于构造函数的操作
		 * getFields() 获取所有public的成员变量
		 * getDeclaredFields() 获取所有该类声明的成员变量
		 */
		Constructor[] conList =  c.getConstructors();
		for(Constructor con : conList)
		{
			//得到构造函数的类型的类类型
			Class conType = con.getClass();
			System.out.println("成员变量类型的类类型:" + con.getName());
			//得到构造函数的入参
			Class[] pType=con.getParameterTypes();
			for(Class p :pType)
			{
				//入参的类类型
				System.out.println("入参的类类型:" + p.getName());
				
			}
		}
	}

5 方法的反射

public class MethodDemo {
	public static void main(String[] args) {
		// 要获取print(int ,int )方法 1.要获取一个方法就是获取类的信息,获取类的信息首先要获取类的类类型
		A a1 = new A();
		Class c = a1.getClass();
		/*
		 * 2.获取方法 名称和参数列表来决定 getMethod获取的是public的方法 getDelcaredMethod自己声明的方法
		 */
		try {
			Method m = c.getDeclaredMethod("print", int.class, int.class);
			Method m1 = c.getDeclaredMethod("print", new Class[] { int.class, int.class });
			// 方法的反射操作
			// a1.print(10, 20);方法的反射操作是用m对象来进行方法调用 和a1.print调用的效果完全相同
			a1.print(10, 9);
			Object o1 = m.invoke(a1, new Object[] { 10, 9 });
			Object o2 = m1.invoke(a1, 10, 9);
			// 方法如果没有返回值返回null,有返回值返回具体的返回值
			// 获取方法print(String,String)
			// 用方法进行反射操作
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

class A {
	public void print() {
		System.out.println("helloworld");
	}
	public void print(int a, int b) {
		System.out.println(a + b);
	}
	public void print(String a, String b) {
		System.out.println(a.toUpperCase() + "," + b.toLowerCase());
	}
}

6 通过反射了解集合泛型的本质

public class ClassFanXing {
	public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException {
		ArrayList list = new ArrayList();
		ArrayList<String> list1 = new ArrayList<String>();
		Class c = list.getClass();
		Class c1 = list1.getClass();

		list1.add("hello");
		// list1.add(1);
		System.out.println(c == c1);
		// 反射的操作都是编译后的操作
		// c==c1返回结果是true 是为了防止输错 只在编译阶段有效
		// 验证 我们可以通过方法的反射来绕过编译
		Method m = c1.getMethod("add", Object.class);
		m.invoke(list1, 100);
		System.out.println(list1.size());
		System.out.println(list1);
	}
}

结果

true
2
[hello, 100]

参考文献:
慕课网–反射

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值