java反射学习-以demo加理伦

来源:互联网 发布:英语 荷兰语知乎 编辑:程序博客网 时间:2024/05/01 13:20

一、首先介绍一下Class类是什么?

1.class类的实例表示java应用运行时的类(class ans enum)或接口(interface and annotation)(每个java类运行时都在JVM里表现为一个class对象,可通过类名.class,类型.getClass(),Class.forName(“类名”)等方法获取class对象)。数组同样也被映射为为class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本类型boolean,byte,char,short,int,long,float,double和关键字void同样表现为 class 对象。(哈哈,以上均来自百度)
2.class的主要方法
class类的方法还是挺多的。主要是用于得到运行时类的相关信息(可用于反射)。

重要的几个方法:

1public static Class<?> forName(String className) :natice 方法,动态加载类。非常重要。       如在sql中动态加载驱动程序:class.forName(sqlDriver);2public T newInstance() :根据对象的class新建一个对象,用于反射。非常重要。       可用在反射中构建对象,调用对象方法:       class doubleClass= class.forName("java.lang.Double");       Object objDouble = doubleClass.newInstance();       如在javaBean中就应用了这个方法,因为java默认要有一个无参构造函数。3public ClassLoader getClassLoader() :获得类的类加载器Bootstrap  ,Extension ,System or user custom      ClassLoader(一般为system classloader)。重要。4,public String getName() :获取类或接口的名字。记住enum为类,annotation为接口。重要5,public native Class getSuperclass():获取类的父类,继承了父类则返回父类,否则返回java.lang.Object。返回Object的父类为空-null。一般6,public java.net.URL getResource(String name) :根据字符串获得资源。7,其他类  public boolean isEnum() :判断是否为枚举类型。 public native boolean isArray() :判断是否为数组类型。 public native boolean isPrimitive() :判断是否为基本类型。 public boolean isAnnotation() :判断是否为注解类型。public Package getPackage() :反射中获得package,如java.lang.Object 的package为java.lang。public native int getModifiers() : 反射中获得修饰符,如public static void等 。public Field getField(String name):反射中获得域成员。public Field[] getFields() :获得域数组成员。    public Method[] getMethods() :获得方法。public Method getDeclaredMethod(String name, Class<?>... parameterTypes):加个Declared代表本类,继承,父类均不包括。public Constructor<?>[] getConstructors() :获得所有的构造函数。

案例一,获取Class对象:

