黑马程序员-基础加强03反射

----------------------- android培训java培训、java学习型技术博客、期待与您交流! ----------------------
 
反射
1. 什么是反射
  程序在运行时期,对一个类的class文件,进行解剖
  获取成员方法,成员变量,构造方法,来运行这些方法
当编译时根本无法预知该对象和类可能属于哪些类,程序只依靠运行时信息来发现该对象和类的真实信息,就必须要用到反射。
2. 反射的目的增强程序的扩展性
 
获取class文件--字节码文件
   Java中一切都是对象,class文件也是对象java.lang.Class
一个class文件中,包含有构造方法,成员变量,成员方法
 *   构造方法也是一个对象,描述这个对象的类 java.lang.reflect.Constructor
 *   成员变量也是一个对象,描述这个对象的类 java.lang.reflect.Field
 *   成员方法也是一个对象,描述这个对象的类 java.lang.reflect.Method
 
   种获取class文件对象的方式     a.通过对象获取,使用的是getClass()方法   类的对象.getClass()
     b.通过类的静态属性.class获取   类名.class
     c.通过Class类的一个静态方法 forName (String classname)类名,最常用
       例如Class.forName("cn.itcast.reflect.Person");类名,是一个字符串的表现形式,可以采用参数传递的方式来获取。灵活性,更高
       forName(String name, boolean initialize, ClassLoader loader);
通过指定的类加载器来加载指定字符串的全类名的Class对象
     d.自定义类加载器从特殊的位置获取指定的Class对象 
Class clazz =new MyClassLoader().loadClass("D:\\BlackHorse\\OuterClass");
 
4. 从字节码文件对象中获取构造方法,并运行
   步骤:
     A 获取字节码文件对象
     B 通过字节码文件对象,获取构造方法
        getConstructors()返回数组,所有的公共的
	    getDeclaredConstructors()返回数组,所有的,包含私有的
 
	    getConstructor()返回一个构造,公共的
	    getConstructor(可变参数)
 
	    getDeclaredConstructor()返回一个,私有的
     C 通过newInstance()方法,建立对象
 
/* 
  获取构造方法并运行
*/
import java.lang.reflect.*;
class ReflectDemo1 
{
	public static void main(String[] args) throws Exception 
	{    //获取字节码文件对象
		Class clazz = Class.forName("Person");
 
//Constructor<?>[] getConstructors() 获取所有公共构造方法
      //  返回一个包含某些 Constructor 对象的数组,获取所有公共构造方法。
//Constructor类,描述构造方法对象的类
 
//Constructor<?>[] getDeclaredConstructors()获取全部的构造方法
/*Constructor[] cons = clazz.getDeclaredConstructors();
 
for(Constructor c : cons){
System.out.println(c);
}
*/
//获取到的构造方法,运行起来,建立对象
//获取空参数的一个构造方法,就可以了
//getConstructor获取一个构造方法
//Constructor<T> getConstructor(Class<?>... parameterTypes) 括号里可以加上带参数的格式,如带上int获取的就是int参数的person构造方法
 
		Constructor con = clazz.getConstructor(int.class);//传入(int x)的构造函数
// T newInstance(Object... initargs) 
		Object obj = con.newInstance(99);//创建实例  不new对象 直接用
		System.out.println(obj);
 
//获取私有的构造方法并运行 暴力访问
		Constructor conprivate = clazz.getDeclaredConstructor(String.class,int.class);
		System.out.println(conprivate);	
// Constructor父类的方法 void setAccessible(boolean flag) 
		conprivate.setAccessible(true); //为true则取消访问检查,暴力访问
		Object objprivate = conprivate.newInstance("zhangsan",18);
		System.out.println(objprivate);
 
 
//不获取构造方法,直接创建对象
		Class clazz2 = Class.forName("Person");
//T newInstance()    Class类的方法,创建此 Class 对象所表示的类的一个新实例。 
//适合有空参数的,权限是public的情况
		Object obj2 = clazz2.newInstance();
		System.out.println(obj2+ "没有获取构造,直接建立的对象");
	}
}


 
5. 从字节码文件,获取成员属性,并改值
   步骤
     A 获取字节码文件对象
     B 通过字节码文件对象,获取成员属性
     Field[] getFields() 获取所有的成员变量,返回数组,公共的
