java基础--反射(1)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sky_20131213/article/details/77146099
  • 类的加载
    当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。
    加载:将class文件读入内存,并为之创建一个Class文件,任何类被使用时系统都会建立一个Class对象(由类加载器完成);
    连接:验证,是否有正确的内部结构,并和其他类协调一致;准备,为类的静态成员分配内存,并设置默认初始化值;解析,将类的二进制数据中的符号引用替换为直接引用;
    类加载器的组成:
    Bootstrap ClassLoader 根类加载器:又称引导类加载器,负责java核心类的加载;
    Extension ClassLoader 扩展类加载器:负责jre的扩展目录中jar包的加载;
    System ClassLoader 系统类加载器:负责在jvm启动时加载来自java命令的class文件,以及classpath环境变量所制定的jar包和类路径。
  • 什么是反射:Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
  • 得到class文件对象,即得到Class类的对象,有三种方法:
    ① Object类中的getClass()方法:
 Person p = new Person();
 Class c=p.getClass();

②数据类型的静态属性class:

Class c = Person.class;

③Class类中的静态方法:

//public static class forName(string className)
//className为类的全路径
Class c = Class.forName("com.test.Person");

在开发中,我们一般使用第三种方式,因为这种方式的全路径为一个字符串,在开发中可以把这样的字符串配置到文件中,使用灵活。

package com.yx1213.reflect;

/**
 * 获取class文件对象的三种方法
 * 
 * @author Administrator
 * 
 */
public class ReflectTest1 {
    public static void main(String[] args) throws ClassNotFoundException {
        // 第一种方法:Object类中的getClass()方法
        Person person = new Person();
        Class class1 = person.getClass();
        System.out.println("第一种:" + class1);

        // 第二种方法:数据类型的静态属性class
        Class class2 = Person.class;
        System.out.println("第二种:" + class2);

        // 第三种方法:Class类中的静态方法
        // public static class forName(string className)
        // className为类的全路径
        Class class3 = Class.forName("com.yx1213.reflect.Person");
        System.out.println("第三种:" + class3);
    }

}

1、通过反射获取构造方法
现有一Person类:

package com.yx1213.reflect;

public class Person {
    String name;
    private int age;
    public String addr;

    public Person() {
    }

    private Person(String name) {
        this.name = name;
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person(String name, int age, String addr) {
        this.name = name;
        this.age = age;
        this.addr = addr;
    }

    public void say(){
        System.out.println("hello world!");
    }

    public void eat(String food){
        System.out.println("eat"+food);
    }

    public String work(){
        System.out.println("work");
        return "success";
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + ", addr=" + addr + "]";
    }
}

获取以及使用该类的构造方法:

package com.yx1213.reflect;

import java.lang.reflect.Constructor;

/*
 * 通过反射获取构造方法
 */
public class ReflectTest2 {
    public static void main(String[] args) throws Exception {
        // 获取class对象
        String className = "com.yx1213.reflect.Person";
        Class class1 = Class.forName(className);

        // public Constructor getConstructor(Class<?>... parameterTypes)
        // 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
        // 获取无参构造方法
        Constructor constructor = class1.getConstructor();
        System.out.println(constructor);
        // 根据所传形参的个数与类型,获取相应有参构造方法
        Constructor constructor2 = class1.getConstructor(String.class,
                int.class);
        System.out.println("=================");
        System.out.println(constructor2);
        System.out.println("=================");
        // public Constructor[] getConstructors()
        // 返回一个包含某些 Constructor 对象的数组,
        // 这些对象反映此 Class 对象所表示的类的所有公共构造方法。
        Constructor[] constructors = class1.getConstructors();
        for (Constructor cons : constructors) {
            System.out.println(cons);
        }
        // getDeclaredConstructor与getConstructor相似,
        // 返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法
        // getDeclaredConstructors与getConstructors相似
        // 返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。

        // Constructor类中一个方法:public T newInstance(Object... initargs)
        // 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
        // 相当于Person person=new Person("张三",23);
        Object obj = constructor2.newInstance("张三", 23);
        System.out.println("**************");
        System.out.println(obj);
    }
}

2、 通过反射获取成员变量并使用

package com.yx1213.reflect;

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

/*
 * 通过反射获取成员变量
 */
public class ReflectTest3 {
    public static void main(String[] args) throws Exception {
        // 获取class对象
        Class class1 = Class.forName("com.yx1213.reflect.Person");
        // 通过反射获得无参构造方法创建对象
        Constructor constructor = class1.getConstructor();
        Object object = constructor.newInstance();
        // public Field getField(String name)
        // 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
        // name 参数是一个 String,用于指定所需字段的简称。
        Field field = class1.getField("addr");
        // public void set(Object obj,Object value)
        // 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
        field.set(object, "深圳");
        System.out.println(object);

        // public Field getDeclaredField(String name)
        // 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明所有字段。
        Field field2 = class1.getDeclaredField("name");
        // 对私有变量要设置取消访问检查,否则会报java.lang.IllegalAccessException
        field2.setAccessible(true);
        field2.set(object, "李四");
        System.out.println(object);

        // public Field[] getFields()
        // 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。
        Field[] fields = class1.getFields();
        for (Field fieldss : fields) {
            System.out.println(fieldss);
        }
        // public Field[] getDeclaredFields()与getFields相似
        // 返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。
        Field[] fields2=class1.getDeclaredFields();
        System.out.println("================");
        for (Field field3 : fields2) {
            System.out.println(field3);
        }
    }
}

3、通过反射获取并使用成员方法

package com.yx1213.reflect;

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

public class ReflectTest4 {
    public static void main(String[] args) throws Exception {
        // 获取class对象
        Class class1 = Class.forName("com.yx1213.reflect.Person");
        // 通过反射获得无参构造方法创建对象
        Constructor constructor = class1.getConstructor();
        Object object = constructor.newInstance();
        //public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
        //返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。
        //name 参数是一个 String,它指定所需方法的简称
        //parameterTypes 参数是 Class 对象的一个数组,它按声明顺序标识该方法的形参类型。
        Method method = class1.getDeclaredMethod("say");
        //对私有方法要设置取消访问检查,否则会报java.lang.IllegalAccessException
        method.setAccessible(true);
        //public Object invoke(Object obj,Object... args)
        //第一个形参对象是谁,第二个形参表示该方法所需要的实参
        method.invoke(object);

        //如果有参数的情况下
        Method method2 = class1.getDeclaredMethod("eat",String.class);
        method2.invoke(object,"苹果");
        System.out.println("=============");

        //有返回值的情况下
        Method method3 = class1.getDeclaredMethod("work");
        String st=(String) method3.invoke(object);
        System.out.println("执行"+st);
    }
}

猜你喜欢

转载自blog.csdn.net/sky_20131213/article/details/77146099