博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java反射机制——学习总结
阅读量:4290 次
发布时间:2019-05-27

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

环球优教
2016-10-18 20:51

前几天上REST课,因为涉及到Java的反射机制,但是老师当时只是带过一下,没有细讲,周末找了些资料来学习,现在总结一下,加深印象。

什么是反射机制?

参考百度百科对java反射机制的定义:

“JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。”

我们通过一些例子,更好理解反射机制。

Class类

我们知道Java是一门面向对象语言,在Java的世界里,万物皆为对象,比如我们有一个Person类:

public class Person {}

我们创建一个Person类的实例,Person person = new Person; 那么这个person,就是Person类的实例对象。

那么既然万物都为对象,所以类也是对象。

类是什么的对象呢?类是Class类的对象,表示方式有三种:

//第一种,任何一个类都有一个隐含的静态成员变量classClass c1 = Person.class;//第二种,已经知道该类的对象,通过getClass获得Class c2 = person.getClass;//第三种,Class类的forName方法Class c3 = Class.forName("Person");//这里,c1,c2,c3都是Class类的实例,我们称c1, c2 ,c3为Person类的类类型//不难看出,c1 == c2结果是true, c2 == c3结果也是true

通过类的类类型,我们经常会用到的方法就是newInstance方法,通过该方法可以创建该类的实例:

Person personA = new Person; //直接new一个实例Person personB = Person.class.newInstance; //通过newInstance方法获得Person的实例//在学习JAVAEE时候,newInstance方法我们最常见于获取数据库驱动Class.forName("com.mysql.jdbc.Driver").newInstance;//需要注意的是,在使用newInstance方法的前提是该类必须要有无参构造方法

动态加载类:

编译时刻加载类称为静态加载,运行时刻加载类称为动态加载,使用new方法新建实例即为静态加载类,在编译时候就要加载全部类。这里我们举一个例子:

为了更好的区分编译和运行,我们不适用IDE工具,而使用记事本来实现这个例子:

//我们举女娲造人的例子,创建一个CreatePerson类public class CreatePerson {    public static void main(String[] args) {        if(args[0].equalsIgnoreCase("man")) {  //如果从命令行传入的参数为man 则创建Man的实例并调用say方法 new Man.say;        }        if(args[0].equalsIgnoreCase("woman")) {  //如果从命令行传入的参数为woman 则创建Woman的实例并调用say方法 new Woman.say;        }    }}//CreatePerson类用到了2个类,分别是Man和Woman。//但是我们现在只创建Man类public class Man {    public void say {        System.out.println("I am a man !");    }}

我们在CMD中编译CreatePerson,看看会发生什么:

Java反射机制——学习总结

提示我们找不到Woman这个类。这就是静态加载,在编译时刻需要加载全部类。那么问题来了,如果我要写一个程序,里面有100个功能,这100个功能分别由100个类实现,那么一旦缺少一个类,这整个程序是不是就不能用了。

为了解决这个问题,我们可以使用动态加载。我们把上面这个例子改一下:

//创建一个Person接口public interface Person {    void say;}//修改Man类,继承Person接口public class Man implements Person{    public void say {        System.out.println("I am a man !");    }}//修改CreatePerson类,实现动态加载类public class CreatePerson{    public static void main(String[] args) {                try{ //动态加载类 Class c = Class.forName(args[0]); //通过类的类类型,创建该类实例对象 Person person = (Person)c.newInstance; person.say;         } catch(Exception e) { e.printStackTrace;        }    }}

这个时候,我们再进行编译:

没有报错了,那么我们继续把Man编译,再运行一下:

如果我们在命令行中输入的参数是Woman呢?

Java反射机制——学习总结

抛出ClassNotFoundException异常。因为我们并没有创建Woman类,所以如果以后需要创建Woman类实例,我们只需要新建一个Woman类,并实现Person接口就行了。

通过反射机制,获得类的信息

在Java反射机制的定义中有:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法。下面是一个实例:

import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;public class ClassUtil {    /**     * 获取成员函数的信息     */    public static void getClassMethodMessage(Object obj) {        Class c = obj.getClass;        //获取类的名称        //System.out.println(c.getName);                /**         *          * Method类,方法对象         *getMethods方法获得所有public的方法,包括继承而来         *getDeclaredMethods是获取该类自己的声明的方法         */        Method ms = c.getMethods;        for(int i = 0; i < ms.length; i++) { //得到方法的返回值类型的类类型 Class returnType = ms[i].getReturnType; System.out.print(returnType.getName + " "); //得到方法的名称 System.out.print(ms[i].getName + "("); //获取参数类型 Class paramTypes = ms[i].getParameterTypes; for(Class class1:paramTypes) { System.out.print(class1.getName + ","); } System.out.println(")");        }                    }    public static void getFieldMessage(Object obj) {        Class c = obj.getClass;                /**         * 成员变量也是对象         * java.lang.reflect.Field         *          */        Field fs = c.getDeclaredFields;        for(Field field:fs) { //得到成员变量类型的类类型 Class fieldType = field.getType; String typeName = fieldType.getName; //得到成员变量的名称 String fieldName = field.getName; System.out.println(typeName + " " + fieldName);         }    }        public static void printConMessage(Object obj) {        Class c = obj.getClass;        /**         * 构造函数也是对象         *          */        Constructor cs = c.getConstructors;        for (Constructor constructor : cs) { System.out.print(constructor.getName + "("); //获取构造函数参数列表------>参数列表的参数类型 Class paramType = constructor.getParameterTypes; for (Class class1 : paramType) { System.out.print(class1.getName + ","); } System.out.println(")");        }            }        public static void main(String[] args) {        String s = "hello";        getFieldMessage(s);        ClassUtil.printConMessage(s);        getClassMethodMessage(s);    }}

方法的反射操作

可以通过方法的反射操作实现方法的调用:

import java.lang.reflect.Method;public class MethodDemo1 {    public static void main(String[] args) {        //要获取print(int, int)        //要获取类的方法就要获取类的信息,获取类的信息就要获取类的类类型        A a1 = new A;        Class c = a1.getClass;        //2,获取方法 名称和参数列表        //getMethod获取的是public的方法        try { Method m = c.getDeclaredMethod("print", int.class,int.class);  //方法的反射操作 //a1.print(10, 20);方法的反射操作,用m来进行方法调用和前者效果一致 Object obj = m.invoke(a1, 10,20);//如果方法有返回值返回值,没有就null          } catch (Exception e) {  e.printStackTrace;        }    }        }class A {    public void print(int a , int b) {        System.out.println(a + b);    }        public void print(String a , String b) {        System.out.println(a.toUpperCase + "," + b.toUpperCase);    }}

以上就是我对Java反射机制的学习和理解,如果有错误,望指出,以便及时更正!谢谢!

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

你可能感兴趣的文章
Thrift学习(一)协议基础
查看>>
Thrift学习(二)协议架构
查看>>
Thrift学习(三)协议通信实现
查看>>
Thrift学习(四)通信实现(优化)
查看>>
用scrapy写爬虫(七)存储数据
查看>>
用scrapy写爬虫(八)中间件的应用
查看>>
Mac下安装JMeter
查看>>
Yar 搭建RPC服务
查看>>
PHP 代码简洁之道
查看>>
架构设计之——域名设计
查看>>
PHP设计模式之——观察者模式
查看>>
php设计模式之——门面模式
查看>>
Laravel 项目加速指南
查看>>
Chrome 扩展开发教程
查看>>
php常用代码片段
查看>>
Git 分支开发规范
查看>>
UMLet使用教程
查看>>
UML类图详解
查看>>
SSH与SSM的组成及其区别
查看>>
阿里巴巴为什么能抗住90秒100亿?看完这篇你就明白了!
查看>>