【java反射机制】java反射机制的学习

java的反射机制。获取Class实例的4种方式。通过反射获取类的属性、方法、注解、父类、接口等全部信息。通过反射调用类的属性、方法。

1.接口类 Person

package com.example.demo.springProxy.dynamicProxy;

public interface Person {
    void wakeup();
    void sleep();
}

2.父类 TFather

package com.example.demo.springProxy.dynamicProxy;

public class TFather {
    /**
     * 专家id
     */
    public  Long expertId;
    /**
     *专家名称(模糊匹配)
     */
    String name;


    public TFather (Long expertId, String name) {
        this.expertId = expertId;
        this.name = name;
    }

    public TFather () {
    }

    public void do1(){

    }
    public void do2(String x2){

    }
    public int do3(String x3){

        return 1;
    }
    private void doMy(){

    }

}

3.子类 Teacher,继承TFather,实现 Person接口

package com.example.demo.springProxy.dynamicProxy;

import java.io.File;
import java.io.FileNotFoundException;

public class Teacher extends  TFather implements Person  {

    private Integer id;
    private String name;
    public Teacher() {
    }
    public Teacher(String name) {
        this.name = name;
    }
    @Override
    public void wakeup() {
        System.out.println("老师"+name+"早晨醒来啦");
    }
    @Override
    public void sleep() {
        System.out.println("老师"+name+"晚上睡觉啦");
    }

    private int currentCount(){
        return 1;
    }

    private int currentNameUpdate(Integer id,String name){
        return 1+id;
    }

    private Long currentService(Integer id,String name)throws FileNotFoundException {
        return 1L;
    }
}

4.通过反射获取 类的所有信息

package com.example.demo.springProxy.dynamicProxy;

import java.lang.annotation.Annotation;
import java.lang.reflect.*;


public class ReflectTest {