Field getField(变量的名字)获取一个成员变量,公共的
 
Field[] getDecalredFields() 获取所有的成员变量,返回数组,全部的,包含私有
Field getDeclaredField(变量的名字)获取一个成员变量,包含私有
 
     C 使用Field类中的方法 set(获取到的变量,值)修改成员变量的值
举例:
Class clazz = Class.forName("cn.itcast.reflect.Person");
Field field = clazz.getDeclaredField("name");
field.setAccessible(true);
Object obj = clazz.newInstance();//Class类中的方法 newInstanse()保证类有空参数的,权限是public的构造方法
field.set(obj, "abc");
System.out.println(obj);
6. 从字节码文件。获取成员方法,并运行.                    重要部分********
     A 获取字节码文件对象
     B 通过字节码文件对象,获取成员方法
 
       Method[]  getMethods()获取所有的,返回数组,公共的,继承的
       Method getMethod(方法名,方法中的参数)获取指定的方法
 
     C 调用Method方法中的invoke运行方法
/*
   获取成员方法并运行
*/
import java.lang.reflect.*;
class ReflectDemo2 
{
	public static void main(String[] args) throws Exception
	{
		Class clazz = Class.forName("Person");
	   //getMethods返回所有的方法,包括继承的,和公共的
/*Method[] method = clazz.getMethods();
 
for(Method m : method){
 //  System.out.println(m);
}
//getDeclaredMethods()获取方法,包含共有,私有,不包含继承的
Method[] method2 = clazz.getDeclaredMethods();
for(Method m2 : method2){
System.out.println(m2);
}*/
 
//获取person类中method方法,并运行  ----getMethod(方法名)
		Method method = clazz.getMethod("method",String.class);
		System.out.println(method);
 
//运行方法,调用Method类中的一个方法,invoke (Object obj, Object... args)
		Object obj = clazz.newInstance();
		method.invoke(obj,"你好");
 //获取私有方法,并运行
		Method methodprivate = clazz.getDeclaredMethod("function");
		methodprivate.setAccessible(true);
		methodprivate.invoke(obj);
	}
}
 


程序通过配置文件运行,用户配置什么,运行什么.            重要部分********
    如果后期需要进行修改的话,如果是服务器端程序修改源码,编译成class文件,在部署到服务器中。这样的写法,不利于修改,后期的扩展,硬编码
    可不可以,不修改源码,实现程序的扩展性呢?
    在不修改源码的情况下,采用配置文件的方法,由用户指定运行哪一个类,哪一个方法。
配置文件,其实就是一个记事本。这样的形式,以配置文件出现,不会修改源码,软编码
    用到了:反射技术,配置文件技术 Properties, IO
实现步骤:
    A 准备配置文件 集合类 Properties
    B 使用IO流技术,关联集合类,读取配置文件
    C 通过配置文件获取用户配置的类和方法
    D 反射获取用户配置的类的字节码文件对象
获取类中的方法。并运行
 
//通过配置文件运行    重点内容
import java.io.FileInputStream;
import java.util.Properties;
import java.lang.reflect.Method;
class ReflectTest 
{
	public static void main(String[] args)throws Exception 
	{
//建立集合对象
		Properties proc = new Properties();
 
//字节输入流,读取配置文件
		FileInputStream fis = new FileInputStream("config.txt");
 
//集合IO关联
		proc.load(fis);
//System.out.println(proc.getProperty("className"));
//System.out.println(proc.getProperty("methodName"));
		System.out.println(proc.size());
		for(int x = 1 ; x <= proc.size()/2; x++){
		String className = proc.getProperty("className"+x);
		String methodName = proc.getProperty("methodName"+x);
//获取字节码文件对象
		Class clazz = Class.forName(className);  
//通过字节码文件对象获取方法
		Method method = clazz.getMethod(methodName);
 
//建立对象
		Object obj = clazz.newInstance();
 
//运行方法
		method.invoke(obj);
		}
	}
}
使用反射技术,绕过泛型的编译期间检查----泛型的擦除
 
