Java基础之反射

一、简介

Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。

Java 是一门面向对象的语言。每一个类都可以看成一个对象,是 java.lang.Class 类的对象。

二、Class类

Class是一个类,封装了当前对象所对应的类的信息。对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。

获取Class对象的三种方式:

1、第一种方式 getClass()

    Test test = new Test();
	
	Class ts = test.getClass();

2、第二种方式 .class

    Class ts = Test.class;
	
3、第三种方式 通过类的全名获取

    try{
	    Class ts = Class.forName("com.cpf.Test");
		System.out.println(ts.getName());
	}catch(Exception e){
	   
	}
    Class ts = Test.class;

开发过程中一般选中第三种方式。

三、方法介绍

//获得类的完整名字。
getName():
//获得类的public类型的属性。包括父类中的字段。
getFields():
//获得类的所有属性。包括public、private和proteced。 但是不包括父类的申明字段。
getDeclaredFields():
所有公用(public)方法包括其从父类继承的公用方法,当然也包括它所实现接口的方法。
getMethods():
//获得类的所有方法。包括public、private、proteced和接口实现的方法,但不包括父类继承的方法
getDeclaredMethods():
//获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。
getMethod(String name, Class[] parameterTypes):
//获得类的public类型的构造方法。包括父类中的构造方法。
getConstructors():
//获得类的所有构造方法,包括public、private、proteced。但不包括父类继承的方法。
getDeclaredConstructors():
//获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
getConstructor(Class[] parameterTypes):
//通过类的不带参数的构造方法创建这个类的一个对象。
Object newInstance():
//返回类加载器
ClassLoader getClassLoader():
//返回当前Class对象的接口
Class<?>[] getInterfaces()

四、通过反射获取类的构造方法、方法以及属性

1、获取构造方法

//加载Class对象  
Class clazz = Class.forName(”com.cpf.Test”);  
//获取所有公有构造方法  
System.out.println(”**********************所有公有构造方法*********************************”);  
Constructor[] conArray = clazz.getConstructors();  
//获取所有构造方法  
System.out.println(”************所有的构造方法(包括:私有、受保护、默认、公有)***************”);  
conArray = clazz.getDeclaredConstructors();  
//获取单个无参公有构造方法  
System.out.println(”*****************获取公有、无参的构造方法*******************************”);  
Constructor con = clazz.getConstructor(null); //因为是无参的构造方法所以类型是一个null,不写也可以 
//获取单个有参构造方法 
System.out.println(”******************获取带参的私有构造方法*******************************”);  
con = clazz.getDeclaredConstructor(String.class);  	

2、创建实例对象

创建实例对象有两种方式
	
<1> 直接使用Class.newInstance()
    //加载Class对象  
    Class clazz = Class.forName(”com.cpf.Test”); 
    //创建实例对象
    Object obj = clazz.newInstance();  
    
	这种方式只适用于类中包含有公有的无参构造方法
	
<2> 使用构造方法的newInstance()
	//加载Class对象  
    Class clazz = Class.forName(”com.cpf.Test”); 
    //调用单个有参私有构造方法
    Constructor con = clazz.getDeclaredConstructor(String.class);   
    //如果构造方法是私有的,那么就需要设置setAccessible方法true
    con.setAccessible(true);//暴力访问(忽略掉访问修饰符)
    //创建实例对象		
    Object obj = con.newInstance(’男’);  
		
    这种方式既可以用于私有也可以用于公有构造方法,同样的可以用于有参,也可以用于无参

3、获取成员变量并调用

    //加载Class对象  
    Class clazz = Class.forName(”com.cpf.Test”); 
    //创建实例对象
    Object obj = clazz.newInstance();  
	
<1> getFields() 获取所有公有属性(包括接口实现和父类继承的)
	
    Field[] fields = clzz.getFields();
    //赋值
    field.set(obj,"Apple");
    //取值
    field.get(obj);
		
<2> getField("") 根据变量名获取公有的属性(包括接口实现和父类继承的)
	
    Field field = clzz.getField("age");
	
	field.set(obj,"12");
	
	System.out.println(field.get(obj));
		
<3> getDeclaredFields() 获取所有变量public、private、proteced(包括接口实现,但不包括父类继承的)  
	
	Field[] fields = clzz.getDeclaredFields();
	
	for(Field field : fields){
	    //输出所有的属性名
		System.out.println(field.getName());
    }
		
<4> getDeclaredField("")根据变量名获取属性
	
	Field field = clzz.getDeclaredField("email");
	//如果属性是private的,就必须加
    field.setAccessible(true);
	
	field.set(obj,"12");
	
     System.out.println(field.get(obj));

3、获取方法并调用

	//加载Class对象  
    Class clazz = Class.forName(”com.cpf.Test”); 
    //创建实例对象
	Object obj = clazz.newInstance();  
	
	<1> getMethods() 获取所有公有方法(包括接口实现和父类继承的)
	
	    Method[] methods = clzz.getMethods();
	
	    for(Method method : methods){
		    //方法名
		    System.out.println("name==" + method.getName());
			//返回值类型
		    System.out.println("retrunType==" + method.getReturnType());
		
	    }
		
	<2> getMethod("") 根据方法名获取公有的方法(包括接口实现和父类继承的)
	
	    //有参
	    Method method = clzz.getMethod("getAge",String.class);
	
	    method.invoke(obj, "Apple");
	    //无参
	    Method method1 = clzz.getMethod("getAge");
	
	    String age = (String)method1.invoke(obj);
	
	    System.out.println(age);
		
	<3> getDeclaredMethods() 获取所有方法public、private、proteced包括接口实现,但不包括父类继承的)  
	
	    Method[] methods = clzz.getDeclaredMethods();
	
	    for(Method method : methods){
		
		    System.out.println("name==" + method.getName());
		    System.out.println("retrunType==" + method.getReturnType());
		
	    }
		
	<4> getDeclaredMethod("")根据方法名获取方法
	
	    //获取私有有参方法
	    Method method = clzz.getDeclaredMethod("getName",String.class);
	    //调用私有方法必须要设置
	    method.setAccessible(true);
	    //调用私有有参方法
	    method.invoke(obj, "Apple");
	    
		//获取私有无参方法
	    Method method1 = clzz.getDeclaredMethod("getName");
	    method1.setAccessible(true);
	    String age = (String)method1.invoke(obj);
	    System.out.println(age);
	
	    //获取公有有参方法
	    Method method2 = clzz.getDeclaredMethod("getAge",String.class);
	    //调用方法
	    method2.invoke(obj, "Apple");

动态代理实现原理中就可以看到反射的使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值