java反射学习

本文参考imooc的教学视频:https://www.imooc.com/video/3736 编写


1、Class类的说明

a、java是面向对象的语言,在java中一切都是对象。

b、类也是对象,类是java.lang.Class类的实例对象, 例如说:String类的类类型用   String.class表示;基本的数据类型 都存在类类型。

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

d、编译时加载类是静态加载类(比如new 类),运行时刻加载类是动态加载类(比如Class.forName)


2、获取类的全部信息(用java实现);  想获取类的信息,那么必须想获取类的类类型

public class ClassInfoUtil {	
	/**
	 * 获取函数信息
	 * */
	public static void queryMethodInfo(Object object){
		//获取类的类类型
		Class objClass = object.getClass();
		//获取类的名称
		System.out.println("对象"+object+"的类名为:"+objClass.getName());
		/*Method类,方法对象
		 * 一个成员方法就是一个Method对象
		 * getMethods()方法获取的是所有的【public】的函数,包括父类继承而来
		 * getDeclaredMethods()获取的是 该类自己声明所有方法,无访问权限的限制。当时父类的就不能显示,必须自己声明的
		 * */
		Method[] methods = objClass.getMethods();		
		for (Method method : methods) {
			//得到方法的返回值类型的类类型
			Class returnType = method.getReturnType();
			//获取方法的名字
			String name = method.getName();
			System.out.println("方法的返回类型: "+returnType.getName()+"方法的名字"+name);
			
			//获取参数的类型----》得到的是参数列表的类型的类类型
			Class[] paramType = method.getParameterTypes();
			for (Class class1 : paramType) {
				System.out.println("     入参的类型名字"+class1.getName());
			}
		}		
}
	
public static void printFeildInfo(Object object) {
		/*
		 * 成员变量也是对象
		 * java.lang.reflect.Field
		 * Filed类封装了成员变量的操作
		 * getFields()方法来获取的是所有 public 的成员变量的信息
		 * getDeclaredFields()获取的是该类自己声明的成员变量的信息,无访问权限限制
		 * */
		//获取类的类类型
		 Class objClass = object.getClass();
		 Field[] fs = objClass.getFields();
		 for (Field field : fs) {
			 //得到成员变量的类型的类类型:如果成员变量是int,那么返回的就是int.class
			 Class fieldType = field.getType();
			 String typeName = fieldType.getName();
			 //得到成员变量的名称
			 String fieldName = field.getName();
			 System.out.println(typeName+" "+fieldName);
		}
	}


public static void printConstructorInfo(Object object) {
	/*
	 * 构造函数也是对象
	 * java.lang.reflect.Field
	 * Filed类封装了成员变量的操作
	 * getConstructor()方法来获取的是所有 public 的构造函数的信息
	 * getDeclaredConstructors()获取的是该类自己声明的构造函数信息
	 * */
	//获取类的类类型
	 Class objClass = object.getClass();
     Constructor[] constructors = objClass.getDeclaredConstructors();
	 
	 for (Constructor constructor : constructors) {
		 System.out.print(constructor.getName()+"(");
		 //获取构造函数的的参数列表--》得到的参数列表的类类型
		 Class[] paramTypes = constructor.getParameterTypes();
		 for (Class class1 : paramTypes) {
			 System.out.print(class1.getName()+",");
		}
		 System.out.println(")");
	}
}
}

3、方法反射的基本操作

public class TestClass {
	public static void main(String[] args)  {
		//要获取print(int,int)方法,1、首先获取一个方法就是获取类信息,获取类信息首先要获取类的类类型
	    Cal calObject = new Cal();
	    Class c = calObject.getClass();
	    //获取方法 名称和参数列表
	    //getDeclaredMethod()获取类声明的方法
	    //getMethod() 获取public方法,包括继承父类的
		try {
		  //... 表示可变参数  两种写法一种,一种是直接传数组 new Class[]{int.class,int.class},另一种写全部入参int.class,int.class
			Method	method = c.getDeclaredMethod("print", new Class[]{int.class,int.class});
	      //方法的反射  如果被调用的方法有返回参数,即返回。如果没有则返回null
	      //Object o = method.invoke(calObject,new Object[]{5,6});//两种写法一种,一种是直接传数组(calObject,new Object[]{5,6}),另一种写全部入参invoke(calObject,5,6)
		   Object o = method.invoke(calObject,5,6); //等同于  calObject.print(5, 6);
		   
		   System.out.println(o);
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		
		System.out.println("***************************************************");
		Cal strObject = new Cal();
		Class strClass = strObject.getClass();//获取类的类类型
		try {
			Method method = strClass.getDeclaredMethod("print", new Class[]{String.class,String.class});
			Object o  = method.invoke(strObject, "aBcD","xYz");
			System.out.println(o);
		} catch (Exception  e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	
	
}
//一个类文件当中,只能有一个类是public 修饰的,然后如果再写一个类的话,默认是protected的修饰权限,一般这样安排的话是比较亲密的关系


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




4、java 反射了解集合泛型的本质【重要,仔细阅读思考代码有提升】

public class TestClass {
	public static void main(String[] args)  {
	ArrayList list1 = new ArrayList<>();
	ArrayList<String> list2 = new ArrayList<String>();
	list2.add("hello");
	//list2.add(20);  //编译的时候会报错
	
	Class c1 = list1.getClass();
	Class c2 = list2.getClass();
	//反射的操作都是编译以后的操作
	
	System.out.println(c1 == c2);
	/*
	 * c1==c2结果返回ture说明编译之后集合的泛型是去泛型化的
	 * 结论:java中集合的泛型,是防止错误输入的,只在编译阶段有效
	 * 绕过编译就无效了
	 * 验证:我们可以通过方法的反射来操作,绕过编译,只在运行的时候有效

	 * */
	
	 
	try {
		Method m = c2.getMethod("add", Object.class); 
		m.invoke(list2, 20);//绕过了编译操作就绕过了泛型,这时候20就加到了list2中
		System.out.println(list2.size());
		System.out.println(list2);

	/*	for (String string : list2) {
			
		}*/ //现在不能这样遍历
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}

}
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值