Java反射机制浅谈

前言:

我们在程序开发的过程中,有时会碰到这样一种情况:A程序员和B程序员共同开发某一项功能,因为是并行开发,有可能A程序员需要用到B程序员所写的类,但是B程序员并没有完成,这种情况下,A程序员的代码是不能通过编译的,有没有办法解决呢?

还有一种情况,当我们想去查看java对象的属性、方法、构造方法,有没有更方便简洁的办法呐?

这个时候我们引用了 java反射机制。

反射机制:

是指在运行状态中,对于任意一个类,都能知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个属性和方法;这种动态获取调用对象的方法的功能成为java语言的反射机制。

JAVA反射(放射)机制:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。换句话说,就是java程序可以加载一个运行时才得知名称的class,并能对其进行操作。----java反射机制(百度百科)

1)在运行时,可以判断任意一个对象所属的类;

2)在运行时,构造任何一个类的对象;

3)在运行时,判断任意一个对象所具有的成员变量和方法;

4)在运行时,调用任意一个对象的方法;

5)生成动态代理

java反射提供的类:

java.lang.Class;

java.lang.reflect.Constructor;

java.lang.reflect.Field;

java.lang.reflect.Method;

java.lang.reflect.Modifier;

使用:

一)获得类的Class实例

所有类都是Class的类类型

Person(一个普通的类)类为例:

class RefleDemo {

public static void main(String [] args) {

//方式1)直接调用该类的class方法

Class c1=Person.class;

//方式2)调用对象的getClass()方法

Person person=new Person();

Class c2=person.getClass();

//方式3)通过该类的路径获得

Class c3=Class.forName("该类的全路径");

Person person = (Person) c3.newInstance();(运行时,构建任何一个类的对象)

}

}

二)操作类的Class实例

反射:运行时的类信息---java编程思想。

通过获取到的类的实例,我们可以获取到该类的成员类型,方法,构造函数信息,Class类也java.lang.reflect类库一起对反射的概念进行了支持;

1)获取类的方法

      /**
* 获取Class实例的方法
* getDeclaredMethods():仅获得该类的所有的方法(包括重写),不获取Object父类的方法
* getMethods():获得该类以及Object父类的public类型方法(包括重写)
*/
private void getClassMethods() {
Class c1 = Person.class;
                Method[] methods = c1.getDeclaredMethods();
Method[] methods = c1.getMethods();
                for (Method method : methods) {
Log.i("info", method.getName());
}
}

2)获取类的构造器

       /**
* 获得Class实例的构造函数
* getDeclaredConstructors()
* getConstructors()
*/
private void getConstructors() {
Class c1 = Person.class;
                //Constructor[] constructors = c1.getDeclaredConstructors();
Constructor[] constructors = c1.getConstructors();
                for (Constructor constructor : constructors) {
Log.i("info", constructor.getName());
}
}

3)获取类的成员

/**
     * 获得Class实例的成员
     * getFields():获得该类的public类型的
     * getDeclaredFields():获得该类所有的成员
     */
    private void getFields() {
        Class c1 = Person.class;
        Field[] fields = c1.getFields();
//        Field[] fields = c1.getDeclaredFields();
        for (Field field : fields) {
            Log.i("info", field.getName());
        }
    }

三)方法反射

已知Person类中有一个方法refleMethod(),我们可以通过java方法反射的机制获取到该方法。

public class Person {
public void refleMethod(String args) {
System.out.print(args);
}
}

/**
     * java方法反射
     */
    private void getRefleMethod() {
        //获得Class实例
        Person person = new Person();
        Class c1 =person.getClass();
        try {
            //获得对应的方法 getMethod 参数1:对应的方法名称,参数2:对应方法的参数类型 (没有参数类型 则空)
            //Method method = c1.getMethod("refleMethod", new Class[]{String.class});
            Method method = c1.getMethod("refleMethod", String.class);
            //操作对应的方法 invoke 参数1:是该方法所在的类的对象,参数2:赋值 (没有参数则空)
            //Object object = method.invoke(person, new Object[]{"this is a test!"});
            Object object = method.invoke(person, "this is a test!");
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

4)java泛型的扩展:测试泛型

      /**
     * 测试泛型的本质 (生命周期只存在编译期间,运行期间去泛型化)
     */
    private void testFX() {
        ArrayList array1 = new ArrayList();
        ArrayList array2 = new ArrayList<>();
        Log.i("info", "array1与array2相等吗:" + (array1.getClass() == array2.getClass()));//true
        /**
         * 反射操作都是编译之后的操作(变成字节码之后),是运行时期的操作。
         * 从上面的结果可以看出编译之后集合的泛型是去泛型化的
         */

        try {
            Method method = array2.getClass().getMethod("add", Object.class);
            method.invoke(array2, 100);
            Log.i("info", "array2:" + array2.size());//长度为1
            /**
             * 我们通过方法反射的机制,测试了把类型为int的值加入到了ArrayList中,

             * 这种操作是在编译期间不允许的,

             * 之所以有这种限制,就是减少操作数据的错误
             * 在运行期间可以实现,这说明了java的泛型在运行期间是去泛型化的
             */

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

  推荐视频:慕课网 https://www.imooc.com/video/3725

       

你可能感兴趣的:(java)