java反射机制

反 射

 

一、简介

       JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

 

自己理解:

      想知道一个类有哪些方法属性,java里针对方法、属性、类的描述,获取一个类有哪些方法、属性、接口就是反射机制。(不用看到源代码,比如jar包)

 

二、相关类

(1)Class类

1.介绍:

       既然万事万物皆对象,那么我们的类是不是对象呢?是的,我们写的每一个类都是对象,是 java.lang.Class 类的对象。也就是说,每一个类既有自己的对象,同时也是 Class 类的对象。

 

2.复习一下泛型:

       泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口和泛型方法。 Java语言引入泛型的好处是安全简单。

       对于数据结构来说,泛型用于指定当前数据结构存储的元素类型,例如:ArrayList<String>表示当前的数组线性表只能存储String类型的数据。

       也可以在List中存储自定义类型,例如:LinkedList<Student>表示当前的双向链表中只能存储Student的对象。

 

3.API的定义:

       java.lang

类 Class<T>

java.lang.Object

  |__java.lang.Class<T>

类型参数:

T - 由此 Class 对象建模的类的类型。例如,String.class 的类型是 Class<String>。如果将被建模的类未知,则使用 Class<?>。

 

4.生成对象:

 

返回值 static Class<?>

类名 forName(String className)

          返回与带有给定字符串名的类或接口相关联的 Class 对象。

 

代码:Class cls =Class.forName("com.zzxtit.mvc.ref.UserInfo");

 

5.常用方法:

(以下获取的Method都是成员方法,不是类方法)

获得当前类的public Method 以及当前类继承的超类的public Method

Method[] arrMethods = classType. getMethods();

 

获得当前类声明的所有Method:(即本类重写的父类的Method和自己独立声明的Method)

Method[] arrMethods = classType. getDeclaredMethods();

 

获得当前类指定的public Method 以及当前类继承的超类指定的public Method

Method method = classType. getMethod(String name,Class<?>... parameterTypes);  没有就写null

 

获得当前类声明的指定的Method:

Method method = classType. getDeclaredMethod(String name,Class<?>... parameterTypes); 没有就写null

(前面是方法名,后面是参数列。因为成员方法可以重名。但参数列不能一样。)

parameterTypes 参数是 Class 对象的一个数组,它按声明顺序标识该方法的形参类型。为什么前面写泛型,因为一个方法参数类型都是不一样的。

(String name写字符串,即方法名。后面参数)

 

没有方法能够获得当前类超类的private方法和属性。

 

(2)Method类

1.API的定义:

       public final class Method

extendsAccessibleObject

implementsGenericDeclaration, Member

Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。 

 

2.生成对象:

常规生成。见上面Class类的代码代码

 

3.常用方法:

//这里先不深究

通过反射动态运行指定Method:

Object obj = method. invoke(Object obj, Object... args);

 

 Object

invoke(Object obj, Object... args)
   对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。

 

其余方法Class类已讲了。

 

 

 

(3)Field类

1.API的定义:

       public final class Field

extendsAccessibleObject

implementsMember

Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。

 

2.生成对象:

“常规生成”

★这里可以重点理解一下

Field field = classType. getField(String name); (字段)

field是个Field对象。假如说get到的是Stu类中的属性stuNo,这个属性是个Field对象。它们共用hash地址只不过是临时(动态)的

 

3.常用方法:

获得当前类以及超类的public Field:

Field[] arrFields = classType. getFields();

 

获得当前类声明的所有Field:

Field[] arrFields = classType. getDeclaredFields();

 

获得当前类以及超类指定的public Field:

Field field = classType. getField(String name);

 

获得当前类声明的指定的Field:

Field field = classType. getDeclaredField(String name);

 

通过反射动态设定Field的值:

(将指定对象变量上此 Field 对象表示的字段设置为指定的新值。)

fieldType.set(Object obj, Object value);

 

通过反射动态获取Field的值:

(返回指定对象上此 Field 表示的字段的值。)

Object obj = fieldType. get(Object obj);

 

 

 

( )用于要来一波代码了:

StuInfo.java

package com.zzxtit.mvc.ref;

public class StuInfo {
	public String stuNo;
	
	String stuName;
	
	private String passwd;

