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

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

说到反射机制,第一次接触的人可能会比较懵,反射?什么反射?怎么反射?反射是干嘛的?下面我将在这篇文章中讲讲Java的反射机制


不过在这之前,还有一个问题需要解决,标题名中的动态性,说起动态性,我先介绍介绍动态语言和静态语言

静态语言

  静态语言是在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型。 例如:C++、Java、Delphi、C#等。

动态语言

  动态语言是在运行时确定数据类型的语言。变量使用之前不需要类型声明,通常变量的类型是被赋值的那个值的类型。 例如PHP/ASP/Ruby/Python/Perl/ABAP/SQL/JavaScript/Unix Shell等等。并且动态语言,是指程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化。

  这时可能你就会有疑问了,既然Java属于静态语言,又怎么会有动态性?其一就是Java存在与动态性相关的机制:反射机制。Java通过反射机制,可以在程序运行时加载,探知和使用编译期间完全未知的类,并且可以生成相关类对象实例,从而可以调用其方法或则改变某个属性值。所以JAVA也可以算得上是一个半动态的语言


 

下面来讲讲反射机制

  反射机制概念

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

  反射的原理在于Class对象

    看一看程序加载的过程

从图中大概可以看出反射是干什么用的了,那接下来就讲讲有关反射的其他方面

  反射的API

    反射API用来生成JVM中的类、接口或则对象的信息。

    - Class类:反射的核心类,可以获取类的属性,方法等信息。
    - Field类:Java.lang.reflec包中的类,表示类的成员变量,可以用来获取和设置类之中的属性值。
    - Method类: Java.lang.reflec包中的类,表示类的方法,它可以用来获取类中的方法信息或者执行方法。
    - Constructor类: Java.lang.reflec包中的类,表示类的构造方法。

 


 

下面就来讲讲怎么使用反射了  

1.步骤

  • 获取想要操作的类的Class对象
  • 调用Class类中的方法
  • 使用反射API来操作这些信息

 2.获取Class对象的方法

//假设我们有一个Student类方法一、(推荐)    Class clas = Class.forName("first.Student");//“”里写的是类的全路径方法二、    Student stu = new Student();    Class clas = stu.getClass();方法三、    Class clas = Student.Class;

可以试试用两个不同的方法获取clas1和clas2,然后System.ou.println(clas1==clas2)看看会输出什么,原因在图上

3.获取构造方法、字段、main方法并调用

Student.java

