• Java反射机制生成实例


    http://hi.baidu.com/wuming3632171/item/49834a269bf59b3794f62bc4

    看了一下Java OOP的项目,在创建门禁卡登录类别时可以用工厂模式来实现;但后来又考虑了一下在应用工厂模式的同时可以应用Java的反射机制,Java反射的概念我 个人认为很不好理解,通过例子才能融会贯通;其实理解Java的反射和理解JavaScript的eval函数一样,都是将一个字符型数据转换为相应的 类、属性和方法;通过下面的例子来熟悉一下Java的反射;
    首先定义一个教员类,如下:
    //教员类
    public class AccpTeacher {
    private String name;

    private int age;

    public AccpTeacher() {
    name = "无名氏";
    age = 22;
    }

    public AccpTeacher(String name) {
    this.name = name;
    this.age = 22;
    }

    public String toString() {
    return "名字是:" + name;
    }

    public String toString(int age, String name) {
    this.name = name;
    this.age = age;
    return "名字是:" + name + ";年龄是:" + age;
    }
    }
    如果我们实例化这个类可以用我们常用的如下方式:
    public static void main(String[] args){
    AccpTeacher accpTeacher = new AccpTeacher();
    System.out.println(accpTeacher);
    }
    可以清晰的想到运行结果是:名字是:无名氏
    以上是我们最常用的方式,但有时我们想通过字符串来实例化一个类如何做呢,看下面代码:
    public static void main(String[] args){
    // 实例化一个类
    Object accpTeacher = Class.forName(AccpTeacher.class.getName()).newInstance();
    System.out.println(accpTeacher);
    }运行结果同样是:名字是:无名氏
    首先Class.forName(类名)是将这个类加载到JVM虚拟机中,获得一个类型为Class的类,然后调用其newInstance()方法,相当于实例化(调用无参的构造函数);所以以上两段代码的运行效果是一致的。
    我们看到AccpTeacher这个类有一个带参数的构造方法,那如何通过反射来调用它呢?看下面代码:
    public static void main(String[] args){
    // 通过构造方法实例化一个类;本例是一个有参数的构造函数,并且构造函数可以为private修饰
    Class[] argtype = new Class[] { String.class };//代表构造方法的参数类型数组
    Object[] argparam = new Object[] { "张三" };//代表构造方法的参数值数组
    Class classType = Class.forName(AccpTeacher.class.getName());
    Constructor constructor = classType.getDeclaredConstructor(argtype); //获得构造方法,argtype是参数类型数组,我们这里代表的是参数只有一个String类型
    constructor.setAccessible(true);// 访问私有构造函数,Spring可以配置私有的属性和方法,其实就是用到的这里
    Object accpTeacher2 = constructor.newInstance(argparam);
    System.out.println(accpTeacher2);
    }以上代码的运行结果是:名字是:张三
    在把教员类放在这里,如下:
    //教员类
    public class AccpTeacher {
    private String name;

    private int age;

    public AccpTeacher() {
    name = "无名氏";
    age = 22;
    }

    public AccpTeacher(String name) {
    this.name = name;
    this.age = 22;
    }

    public String toString() {
    return "名字是:" + name;
    }

    public String toString(int age, String name) {
    this.name = name;
    this.age = age;
    return "名字是:" + name + ";年龄是:" + age;
    }
    }下面我想修改类中的属性,看代码:
    public static void main(String[] args){
    // 访问类中的属性,属性可以是private修饰的
    AccpTeacher accpTeacher3 = (AccpTeacher) Class.forName(
    AccpTeacher.class.getName()).newInstance();//实例化一个对象
    Field field = AccpTeacher.class.getDeclaredField("name");//声明一个属性对象,针对这个例子我们操作的这个属性是AccpTeacher类中的name属性
    field.setAccessible(true);// 私有成员变量
    System.out.println(field.get(accpTeacher3));//通过实例化的对象调用
    }
    以上代码的运行结果是:无名氏
    再看一下修改属性:接上例
    public static void main(String[] args){
    // 修改类中的属性,属性可以是private修饰的
    // 接上例
    field.set(accpTeacher3, "李四");//属性类通过set方法设置属性的值
    System.out.println(field.get(accpTeacher3));
    }
    以上代码的运行结果是:李四
    最后我们看一下通过反射调用方法:
    public static void main(String[] args){
    // 调用类中的方法(无参),方法可以是private修饰的
    AccpTeacher accpTeacher4 = (AccpTeacher) Class.forName(
    AccpTeacher.class.getName()).newInstance();//实例化一个对象
    Method method = AccpTeacher.class.getMethod("toString", null);//首先声明一个方法类,并通过getMethod()方法获得相应的方法,这个方法中有两个参数,第一个是方法名称的字符串,第二个是方法 中参数类型的数组,这里获得的是AccpTeacher中的toString方法
    System.out.println(method.invoke(accpTeacher4, new Object[0]));//再看一下方法类中的invoke()这个方法,方法中有两个参数,第一个参数为这个方法的实例对象,第二个参数为方法参数的值的数组
    }
    以上代码的运行结果是:名字是:无名氏
    在看带参的方法:
    public static void main(String[] args){
    // 调用类中的方法(有参),方法可以是private修饰的
    AccpTeacher accpTeacher5 = (AccpTeacher) Class.forName(
    AccpTeacher.class.getName()).newInstance();
    Class[] clazz = new Class[2];//声明类型的数组,AccpTeacher中有一个toString(int,String)的方法
    clazz[0] = int.class;
    clazz[1] = String.class;
    Method method2 = AccpTeacher.class.getMethod("toString", clazz);//获得带参数的方法
    Object[] obj = new Object[2];//参数值的数组
    obj[0] = 20;
    obj[1] = "王五";
    System.out.println(method2.invoke(accpTeacher5, obj));
    }
    以上代码的运行结果是:名字是:王五;年龄是:20


    以下是我个人分析学习代码:

    Teacher类

    package test;

    public class Teacher {
        private String name;

        private int age;

        public Teacher() {
        name = "无名氏";
        age = 22;
        }

        public Teacher(String name) {
        this.name = name;
        this.age = 22;
        }

        public String toString() {
        return "名字是:" + name;
        }

        public String toString(int age, String name) {
        this.name = name;
        this.age = age;
        return "名字是:" + name + ";年龄是:" + age;
        }
    }

    package test;

    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;

    public class Test {
        public static void main(String[] args) throws Exception {
            Class[] paramenterTypes=new Class[]{String.class};//参数类型
            Object[] obj=new Object[]{"张三"};//参数值
            Class type=Class.forName(Teacher.class.getName());//通过Class.forName()来加载类,得到这个类类型
            Constructor constructor=type.getDeclaredConstructor(paramenterTypes);//由这个类类型以及它的参数得到构造器
            constructor.setAccessible(true);//访问私有构造函数,Spring可以配置私有的属性和方法,其实就是用到的这里
            Object o=constructor.newInstance(obj);
            System.out.println(o);
            
            Teacher t=(Teacher)Class.forName(Teacher.class.getName()).newInstance();
            Field field=Teacher.class.getDeclaredField("name");
            field.setAccessible(true);
            System.out.println(field.get(t));
            field.set(t, "李四");
            System.out.println(field.get(t));
            Teacher t2=(Teacher)Class.forName(Teacher.class.getName()).newInstance();
            Method method=Teacher.class.getMethod("toString", null);
            System.out.println(method.invoke(t2,  new Object[0]));
            
            Teacher t3=(Teacher)Class.forName(Teacher.class.getName()).newInstance();
            Class[] clazz=new Class[2];
            clazz[0]=int.class;
            clazz[1]=String.class;
            Method method2=Teacher.class.getDeclaredMethod("toString", clazz);
            Object[] objs=new Object[2];
            objs[0]=20;
            objs[1]="王五";
            System.out.println(method2.invoke(t3, objs));
        }
    }

    输出结果:

    名字是:张三
    无名氏
    李四
    名字是:无名氏
    名字是:王五;年龄是:20

    I'm falling off the sky all alone.The courage inside is gonna break the fall. Nothing can dim my light within. I am That I am 程序 = 数据结构 + 算法
  • 相关阅读:
    shell查看内存
    shell 终端字符颜色
    PHP获取一年有几周以及每周开始日期和结束日期
    PHP 计算当前时间是这一年的第几周
    laravel orWhere
    进程与线程的一个简单解释
    go cap和len的区别
    go 总结常用函数
    go append 函数常见操作
    php 字符串常用函数
  • 原文地址:https://www.cnblogs.com/IamThat/p/2881955.html
Copyright © 2020-2023  润新知