反射

2020-04-26  本文已影响0人  77fb554dbace

反射


一、什么是反射

        反射是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。是Java被视为动态语言的关键。

Java反射机制主要提供了以下功能:

        在运行时构造任意一个类的对象

        在运行时获取或者修改任意一个类所具有的成员变量和方法

        在运行时调用任意一个对象的方法(属性)

二、获取Class类

获取Class对象的三种方式

        1. 通过类名获取 类名.class

        2. 通过对象获取 对象名.getClass()

        3. 通过全类名获取 Class.forName(全类名) classLoader.loadClass(全类名)

        使用 Class 类的 forName 静态方法

                public static Class<?> forName(String className)

        直接获取某一个对象的 class

                Class<?> klass = int.class;

                Class<?> classInt = Integer.TYPE;

        调用某个对象的 getClass() 方法

                StringBuilder str = new StringBuilder("123");

                Class<?> klass = str.getClass();

三、创建实例

        通过反射来生成对象主要有两种方式。

        使用Class对象的newInstance()方法来创建Class对象对应类的实例。

                Class<?> c = String.class;

                Object str = c.newInstance();

        先通过Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建实例。这

种方法可以用指定的构造器构造类的实例。

        //获取String所对应的Class对象

        Class<?> c = String.class;

        //获取String类带一个String参数的构造器

        Constructor constructor = c.getConstructor(String.class);

        //根据构造器创建实例

        Object obj = constructor.newInstance("23333");

        System.out.println(obj);

四、获取构造方法

        Constructor getConstructor(Class[] params) -- 获得使用特殊的参数类型的public构造函数(包括父类)

        Constructor[] getConstructors() -- 获得类的所有公共构造函数

        Constructor getDeclaredConstructor(Class[] params) -- 获得使用特定参数类型的构造函数(包括私有)

        Constructor[] getDeclaredConstructors() -- 获得类的所有构造函数(与接入级别无关)

        获取类构造器的用法与上述获取方法的用法类似。主要是通过Class类的getConstructor方法得到Constructor类的一个实例,而Constructor类有一个newInstance方法可以创建一个对象实例:

        public T newInstance(Object ... initargs)

五、调用方法

    获得方法信息的方法

        Method getMethod(String name, Class[] params) -- 使用特定的参数类型,获得命名的公共方法

        Method[] getMethods() -- 获得类的所有公共方法

        Method getDeclaredMethod(String name, Class[] params) -- 使用特写的参数类型,获得类声明的命名的方法

        Method[] getDeclaredMethods() -- 获得类声明的所有方法

当我们从类中获取了一个方法后,我们就可以用 invoke() 方法来调用这个方法。invoke 方法的原型为:

        public Object invoke(Object obj, Object... args)

六、利用反射创建数组

        数组在Java里是比较特殊的一种类型,它可以赋值给一个Object Reference 其中的Array类为

java.lang.reflect.Array类。

        我们通过Array.newInstance()创建数组对象,它的原型是:

public static Object newInstance(Class<?> componentType, int length);

六、获取泛型信息

        当我们对一个泛型类进行反射时,需要的到泛型中的真实数据类型,来完成如json反序列化的操作。此时需要通过Type 体系来完成。Type 接口包含了一个实现类(Class)和四个实现接口,他们分别是:

TypeVariable

        泛型类型变量。可以泛型上下限等信息;

ParameterizedType

        具体的泛型类型,可以获得元数据中泛型签名类型(泛型真实类型)

GenericArrayType

        当需要描述的类型是泛型类的数组时,比如List[],Map[],此接口会作为Type的实现。

WildcardType

        通配符泛型,获得上下限信息;

反射demo源码

