java反射


掌握通过反射获得类名
掌握通过反射实例化其他类的对象
掌握通过反射获得其他类中的全部构造函数
掌握获得其他类中的全部属性
掌握调用其他类中的方法
掌握通过反射操作属性
掌握通过反射取得数组的信息

Java 语言的反射机制

  1. 在Java运行时环境中,对于任意一个类对象,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?答案是肯定的。这种动态获取类的信息以及动态调用对象的方法的功能来自于Java 语言的反射(Reflection)机制。
  2. Java 反射机制主要提供了以下功能
    在运行时判断任意一个对象所属的类。
    在运行时构造任意一个类的对象。
    在运行时判断任意一个类所具有的成员变量和方法。
    在运行时调用任意一个对象的方法
    在这里插入图片描述
  3. Reflection 是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等权限)、superclass(例如Object)、实现interfaces(例如Serializable),也包括fields(属性)和methods(方法)的所有信息,并可于运行时改变fields内容或调用methods
  4. 一般而言,开发者社群说到动态语言,大致认同的一个定义是:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言
  5. 尽管在这样的定义与分类下Java不是动态语言,它却有着一个非常突出的动态相关机制:Reflection。这个字的意思是“反射、映象、倒影”,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。这种“看透class”的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语

Java Reflection API 简介

  • 在JDK中,主要由以下类来实现Java反射机制,这些类(除了Class类在java.lang包),其他类都位于java.lang.reflect包中
    Class类:代表一个类。
    Field 类:代表类的成员变量(成员变量也称为类的属性)。
    Method类:代表类的方法。
    Constructor 类:代表类的构造方法。
    Array类:提供了动态创建数组,以及访问数组的元素的静态方法
  • 在java.lang.Object 类中定义了getClass()方法,因此对于任意一个Java对象,都可以通过此方法获得对象的类型。Class类是Reflection API 中的核心类,它有以下方法
    getName():获得类的完整名字。
    getFields():获得类的public类型的属性。
    getDeclaredFields():获得类的所有属性。
    getMethods():获得类的public类型的方法。
    getDeclaredMethods():获得类的所有方法。
  • getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。
  • getConstructors():获得类的public类型的构造方法。
  • getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
  • newInstance():通过类的不带参数的构造方法创建这个类的一个对象。
  • (2)通过默认构造方法创建一个新对象
    Object objectCopy=classType.getConstructor(new Class[]{}).newInstance(new Object[]{});
    以上代码先调用Class类的getConstructor()方法获得一个Constructor 对象,它代表默认的构造方法,然后调用Constructor对象的newInstance()方法构造一个实例。
  • (3)获得对象的所有属性:
    Field fields[]=classType.getDeclaredFields();
    Class 类的getDeclaredFields()方法返回类的所有属性,包括public、protected、默认和private访问级别的属性

获取类中的成员方法和成员变量

public static void main(String[] args) {
        try {

            //第一种方法
            //根据类名.class属性获取该类的字节码类对象,该类对象是在虚拟机加载类时创建
            Class<Student> s1 = Student.class;
            Class<Student> s2 = Student.class;

            //第二种方法
            //调用class的静态方法,通过类的完整名称字符串forName,获取Class实例。?是不知道那个类
            Class<?> s3 = Class.forName("com.test.demo46_反射.test.Student");

            //第三种方法
            Student s = new Student();
            Class<? extends Student> s4 = s.getClass();

            //获取该类中所有的公共属性
            System.out.println("--------------------所有公共属性------------------");
            Field[] fields = s1.getFields();
            for (Field field : fields) {
                System.out.println(field.getName());
            }

            //获取类中的所有属性
            System.out.println("--------------------所有属性------------------");
            Field[] fields1 = s1.getDeclaredFields();
            Arrays.stream(fields1).forEach(ss -> {
                System.out.print("属性修饰词  "+ Modifier.toString(ss.getModifiers()));
                System.out.print("属性类型  "+ss.getType().getSimpleName());
                System.out.print("属性名称  "+ss.getName());
                System.out.println("\n");
            });

            //获取类中所有的公共方法
            System.out.println("--------------------所有公共方法------------------");
            Method[] methods = s1.getMethods();
            Arrays.stream(methods).forEach(ss -> {
                System.out.print("属性修饰词  "+ Modifier.toString(ss.getModifiers()));
                System.out.print("属性类型  "+ss.getReturnType().getSimpleName());
                System.out.print("属性名称  "+ss.getName());
                Class<?>[] parameterTypes = ss.getParameterTypes();
                System.out.print("--------------参数列表--------------");
                Arrays.stream(parameterTypes).forEach(sss->{
                    System.out.print("属性名称  "+sss.getSimpleName());
                });
                System.out.println("\n");
            });

            //获取类中所有的方法
            System.out.println("--------------------所有方法------------------");
            Method[] methods1 = s1.getDeclaredMethods();
            Arrays.stream(methods1).forEach(ss -> {
                System.out.print("属性修饰词  "+ Modifier.toString(ss.getModifiers()));
                System.out.print("属性类型  "+ss.getReturnType().getSimpleName());
                System.out.print("属性名称  "+ss.getName());
                System.out.println("\n");
            });


            System.out.println(s1 == s2);//true 单例模式
            System.out.println(s1 == s3);//true 单例模式
            System.out.println(s1 == s4);//true 单例模式
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

调用实例对象的构造方法

public static void main(String[] args) {
        Class<Student> c = Student.class;
        try {
//            //获取公共默认无参的构造方法
//            Constructor<Student> con = c.getConstructor();
//            //通过构造方法生成对象
//            Student student = con.newInstance();
//            System.out.println(student);


//            //获取公共有参数的构造方法
//            Constructor<Student> con = c.getConstructor(String.class,String.class,Integer.class);
//            Student student = con.newInstance("张三", "女的", 10);
//            System.out.println(student);

            //获取所有(包括私有)构造方法
            Constructor<Student> gdc = c.getDeclaredConstructor(String.class, String.class, Integer.class);
            gdc.setAccessible(true);//提供权限能够访问私有的方法
            Student student = gdc.newInstance("张三", "女的", 10);
            System.out.println(student);

        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

调用实例对象的成员方法

public static void main(String[] args) {
        try {
            //通过类的全限定名获取Class实例对象,
            Class<?> c = Class.forName("com.entor.test.demo46_反射.test.Student");

            //获取所有(包括私有)构造方法
            Constructor<?> gdc = c.getDeclaredConstructor(String.class, String.class, Integer.class);
            //创建类对象
            gdc.setAccessible(true);
            Object o = gdc.newInstance("张三", "男的", 10);

            //通过反射获取指定的方法
            Method setName = c.getDeclaredMethod("setName", String.class);
            Method getName = c.getDeclaredMethod("getName");
            getName.setAccessible(true);//私有方法需要设置访问权限

            //调用方法 o 为指定到那个对象
            Object in = setName.invoke(o,"乌龟");
            Object invoke = getName.invoke(o);
            System.out.println(invoke);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值