public class Student {    public String name;    protected int age;    char sex;    private String phoneNum;        public static void main(String[] args) {        System.out.println("main方法执行了。。。");    }    //---------------构造方法-------------------    Student(String str) {        System.out.println("(默认)的构造方法 s = " + str);    }    // 无参构造方法    public Student() {        System.out.println("调用了公有、无参构造方法执行了。。。");    }    // 有一个参数的构造方法    public Student(char name) {        System.out.println("姓名:" + name);    }    // 有多个参数的构造方法    public Student(String name, int age) {        this.name=name;this.age=age;        System.out.println("姓名:" + name + "年龄:" + age);// 这的执行效率有问题,以后解决。    }    // 受保护的构造方法    protected Student(boolean n) {        System.out.println("受保护的构造方法 n = " + n);    }    // 私有构造方法    private Student(int age) {        System.out.println("私有的构造方法   年龄:" + age);    }        public String toString() {        return "Student [name=" + name + ", age=" + age + ", sex=" + sex                + ", phoneNum=" + phoneNum + "]";    }}

Constructors.java(构造方法)

package first;import java.lang.reflect.Constructor;public class Constructors {    public static void main(String[] args) throws Exception {                Class clas=Class.forName("first.Student");                System.out.println("所有公有构造方法");        Constructor[] conArry=clas.getConstructors();        for(int i=0;i

输出

所有公有构造方法public first.Student(char)public first.Student()public first.Student(java.lang.String,int)所有的构造方法protected first.Student(boolean)private first.Student(int)public first.Student(char)public first.Student()first.Student(java.lang.String)public first.Student(java.lang.String,int)获取公有无参的构造方法con=public first.Student()调用了公有、无参构造方法执行了。。。获取私有构造方法,并调用public first.Student(char)姓名:a

Fields.java(字段)

package first;import java.lang.reflect.Field;public class Fields {    public static void main(String[] args)throws Exception {        // TODO Auto-generated method stub        Class StuClass=Class.forName("first.Student");                System.out.println("获取所有公有的字段");        Field[] fieldArry=StuClass.getFields();        for(Field f:fieldArry) {            System.out.println(f);        }        System.out.println("获取所有的字段(包括私有、受保护、默认的)");        fieldArry=StuClass.getDeclaredFields();        for(Field f:fieldArry) {            System.out.println(f);        }        System.out.println("获取公有字段并调用");        Field f = StuClass.getField("name");        System.out.println(f);        Object obj=StuClass.getConstructor().newInstance();        StuClass.getConstructor(String.class,int.class).newInstance("a",10);        f.set(obj, "b");        Student stu=(Student)obj;        System.out.println(stu.name);                System.out.println("获取私有字段并调用");        f = StuClass.getDeclaredField("phoneNum");        System.out.println(f);        f.setAccessible(true);//暴力反射,解除私有限定        f.set(obj, "18888889999");        System.out.println("验证电话:" + stu);    }    }

输出

获取所有公有的字段public java.lang.String first.Student.name获取所有的字段(包括私有、受保护、默认的)public java.lang.String first.Student.nameprotected int first.Student.agechar first.Student.sexprivate java.lang.String first.Student.phoneNum获取公有字段并调用public java.lang.String first.Student.name调用了公有、无参构造方法执行了。。。姓名:a年龄:10b获取私有字段并调用private java.lang.String first.Student.phoneNum验证电话:Student [name=b, age=0, sex=

Main.java

package first;import java.lang.reflect.Method;public class Main {    public static void main(String[] args) {        try {            // 1、获取Student对象的字节码            Class clazz = Class.forName("first.Student");            // 2、获取main方法            Method methodMain = clazz.getMethod("main", String[].class);// 第一个参数:方法名称,第二个参数:方法形参的类型,            // 3、调用main方法            // methodMain.invoke(null, new String[]{"a","b","c"});            // 第一个参数,对象类型,因为方法是static静态的,所以为null可以,第二个参数是String数组            // 这里拆的时候将 new String[]{"a","b","c"} 拆成3个对象。。。所以需要将它强转。            methodMain.invoke(null, (Object) new String[] {});// 方式一            // methodMain.invoke(null, new Object[]{new String[]{"a","b","c"}});//方式二        } catch (Exception e) {            e.printStackTrace();        }    }}

未完待续。。。。。

 

 

参考文章:

 

转载于:https://www.cnblogs.com/csu-lmw/p/9676170.html

你可能感兴趣的文章
云计算助力CDN加速
查看>>
iphone开发之多线程NSThread和NSInvocationOperation
查看>>
MFMailComposeViewController 发邮件
查看>>
velocity 模板解析类
查看>>
HTTP以及HTTPS协议
查看>>
Browser:浏览器版本判断类
查看>>
MyEclipse Servers视窗出现“Could not create the view: An unexpected exception was thrown”错误解决办法...
查看>>
伪类和伪元素
查看>>
jquery
查看>>
Day 3:模块结构和布局
查看>>
PWP+Nginx 集成环境下载
查看>>
【整理】RabbitMQ publish方法中的immediate和mandatory属性
查看>>
JAVA CAS原理深度分析
查看>>
权限模型
查看>>
如何配置 Log4J 只保留最近七天的日志文件
查看>>
Python 类与元类的深度挖掘 II
查看>>
prometheus收集springboot指标
查看>>
global gtags的配置
查看>>
iOS开发 — Quartz 2D知识点应用 (制作了一个Demo,源代码)
查看>>
Creating a Windows Image on OpenStack
查看>>