java中反射(Reflect)的常见应用场景

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java中反射(Reflect)的常见应用场景相关的知识,希望对你有一定的参考价值。

简介:

总结于imooc课程:     http://www.imooc.com/learn/199  

本文通过几个简单的例子,介绍Class类的使用,方法和成员变量的反射,以及通过反射了解集合泛型的本质等知识。

 

1.Class类的使用

/**
 * 使用java.lang.Class类动态加载一个类,编译时不对类是否存在以及对错进行检查,运行时检查
 */
public class OfficeBetter {
	public static void main(String[] args) {
		args = new String[1];
		Scanner input = new Scanner(System.in);
		args[0] = input.next();
		try {
			Class<?> c = Class.forName("动态加载."+args[0]);
			IOfficeStart officeStart = (IOfficeStart)c.newInstance();
			officeStart.start();
		} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
			e.printStackTrace();
		} finally{
			input.close();
		}

	}

}


//office功能接口
public interface IOfficeStart {

	void start();

}

//实现1
public class Word implements IOfficeStart{

	@Override
	public void start() {
		System.out.println("Word...start...");
	}

}

//实现2
public class Excel implements IOfficeStart{

	@Override
	public void start() {
		System.out.println("Excel...start...");
	}

}

  

2.通过对象或类名获取类的信息

/**
 * 通过类对象来获取该类的所有方法、构造函数、变量
 */
public class ClassUtil {

        public static void main(String[] args) {
		
		Class c1 = int.class;
		Class c2 = void.class;
		System.out.println(c1.getName());
		System.out.println(c2.getName());
		
		ClassUtil.printClassMethods(new Double(1.0d));
		ClassUtil.printClassFields(new Integer(1));
		ClassUtil.printClassConstructors(new String());

	}


	/**
	 * 打印obj对象所在类的所有方法
	 * @param obj
	 */
	public static void printClassMethods(Object obj){
		//首先获取类的类类型
		Class c = obj.getClass();
		System.out.println(c.getName() + "类所有的方法:");
		
		//getMethods返回所有public方法,包括继承的方法
		//getDeclaredMethods()返回所有的方法,不包括继承的方法
		Method []ms = c.getMethods();
		
		//遍历集合打印每个方法,包括方法返回值,方法名,方法参数
		for (int i = 0; i < ms.length; i++) {
			Method m = ms[i];
			//返回类型
			System.out.print(m.getReturnType().getSimpleName() + " ");
			//方法名
			System.out.print(m.getName() + " (");
			//参数集合
			Class []args = m.getParameterTypes();
			for (Class class1 : args) {
				System.out.print(class1.getSimpleName() +",");		
			}
			System.out.println(")");
		}
		
		System.out.println("\n\n");
		
	}

	/**
	 * 打印obj对象所在类的所有构造函数
	 */
	public static void printClassConstructors(Object obj){

		Class c = obj.getClass();
		System.out.println(c.getName() + "类的所有构造函数:");
		Constructor []cs = c.getDeclaredConstructors();
		for (int i = 0; i < cs.length; i++) {
			System.out.print(cs[i].getName() + " (");
			
			Class []paras = cs[i].getParameterTypes();
			for (Class class1 : paras) {
				System.out.print(class1.getName() + ",");
				
			}
			System.out.println(")");
		}
		System.out.println("\n\n");
	}

	/**
	 * 打印obj对象所在类的所有变量
	 */
	public static void printClassFields(Object obj){
		Class c = obj.getClass();
		System.out.println(c.getName() + "类的所有成员变量:");
		Field[] fields = c.getFields();
		for (int i = 0; i < fields.length; i++) {
			Field field = fields[i];
			System.out.println(field.getType().getName() + " " + field.getName());
			
		}
		System.out.println("\n\n");
	}
}
    

  

3.通过对象获取到所在类的某个方法后,通过反射的方式调用该方法

import java.lang.reflect.Method;

public class Main {
	public static void main(String[] args){
		A a = new A();
		//下面通过对象a来反射调用方法
		Class<? extends A> c = a.getClass();
		try {
			//Method m1 = c.getMethod("print1", new Class[]{String.class,String.class});
			Method m1 = c.getMethod("print1", String.class,String.class);
			//Method m2 = c.getMethod("print2",new Class[]{});
			Method m2 = c.getDeclaredMethod("print2");
			m1.invoke(a,"HELLO","world");
			m2.invoke(a);
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
	
	

}

class A{
	public void print1(String a,String b){
		System.out.println(a.toLowerCase() +" "+ b.toUpperCase());
	}
	
	public void print2(){
		System.out.println("hello world");
	}
}

  

4.通过反射理解泛型(不能算是应用场景)

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

public class Main {
	public static void main(String[] args) {
		ArrayList list1 = new ArrayList();
		
		ArrayList<String> list2 = new ArrayList<String>();
		list2.add("hello");//ok
		//list2.add(1111);//false
		
		System.out.println(list1.getClass() == list2.getClass());//输出true
		
		//因为带泛型和不带泛型通过反射得到类类型都发现是==的
		//所以推测泛型的实质是在编译之前起到提醒的作用,在编译之后是没有泛型的
		//通过反射验证
		try {
			Method m = list1.getClass().getMethod("add", Object.class);
			m.invoke(list2, 1111);
			
			System.out.println(list2);//测试是否add进去1111
//			for (String string : list2) {
//				System.out.print(string);
//			}此时不能这么遍历
			for (Object obj : list2) {
				System.out.print(obj + " ");
			}//发现可以add
		} catch (Exception e) {
			// TODO: handle exception
		}
		
	}
}

  

以上是关于java中反射(Reflect)的常见应用场景的主要内容,如果未能解决你的问题,请参考以下文章

细说java系列之反射

GoLang反射

java反射初探

java反射基础应用备注

Java反射机制(Reflect)解析

JAVA编程之——反射Reflect