您的位置:首页 > 职场人生

黑马程序员-Java反射机制

2015-11-12 16:07 447 查看
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------

!--概述和应用场景

1 概念:

Java的反射机制是在运行状态中,对于任意一个类(class文件),都能知道这个类的所有属性和方法,对于任意一个对象

,都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能被称为Java语言的反射机制

总结:动态获取类的信息,就是反射机制

目的:反射的目的就是为了拿到类的字节码文件内容--Class

2:应用场景

一个应用程序,如果需要更新,那么怎么更新的呢?

那是因为应用程序启动前都会首先读取配置文件,比如Tomcat的Servlet

而我们要做的就是把通过继承应用程序暴露出来的接口的方式,把自定义的接口的子类放到配置.xml文件中,这样,应用程序会动态的加载并获取接口子类中的内容并调用

!--获取字节码文件对象的三种方式

1:new Object().getClass();//使用上帝类中的getClass()方法获得--通过对象获取

2:任意一个数据类型都具备一个静态的属性class--Object.class;

3:以上两种都还不够拓展

只要通过给定类的字符串名称就可以获得该类的字节码文件,这样更为拓展,可以用Class类中的方法完成,forName(类名)

!--首先定义一个可测试的类:

public class Person {
	public String sex;
	private String name;//姓名
	private int age;//年龄
	public Person(){};//空参数
	/**
	 * 有参构造函数
	 * @param name
	 * @param age
	 */
	public Person(String name,int age){
		
		this.name=name;
		this.age=age;
		System.out.println(name+"有参的构造函数"+age);
	}
	/**
	 * 无参方法
	 */
	public void show(){
		System.out.println(name+"--无参方法---"+age);
	}
	/**
	 * 带参方法
	 * @param info
	 */
	public void paraShow(String info){
		System.out.println(info+"----"+name+age);
	}
	/**
	 * 私有方法
	 */
	private void privateShow(){
		System.out.println("私有方法");
	}
}


!--获取Class中的构造函数并实例化

步骤:

第一步:得到类名

第二步:根据类名创建该字节码文件对象

第三步(空参):直接调用Class对象的newInstance()方法返回一个Object对象--多态的应用

(有参):这就要使用到反射包java.lang.reflect包里面的Constructor类,再根据Constructor对象实例化字节码文件对象

如下:

import java.lang.reflect.Constructor;

/**
 * !--Java反射机制概述:应用场景
 * @author Administrator
 *
 */
 
public class ReflexOverViewDemo {

	public static void main(String[] args) throws Exception{
			getMethod_1();
	}

	/**
	 * 获取Class中的构造函数
	 */
	private static void getMethod_1() throws Exception{
		//第一步:获得该类Class对象
		Class clazz=Class.forName("reflex.Person");//必须指定包名
		//第二步:导入反射包,声明构造方法
		Constructor constructor=clazz.getConstructor(String.class,int.class);
		//第三步:获得该构造方法的Class实例
		Object obj=constructor.newInstance("小王",19);
	}
}


!--获取Class文件中的字段

方法: 1:Field
getField(String name)


返回一个
Field
对象,它反映此
Class
对象所表示的类或接口的指定公共成员字段。

2:Field
getDeclaredField(String name)
//任意权限的字段

返回一个
Field
对象,该对象反映此
Class
对象所表示的类或接口的指定已声明字段。

3:Field[]
getFields()


返回一个包含某些
Field
对象的数组,这些对象反映此
Class
对象所表示的类或接口的所有可访问公共字段。

4:Field[]
getDeclaredFields()


返回
Field
对象的一个数组,这些对象反映此
Class
对象所表示的类或接口所声明的所有字段。

5;当通过上述方法获得相应字段后,就可以对该字段对象通过方法进行操作

Field对象的方法:

5.1:void
set(Object obj,Object value)
//这里Object表示的是任意的字节码文件对象实例

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

5.2:Object
get(Object obj)
//这里的Object--是多态的用法,可以得到对应字段的值

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

如下:

import java.lang.reflect.Field;

/**
 * 获得Class中的字段
 * @author Administrator
 *
 */
public class ReflexGetField {

	public static void main(String[] args) throws Exception{
		getField();
		/*Person p=new Person();
		Class c=Person.class;*/
	}

	private static void getField() throws Exception {
		Class clazz=Class.forName("reflex.Person");//必须指定包名
		//获得某一个公共字段
		Field f=clazz.getField("sex");
		System.out.println(f);
		//获取全部公共字段
		Field[] ff=clazz.getFields();
		for(Field fi : ff){
			System.out.println(fi);
		}
		//获取任意权限的字段
		Field fd=clazz.getDeclaredField("name");
		System.out.println(fd);
		//获得全部的字段
		Field []fds=clazz.getDeclaredFields();
		for(Field fid : fds){
			System.out.println(fid);
		}
		//获得实例
		Object obj=clazz.newInstance();
		f.set(obj,"男");//都是某个字段针对某个对象的操作
		Object o=f.get(obj);//返回Object类型--多态
		System.out.println(o);
	}
}
!--获取Class中的函数

创建字节码文件对象不变,其他步骤如下:

第一步:获得方法--Method clazz.
getMethod(String name,Class<?>... parameterTypes)
//如果无参的方法,Class<?>处就写null,记住:参数都是指定数据类型的class形式

返回一个
Method
对象,它反映此
Class
对象所表示的类或接口的指定公共成员方法。

第二步:调用方法--Object new Method(...).
invoke(Object obj,Object... args)
//这里obj
表示字节码文件对象的实例,

args 不在是数据类型的class形式,而是传入对应值。。。

对带有指定参数的指定对象调用由此
Method
对象表示的底层方法。

补充:获得本类中所有公共的方法:clazz.getMethods();

获取本类中所有的方法:clazz.getDeclaredMethods();

如下:

import java.lang.reflect.*;

/**
 * 获得Class中的方法
 * @author Administrator
 *
 */
public class ReflexGetMethod {

	public static void main(String[] args)throws Exception {
		getMethods();
	}

	private static void getMethods() throws Exception{
		// TODO Auto-generated method stub
		Class clazz=Class.forName("reflex.Person");//必须指定包名
		//获得对应参数列表的对应方法,空参数用null补
		Method m=clazz.getMethod("show",null);//导入反射包
		System.out.println(m);
		//带参的方法--参数列表是对应的数据类型的Class表现形式
		Method mp=clazz.getMethod("paraShow",String.class);
		System.out.println(mp);
		//获取Class中所有公共方法,包括从父类中继承的方法
		Method[]methods=clazz.getMethods();
		for(Method md : methods){
			System.out.println(md);
		}
		//获取本类的所有方法,包含私有
		Method[]methodsd=clazz.getDeclaredMethods();
		for(Method md : methodsd){
			System.out.println(md);
		}
		//创建一个有参构造函数的对象
		Constructor constructor=clazz.getConstructor(String.class,int.class);
		Object obj=constructor.newInstance("张三",23);//注意获得实例的顺序
		//调用方法--必须对象才能调用方法
		//Object obj=clazz.newInstance();
		m.invoke(obj,null);
		mp.invoke(obj,"传入的");
	}
}
总结:反射是很重要的比分,它为应用程序自定义处理请求和应答提供了技术支持

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: