博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java学习——Java动态性之反射机制(reflection)
阅读量:3942 次
发布时间:2019-05-24

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

Java学习——Java动态性之反射机制(reflection)

动态性:

  • 动态语言:程序在运行时,可以改变程序结构或者变量类型。典型的动态语言:Python、ruby、JavaScript等。
  • C、C++、Java不是动态语言,但是Java可以称之为准动态语言。但是Java有一定的动态性、我们可以利用反射机制、字节码操作获得类似于动态语言的特性。这样就使得Java更加灵活

反射机制:

  • 指的是在运行时再加载一些新的类
  • 程序在运行状态时,可以动态加载一个只有名称的类,对于任意一个已经加载的类都能知道这个类的所有信息(属性、方法);对于任何一个对象,都能调用它的任何一个属性和方法
  • 这个就是我们在反射中常用的一段代码,用来通过类名获取这个类的字节码对象
Class clazz = Class.forName("cn.xiyou.Scanner.MyTest");
  • 加载完类之后,在堆内存中就产生了一个class类型的对象(一个类只有一个class对象),这个对象包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像是一面镜子,透过这个镜子看到类的结构,所以,我们形象的称之为:反射。

利用反射获取相关信息:

先创建一个标准的实体类:

public class Student {    private String name;    private int age;    private int id;        public Student() {    }    public Student(String name, int age, int id) {        this.name = name;        this.age = age;        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }}

反射机制获取相关信息:

