java反射
发布日期:2021-05-09 05:38:33 浏览次数:19 分类:原创文章

本文共 9294 字,大约阅读时间需要 30 分钟。

关联知识


在存在的编程语言中,大致分为动态语言与静态语言这两种。其中静态语言的代表是c,c++等,动态语言的代表则是js,python等。这两种语言的区别有很多,其中最重要的几点如下:



  • 静态语言的运行速度要比动态语言更快。

  • 动态语言的学习成本低于静态语言。

  • 动态语言的开发效率要高于静态语言。

  • .......
    java是介于静态语言与动态语言之间的一门编程语言。它在书写后,需要先进行编译,这是静态语言的特性,编译后生成字节码文件,运行时jvm会将字节码文件加载到内存中,jvm会对字节码文件进行解释执行,这是动态语言的特性。其实,在真实的java环境,要比这些更加复杂。


反射简介


java的反射其实就是java程序在运行时动态的操作java代码的一门技术。通过这门技术,我们可以在运行时分析类的信息与结构,也可以在运行时检查对象等。java反射是功能十分强大的一门技术,虽然我们平时开发时并不会经常用到它,但反射却是框架最基层的一门技术。学习好反射,利于后期学习各种框架。


Class类的简介与获取



  1. Class类是java十分重要的一个类,我们想要使用反射,那就离不开这个类。

  2. 当jvm加载一个class文件后,就会在内存中生成一个与之相对应的Class对象,这个对象保存着该class文件的全部信息。

  3. 同一类型的多个实例对象,它们的Class对象都是同一个,即在内存中,每一个Class对象都是独一无二的。

  4. Class对象的获取方式



  • 使用Class类的静态发放forName。如 Class c1 = Class.forName("java.lang.String");

  • 使用完整类名.class获取,如 Class c2 = String.class;

  • 使用实例对象的getClass()方法获取,如Class c3 = "sssss".getClass();

  • 基本数据类型可是使用类型名.TYPE获取。
    示例代码如下:


