Java反射基础详述

1、Java反射(Reflection)是一种新的操作类中成员变量、构造方法和普通方法的机制,为了实现对成员变量、构造方法和普通方法的操作,我们需要借助Java自身提供的java.lang包下的Class类和java.lang.reflect包下的反射API 。

2、Class类是Java 反射机制的入口,封装了一个类或接口的运行时信息,通过调用Class类的方法可以获取这些信息。

Class类的四个特点

                               1、该类在java.lang包中;

                               2、 该类被final所修饰,即该类不可以被子类继承;

                               3、该类实现了Serializable接口;

                               4、该类的构造方法被private所修饰,即不能通过new关键字创建该类的对象;

Java反射基础详述_第1张图片

 

3、获取Class类实例化对象

可以用以下六种方法获取Class类实例化对象,这里创建了一个Student类用以实验。

package com.jd;

public class ClassTest {

    public static void main(String[] args) {

        //反射是一种新的操作类中的属性、构造方法和普通方法的机制

        Class clazz=null;
        //获取Class类实例化对象的六种方法
        //1、Class.forName(String classname[这个类的全名]);
        try {
            clazz = Class.forName("com.jd.Student");
            System.out.println(clazz.getName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }//检查时异常
        //2、类名.class
        clazz = Student.class;
        System.out.println(clazz.getName());
        //3、对象.getClass()
        clazz = new Student().getClass();
        System.out.println(clazz.getName());
        //4、基本数据类型对应的class对象:包装类.TYPE
        clazz = Integer.TYPE;
        System.out.println(clazz.getName());
        //5、数组类对应的class:元素类型[].class
        clazz = String[].class;
        System.out.println(clazz.getName());
        //6、某个类父类所对应的class对象
        try {
            clazz = Class.forName("com.jd.Student").getSuperclass();
            System.out.println(clazz.getName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

 运行结果

1、com.jd.Student
2、com.jd.Student
3、com.jd.Student
4、int
5、[Ljava.lang.String;
6、java.lang.Object

4、获取Class类对应类中声明的构造方法的几种方法

以Student类为例

package com.jd;

public class Student {

    public String name;

    public int number;

    public Student(){

    }

    public Student(String name,int number){//private
        this.name=name;
        this.number = number;
    }

    public void doHomeWork(String name){

        System.out.println(name+"正在做作业。。。");
    }
}

 获取构造方法

//获取某个类对应的Class类对象
        Class clazz = Student.class;
        //权限是public
        try {
            Constructor constructor = clazz.getConstructor();
            System.out.println(constructor.getName());
            constructor = clazz.getConstructor(String.class,Integer.TYPE);
            System.out.println(constructor.getName());
        } catch (Exception e) {
            e.printStackTrace();
        }

运行结果

无参:com.jd.Student
有参:com.jd.Student

1、Constructor[] getConstrutors():返回该Class对象表示类包含的所有public构造方法(不含继承)所对应Constructor对象数组。

2、Constructor getConstrutor(Class... parameterTypes):返回与该Class对象表示类中参数列表相匹配的public构造函数(不含继承)对应的Constructor对象。

注意这两种的访问权限是public,若将Student中的构造方法权限改为private则会报错。这时需要另外两种方法。

Java反射基础详述_第2张图片

1、Constructor[] getDeclaredConstructors():返回一个该Class对象表示类中声明的所有构造方法(不区分访问权限)对应的Constructor对象数组。

2、Constructor getDeclaredConstructor(Class... parameterTypes):返回与该Class对象表示类中定义的形参类型相匹配的构造方法(不区分访问权限)的Constructor对象。

//无权限限制
        try {
            Constructor constructor = clazz.getDeclaredConstructor();
            System.out.println(constructor.getName());
            constructor = clazz.getDeclaredConstructor(String.class,Integer.TYPE);
            System.out.println(constructor.getName());
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

运行结果

无参:com.jd.Student
有参:com.jd.Student

5、获取构造方法的信息

通过Constructor类某些方法可以获取某个构造方法的信息

 Class clazz = Student.class;
        try {
            Constructor constructor = clazz.getDeclaredConstructor(String.class,Integer.TYPE);
         
            //获取该构造方法来自哪一个类
            clazz = constructor.getDeclaringClass();
            System.out.println(clazz.getName());
            //获取修饰符
            int mod = constructor.getModifiers();
            String result = Modifier.toString(mod);
            System.out.println(result);
            //获取方法名称
            System.out.println(constructor.getName());
            //获取参数列表(以各个参数class类的形式)
            Class [] classes = constructor.getParameterTypes();
            for (Class zz:classes) {
                System.out.println(zz.getName());
            }

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

运行结果

来自类:com.jd.Student
修饰符:private
方法名:com.jd.Student
参数列表:java.lang.String
int

1、Class getDeclaringClass():返回声明Constructor对象对应构造方法的类的Class对象。

2、int getModifiers():以整数形式返回Constructor对象表示的构造函数的修饰符。

3、String getName() :以字符串形式返回Constructor对象所表示得构造方法的名称。

4、 Class[] getParameterTypes():返回由Constructor对象所表示的构造方法的形参类型对应Class对象组成的数组此 。如果构造方法没有参数,则数组长度为0。

 

通过Constructor类某些方法可以创建对象

void setAccessible(boolean flag):调用构造函数时是否忽略访问权限的影响,true表示忽略,false表示不忽略。

T newInstance(Object... initargs):使用此Constructor对象表示的构造方法来创建声明该构造方法类的新对象。initargs为传入该构造方法中的参数,如果该构造方法没有参数,则可设定为null或一个长度为0的数组。

Student类

package com.jd;

public class Student {

    public String name;

    public int number;

    private Student(){

    }

    private Student(String name,int number){
        this.name=name;
        this.number = number;
    }

    public void doHomeWork(){

        System.out.println(name+"正在做作业。。。"+number);
    }
}

操作构造方法——创建对象

Class clazz = Student.class;
        try {
            Constructor constructor = clazz.getDeclaredConstructor(String.class,Integer.TYPE);
            
            //设置权限为合法,及无视权限
            constructor.setAccessible(true);//因为此处有参构造方法访问权限为private
            Object object = constructor.newInstance("Tom",123);//创建对象,传入参数
            Student stu = (Student)object;
            stu.doHomeWork();

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

运行结果

Tom正在做作业。。。123

6、获取Class类对应类中声明的普通方法的几种方法

a、public 不仅限于本类还包括继承自父类的public方法

1、Method[] getMethods():返回一个该Class对象表示类或接口中所有public方法(含继承的)对应的Method对象数组。

2、Method getMethod(String methodName, Class... parameterTypes):返回与该Class对象表示类或接口中方法名和方法形参类型相匹配的public方法(含继承的)的Method对象

示例1

        //获取该对象所在类所有的public方法(含继承)
        Class clazz = Student.class;
        Method[] methods = clazz.getMethods();
        for (Method method:methods) {
            System.out.println(method.getName());
        }

运行结果

doHomeWork
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAll

示例2

        //获取某一个符合条件的方法
        Class clazz = Student.class;
        try {
            Method method = clazz.getMethod("doHomeWork");
            System.out.println(method.getName());//获取整个方法
        } catch (Exception e) {
            e.printStackTrace();
        }

运行结果

doHomeWork

b、不考虑权限问题,获取“本类”中声明的方法

1、Method[] getDeclaredMethods():返回一个该Class对象表示类或接口内声明定义的所有访问权限的方法(不含继承的)对应的Method对象数组。

2、Method getDeclaredMethod(String methodName,Class... parameterTypes) :返回与该Class对象表示类或接口中方法名和方法形参类型相匹配方法(不含继承的)对应的Method对象。

示例3

        //获取某一个符合条件的方法
        Class clazz = Student.class;
        try {
            Method [] methods = clazz.getDeclaredMethods();
        for (Method method:methods) {
            System.out.println(method.getName());
        }
        } catch (Exception e) {
            e.printStackTrace();
        }

运行结果

doHomeWork

6、获取Class类对应类中声明的普通方法的信息

Student类

package com.jd;

public class Student {

    public static int doHomeWork(String name,int number){
        System.out.println(name+"正在做作业。。。"+number);
        return 1;
    }
}

通过Method类某些方法可以获取某个普通方法的信息,

1、Class getDeclaringClass():返回声明Method对象表示方法的类或接口的 Class 对象。

2、int getModifiers():以整数形式返回此Method对象所表示方法的修饰符。应该使用Modifier类中的toString方法对所返回的整数进行解码(示例见备注)。

3、 Class getReturnType():返回Method对象所表示的方法的返回值类型所对应的Class对象。 String getName():返回方法名。

4、Class[] getParameterTypes():返回由Method对象代表方法的形参类型对应Class对象组成的数组。如果方法没有参数,则数组长度为 0。

5、Class[] getExceptionTypes():返回由Method对象表示方法抛出异常类型对应Class对象组成的数组。如果此方法没有在其 throws子句中声明异常,则返回长度为 0 的数组。

        //获取方法信息
        try {
            Method method = clazz.getMethod("doHomeWork",String.class,Integer.TYPE);
            System.out.println(method);//获取整个方法(不包含方法体)
            System.out.println(method.getDeclaringClass());//获取方法所在的类
            System.out.println(Modifier.toString(method.getModifiers()));//获取方法修饰符
            clazz = method.getReturnType();
            System.out.println(clazz.getName());//获取方法返回值
            System.out.println(method.getName());//获取方法名称
            Class [] clazzes = method.getParameterTypes();//获取方法参数类型
            for (Class zz:clazzes) {
                System.out.println(zz.getName());
            }

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

运行结果

整个方法:public static int com.jd.Student.doHomeWork(java.lang.String,int)
所在类:class com.jd.Student
修饰符:public static
返回类型:int
方法名:doHomeWork
参数类型:java.lang.String
int

操作普通方法——调用普通方法

1、void setAccessible(boolean flag):调用方法时是否忽略访问权限的影响,true表示忽略,false表示不忽略。

2、Object invoke(Object obj, Object... args):调用Method对象指代的方法并返回Object类型结果。obj表示该方法所在类实例,如果方法时静态的则obj可以指定为null; args表示传入该方法的参数,如果方法没有参数,则args数组长度可以为 0 或 null 。

       //操作普通方法
        try {
            Method method = clazz.getMethod("doHomeWork",String.class,Integer.TYPE);

            //反射中方法的调用不区分静态和非静态
            Object object = method.invoke(new Student(),"Tom",1);
            System.out.println(object);
        } catch (Exception e) {
            e.printStackTrace();
        }

运行结果

Tom正在做作业。。。1
1

 

 

你可能感兴趣的:(java,反射)