import java.util.*;
import java.lang.reflect.*;
class ReflectDemo3 
{
	public static void main(String[] args) throws Exception
	{
		ArrayList<Integer> arr = new ArrayList<Integer>();
 
		arr.add(123);
		arr.add(456);
		arr.add(789);
 
		//arr.add("abc");
/*
使用反射技术,绕过泛型的编译期间检查
将不同的数据类型,存储到带有泛型的集合----泛型的擦除
*/
//获取ArrayList字节文件对象
		Class clazz = arr.getClass();
//存储对象,调用的是集合中的add方法,反射获取add方法
		Method method = clazz.getMethod("add",Object.class);    //泛型 传object类型
 
//对象有了 arr,方法有了,运行add方法
		method.invoke(arr,"abc");
		method.invoke(arr,"QQQ");
		method.invoke(arr,"www");
		System.out.println(arr);
 
		Iterator it = arr.iterator();
		while(it.hasNext()){
		  System.out.println(it.next());
		}
	}
}
 
----------------------- android培训java培训、java学习型技术博客、期待与您交流! ----------------------


 
基于MATLAB实现旅行推销员问题(TSP)的代码+项目说明(课程大作业)+测试数据.zip基于MATLAB实现旅行推销员问题(TSP)的代码+项目说明(课程大作业)+测试数据.zip基于MATLAB实现旅行推销员问题(TSP)的代码+项目说明(课程大作业)+测试数据.zip基于MATLAB实现旅行推销员问题(TSP)的代码+项目说明(课程大作业)+测试数据.zip基于MATLAB实现旅行推销员问题(TSP)的代码+项目说明(课程大作业)+测试数据.zip基于MATLAB实现旅行推销员问题(TSP)的代码+项目说明(课程大作业)+测试数据.zip基于MATLAB实现旅行推销员问题(TSP)的代码+项目说明(课程大作业)+测试数据.zip基于MATLAB实现旅行推销员问题(TSP)的代码+项目说明(课程大作业)+测试数据.zip基于MATLAB实现旅行推销员问题(TSP)的代码+项目说明(课程大作业)+测试数据.zip基于MATLAB实现旅行推销员问题(TSP)的代码+项目说明(课程大作业)+测试数据.zip基于MATLAB实现旅行推销员问题(TSP)的代码+项目说明(课程大作业)+测试数据.zip基于MATLAB实现旅行推销员问题(TSP)的代码+项目说明(课程大作业)+测试数据.zip基于MATLAB实现旅行推销员问题(TSP)的代码+项目说明(课程大作业)+测试数据.zip基于MATLAB实现旅行推销员问题(TSP)的代码+项目说明(课程大作业)+测试数据.zip基于MATLAB实现旅行推销员问题(TSP)的代码+项目说明(课程大作业)+测试数据.zip基于MATLAB实现旅行推销员问题(TSP)的代码+项目说明(课程大作业)+测试数据.zip基于MATLAB实现旅行推销员问题(TSP)的代码+项目说明(课程大作业)+测试数据.zip基于MATLAB实现旅行推销员问题(TSP)的代码+项目说明(课程大作业)+测试数据.zip基于MATLAB实现旅行推销员问题(TSP)的代码+项目说明(课程大作业)+测试数据.zip基于MATLAB实现旅行推销员问题(TSP)的代码+项目说明(课程大作业)+测试数据.zip 【备注】 1、该资源内项目代码百分百可运行,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值