Java反射的应用

一:Class类的使用

    在面向对象的世界里,世间万物皆对象。类也是对象,类是java.lang.Class类的实例对象

    任何一个类都是Class类的实例对象,这个对象称为该类的类类型。这个实例对象有三种表达方式

public class Demo1 {

	public static void main(String[] args) {
      //Reflect的对象
	  Reflect re=new Reflect();
	  
	  //1.第一种表达方式,实际也在告诉我们任何一个类都有一个隐含的静态成员class
	  Class c1=Reflect.class;
	  
	  //2.第二种方式,已经知道该类的对象通过getClass方式
	  Class c2=re.getClass();
	  
	  //官网说c1,c2表示了Reflect的类类型(Class Type),即万事万物皆对象
	  
	  //一个类只可能是Class类的一个实例对象
	  System.out.println(c1==c2); //true
	  
	  //3.第三种方式
	  try {
		Class c3=Class.forName("com.swpu.relect.Reflect");
	} catch (ClassNotFoundException e) {
		e.printStackTrace();
	}
	}
}
 class Reflect{}

二:动态加载类

    Class.forName("类的全称")不仅表示了类的类类型,还表示了动态加载类。

        编译时刻加载类是静态加载类,new创建对象是静态加载类,在编译时刻就需要加载所有可能使用到的类,通过动态加载类可以解决该问题。

        运行时刻加载类是动态加载类。

三:java获取方法信息

     基本类型都有类类型

public class Demo2 {
	public static void main(String[] args) {
		Class c1= int.class;
		Class c2=String.class;
		Class c3=void.class;
		
		System.out.println(c1.getName()); //return int
		System.out.println(c2.getName());  //java.lang.String
		System.out.println(c3.getName());  //void
	}
}

    编写了一个API接口来获取类的信息 

public class ClassUtil {
	/**
	 * 打印类的信息,包括类的成员函数,成员变量
	 * @param object
	 */	
	public static void  PrintClassMessage(Object object){
		//要获取类的信息,首先获取类的类类型
		Class c=object.getClass();
		//获取类的名称
		System.out.println("类的名称为:"+c.getName());
		/*
		 * 获取方法.
		 * getMethods()方法获取的是所有public的函数,包括从父类继承而来的
		 * getDeclaredMethods:获取的是所有自己定义的方法,不问访问权限,不包括父类继承过来的
		 */
		Method [] ms=c.getMethods();
		for(Method m:ms){
			//得到方法的返回值类型的类型
			Class returnType=m.getReturnType();
			System.out.print(returnType+" ");
			//获取到方法名
			System.out.print(m.getName()+"(");
			//获取参数类型-->得到的是参数 列表类型的类类型
			Class [] ParamTypes=m.getParameterTypes();
			for(Class param:ParamTypes){
				System.out.print(param.getName()+",");
			}
			System.out.println(")");
		}
	}
}

四:java获取成员变量的信息

		/**
		 * 成员变量也是对象,是java.lang.reflect.Field的对象
		 * 
		 */
		Field[] fs=c.getDeclaredFields();
		for(Field f:fs){
			//得到成员变量的类类型
			Class fieldType=f.getType();
			String typeName=fieldType.getName();
			//得到成员变量的名称
			String fieldName=f.getName();
			System.out.println(typeName+"("+fieldName+")");
			//
		}

 五:java获取构造方法的信息

	public static void printConMessage(Object obj){
		Class c=obj.getClass();
		/**
		 * 构造函数也是对象
		 * java.lang.Constructor中封装了构造函数的信息
		 * getConstructors获取所有的public的构造函数
		 * getDeclaredConstructors得到所有的构造函数的信息
		 */
		Constructor[] cs=c.getDeclaredConstructors();
		for(Constructor con:cs){
			System.out.print(con.getName()+"(");
			//获取构造函数的参数列表-->得到的是参数列表的类类型
			Class[] returnType=con.getParameterTypes();
			for(Class class1:returnType){
				System.out.print(class1.getName()+",");
			}
			System.out.println(")");
		}	
	}

六:方法反射对象的基本操作

    1):如何获取一个方法:方法的名称和方法的参数列表唯一确定一个方法

    2):方法反射的操作:method.invoke(对象,参数列表)      

public class MethodInvoke {

	public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		//要获取print(int,int)方法
		A a1=new A();
		Class c=a1.getClass();
	    /*
	     *2.获取方法 名称 参数列表
	     */
		try {
			Method m=c.getMethod("print", new Class[] {int.class,int.class});
			//方法的反射操作:用m对象来进行操作,和a1.print(0的效果一样
			//方法如果没有返回值返回null,有返回值就返回具体的值
			Object o=m.invoke(a1,10,20);
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		}
		
		try {
			Method ms=c.getMethod("print", String.class,String.class);
			Object o1=ms.invoke(a1, "Hello","World");
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
class A {
	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.toUpperCase());
	}
}

七:通过Class,Method了解集合泛型的本质

public class Demo6 {

	public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		ArrayList list=new ArrayList();
		ArrayList<Integer >list1=new ArrayList<Integer>();
		list1.add(1);
		//list1.add("string");是错误的
		
		Class c1=list.getClass();
		Class c2=list1.getClass();
		System.out.println(c1==c2); //return true;说明编译之后集合的泛型是去泛型化的
		//反射的操作都是编译之后的操作	
		
		/*
		 * java中集合的泛型,是防止错误消息的输入,只在编译阶段有效果,绕过编译就无效了
		 * 我们可以通过方法的反射来验证:
		 */
		try {
			Method m=c1.getMethod("add",Object.class);
			Object o=m.invoke(list1, "fanxing");//绕过编译操作就绕过了泛型
			System.out.println(list1.size());
			System.out.println(list1);
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		}
	}

}

最后进行一下总结:

    我们要用到反射,首先要获取类,获取类有三种方法:

        1):通过类.class来获取

        2):通过类实例化之后的对象.getclass()方法来获取

        3):通过class.forName("类名")来获取,这也是动态加载,在这里还要分清楚动态加载和静态加载的区别

     我们获取到类之后就可以通过方法来获取类中的成员变量(getField),方法(getMethod),方法中的参数列表类型(getParamType),构造函数(getConstructor),进而获得他们的类类型和名称。

    当有了这些基础之后我们就可以来进行方法的反射操作,还可以验证泛型的本质。

   

    

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值