java反射机制,以及对反射机制的了解
反射是什么?反射有什么用?我相信大家在开始学的时候都会有疑惑,直到如今我学的还不够深入只能简单的说说反射的作用,理论的我也听得很迷糊,接下来我就以几个例子来
写写反射的用处; 494696003群,有很多一起学习的人~不妨可以来耍耍;
* A反射概述
* JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
* 对于任意一个对象,都能够调用它的任意一个方法和属性;
* 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
* 要想解剖一个类,必须先要获取到该类的字节码文件对象。
* 而解剖使用的就是Class类中的方法,所以先要获取到每一个字节码文件对应的Class类型的对象。
* B:三种方式
* a:Object类的getClass()方法,判断两个对象是否是同一个字节码文件
* b:静态属性class,锁对象
* c:Class类中静态方法forName(),读取配置文件
* C:案例演示
* 获取class文件对象的三种方式
案例1:
package com.reflect2;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/*
* 利用反射来实现榨水果汁的例子
* */
public class Demo_reflect1 {
public static void main(String[] args) {
/*Juicer j=new Juicer();*/
try {
BufferedReader br=new BufferedReader(new FileReader("reflectFruit.txt"));
Class clazz=Class.forName(br.readLine());
Fruit f=(Fruit) clazz.newInstance();
f.squeeze();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
interface Fruit{
public void squeeze();
}
class Apple implements Fruit{
public void squeeze(){
System.out.println("榨出一杯苹果汁");
}
}
class Orange implements Fruit{
@Override
public void squeeze() {
System.out.println("榨出一杯橘子汁");
}
}
/*class Juicer{
public void juicer(Fruit f){
f.squeeze();
}
}
*/
这个是通过修改配置文件文件里面的内容来达到榨汁的一个功能,这也是反射的一个用处;
这样我们只需要修改配置文件里面的水果类名就可以达到我们想要的水果汁。
以上的clazz.clazz.newInstance()方法其实是采用了无参数的构造方法;那我们会想如果是一个类的有参构造我们怎么获取呢?
案例2:
这是person类中的构造和toString()方法方便我们等下好打印;
package com.reflect2;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import com.reflect.Entity.Person;
public class Demo3_Constructor {
public static void main(String[] args) {
try {
Class clazz=Class.forName("com.reflect.Entity.Person"); //这个地方我们把person类的地址放进去,得到一个该类的字节码文件;
Constructor con=clazz.getConstructor(String.class,String.class,int.class); //这个地方的参数不能赋予实际的值,因为还在反射阶段;
Person p=(Person) con.newInstance("张三","男",20); //我们在这里可以看到我们给Person赋予的实际的值
System.out.println(p);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
在这我们可以看得到我们之前赋予的值了;
接下来在之前的基础上我们进一步的去了解这个java反射的强大之处——————暴力反射!!!
俗话说在反射面前一切都是赤裸裸的(当然做不法之事的时候就别反射了!命要紧啊~哈哈)看代码!
案例3:
之前我们都是获取一个类的构造方法;接下来我们用java的反射来获取一个类的字段;
采用的方法是getField();
之前可能有朋友会问一个问题,我们怎么知道他有些什么字段呢?你在参数里面填了“name”,其实在这里我是为了方便用这个方法
其实在API里面还有一个方法就是getFields()方法 大家都知道在ENGLISH里面+s代表负数 在这里也不例外(其实在这里我想说一个想法,
因为这些语言编程都是国外的人发明的,如果是中国人发明的
我们学起来起码轻松了很多,有很多喜欢编程的人但是英语不行学起来很吃力也减少了很多出现天才的机会,
在我这里天才不是一定要各个方面都要很强,在某一个领域异于常人你就是天才!咳咳 扯远了回到正题)
按照这个方法我们打印P;你心里想到的肯定是这个这个人的名字被我们修改了~那么你来看看运行结果吧;
你肯定在想,我擦 怎么回事, 那么我们来看看异常是啥:说没有找到这个叫name的字段,你肯定很好奇我们不是找到了吗?肯定有name这个属性啊
其实在这里我们还没有进入正题,我们是暴力反射!暴力反射不暴力点怎么行呢?看代码你就知道了:
之前我们把person属性是私有了所以得不到~找不到也很正常,你肯定在想那我们怎么办呢?接下来就是java强大之处表现出来了!赤裸在它面前
public static void main(String[] args) {
try {
Class clazz=Class.forName("com.reflect.Entity.Person");
Constructor con=clazz.getConstructor(String.class,String.class,int.class);
Person p=(Person) con.newInstance("张三","男",20);
/*Field f=clazz.getField("name");
f.set(p, "李四");*/
Field f= clazz.getDeclaredField("name"); //这个地方就是我们暴力反射的关键declared! (公然的) 意思是获取到所有的不管是私有还是共有的 全部能得到
System.out.println(p);
你看这段代码,在这里你肯定会想,这下得到了吧!那我这里要告诉你一个很有趣的事情:当你对一个人有非法的思想的时候,
她肯定是不愿意的那么你就用强硬的得到,但是为什么在这里还是打印不出来呢?因为
还差一步没有走 就是你要对她用强的那么你就要褪去她的防备~(你懂得~),所以还差一步就是:
Class clazz=Class.forName("com.reflect.Entity.Person");
Constructor con=clazz.getConstructor(String.class,String.class,int.class);
Person p=(Person) con.newInstance("张三","男",20);
/*Field f=clazz.getField("name");
f.set(p, "李四");*/
Field f=clazz.getDeclaredField("name");
f.setAccessible(true); //这个地方就是褪去她的防备 嘿嘿 里面传一个true,意思是设置为通畅的
f.set(p, "李四");
System.out.println(p);
这样她就是属于你的了~~嘿嘿
接下来我们再一次来了解反射其他的能力,获取一个类中的方法,还是那个样子无论私有还是公有我们都有办法获取私有就加Declared,我这里用获得公有的做例子了
案例4:
这个是在person里面添加的一个无参的方法,等下我们在来一个有参的,方法是找女朋友哈(有没有跟我一样还是单手狗的~我这么英俊居然也单身了~唉 加油吧骚年英俊还要有钱啊~)
public static void main(String[] args) {
try {
Class clazz=Class.forName("com.reflect.Entity.Person");
Constructor con=clazz.getConstructor(String.class,String.class,int.class);
Person p=(Person) con.newInstance("张三","男",20);
/*Field f=clazz.getField("name");
f.set(p, "李四");*/
/*Field f=clazz.getDeclaredField("name");
f.setAccessible(true);
f.set(p, "李四");*/
Method m=clazz.getMethod("findGirlFriend"); //这个地方就是我们获取方法的代码 括号里面写方法名字,因为是无参的,参数可以不写
m.invoke(p); //这个地方是 让这个方法去执行,括号里面是填执行的对象~
我们来看看结果:
执行了person里面的方法;接下来我们来一个有参的方法:
public void findGirlFriend(int num){
System.out.println("今年找了"+num+"个女朋友");
}
在person里面重写一个findGirlFriend(int num)方法 带上参数;
我们来看看代码:
在上面的括号里面填上参数的字节码文件,因为还是在反射这个环节所以不能填实参,在下面invoke()方法里面填上对象 和 实际参数
接下来我们看下打印结果:
额~可能是我比较饥渴吧,我一下找了10个女朋友~ 哈哈 起是作为程序员我们是最厉害的就是没有的东西我们可以new 没有女朋友new一个出来 没有钱new一堆出来
看到这里我估计你们对反射有一定的了解了~那我们继续来个更有意思的,因为之前我们一般的认为在ArrayList<Integer> list=new ArrayList<Integer>(); 加了泛型
的集合里面添加只能是Integer类型的你加其他的会编译就报错,那么在这我们利用反射绕开这个编译的过程直接添加进去(原理就是,泛型只是在编译器起作用,一旦运行时期,泛型会被扔掉~
那么我们通过反射获取到list的字节码就已经是运行时期了,在这个时候我们再操作,这也验证了反射可以在运行时期对类进行得到、修改等):
案例5:
ArrayList<Integer> list=new ArrayList<Integer>();
list.add(111);
list.add(222);
try {
Class clazz=Class.forName("java.util.ArrayList"); //获取字节码文件 ArrayList存在于util包中
Method m=clazz.getMethod("add", Object.class); //我们需要获取到ArrayList的add()方法,add()方法的参数是object在API中写的是E 这的E也就是Object;
m.invoke(list, "abc"); //在这我们队list进行添加
这样我们就实现了往泛型为Intege的集合中添加abc~ 这个过程也叫泛型擦除也叫泛型反射~(是不是感觉之前的安全泛型也不过如此是吧~这就是反射的魅力)
好了,到了这 也快接近尾声了,但是也是一个难点~记得我刚开始的时候是有懵逼过的~那就是java反射的动态代理(代理的意思就是本来该自己做的事情让别人来帮你做)
例如:春节买票,你叫黄牛给你买 这就是代理:
案例6:我们先创建一个User借口 写2个抽象方法 添加和删除 因为动态代理是针对借口而言的
1)package com.proxy.reflect;
public interface User {
public void add();
public void delete();
}
2)写一个User的实现类~ 重写添加删除方法
package com.proxy.reflect;
public class UserImp implements User{
@Override
public void add() {
System.out.println("增添");
}
@Override
public void delete() {
System.out.println("删除");
}
}
3):这就是重点了 创建一个类去实现InvocationHandler 重写它里面的实现方法;
package com.proxy.reflect;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler{
private Object ob;
public MyInvocationHandler(Object ob){ //这个地方创建一个构造方法,方便将待会儿的需要代理的对象传进来
this.ob=ob;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("权限校验"); //这个地方就是代理需要做的事情
method.invoke(ob, args); //这里就是实现该方法参数为需要实现的代理对象和对象需要的参数(执行被代理ob对象的方法)
System.out.println("日志记录");
return null;
}
}
4):最后这里就是测试类
package com.proxy.reflect;
import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) {
UserImp ui=new UserImp(); //先创建User实现类对象
ui.add();
ui.delete();
System.out.println("-------------------"); //代理之前
MyInvocationHandler m=new MyInvocationHandler(ui); //我们需要创建一个代理实现的实现类(这里可以理解为处理者的实现类) 将我们需要代理的对象ui传进去
//这是一个静态的方法由proxy类名点直接调用,参数(类加载器(我们通过反射获取);需要一个开对象需要实现的借口(通过反射获取);最后需要将我们的处理者放进来m)
User u= (User)Proxy.newProxyInstance(ui.getClass().getClassLoader(), ui.getClass().getInterfaces(), m);
u.add();
u.delete();
}
}
那么我们来看看 代理之后的样子:
这样我们就完成了一个动态代理,下次谁需要代理直接可以用我就可以了~
到这里反射机制的概述和实现差不多了~反射机制的基础认识不难,但是需要调整好思维,我只是个才学不久的,说的不好勿喷呀~这是我的处女作~哈哈 希望对你们又所帮助~
java反射机制,以及对反射机制的了解的更多相关文章
- 【代码笔记】Java——远程监控、反射、代理、内省机制
远程控制的基本原理 远程控制(RemoteControl)拥有控制端和被控端双方. 控制方通过请求,取得对远端的操作,实现远端的事件回放功能,同时,应该看得到远端桌面的画面.而被控方必须在建立Serv ...
- Java程序语言的后门-反射机制
在文章JAVA设计模式-动态代理(Proxy)示例及说明和JAVA设计模式-动态代理(Proxy)源码分析都提到了反射这个概念. // 通过反射机制,通知力宏做事情 method.invoke(obj ...
- 深入理解java:1.1.1. 反射机制
反射 到底什么是反射(Reflection)呢? 反射有时候也被称为内省(Introspection),事实上,反射,就是一种内省的方式, Java不允许在运行时改变程序结构或类型变量的结构,但它允许 ...
- 【转】Java之 内存区域和GC机制
转自:Leo Chin 目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage ...
- Java运行时环境---ClassLoader类加载机制
背景:听说ClassLoader类加载机制是进入BAT的必经之路. ClassLoader总述: 普通的Java开发其实用到ClassLoader的地方并不多,但是理解透彻ClassLoader类的加 ...
- Java学习点滴——Class和反射
基于<Java编程思想>第四版 前言 我们要操作一个类实例对象时,一般都要先知道这个类有哪些方法或者成员变量.反射就是在我们不知道这个类有哪些方法或成员变量时,使用特定方式得到类的这些信息 ...
- 【Java】利用注解和反射实现一个"低配版"的依赖注入
在Spring中,我们可以通过 @Autowired注解的方式为一个方法中注入参数,那么这种方法背后到底发生了什么呢,这篇文章将讲述如何用Java的注解和反射实现一个“低配版”的依赖注入. 下面是我们 ...
- 转 Java虚拟机5:Java垃圾回收(GC)机制详解
转 Java虚拟机5:Java垃圾回收(GC)机制详解 Java虚拟机5:Java垃圾回收(GC)机制详解 哪些内存需要回收? 哪些内存需要回收是垃圾回收机制第一个要考虑的问题,所谓“要回收的垃圾”无 ...
- JAVA中的糕富帅技术——反射(一)
前言 突然发现好久没写博客了,前面写的都是关于Android的东西,今天心血来潮突然有一种冲动想写一篇基于JAVA技术的博客,别问我为什么?有钱.任性! 今天就来谈谈反射机制:学过JAVA的人不一定懂 ...
- 杨晓峰-Java核心技术-6 动态代理 反射 MD
目录 第6讲 | 动态代理是基于什么原理? 典型回答 考点分析 知识扩展 反射机制及其演进 动态代理 精选留言 Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAnd ...
随机推荐
- HBase的高可用(HA)
在公司写文档时候查到的一些资料,感觉对自己很有帮助,现在整理如下: 介绍 HBase是一个高可靠性.高性能.列存储.可伸缩.实时读写的分布式数据库系统,基于列的存储模式适合于存储非结构化数据. 适用场 ...
- maven学习(3)pom.xml文件说明以及常用指令
pom.xml文件的结构: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http:/ ...
- 从 Python 之父的对话聊起,关于知识产权、知识共享与文章翻译
一.缘起 前不久,我在翻译 Guido van Rossum(Python之父)的文章时,给他留言,申请非商业用途的翻译授权. 过程中起了点小误会,略去不表,最终的结果是:他的文章以CC BY-NC- ...
- Flink中watermark为什么选择最小一条(源码分析)
昨天在社区群看到有人问,为什么水印取最小的一条?这里分享一下自己的理解 首先水印一般是设置为:(事件时间 - 指定的值) 这里的作用是解决迟到数据的问题,从源码来看一下它如何解决的 先来看下wind ...
- 分享:个人APP(非企业资质)的微信登录方案
目前微信开放平台个人主体类APP不支持开通微信登录,那么个人开发者如何解决微信登录的问题呢?目前有一种替代方案是用微信小程序作为媒介来达到微信登录的目的. 微信小程序的登录无需企业资质,同时登录后返回 ...
- Java多线程之线程的暂停
Java多线程之线程的暂停 下面该稍微休息一下了呢……不过,这里说的是线程休息,不是我们哦.本节将介绍一下让线程暂停运行的方法. 线程Thread 类中的sleep 方法能够暂停线程运行,Sleep ...
- Leetcode之二分法专题-367. 有效的完全平方数(Valid Perfect Square)
Leetcode之二分法专题-367. 有效的完全平方数(Valid Perfect Square) 给定一个正整数 num,编写一个函数,如果 num 是一个完全平方数,则返回 True,否则返回 ...
- C#开发BIMFACE系列2 二次开发流程
系列目录 [已更新最新开发文章,点击查看详细] BIMFACE 平台是一个对外开放的平台,建筑行业的相关公司.软件公司或者有 BIM 业务需求的公司都可以注册成为开发者并使用其提供的强大功能. ...
- HDU4289Control 无向图拆点最大流
/* ** 无向图拆点,求最大流,最大流即为割点个数. */ #include <iostream> #include <cstdio> #include <cstrin ...
- 2017ACM总结
首先对自己表示强烈的谴责, 这个时间应该是打cf的时间, 没有想到我又秀到了自己, 放弃了CF, 23333, 菜鸡wxk. 高中刚毕业的时候,听大学生们跪求老师不要给挂科,当时想的是,哇上了大学就不 ...