```

import java.lang.reflect.Constructor;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

public class Reflect {

public static void main(String[] args) {

System.out.println("--------获取class类-----------");

        Person person =new Person();

        Class clazz = person.getClass();

        System.out.println(clazz);

        Class clazz1 = Person.class;

        System.out.println(clazz1);

        try {

Class clazz2 = Class.forName("com.example.Person");

            System.out.println(clazz2);

        }catch (ClassNotFoundException e) {

e.printStackTrace();

        }

System.out.println("---------获取构造方法-----------");

        getConstractor(clazz);

        System.out.println("------获取对象方法---------");

        getMethod(clazz);

        System.out.println("---------构造方法创建对象-------------");

        //创建Person对象

        try {

Constructor con = clazz.getDeclaredConstructor();

            //无参构造方法

            Object object = con.newInstance();

            System.out.println(object.toString());

            //指定参数构造方法

            Constructor con1 = clazz.getDeclaredConstructor(String.class, int.class);

            Object object1 = con1.newInstance("张三", 18);

            System.out.println(object1.toString());

            System.out.println("-------执行方法---------");

            try {

Method m = clazz.getDeclaredMethod("getName");

                //执行方法

                Object name = m.invoke(object1);

                System.out.println(name);

                //执行私有方法需要设置setAccessible

                Method m1 = clazz.getDeclaredMethod("toStr");

                m1.setAccessible(true);

                Object obj = m1.invoke(object1);

                System.out.println(obj);

                //执行完毕关闭

                m1.setAccessible(false);

            }catch (NoSuchMethodException e){

e.printStackTrace();

            }

}catch (NoSuchMethodException | InstantiationException |

IllegalAccessException | InvocationTargetException e) {

e.printStackTrace();

        }

}

private static void getConstractor(Class clazz) {

//获取所有公有构造方法

        Constructor[] cons = clazz.getConstructors();

        for (Constructor constructor : cons) {

System.out.println(constructor);

        }

System.out.println("------------------");

        try {

//获取指定参数的公有构造方法

            Constructor con = clazz.getConstructor(new Class[]{String.class, int.class});

            System.out.println(con);

        }catch (NoSuchMethodException e) {

e.printStackTrace();

        }

System.out.println("------------------");

        //获取所有构造方法

        Constructor[] declardcons = clazz.getDeclaredConstructors();

        for (Constructor constructor : declardcons) {

System.out.println(constructor);

        }

System.out.println("------------------");

        try {

//获取指定参数的所有构造方法

            Constructor con = clazz.getDeclaredConstructor();

            System.out.println(con);

        }catch (NoSuchMethodException e) {

e.printStackTrace();

        }

}

private static void getMethod(Class clazz){

//获取所有公有方法包含父类

        Method[] methods = clazz.getMethods();

        for (Method m:methods){

System.out.println(m);

        }

System.out.println("-----------------");

        try {

//获取指定名称的公有方法

            Method method = clazz.getMethod("getName");

            System.out.println(method);

        }catch (NoSuchMethodException e){

e.printStackTrace();

        }

System.out.println("------------------");

        //获取类的所有方法不包含父类

        Method[] methods1 = clazz.getDeclaredMethods();

        for (Method m:methods1){

System.out.println(m);

        }

System.out.println("------------------");

        try {

Method m = clazz.getDeclaredMethod("toStr");

            System.out.println(m);

        }catch (NoSuchMethodException e){

e.printStackTrace();

        }

}

}

class Person {

private Stringname;

    private int age;

    public Person() {

}

private Person(int age) {

this.age = age;

    }

public Person(String name) {

this.name = name;

    }

public Person(String name, int age) {

this.name = name;

        this.age = age;

    }

public StringgetName() {

return name;

    }

public void setName(String name) {

this.name = name;

    }

public int getAge() {

return age;

    }

public void setAge(int age) {

this.age = age;

    }

@Override

    public StringtoString() {

return "Person{" +

"name='" +name +'\'' +

", age=" +age +

'}';

    }

private StringtoStr() {

return "Person{" +

"name='" +name +'\'' +

", age=" +age +

'}';

    }

}

```

上一篇 下一篇

猜你喜欢

热点阅读