1、认识Class类
任何一个类都是Class类的实例对象,这个实例对象有三种表示方式。
1 /*java 反射机制*/ 2 // 获取类的方法 3 UserDao userDao = new UserDao(); 4 Class c = UserDao.class; // 1、知道类名 使用.class获取类 5 Class d = userDao.getClass(); // 2、知道对象 使用.getClass()获取类 6 Class m = null; // 3、知道类 使用class.forName("")获取类 7 try { 8 m = Class.forName("com.description.dao.UserDao"); 9 } catch (ClassNotFoundException e) { 10 e.printStackTrace(); 11 } 12 13 System.out.println("c d是否相等 : " + (c==d)); 14 System.out.println("c m是否相等 : " + (c==m)); 15 16 try { 17 UserDao ud = (UserDao) c.newInstance(); // 通过反射实例化一个对象,前提是UserDao必须有一个默认的无参构造方法 18 } catch (InstantiationException e) { 19 e.printStackTrace(); 20 } catch (IllegalAccessException e) { 21 e.printStackTrace(); 22 }
2、动态加载类实例
新建四个类,一个Software接口,另外新建两个类继承该接口。
Software.java
1 package com.hua.reflect; 2 3 /** 4 * Created by 华天 on 2016/06/06. 5 */ 6 public interface Software { 7 public void show(); 8 }
Word.java
1 package com.hua.reflect; 2 3 /** 4 * Created by 华天 on 2016/06/06. 5 */ 6 public class Word implements Software{ 7 8 9 @Override 10 public void show() { 11 System.out.println("实现wold功能"); 12 } 13 }
Excel.java
1 package com.hua.reflect; 2 3 /** 4 * Created by HuaTian on 2016/06/06. 5 */ 6 public class Excle implements Software { 7 @Override 8 public void show() { 9 System.out.println("实现Excel功能"); 10 } 11 }
JavaReflect.java
1 /** 2 * 动态加载类 3 */ 4 public static void getClass(String className) { 5 Software software = null; 6 try { 7 Class c = Class.forName("com.hua.reflect."+className);// 获取类 8 software = (Software) c.newInstance(); // 实例化类 9 } catch (ClassNotFoundException e) { 10 e.printStackTrace(); 11 } catch (InstantiationException e) { 12 e.printStackTrace(); 13 } catch (IllegalAccessException e) { 14 e.printStackTrace(); 15 } 16 software.show(); 17 18 } 19 public static void main(String[] args){ 20 21 /** 22 * 编译加载类属于静态加载类,运行加载类属于动态加载类 23 * new 对象属于静态加载类,在编译时期就要加载所有可能用到的类。 24 * 通过使用动态加载类,类在使用时加载,不使用不加载。 25 * 26 */ 27 JavaReflect.getClass("Word");
知识点:
1、编译加载类属于静态加载类,运行加载类属于动态加载类。
2、new 对象属于静态加载类,在编译时期就要加载所有可能用到的类。
3、通过使用动态加载类,类在使用时加载,不使用不加载。
4、void 等关键字都有类类型。
5、获取类类型后就能获取类的相关信息。
6、反射的操作都是编译后的操作。
7、Java中的泛型是防止错误输入的,只在编译时期有效。ArrayList<String> == ArrayList
编译完成后泛型就不存在了,反射可以绕过编译将信息添加进去。
3、获取类中的相关信息
新建一个ClassUtil.java 帮助类
1 /** 2 * Created by 10113513 on 2016/06/06. 3 */ 4 public class ClassUtil { 5 6 /** 7 * 显示类的相关信息 8 * @param obj 9 */ 10 public static void classMessage(Object obj) { 11 Class cs = obj.getClass(); 12 System.out.println("类的全名称----------->" + cs.getName()); 13 System.out.println("类的简写名称--------->" + cs.getSimpleName()); 14 } 15 16 /** 17 * 显示类中声明的方法 18 * @param obj 19 */ 20 public static void getMethods(Object obj){ 21 Class cs = obj.getClass(); 22 System.out.println("-------"+cs.getName()+"类中的方法"); 23 Method[] methods = cs.getDeclaredMethods(); 24 String show; 25 for (Method md : methods) { 26 show = md.getName() + md.getReturnType() + "("; 27 Class[] paramType = md.getParameterTypes(); 28 for (Class c : paramType) { 29 show += c.getSimpleName() + ","; 30 } 31 show +=")"; 32 System.out.println(show); 33 } 34 } 35 36 /** 37 * 获取类的成员变量 38 * 只能获取公有的成员变量 39 * @param obj 40 */ 41 public static void getFiled(Object obj){ 42 Class cs = obj.getClass(); 43 System.out.println("-------"+cs.getName()+"类中的成员变量--------"); 44 Field[] fds = cs.getFields(); 45 for (Field fd:fds) { 46 System.out.println(fd.getName()); 47 } 48 } 49 50 /** 51 * 获取类中的构造函数 52 * @param obj 53 */ 54 public static void getConstructor(Object obj){ 55 Class cs = obj.getClass(); 56 System.out.println("-------"+cs.getName()+"类中的构造函数"); 57 Constructor[] ctrs = cs.getConstructors(); 58 String show = ""; 59 for (Constructor ctr:ctrs) { 60 show += ctr.getName()+"("; 61 Parameter[] pars = ctr.getParameters(); 62 for (Parameter par:pars) { 63 show += par.getName()+","; 64 } 65 show +=")"; 66 System.out.println(show); 67 } 68 } 69 70 }
4、获取方法的相关信息(获取的public的方法)
1>方法名和参数列表决定了方法的唯一性
2>方法反射的操作,method.invoke(对象,参数列表)
1>> 方法没有返回值返回null,又返回值返回具体返回值。
2>> 方法有参数列表就写成method.invoke(a1,int.class,int.class) 两个参数为例,
没有参数直接写成method.invoke(a1,int.class,int.class) 。
5、整体代码
JavaReflect.java
1 package com.hua.reflect; 2 3 import com.description.dao.UserDao; 4 5 6 /** 7 * Created by 华天 on 2016/06/06. 8 */ 9 public class JavaReflect { 10 public String animal; 11 private int num; 12 protected boolean isOk; 13 14 public JavaReflect(){ 15 16 } 17 public JavaReflect(String a){ 18 System.out.println("do someThing"); 19 } 20 21 22 /** 23 * 动态加载类 24 * @param className 25 */ 26 public static void getClasses(String className) { 27 Software software = null; 28 try { 29 Class c = Class.forName("com.hua.reflect." + className);// 获取类 30 software = (Software) c.newInstance(); // 实例化类 31 } catch (ClassNotFoundException e) { 32 e.printStackTrace(); 33 } catch (InstantiationException e) { 34 e.printStackTrace(); 35 } catch (IllegalAccessException e) { 36 e.printStackTrace(); 37 } 38 software.show(); 39 40 } 41 42 /** 43 * 测试 44 * @param str 45 */ 46 public void test(String str) { 47 System.out.println("这是全部大写的测试方法:"+str.toUpperCase()); 48 } 49 /** 50 * 测试1 51 */ 52 public void test1() { 53 System.out.println("这是全部小写的测试方法:"+"LIuBaoHua".toLowerCase()); 54 } 55 56 57 public static void main(String[] args) { 58 /*java 反射机制*/ 59 // 获取类的方法 60 UserDao userDao = new UserDao(); 61 Class c = UserDao.class; // 1、知道类名 .class 62 Class d = userDao.getClass(); // 2、知道对象 .getClass() 63 Class m = null; // 3、知道类的路径直接 class.forName(""); 64 try { 65 m = Class.forName("com.description.dao.UserDao"); // 动态加载类 66 } catch (ClassNotFoundException e) { 67 e.printStackTrace(); 68 } 69 70 System.out.println("c d是否相等 : " + (c == d)); 71 System.out.println("c m是否相等 : " + (c == m)); 72 System.out.println("打印类名称: " + c.getName() + " " + d.getName() + " " + m.getName()); 73 System.out.println("不包含包名的类名称: " + c.getSimpleName() + " " + d.getSimpleName()+ " " + m.getSimpleName()); 74 75 try { 76 77 UserDao ud = (UserDao) c.newInstance(); // 通过反射实例化一个对象,前提是UserDao必须有一个默认的无参构造方法 78 } catch (InstantiationException e) { 79 e.printStackTrace(); 80 } catch (IllegalAccessException e) { 81 e.printStackTrace(); 82 } 83 /** 84 * 1、编译加载类属于静态加载类,运行加载类属于动态加载类 85 * 2、new 对象属于静态加载类,在编译时期就要加载所有可能用到的类。 86 * 3、通过使用动态加载类,类在使用时加载,不使用不加载。 87 * 4、void 等关键字都有类类型 88 * 5、获取类类型后就能获取类的相关信息 89 */ 90 JavaReflect.getClasses("Word"); 91 92 ClassUtil.classMessage(new JavaReflect()); 93 94 ClassUtil.getMethods(new JavaReflect()); 95 96 ClassUtil.getFiled(new JavaReflect()); 97 98 ClassUtil.getConstructor(new JavaReflect()); 99 100 // 参数列表 101 Class[] parms = new Class[]{String.class}; 102 String[] strs = new String[]{"liubaohua"}; 103 // 测试有参数 104 ClassUtil.getMethod(new JavaReflect(),"test",parms,strs); 105 // 测试无参数 106 ClassUtil.getMethod(new JavaReflect(),"test1",null,null); 107 108 } 109 110 111 }
ClassUtil.java
1 package com.hua.reflect; 2 3 import java.lang.reflect.*; 4 5 /** 6 * Created by 华天 on 2016/06/06. 7 */ 8 public class ClassUtil { 9 10 /** 11 * 显示类的相关信息 12 * @param obj 13 */ 14 public static void classMessage(Object obj) { 15 Class cs = obj.getClass(); 16 System.out.println("类的全名称----------->" + cs.getName()); 17 System.out.println("类的简写名称--------->" + cs.getSimpleName()); 18 } 19 20 /** 21 * 显示类中声明的方法 22 * @param obj 23 */ 24 public static void getMethods(Object obj){ 25 Class cs = obj.getClass(); 26 System.out.println("-------"+cs.getName()+"类中的方法"); 27 Method[] methods = cs.getDeclaredMethods(); 28 String show; 29 for (Method md : methods) { 30 show = md.getName() + md.getReturnType() + "("; 31 Class[] paramType = md.getParameterTypes(); 32 for (Class c : paramType) { 33 show += c.getSimpleName() + ","; 34 } 35 show +=")"; 36 System.out.println(show); 37 } 38 } 39 40 /** 41 * 获取类的成员变量 42 * 只能获取公有的成员变量 43 * @param obj 44 */ 45 public static void getFiled(Object obj){ 46 Class cs = obj.getClass(); 47 System.out.println("-------"+cs.getName()+"类中的成员变量--------"); 48 Field[] fds = cs.getFields(); 49 for (Field fd:fds) { 50 System.out.println(fd.getName()); 51 } 52 } 53 54 /** 55 * 获取类中的构造函数 56 * @param obj 57 */ 58 public static void getConstructor(Object obj){ 59 Class cs = obj.getClass(); 60 System.out.println("-------"+cs.getName()+"类中的构造函数"); 61 Constructor[] ctrs = cs.getConstructors(); 62 String show = ""; 63 for (Constructor ctr:ctrs) { 64 show += ctr.getName()+"("; 65 Parameter[] pars = ctr.getParameters(); 66 for (Parameter par:pars) { 67 show += par.getName()+","; 68 } 69 show +=")"; 70 System.out.println(show); 71 } 72 } 73 74 /** 75 * 获取特定的方法 76 * @param obj 类 77 * @param mdName 方法名 78 * @param parms 参数列表 79 * @param objs 传入参数 80 */ 81 public static void getMethod(Object obj,String mdName,Class[] parms,Object[] objs){ 82 Class cs = obj.getClass(); 83 System.out.println("----------"+cs.getName()+"类中的具体方操作------------"); 84 try { 85 JavaReflect ncs = (JavaReflect) cs.newInstance(); 86 // getDeclaredMethod(方法名,参数列表); 87 Method md = null; 88 if(parms == null){ 89 md = cs.getDeclaredMethod(mdName); 90 // 调用方法 91 md.invoke(ncs); 92 }else{ 93 md = cs.getDeclaredMethod(mdName,parms); 94 // 调用方法 95 md.invoke(ncs,objs); 96 } 97 } catch (NoSuchMethodException e) { 98 e.printStackTrace(); 99 } catch (InvocationTargetException e) { 100 e.printStackTrace(); 101 } catch (IllegalAccessException e) { 102 e.printStackTrace(); 103 } catch (InstantiationException e) { 104 e.printStackTrace(); 105 } 106 107 } 108 109 }
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用
对象的方法的功能称为java语言的反射机制。