public class Test01 {    public static void main(String[] args) throws Exception {        /**         * 对象是表示或封装一些数据。         * 一个类被加载后,JVM会创建一个对应该类的Class对象,类的整个结构信息会被放到对应的Class对象中去         */        //利用反射获取类的信息(类名、属性、方法、构造器),注意:一个类只有一个Class对象        Class clazz = Class.forName("cn.反射机制.demo01.Student");        /*         *  1.获取类的名字         */        String clazzName = clazz.getName();//(包名+类名)        System.out.println(clazzName);        String clazzSimpleName = clazz.getSimpleName();//类名        System.out.println(clazzSimpleName);        System.out.println("----------------这是一个华丽的分割线----------------");        /*         * 2.获得属性信息         */        //获取public的属性        Field[] fields = clazz.getFields();        for (Field field : fields) {            System.out.println(field);        }        //获取所有的属性(不论public和private)        Field[] declaredFields = clazz.getDeclaredFields();        for (Field declaredField : declaredFields) {            System.out.println("属性:"+declaredField);        }        //获取某个属性(不论public和private)        Field name = clazz.getDeclaredField("name");        System.out.println(name);        System.out.println("----------------这是一个华丽的分割线----------------");        /*         *3.获取方法信息         */        //获得所有public的方法        Method[] methods = clazz.getMethods();        for (Method method : methods) {            System.out.println(method);        }        //获取所有的方法(不论public和private)        Method[] declaredMethods = clazz.getDeclaredMethods();        for (Method declaredMethod : declaredMethods) {            System.out.println("方法:"+declaredMethod);        }        //获取指定方法,参1:方法名,参2:传递的参数类型的class对象        Method declaredMethod = clazz.getDeclaredMethod("getAge");        System.out.println(declaredMethod);        Method declaredMethod1 = clazz.getDeclaredMethod("setAge", int.class);        System.out.println(declaredMethod1);        System.out.println("----------------这是一个华丽的分割线----------------");        /*         *4.获取构造方法信息         */        //获取所有的构造器        Constructor[] constructors = clazz.getDeclaredConstructors();        for (Constructor constructor : constructors) {            System.out.println("构造器:"+constructor);        }        //获取无参构造        Constructor constructor = clazz.getDeclaredConstructor(null);        System.out.println("无参构造:"+constructor);        //获取有参构造        Constructor constructor1 = clazz.getDeclaredConstructor(String.class,int.class,int.class);        System.out.println("有参构造:"+constructor1);    }}

通过反射动态操作:构造器、方法、属性:

/** * 通过反射动态操作:构造器、方法、属性 */public class Test02 {    public static void main(String[] args) throws Exception {        Class clazz = Class.forName("cn.反射机制.demo01.Student");        /*         * 1.通过反射动态操作构造方法,构造对象         */        //通过调用的是无参构造器构造对象        Student student = (Student) clazz.newInstance();        System.out.println(student);        //通过调用的是有参构造器构造对象        Constructor c = clazz.getDeclaredConstructor(String.class,int.class,int.class);        Student student2 = (Student) c.newInstance("张三", 18, 02165055);        System.out.println(student2.getName()+"==="+student2.getAge()+"==="+student2.getId());        /*         * 2.通过反射操作方法         */        //通过反射调用方法        Student student3 = (Student) clazz.newInstance();        Method method = clazz.getDeclaredMethod("setName", String.class);        method.invoke(student3,"李四");        /*         * 3.通过反射操作属性         */        Student student4 = (Student) clazz.newInstance();        Field f = clazz.getDeclaredField("name");        //setAccessible(true)意思是:这个属性关闭安全检查,直接可以访问(就可以访问private的属性了),提高效率        f.setAccessible(true);        f.set(student4,"王五");//给student4的name设置值        String sname = (String) f.get(student4);//获取student4的name值        System.out.println(sname);    }}
  • 我们还需要知道,反射固然强大,但是它在执行效率上还是不如正常执行。那么我们可以适当的使用setAccessible()打开关闭访问检查用来提高效率。

反射操作泛型(Generic)(了解):

Java中的泛型是在编译器给javac使用的,确保数据的安全性和免掉强制类型转换的麻烦。但是一旦编译完成,所有的泛型都会被擦除。那么Java新增了ParameterizedType,GenericArrayType,TypeVariable和WildcardType几种类型来代表不能被归一到class类中的类型但是又和原始类型齐名的类型。

  • ParameterizedType:表示一张参数化的类型,比如:Collection< String >
  • GenericArrayType:泛型数组类型
  • TypeVariable:是各种泛型变量的公共父接口
  • WildcardType:代表一种通配符类型表达式,比如?,?extends Number,?super Integer

反射操作注解(了解):

public class Test03 {    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {        Class clazz = Class.forName("cn.反射机制.demo01.Student");        //获取这个类的所有注解        Annotation[] annotations = clazz.getDeclaredAnnotations();        for (Annotation annotation : annotations) {            System.out.println(annotation);        }        //获取类指定注解的值        MyTable tb = (MyTable) clazz.getAnnotation(MyTable.class);        System.out.println(tb.value());        //获得类的属性的注解        Field f = clazz.getDeclaredField("name");        MyField myField = f.getAnnotation(MyField.class);        System.out.println(myField.name()+"--"+myField.type()+"--"+myField.length());    }}

转载地址:http://daiwi.baihongyu.com/

你可能感兴趣的文章
2.嵌入式开发环境搭建--(unbutu)系统
查看>>
Linux USB驱动分析之USB2.0协议分析
查看>>
关于iwpriv :no private ioctls 的问题
查看>>
SQL Server Union等操作时解决不同数据库字符集冲突的问题
查看>>
Linq GroupJoin(二)
查看>>
递归:访问页面的控件或文件夹的下文件
查看>>
DataGridView分頁控件
查看>>
Linq 使用entity framework查询视图返回重复记录的问题(转)
查看>>
项目中得到执行文件版本或其它信息
查看>>
WinForm DatagridView绑定大量数据卡顿的问题
查看>>
DataGridView或 DataTable导出到excel
查看>>
Ilist To DataTable
查看>>
SQL @@IDENTITY, IDENT_CURRENT,SCOPE_IDENTITY
查看>>
簡單工廠模式
查看>>
SQL Server的數據類型
查看>>
允許文本框輸入數字,退格鍵,小數點,負號
查看>>
SOLR的一些错误
查看>>
Linux下python升级步骤
查看>>
关于mongodb ,redis,memcache
查看>>
DEDECMS BUG汇总
查看>>