1.学习了Class对象,Filed对象(对应数据),Method对像(对应函数),Constructor对象(对应构造函数)。
2.Declared可用于获取私有的数据和方法,但是打印得使用setAccessible(true);来要忽略访问权限修饰符的检查。
3.FS5()函数有一个点需要注意就是地址一致,原因我写在注释里了。
#FS练习配置文件 #1.将需要创建的对象的全类名和需要执行的方法定义在配置文件中 #2.在程序中加载读取配置文件 #3.使用反射技术来加载类文件进入内存 #4.创建对象 #5.执行方法 # #
className=bean.Admin
methodName=eat
Filed对象的学习
/** * 学习java反射机制 * Field对象的学习 */ @Test public void FS1() throws NoSuchFieldException, IllegalAccessException { Class userClass = User.class; Field[] fields = userClass.getFields();//获取所有public的成员对象 for(Field field:fields) { System.out.println(field); } Field field1 =userClass.getField("fs");//按照变量名获取 /* Field 操作 1.设置 set 2.获取 get */ User user1=new User(); System.out.println(field1.get(user1)); field1.set(user1,"dada"); System.out.println(field1.get(user1)); //忽略修饰符 可以获取到私有的 Field[] full=userClass.getDeclaredFields(); for(Field field:full) { System.out.println(field); } //获取单个某一个 忽略修饰符 Field privateField=userClass.getDeclaredField("id"); //但是打印私有的,需要忽略访问权限修饰符的检查 privateField.setAccessible(true); //暴力反射 System.out.println(privateField.get(user1)); }
Constructor对象的学习
/** * 反射机制获取构造方法 */ @Test public void FS2() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { Class userClass = User.class; //获取所有的 Constructor[] constructors=userClass.getConstructors(); for(Constructor constructor:constructors) { System.out.println(constructor); } //获取单个 Constructor constructor =userClass.getConstructor(Integer.class,String.class); System.out.println(constructor); //使用获取的constructor创建对象 Object user =constructor.newInstance(5,"dada"); System.out.println(user.toString()); /* 使用空参的构造方法 */ Constructor constructor1 =userClass.getConstructor(); System.out.println(constructor); Object user1 =constructor1.newInstance(); System.out.println(user1.toString()); System.out.println("与上同理"); //与上同理,Class这个方法就是为了方便调用空参的构造方法 Object user2=userClass.newInstance(); System.out.println(user2.toString()); //暴力反射constructor.setAccessible(); }
Method对象的学习
/** * 反射机制获取方法 * Method */ @Test public void FS3() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { Class userClass = User.class; //获取类名 String className =userClass.getName(); System.out.println(className); //获取public所有方法 Method[] methods = userClass.getMethods(); for (Method method:methods) { //也会打印Obj里的方法 System.out.println(method); //获取方法名 System.out.println(method.getName()); } // 获取方法 根据方法名 返回值 Method eat = userClass.getMethod("eat"); Method eat1= userClass.getMethod("eat",int.class); User user=new User(); eat.invoke(user);//执行方法 eat1.invoke(user,1);//执行方法 }
配置文件和反射的使用
/** *配置文件和反射的使用 */ @Test public void FS4() throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { //1.加载配置文件 Properties pro =new Properties(); //获取classes目录下的配置文件 ClassLoader类 ClassLoader classLoader=TestUserFS.class.getClassLoader(); //获取输入流 InputStream resourceAsStream = classLoader.getResourceAsStream("FS.properties"); //加载 pro.load(resourceAsStream); //2.获取配置文件中定义的数据 String className =pro.getProperty("className"); String methodName =pro.getProperty("methodName"); System.out.println(methodName); //3.加载类进内存 Class userClass = Class.forName(className); //4.创建对象 Object obj=userClass.newInstance(); //5.获取对象方法 Method method=userClass.getMethod(methodName); //获取带参数的那个eat函数 Method method1=userClass.getMethod(methodName,int.class); //6.执行方法 method.invoke(obj); method1.invoke(obj,1); }
三种常用的方法: Class.forName()函数,我在用JDBC的时候用到过,其他俩种很少。
/** * 笔记 * 1.Class.forName("全类名") * 2.对象.getClass():方法获取 * 3.类名.class:通过类名的属性class获取 */ @Test public void FS5() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { //1用于配置文件中 Class objClass1= Class.forName("bean.User"); System.out.println(objClass1); Object user1=objClass1.newInstance(); Method method1=objClass1.getMethod("eat"); method1.invoke(user1); //2.用于现有对象的获取字节码 Class objClass2=User.class; System.out.println(objClass2); //3.用于参数传递 User user3=new User(); Class objClass3=user3.getClass(); System.out.println(objClass3); /* * 三个是相同的地址 * 为什么呢? * 因为class加载进内存后只会一次,所以你获取他的时候只有一个 */ System.out.println(objClass1.hashCode()); System.out.println(objClass2.hashCode()); System.out.println(objClass3.hashCode()); }
总结:java的反射机制和配置文件真的太好用了,就我之前学习的log4的配置在控制台错误输出对我帮助很大。
java的Junit让我写代码越来越方便。