java知识之反射详解

来源:互联网 发布:淘宝货到付款怎么退款 编辑:程序博客网 时间:2024/06/08 08:47

因为项目中比较少用到反射,基本已经教回给老师了,前天回头学习一下,先mark一下!

一个对象在内存中只存在一个class对象

获取calss对象的三种方式:

/* * 获取Class对象的三种方式: *  * 1.调用Object类的getClass():任何类都会继承此方法; * 2.任何的数据类型(包括基本类型)都有一个:静态的class属性: * Student.class; * int.class * 3.调用Class类的静态方法forName(String 全名限定的类名): *  * 通过这个Class对象,可以获取Student类内部的成员属性、构造方法、成员方法的一些信息, * 并能够调用它们; */public class Demo {public static void main(String[] args) throws Exception {Student stu = new Student();Class stuClass1 = stu.getClass();Class stuClass2 =Student.class;Class stuClass3 = Class.forName("包名.Student");System.out.println(stuClass1 == stuClass2);System.out.println(stuClass1 == stuClass3);Student stu2 = new Student();Class stuClass4 = stu2.getClass();System.out.println(stuClass1 ==  stuClass4);}}
觉得第三种才是解锁反射的正确姿势!

第一种:如果对象中没有无参数的构造方法(或者你不知参数的情况,是无法获取对象的)

第二种:说不上不好,但是没有第三种好!!

第三种:可以通过配置文件进行动态替换!



获取对象中的构造方法:

