java反射学习-以demo加理伦

一、首先介绍一下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)+" ");
            }
        }

由于平时很少写博客,写的很差,请多见谅。

这里推荐下我的开源项目:
hxyFrame是一个OA办公系统,采用流行的框架springMvc+spring+mybatis+shiro+ehcache开发,还集成了权限管理(菜单权限、数据权限),完善的代码生成器,solr全文搜索引擎,activiti工作流程引擎,cas单点登陆等功能,后期还会考虑改造成Dubbo微服务化,做到模块的相对独立,使用更加灵活,努力做到快速开发OA办公系统。 感兴趣可以Watch、Start持续关注项目最新状态,加入QQ群:210315502
oschina仓库:https://git.oschina.net/huangxianyuan/hxyFrame.git
github仓库:https://github.com/huangxianyuan/hxyFrame.git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值