Java之反射(言简意赅,小白易懂)

大家都知道Java的反射机制,是框架的灵魂所在,所以由此而知,学好反射是我们通往技术大牛的必经之路。

一.什么是反射?
    反射是Java中的一种动态调用技术,允许程序在运行过程中动态调用类的方法,从而提高代码的灵活性。
    正常情况:我们事先知晓我们要调用哪个方法,然后再去编写代码去调用该方法,再经过编译后运行。(静态调用)
    反射情况:我们事先不用知晓我们要调用哪个方法,而是在运行过程中通过其它变量等方式确定要调用的方法,再使用反射技术去调用。(动态调用技术)

        下图为静态调用与动态调用技术的图解: 

二.获取Class对象的三种方式:

Class:一个类被加载到内存后,JVM会创建一个对应的Class对象,且全局唯一,该对象的类型就是Class类型。Class对象是反射核心,因为可以通过Class对象获取类中所有的信息。

Class对象的三种获取方式
        1.类名.class
        2.对象名.getClass()
        3.Class.forName("类全路径");

        代码示例:

package com.bailiban.demo4;

public class Demo1 {
    /**
     * 获取Class对象的三种方式
     */
    public static void main(String[] args) throws ClassNotFoundException {
        //1、类名.class
        Class<Demo1> clazz1 = Demo1.class;
        //2、对象名.getClass()
        Class<? extends Demo1> clazz2 = new Demo1().getClass();
        //Class.forName("类的全路径")
        //Class.forName:加载某个类到内存中
        Class<?> clazz3 = Class.forName("com.bailiban.demo4.Demo1");
    }
}

三.通过Class对象获取类中的属性

一、通过Class对象获取类的构造方法

        1.clazz.getConstructor(参数类类型)        //获取指定参数的公共的构造方法
        2.clazz.getConstructors();                //获取所有的公共构造方法
        3.clazz.getDeclaredConstructor()        //获取所有的指定参数的构造方法
        4.clazz.getDeclaredConstructors()        //获取所有的构造方法
        
        如果是想调用无参构造,则不需要先获取Constructor对象,直接通过Class对象调用无参构造即可clazz.newInstance();

             1、获取指定参数类型的公共的构造方法

public class Demo2 {

    private Demo2(int a){

    }

    public Demo2(String a){

    }

    public static void main(String[] args) throws NoSuchMethodException {
        //1、获取Class对象
        Class<Demo2> clazz = Demo2.class;
        //2、获取构造方法

        //1、获取指定参数类型的公共的构造方法
        Constructor<Demo2> constructor = clazz.getConstructor(String.class);
//        Constructor<Demo2> constructor = clazz.getConstructor(int.class);
        System.out.println(constructor);
    }
}

        注意:此方法只能获取权限修饰符为public的构造方法,不能获取private的构造方法,否则出出现报错。

               2、获取所有的公共的构造方法

public class Demo2 {

    private Demo2(int a){
    }

    public Demo2(String a){
    }

    public static void main(String[] args) throws NoSuchMethodException {
        //1、获取Class对象
        Class<Demo2> clazz = Demo2.class;
        //2、获取构造方法

        //2、获取所有的公共的构造方法
        Constructor<?>[] constructors = clazz.getConstructors();
        System.out.println(Arrays.toString(constructors));
    }
}

            注意:此方法只能获取权限修饰符为public的构造方法,所以此方法只能获取参数类型为String的构造方法。

                运行结果:

                3、获取指定所有参数类型的构造方法(所有)

public class Demo2 {

    private Demo2(int a){
    }

    public Demo2(String a){
    }

    public static void main(String[] args) throws NoSuchMethodException {
        //1、获取Class对象
        Class<Demo2> clazz = Demo2.class;
        //2、获取构造方法

        //3、获取指定所有参数类型的构造方法(所有)
        Constructor<Demo2> constructor = clazz.getDeclaredConstructor(String.class);
        Constructor<Demo2> constructor1 = clazz.getDeclaredConstructor(int.class);
        System.out.println(constructor);
        System.out.println(constructor1);
    }
}

        注意:此方法可以获取权限修饰符为private的构造方法,即为所有。

                运行结果:

                4、获取所有的构造方法

public class Demo2 {

    private Demo2(int a){
    }

    public Demo2(String a){
    }

    public static void main(String[] args) throws NoSuchMethodException {
        //1、获取Class对象
        Class<Demo2> clazz = Demo2.class;
        //2、获取构造方法

        //4、获取所有的构造方法
        Constructor<?>[] constructors = clazz.getDeclaredConstructors();
        System.out.println(Arrays.toString(constructors));
    }
}

                运行结果:

                 5、如果是想调用无参构造,则不需要先获取Constructor对象,直接通过Class对象调用无参构造即可clazz.newInstance();

public class Demo2 {

//    private Demo2(int a){
//    }
//
//    public Demo2(String a){
//    }

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //1、获取Class对象
        Class<Demo2> clazz = Demo2.class;
        //2、获取构造方法

        //5、获取无参构造方法
        Constructor<Demo2> constructor = clazz.getDeclaredConstructor();
        //反射调用无参构造方法
        Demo2 demo2 = constructor.newInstance();
        System.out.println(demo2);
        //直接通过class对象调用无参构造方法
        Demo2 demo21 = clazz.newInstance();
        System.out.println(demo21);
    }
}

                运行结果:

四、通过Class对象获取类中的方法

我们也可以通过API获取对应的成员方法,常用API如下:

  • Method[] getDeclaredMethods(): 获取当前类声明的所有方法,包括private的方法。

  • Method[] getMethods(): 获取当前类声明的所有的公共(public)方法,包括继承过来的。

  • Method getDeclaredMethod(String name, Class<?>... parameterTypes): 获取当前类声明的某个方法,包括private的方法 。

  • Method getMethod(String name, Class<?>... parameterTypes): 获取当前类声明的某个公共(public)方法,包括继承过来的 。

代码示例:

class  Student{

    public void study(){
        System.out.println("好好学习,天天向上。");
    }

    private int exam(String name){
        System.out.println(name+"同学,认真考试");
        int score = 90 ;
        return score ;
    }

}

public class Demo04Reflect {

    public static void main(String[] args) throws Exception {
//      获取对应的Class对象
        Class clazz = Student.class ;
//      获取对象
        Student s = (Student) clazz.newInstance();
//       获取当前类定义的所有的属性
        Method[] methods = clazz.getDeclaredMethods();

//        遍历所有的方法
        for (Method m: methods) {
//          打印方法名称
            System.out.println(m.getName());
        }

//      获取方法名为study的方法
        Method study = clazz.getDeclaredMethod("study");
//      通过invoke方法调用这个s对象的study方法
        study.invoke(s);

//      获取方法名为exam的方法,参数类型要一致
        Method exam = clazz.getDeclaredMethod("exam",String.class);
//      私有方法,必须要设置访问权限
        exam.setAccessible(true);
//      通过invoke方法调用这个s对象的exam方法,接收方法调用的结果
        Integer result = (Integer) exam.invoke(s,"blb");
        System.out.println("考试分数为: "+result);

    }
}

tips:

  • 方法的调用依赖于某个对象,表示调用哪个对象方法。

  • 调用私有的方法需要设置权限setAccessible

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值