/** * 每个java类运行时都在JVM里表现为一个class对象, * 1.可通过类名.class, * 2.对象.getClass(), * 3.Class.forName("类名") * 等方法获取class对象 * @author hxy * */public class Test {    public static void main(String[] args) {        Class<?> c1=null;        Class<?> c2=null;        Class<?> c3=null;        try {            //通过类路径获取Class            c1=Class.forName("com.cdc.console.controller.Test");        } catch (ClassNotFoundException e) {            e.printStackTrace();        }        //通过对象获取Class        c2=new Test().getClass();        //通过类名获取Class        c3=Test.class;        System.out.println("类名称   "+c1.getName());        System.out.println("类名称   "+c2.getName());        System.out.println("类名称   "+c3.getName());    }}

案例二:通过Class实例化对象 newInstance(),类必须有无参构造函数

/** * 通过Class实例化对象 newInstance(),类必须有无参构造函数,否则会报错 * 1.可通过类名.class, * 2.对象.getClass(), * 3.Class.forName("类名") * 等方法获取class对象 * @author hxy * */public class Test {     public static void main(String[] args) {          Class<?> conf=SysConfLog.class;//        Class<?> conf=new SysConfLog().getClass();//        Class<?> conf=Class.forName("com.cdc.entity.sys.SysConfLog");          try {            SysConfLog c = (SysConfLog) conf.newInstance();            c.setBuName("哈哈");            System.out.println(c.getBuName());        } catch (InstantiationException e) {            e.printStackTrace();        } catch (IllegalAccessException e) {            e.printStackTrace();        }       }

案例三:通过Class取得全部的构造函数

/** * 通过Class取得所有构造函数getConstructors(),实例化对象 newInstance() * 1.可通过类名.class, * 2.对象.getClass(), * 3.Class.forName("类名") * 等方法获取class对象 * @author hxy * */public class Test {     public static void main(String[] args) {          Class<?> conf=SysConfLog.class;//        Class<?> conf=new SysConfLog().getClass();//        Class<?> conf=Class.forName("com.cdc.entity.sys.SysConfLog");          Constructor<?>[] ars = conf.getConstructors();        try {            SysConfLog c = (SysConfLog) ars[0].newInstance();            SysConfLog c1 = (SysConfLog) ars[1].newInstance("我是叫hxy");            c.setMenuName("我不是hxy");            System.out.println(c.getMenuName());            System.out.println(c1.getMenuName());        } catch (Exception e) {            e.printStackTrace();        }       }}

注:以节省页面,以下只写出代码核心部分
案例四:返回一个类实现的接口

 //保存所有的接口        Class<?> intes[]=demo.getInterfaces();        for (int i = 0; i < intes.length; i++) {            System.out.println("实现的接口   "+intes[i].getName());        }

案例五:返回一个类继承的类

 //取得父类        Class<?> temp=demo.getSuperclass();        System.out.println("继承的父类为:   "+temp.getName());

案例六:取出构造函数的详细信息

/** * 通过Class取得所有构造函数getConstructors(),取出构造函数的详细信息 * 1.可通过类名.class, * 2.对象.getClass(), * 3.Class.forName("类名") * 等方法获取class对象 * @author hxy * */public class Test {     public static void main(String[] args) {          Class<?> conf=SysConfLog.class;//        Class<?> conf=new SysConfLog().getClass();//        Class<?> conf=Class.forName("com.cdc.entity.sys.SysConfLog");          Constructor<?>cons[]=conf.getConstructors();            for (int i = 0; i < cons.length; i++) {                //获取参数类型集合                Class<?> p[]=cons[i].getParameterTypes();                System.out.print("构造方法:  ");                //获取修饰符的字节码,就是返回一个以特定字节码(十六进制)表示的整数                 int mo=cons[i].getModifiers();                System.out.print(Modifier.toString(mo)+" ");                //获取类路径                System.out.print(cons[i].getName());                System.out.print("(");                //循环参数列表                for(int j=0;j<p.length;++j){                    System.out.print(p[j].getName()+" arg"+i);                    if(j<p.length-1){                        System.out.print(",");                    }                }                System.out.println("){}");           }       }

案例七:获取所有的方法,获取方法的异常

/** * 通过Class取得所有方法,取出方法的详细信息,有异常,打印异常 * 1.可通过类名.class, * 2.对象.getClass(), * 3.Class.forName("类名") * 等方法获取class对象 * @author hxy * */public class Test {     public static void main(String[] args) {          Class<?> conf=SysConfLog.class;//        Class<?> conf=new SysConfLog().getClass();//        Class<?> conf=Class.forName("com.cdc.entity.sys.SysConfLog");          //获取所有方法          Method method[]=conf.getMethods();            for(int i=0;i<method.length;++i){                //返回类型                Class<?> returnType=method[i].getReturnType();                //参数类型                Class<?> para[]=method[i].getParameterTypes();                ///获取修饰符的字节码,就是返回一个以特定字节码(十六进制)表示的整数                 int temp=method[i].getModifiers();                //通过字节码,获取修饰符                System.out.print(Modifier.toString(temp)+" ");                System.out.print(returnType.getName()+"  ");                System.out.print(method[i].getName()+" ");                System.out.print("(");                for(int j=0;j<para.length;++j){                    System.out.print(para[j].getName()+" "+"arg"+j);                    if(j<para.length-1){                        System.out.print(",");                    }                }                //方法的抛出异常                Class<?> exce[]=method[i].getExceptionTypes();                if(exce.length>0){                    System.out.print(") throws ");                    for(int k=0;k<exce.length;++k){                        System.out.print(exce[k].getName()+" ");                        if(k<exce.length-1){                            System.out.print(",");                        }                    }                }else{                    System.out.print(")");                }                System.out.println();            }     }

案例八:通过Class取得所有属性,分为本类和父类

/** * 通过Class取得所有属性,分为本类和父类 * 1.可通过类名.class, * 2.对象.getClass(), * 3.Class.forName("类名") * 等方法获取class对象 * @author hxy * */public class Test {     public static void main(String[] args) {          Class<?> conf=SysConfLog.class;//        Class<?> conf=new SysConfLog().getClass();//        Class<?> conf=Class.forName("com.cdc.entity.sys.SysConfLog");          //获取所有方法          System.out.println("===============本类属性========================");            // 取得本类的全部属性            Field[] field = conf.getDeclaredFields();            for (int i = 0; i < field.length; i++) {                // 权限修饰符                int mo = field[i].getModifiers();                String priv = Modifier.toString(mo);                // 属性类型                Class<?> type = field[i].getType();                System.out.println(priv + " " + type.getName() + " "                        + field[i].getName() + ";");            }            System.out.println("===============实现的接口或者父类的属性========================");            // 取得实现的接口或者父类的属性            Field[] filed1 = conf.getFields();            for (int j = 0; j < filed1.length; j++) {                // 权限修饰符                int mo = filed1[j].getModifiers();                String priv = Modifier.toString(mo);                // 属性类型                Class<?> type = filed1[j].getType();                System.out.println(priv + " " + type.getName() + " "                        + filed1[j].getName() + ";");            }     }

案例九:调用类的set get 方法:

 public static void main(String[] args) {          Class<?> conf=SysConfLog.class;//        Class<?> conf=new SysConfLog().getClass();//        Class<?> conf=Class.forName("com.cdc.entity.sys.SysConfLog");           // 取得本类的全部属性          Object obj=null;            try {                obj=conf.newInstance();            } catch (Exception e) {                e.printStackTrace();            }             Field[] field = conf.getDeclaredFields();            //赋值            setter(obj, "clientMark", "clientMark", String.class);            setter(obj, "clientIp", "clientIp", String.class);            for (int i = 0; i < field.length; i++) {                getter(obj, field[i].getName());            }     }     /**     * @param obj     *            操作的对象     * @param att     *            操作的属性     * */    public static void getter(Object obj, String att) {        try {            att=att.substring(0,1).toUpperCase()+att.substring(1,att.length());            Method method = obj.getClass().getMethod("get" + att);            if(method.invoke(obj)==null){                return;            }            System.out.println(method.invoke(obj));        } catch (Exception e) {            e.printStackTrace();        }    }    /**     * @param obj     *            操作的对象     * @param att     *            操作的属性     * @param value     *            设置的值     * @param type     *            参数的属性     * */    public static void setter(Object obj, String att, Object value,            Class<?> type) {        att=att.substring(0,1).toUpperCase()+att.substring(1,att. length());        try {            Method method = obj.getClass().getMethod("set" + att, type);            method.invoke(obj, value);        } catch (Exception e) {            e.printStackTrace();        }    }

案例十:通过反射修改数组信息和改变数组长度

/** * 通过反射修改数组信息和改变数组长度 * @author hxy * */public class Test {     public static void main(String[] args) {         int[] temp={1,2,3,4,5};            Class<?>demo=temp.getClass().getComponentType();            System.out.println("数组类型: "+demo.getName());            System.out.println("数组长度  "+Array.getLength(temp));            System.out.println("数组的第一个元素: "+Array.get(temp, 0));            Array.set(temp, 0, 100);            System.out.println("修改之后数组第一个元素为: "+Array.get(temp, 0));            temp=(int[]) arrayInc(temp, 7);            print(temp);     }     /**         * 修改数组大小         * */        public static Object arrayInc(Object obj,int len){            //返回obj数组类型,如果不是数组则返回Null            Class<?>arr=obj.getClass().getComponentType();            Object newArr=Array.newInstance(arr, len);            int co=Array.getLength(obj);            //复制数组 obj-源数组 ,0-从0开始复制  ,newArr-目标数组 ,0-复制到新数组从0开始,co-复制多少长度            System.arraycopy(obj, 0, newArr, 0, co);            return newArr;        }        /**         * 打印         * */        public static void print(Object obj){            Class<?>c=obj.getClass();            if(!c.isArray()){                return;            }            System.out.println("数组长度为: "+Array.getLength(obj));            for (int i = 0; i < Array.getLength(obj); i++) {                System.out.print(Array.get(obj, i)+" ");            }        }
1 0