	public String getStuNo() {
		return stuNo;
	}

	public void setStuNo(String stuNo) {
		this.stuNo = stuNo;
	}

	public String getStuName() {
		return stuName;
	}

	public void setStuName(String stuName) {
		this.stuName = stuName;
	}

	public String getPasswd() {
		return passwd;
	}

	public void setPasswd(String  passwd) {
		this.passwd =  passwd;
	}
	
	@Override
	public String toString() {
		return "StuInfo [stuNo=" + stuNo + ", stuName=" + stuName + ", passwd=" + passwd + "]";
	}	
}

 

Refmf.java

package com.zzxtit.mvc.ref;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Refmf {
	public static void main(String[] args) {
		try {
			Class cls = Class.forName("com.zzxtit.mvc.ref.StuInfo");
			
			//Method method0 = cls.getMethod("setStuNo", String.class);
			/*StuInfo中错误演示代码
			 * private void setStuNo(String stuNo) {
			this.stuNo = stuNo;
			}*/
			//System.out.println("-----证明打不出非public的------>"+method0);
			/*java.lang.NoSuchMethodException: com.zzxtit.mvc.ref.StuInfo.setStuNo(java.lang.String)
			at java.lang.Class.getMethod(Class.java:1786)
			at com.zzxtit.mvc.ref.Refmf.main(Refmf.java:10)*/
			
			Method[] methods=cls.getDeclaredMethods();
			for(Method method : methods){
				System.out.println("---methodName--->"+method.getName());
				System.out.println("---ReturnType--->"+method.getReturnType());
				System.out.println("方法返回值");
				for(Class pt:method.getParameterTypes()){
				System.out.println("---methodName--->"+pt.getName());
				}
				System.out.println("==================分界线===========");
			}
			System.out.println("~~~~~~~~~~~~~~刘循子墨大波浪分界线~~~~~~~~~~~~~~~~~~");
			
			//生成这个类(StuInfo)的实例
			Object obj = cls.newInstance();
			System.out.println("--------发现这个getClass得到StuInfo----------->" + obj.getClass());
			
			for(Field field : cls.getDeclaredFields()){
				System.out.println("--------------------------->" + field);
				if("passwd".equals(field.getName())){
					//用暴力的方法让private的字段可以用
					field.setAccessible(true);
					field.set(obj, "123456");
				}
			}
			
			Method method = cls.getMethod("toString", null);
			Method method0 = cls.getMethod("setStuName", String.class);
			/*博客上这样写↓:对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。*/
			method0.invoke(obj, "王大锤");//对带有“王大锤”(String)类型的参数 的 obj 对象 、
			//调用method0表示的底层方法。  即对obj这个实例执行 setStuName("王大锤");
			System.out.println("=======================>" + method.invoke(obj, null) );
			//对obj这个实例执行toString();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

 

结果:

---methodName--->toString

---ReturnType--->class java.lang.String

方法返回值

==================分界线===========

---methodName--->setStuName

---ReturnType--->void

方法返回值

---methodName--->java.lang.String

==================分界线===========

---methodName--->getPasswd

---ReturnType--->class java.lang.String

方法返回值

==================分界线===========

---methodName--->setStuNo

---ReturnType--->void

方法返回值

---methodName--->java.lang.String

==================分界线===========

---methodName--->getStuNo

---ReturnType--->class java.lang.String

方法返回值

==================分界线===========

---methodName--->getStuName

---ReturnType--->class java.lang.String

方法返回值

==================分界线===========

---methodName--->setPasswd

---ReturnType--->void

方法返回值

---methodName--->java.lang.String

==================分界线===========

~~~~~~~~~~~~~~刘循子墨大波浪分界线~~~~~~~~~~~~~~~~~~

--------发现这个getClass得到StuInfo----------->classcom.zzxtit.mvc.ref.StuInfo

--------------------------->public java.lang.Stringcom.zzxtit.mvc.ref.StuInfo.stuNo

--------------------------->java.lang.String com.zzxtit.mvc.ref.StuInfo.stuName

--------------------------->private java.lang.Stringcom.zzxtit.mvc.ref.StuInfo.passwd

=======================>StuInfo [stuNo=null, stuName=王大锤, passwd=123456]

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值