/** * @Classname Demo1 * @Date 2020/11/21 12:13 * @author hzq */package com.hzq.reflection;public class Demo1 {    public static void main(String[] args) throws ClassNotFoundException {        Class c1 = Class.forName("java.lang.String");        Class c2 = String.class;        Class c3 = "sssss".getClass();        Class c4 = "wwwww".getClass();        System.out.println(c1);        System.out.println(c2);        System.out.println(c3);        System.out.println(c4);        System.out.println(c3.equals(c4));        //输出结果//        class java.lang.String//        class java.lang.String//        class java.lang.String//        class java.lang.String//        true    }}

Class对象的使用


当我们获取了Class对象后,就可以通过调用Class对象的各种发放来对这个java类进行各种操作了。常见的操作有通过Class对象新建一个java类实例对象,操作字段,操作方法,获取各种信息等。


1. 新建对象


通过反射新建对象的方式有两种,方式1是通过Class对象调用newInstance()方法,该方法要求类必须有公共级别的无参构造器。方式2是通过Class对象调用getConstructor()方法获取该类的构造器,通过传入不同的参数来获取指定的构造器对象,然后通过构造器对象调用newInstance()方法来新建对象。
demo如下:


/** * @Classname Demo2 * @Date 2020/11/21 12:58 * @author hzq */package com.hzq.reflection;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;public class Demo2 {    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {        Class<?> c1 = Class.forName("com.hzq.reflection.User");        //方式1        User o1 = (User) c1.newInstance();        //方式2        Constructor<?> constructor = c1.getConstructor();        User o2 = (User) constructor.newInstance(null);        System.out.println(o1);        System.out.println(o2);        //输出结果//        User{name='null', age=null, sex='null'}//        User{name='null', age=null, sex='null'}    }}class User{    private String name;    private Integer age;    private String sex;    public User() {    }    public User(String name, Integer age, String sex) {        this.name = name;        this.age = age;        this.sex = sex;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Integer getAge() {        return age;    }    public void setAge(Integer age) {        this.age = age;    }    public String getSex() {        return sex;    }    public void setSex(String sex) {        this.sex = sex;    }    @Override    public String toString() {        return "User{" +                "name='" + name + '\'' +                ", age=" + age +                ", sex='" + sex + '\'' +                '}';    }}

2. 操作类的字段


demo示例:


/** * @Classname Demo3 * @Date 2020/11/21 13:14 * @author hzq */package com.hzq.reflection;import java.lang.reflect.Field;public class Demo3 {    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {        Class<?> c1 = Class.forName("com.hzq.reflection.User");        System.out.println("获取全部public字段,包括继承来的");        Field[] fields = c1.getFields();        for (Field field : fields) {            System.out.println(field.getName());        }        System.out.println("获取全部字段(不包括继承来的)");        fields = c1.getDeclaredFields();        for (Field field : fields) {            System.out.println(field.getName());        }        System.out.println("获取指定字段");        Field name = c1.getDeclaredField("name");        System.out.println(name.getName());        System.out.println("给通过反射创建的对象设置字段值");        Field age = c1.getDeclaredField("age");        Field sex = c1.getDeclaredField("sex");        User o = (User) c1.newInstance();        //因为字段都为private级别,不可以直接访问,所以我们需要关闭访问检查        name.setAccessible(true);        age.setAccessible(true);        sex.setAccessible(true);        name.set(o,"小明");        sex.set(o,"男");        age.set(o,18);        System.out.println(o);        System.out.println("获取字段name与age的类型");        Class<?> c2 = name.getType();        Class<?> c3 = age.getType();        System.out.println(c2);        System.out.println(c3);    }    //输出结果//    获取全部public字段,包括继承来的//    获取全部字段(不包括继承来的)//    name//    age//    sex//    获取指定字段//    name //    给通过反射创建的对象设置字段值//    User{name='小明', age=18, sex='男'}//    获取字段name与age的类型//    class java.lang.String//    class java.lang.Integer}

3.操作类的方法(包含构造方法)


demo示例:


/** * @Classname Demo4 * @Date 2020/11/21 15:58 * @author hzq */package com.hzq.reflection;import java.lang.reflect.Constructor;import java.lang.reflect.Method;import java.util.Arrays;import java.util.List;import java.util.stream.Collectors;public class Demo4 {    public static void main(String[] args) throws Exception{        Class<?> c1 = Class.forName("com.hzq.reflection.User");        //获取构造方法        Constructor<?> constructor = c1.getConstructor(String.class, Integer.class, String.class);        System.out.println("通过反射获取构造方法来创建对象");        User o = (User) constructor.newInstance("小红", 18, "女");        System.out.println(o);        System.out.println("获取类的全部方法对象,然后全部调用");        Method[] methods = c1.getDeclaredMethods();        //对方法对象的集合进行排序,是的set方法先被调用,然后再调用get方法        List<Method> collect = Arrays.stream(methods).filter(e -> {            if (e.getName().contains("set") || e.getName().contains("get")) {                if (e.getName().contains("getClass")) {                    return false;                }                return true;            } else {                return false;            }        }).sorted((x,y)->{            if (x.getName().contains("set")){                return -1;            }else {                return 1;            }        }).collect(Collectors.toList());        //对方法集合进行遍历调用        for (Method method : collect) {            String name = method.getName();            if (name.contains("set")){                if (name.contains("Name")){                    method.invoke(o,"小白");                }else if (name.contains("Age")){                    method.invoke(o,22);                }else {                    method.invoke(o,"男");                }            }else if (name.contains("get")){                Object value = method.invoke(o);                System.out.println(value);            }        }        //输出结果//        通过反射获取构造方法来创建对象//        User{name='小红', age=18, sex='女'}//        获取类的全部方法对象,然后全部调用//        小白//        22//        男    }}

4. 与注解配合使用


demo示例:


/** * @Classname Demo5 * @Date 2020/11/21 16:27 * @author hzq */package com.hzq.reflection;import java.lang.annotation.*;import java.lang.reflect.Field;public class Demo5 {    public static void main(String[] args) throws Exception{        Class<?> c1 = Class.forName("com.hzq.reflection.Person");        //获取全部类注解        Annotation[] annotations = c1.getDeclaredAnnotations();        for (Annotation annotation : annotations) {            //找出我们自定义的注解            if (annotation instanceof MyAnnotationType){                MyAnnotationType annotationType = (MyAnnotationType) annotation;                //输出注解的属性                System.out.println(annotationType.tableName());            }        }        //获取全部字段        Field[] fields = c1.getDeclaredFields();        for (Field field : fields) {            //获取字段上的注解            MyAnnotationField annotation = field.getAnnotation(MyAnnotationField.class);            //输出注解属性            System.out.println(annotation.fieldName());        }    }    //输出结果//    db_person//    db_name//    db_age//    db_sex}/** * @author admin * 标注在字段上的注解 */@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@interface MyAnnotationField {    String fieldName();}/** * @author admin * 标注在类上的注解 */@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@interface MyAnnotationType {    String tableName();}@MyAnnotationType(tableName = "db_person")class Person{    @MyAnnotationField(fieldName = "db_name")    private String name;    @MyAnnotationField(fieldName = "db_age")    private Integer age;    @MyAnnotationField(fieldName = "db_sex")    private String sex;    public Person() {    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Integer getAge() {        return age;    }    public void setAge(Integer age) {        this.age = age;    }    public String getSex() {        return sex;    }    public void setSex(String sex) {        this.sex = sex;    }}

ps:特别注意



  1. getDeclaredxxx方法获取的是只属于该类的全部方法或字段,getxxx方法获取的是该类全部公共访问权限的方法或字段,不包含私有的。

  2. 如果获取的字段或方法对象是私有的,无法直接进行访问,应该先关闭权限检查机制,调用setAccessible(true)方法并传入true进行关闭。

上一篇:mysql基础操作
下一篇:java注解

发表评论

最新留言

能坚持,总会有不一样的收获!
[***.219.124.196]2025年04月22日 16时05分50秒