    public static void main(String[] args) {


        try {
            useReflect();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 获取Class类实例的四种方法
     */
    public static void do1() {

        try {
            //方式一:调用运行时类的属性:.class
            Class clazz1 = Teacher.class;
            System.out.println(clazz1);//class com.example.demo.springProxy.dynamicProxy.Teacher
            //方式二:通过运行时类的对象,调用getClass()
            Person p1 = new Teacher("王教授");
            Class clazz2 = p1.getClass();
            System.out.println(clazz2);//class com.example.demo.springProxy.dynamicProxy.Teacher

            //方式三:调用Class的静态方法:forName(String classPath)
            Class clazz3  = Class.forName("com.example.demo.springProxy.dynamicProxy.Teacher");
            Class clazz5 = Class.forName("java.lang.String");
            System.out.println(clazz3);//class com.example.demo.springProxy.dynamicProxy.Teacher
            System.out.println(clazz5);//class java.lang.String

            System.out.println(clazz1 == clazz2);//true
            System.out.println(clazz1 == clazz3);//true

            //方式四:使用类的加载器:ClassLoader  (了解)
            ClassLoader classLoader = Test.class.getClassLoader();
            Class clazz4 = classLoader.loadClass("com.example.demo.springProxy.dynamicProxy.Teacher");
            System.out.println(clazz4);//class com.example.demo.springProxy.dynamicProxy.Teacher
            System.out.println(clazz1 == clazz4);//true
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }



    /**
     * 利用反射  创建对象
     */
    public static void test1()  {

        Class<Teacher> clazz = Teacher.class;
        /*
        newInstance():调用此方法,创建对应的运行时类的对象。内部调用了运行时类的空参的构造器。

        要想此方法正常的创建运行时类的对象,要求:
        1.运行时类必须提供空参的构造器
        2.空参的构造器的访问权限得够。通常,设置为public。


        在javabean中要求提供一个public的空参构造器。原因:
        1.便于通过反射,创建运行时类的对象
        2.便于子类继承此运行时类时,默认调用super()时,保证父类有此构造器

         */
        try {
            Person obj = clazz.newInstance();
            System.out.println(obj);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }


    }

    /**
     * 利用反射获取 类的所有信息
     */
    public static void test2(){

        Class clazz = Teacher.class;

        /*
        一、通过反射获取  成员变量(属性)
        1.getFields(): 类和父类    public访问权限的属性
        2.getDeclaredFields():类中声明的所有属性。(不包含父类中声明的属性)
         */
        Field[] fields = clazz.getFields();//getFields()  类和父类    public访问权限的属性
        Field[] declaredFields = clazz.getDeclaredFields();//getDeclaredFields()  类中声明的所有属性
        for(Field f : declaredFields){
            //1.权限修饰符
            String fMod = Modifier.toString(f.getModifiers());
            System.out.print( fMod+ "\t");

            //2.数据类型
            String  fType = f.getType().getName();
            System.out.print(fType + "\t");

            //3.变量名
            String fName = f.getName();
            System.out.print(fName);

            System.out.println();
        }

        /*
        二、通过反射获取 方法
        1.getMethods():类、所有父类中  public权限的方法
        2.getDeclaredMethods():类中声明的所有方法。(不包含父类中方法)
         */

        Method[] methods = clazz.getMethods();//类及其所有父类中声明为public权限的方法
        Method[] declaredMethods = clazz.getDeclaredMethods();//类中声明的所有方法。(不包含父类的方法)
        for(Method m : declaredMethods){
            //1.获取方法声明的注解
            Annotation[] annos = m.getAnnotations();
            for(Annotation a : annos){
                System.out.println(a);
            }

            //2.权限修饰符
            String mMod=Modifier.toString(m.getModifiers());
            System.out.print(mMod + "\t");

            //3.返回值类型
            String mReturnType=m.getReturnType().getName();
            System.out.print( mReturnType+ "\t");

            //4.方法名
            String methodName=m.getName();
            System.out.print(methodName);
            System.out.print("(");

            //5.形参列表(遍历)
            Class[] parameterTypes = m.getParameterTypes();
            for (int i = 0; i < parameterTypes.length; i++) {
                String paramType=parameterTypes[i].getName();
                if (i == parameterTypes.length - 1) {
                    System.out.print( paramType+ "  args_" + i);
                    break;
                }
                System.out.print(paramType + " args_" + i + ",");
            }
            System.out.print(")");

            //6.抛出的异常(遍历)
            Class[] exceptionTypes = m.getExceptionTypes();
            if(exceptionTypes.length > 0){
                System.out.print("throws ");

                for(int i = 0;i < exceptionTypes.length;i++){
                    String exceptionType=exceptionTypes[i].getName();
                    if(i == exceptionTypes.length - 1){
                        System.out.print(exceptionType);
                        break;
                    }
                    System.out.print(exceptionType + ",");
                }
            }
            System.out.println();
        }

        /*
        三、通过反射获取  构造器
         */
        //getConstructors():获取当前运行时类中声明为public的构造器
        Constructor[] constructors = clazz.getConstructors();
        for(Constructor c : constructors){
            System.out.println(c);
        }
        System.out.println();

        //getDeclaredConstructors():获取当前运行时类中声明的所有的构造器
        Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
        for(Constructor c : declaredConstructors){
            System.out.println(c);
        }


        /*
        四、通过反射获取 当前类的父类
         */
        Class superclass = clazz.getSuperclass();//普通父类
        System.out.println(superclass);

        Type genericSuperclass = clazz.getGenericSuperclass();//带泛型的父类
        System.out.println(genericSuperclass);

          /*
        五、通过反射获取  当前类实现的接口
         */
        Class[] interfaces = clazz.getInterfaces();
        for(Class c : interfaces){
            System.out.println(c);
        }

        System.out.println();
        //获取运行时类的父类实现的接口
        Class[] interfaces1 = clazz.getSuperclass().getInterfaces();
        for(Class c : interfaces1){
            System.out.println(c);
        }


        /*
        六、通过反射获取  当前类所在包
         */
        Package pack=clazz.getPackage();
        System.out.println(pack);

        /*
        七、通过反射获取  当前类声明的注解
         */
        Annotation[] annos=clazz.getAnnotations();
        for (Annotation anno : annos) {
            System.out.println(anno);
        }
    }


    /**
     * 通过反射  调用运行时类的指定结构
     */
    public static void useReflect() throws InstantiationException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {

        /*
        关于setAccessible方法的使用

⭕ Method和Field、Constructor对象都有setAccessible()方法。

⭕ setAccessible启动和禁用访问安全检查的开关。

⭕ 参数值为true则指示反射的对象在使用时应该取消Java语言访问检查。

⭕ 提高反射的效率。如果代码中必须用反射,而该句代码需要频繁的被 调用,那么请设置为true,使得原本无法访问的私有成员也可以访问,
   参数值为false则指示反射的对象应该实施Java语言访问检查。
         */

        /*
        1. 调用运行时类中指定的属性
         */

        Class clazz=Teacher.class;
        //通过反射 创建运行时类的对象
        Teacher p=(Teacher)clazz.newInstance();

        // 1.getDeclaredField(String fieldName):获取运行时类中指定变量名的属性
        Field name=clazz.getDeclaredField("name");
        //2.保证当前属性是可访问的
        name.setAccessible(true);
        //3.获取、设置指定对象的此属性值
        name.set(p,"test");
        System.out.println(name.get(p));


        /*
        2. 调用运行时类中的指定的方法
         */

        //1.获取指定的某个方法getDeclaredMethod():参数1 :指明获取的方法的名称  参数2:指明获取的方法的形参列表
        Method method=clazz.getDeclaredMethod("currentNameUpdate",Integer.class,String.class);
        //2.保证当前方法是可访问的
        method.setAccessible(true);
        //3. 调用方法的invoke():参数1:方法的调用者  参数2:给方法形参赋值的实参 ,invoke()的返回值即为对应类中调用的方法的返回值
        Object returnValue=method.invoke(p,10,"uu");
        /*
        Object invoke(Object obj, Object … args)
说明:
⭕ Object 对应原方法的返回值,若原方法无返回值,此时返回null
⭕ 若原方法若为静态方法,此时形参Object obj可为null
⭕ 若原方法形参列表为空,则Object[] args为null
⭕ 若原方法声明为private,则需要在调用此invoke()方法前,显式调用 方法对象的setAccessible(true)方法,将可访问private的方法。
         */
        System.out.println(returnValue);



        /*
        3 .获取指定的构造器

         */

        //1.getDeclaredConstructor():参数:指明构造器的参数列表
        Constructor constructor = clazz.getDeclaredConstructor(String.class);
        //2.保证此构造器是可访问的
        constructor.setAccessible(true);
        //3.调用此构造器创建运行时类的对象
        Person per = (Person) constructor.newInstance("Tom");
        System.out.println(per);

    }


}

5.感谢大佬的文章,欢迎大家去膜拜大佬,参考链接如下
java反射机制

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值