/* * 获取构造方法,并调用: *  * Class类: * --批量的: * Constructor[] getConstructors() :获取所有的"公有构造方法" * Constructor[] getDeclaredConstructors() :获取全部(包括私有)的构造方法; *  --获取某个构造方法 *  Constructor getConstructor(Class ... parameterTypes) :获取指定的"公有构造方法"; *  Constructor getDeclaredConstructor(Class ... parameterTypes) :获取指定的构造方法(包括私有的); *   *  --调用某个构造方法: *  Constructor的 Object newInstance(Object... initargs) :调用指定构造方法,并实例化此类的对象; *   *  --暴力访问:如果私有成员,需要设置暴力访问; *  Constructor的setAccessible(true):不进行权限检查; */public class Demo {public static void main(String[] args) throws Exception {//1.获取Student的Class对象Class stuClass = Class.forName("包名.Student");System.out.println("************获取所有的\"公有构造方法\"*******************");Constructor[] conArray = stuClass.getConstructors();for(Constructor c : conArray){System.out.println(c);}System.out.println("************获取所有的构造方法(包括私有的)***************");conArray = stuClass.getDeclaredConstructors();for(Constructor c : conArray){System.out.println(c);}System.out.println("************获取\"公有构造方法\"***********************");Constructor con = stuClass.getConstructor(String.class);//获取的是"具有String类型形参的"公有构造方法//Constructor con = stuClass.getConstructor(String.class,int.class);Object obj = con.newInstance("刘德华");//调用此构造方法,并传递实参:相当于:Object obj = new Student("刘德华");System.out.println("************获取\"私有构造方法\"并调用*******************");con = stuClass.getDeclaredConstructor();//设置暴力访问con.setAccessible(true);obj = con.newInstance();}}

获取对象中的成员属性并调用:

/* * 获取成员属性,并调用: *  * Class类的方法: * --批量的: * Field[] getFields():获取所有"公有属性"; * Field[] getDeclaredFields() :获取所有成员属性(包括私有): * --获取单个成员属性 * Field getField(String name) :获取指定的"公有属性"; * Field getDeclaredField(String name) :获取指定的属性,包括私有的; *  * --为成员属性赋值:(注意:1.一定要先实例化此类对象;2.访问私有属性前,要设置暴力访问) * Field的 void set(Object obj, Object value)   */public class Demo {public static void main(String[] args) throws Exception {//1.获取Student的Class对象Class stuClass = Class.forName("包名.Student");System.out.println("********************获取所有\"公有属性\"************************");Field[] fieldArray = stuClass.getFields();for(Field f : fieldArray){System.out.println(f);}System.out.println("********************获取所有属性(包括私有的)************************");fieldArray = stuClass.getDeclaredFields();for(Field f : fieldArray){System.out.println(f);}//创建一个Student对象Object obj = stuClass.getConstructor().newInstance();System.out.println("*********************获取公有属性,并调用*********************************");Field f = stuClass.getField("name");System.out.println("赋值前打印:" + obj);f.set(obj, "刘德华");System.out.println("赋值后打印:" + obj);System.out.println("*********************获取私有属性,并赋值*********************************");f = stuClass.getDeclaredField("score");//暴力访问f.setAccessible(true);f.set(obj, 88.5);System.out.println(obj);}}

获取对象的成员方法并调用


/* * 获取成员方法: *  * Class类的方法: * --批量的: * Method[] getMethods():获取所有"公有方法"(包括继承的) * Method[] getDeclaredMethods() :获取所有成员方法(包括私有): * --获取单个成员方法 * Method getMethod(String name, Class... parameterTypes) :获取指定的"公有方法"; * Method getDeclaredMethod(String name, Class... parameterTypes) :获取指定的方法,包括私有的; *  * --调用方法:(注意:1.要先创建此类的对象;2.调用私有方法前,要先设置暴力访问) * Method: * Object invoke(Object obj, Object... args) :调用Method所代表的方法: * 返回值:此Method对象调用所代表的方法,所获取的返回值; * 形参:obj:方法所属对象; * args:Method所代表的那个方法的实参列表; *  */public class Demo {public static void main(String[] args) throws Exception {//1.获取Class对象Class stuClass = Class.forName("包名.Student");System.out.println("*************获取所有\"公有方法\"*******************");Method[] methodArray = stuClass.getMethods();for(Method m : methodArray){System.out.println(m);}System.out.println("**************获取所有的方法(包括私有的)***************");methodArray = stuClass.getDeclaredMethods();for(Method m : methodArray){System.out.println(m);}//创建Student对象Object obj = stuClass.getConstructor().newInstance();System.out.println("**************获取公有的,带参的show1()方法,并调用******");Method m = stuClass.getMethod("show1", String.class,int.class);Object result = m.invoke(obj, "刘德华",20);//调用show1()方法System.out.println("调用的返回值:" + result);System.out.println("***************获取私有的,无参的、无返回值的show4()方法,并调用****************");m = stuClass.getDeclaredMethod("show4");m.setAccessible(true);m.invoke(obj);}}

通过配置文件动态修改代码:

先创建一个properties.ini

内容为一个键值对 一个classpash (包名.对象名字) 和一个方法名字(函数名字)

public class Demo {public static void main(String[] args) throws Exception {//1.获取Student的Class对象//Class stuClass = Class.forName("包名.Student");String classPath = getValue("className");Class stuClass = Class.forName(classPath);//2.实例化一个Student对象Object obj = stuClass.getConstructor().newInstance();//3.调用方法//Method m = stuClass.getMethod("show");Method m = stuClass.getMethod(getValue("methodName"));m.invoke(obj);}//一个方法,获取配置文件中的某个键对应的值public static String getValue(String key) throws IOException{Properties pro = new Properties();FileReader in = new FileReader("properties.ini");pro.load(in);in.close();return pro.getProperty(key);}}

越过泛型来添加不同数据类型的数据:

泛型只存在于编译期,class对象是编译之后的,所以使用反射的时候没有泛型的说法(生成class对象之后,全都是Object类型)

/* * 通过反射越过泛型检查: *  * 1.定义一个具有String泛型的集合,要求成功向集合中添加一个int数据; */public class Demo {public static void main(String[] args) throws Exception, SecurityException {List<String> strList = new ArrayList<>();strList.add("aaa");strList.add("bbb");//strList.add(10);//通过反射Class listClass = strList.getClass();//获取add方法Method addMethod = listClass.getMethod("add", Object.class);//调用add方法addMethod.invoke(strList, 10);//遍历集合for(Object o : strList){System.out.println(o);}}}

原创粉丝点击