zoukankan      html  css  js  c++  java
  • 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 程序 = 数据结构 + 算法
  • 相关阅读:
    wget(转)
    852. Peak Index in a Mountain Array
    617. Merge Two Binary Trees
    814. Binary Tree Pruning
    657. Judge Route Circle
    861. Score After Flipping Matrix
    832. Flipping an Image
    461. Hamming Distance
    654. Maximum Binary Tree
    804. Unique Morse Code Words
  • 原文地址:https://www.cnblogs.com/IamThat/p/2881955.html
Copyright © 2011-2022 走看看