java反射机制,以及对反射机制的了解,如有差池欢迎点评(初学者勿喷)
本人学习java时间不长,但是对java很感兴趣,知道有博客园这个平台果断的注册,记录我的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的人不一定懂 ...
随机推荐
- UNIX环境高级编程——记录上锁(fcntl函数)以及死锁检测
一.记录锁 record locking 功能:当一个进程正在读或修改文件的某个部分时,它可以阻止其它进程修改同一文件区. 字节范围锁 byte-range locking 二.历史 flock函数, ...
- 《java入门第一季》之泛型引入
泛型的引入: 首先看一段代码体会自动报错. // 看下面这个代码 自动报错 String[] strArray = new String[3]; strArray[0] = "hello&q ...
- Ext JS 6正式版的GPL版本下载地址
下面是Ext JS 6正式版的GPL版本下载地址 https://www.sencha.com/legal/gpl/
- 总账:日记账导入流程(文档 ID 1591640.1)
文档内容 概要 历史记录 详细信息 GL_INTERFACE_CONTROL GL_INTERFACE_HISTORY GL_IMPORT_REFERENCES 摘要 ...
- 小强的HTML5移动开发之路(11)——链接,图片,表格,框架
来自:http://blog.csdn.net/dawanganban/article/details/18098193 一.HTML是什么? HTML(hypertext mark-uplangua ...
- webview与js交互
对于android初学者应该都了解webView这个组件.之前我也是对其进行了一些简单的了解,但是在一个项目中不得不用webview的时候,发现了webview的强大之处,今天就分享一下使用we ...
- EBS 可拓展的外部信用风险导入
DECLARE l_msg_count NUMBER; l_msg_data VARCHAR2(2000); l_return_status VARCHAR2(30); l_cc_hold_comme ...
- QGIS编译
一.准备工作 1.下载QGIS源码 最新版本的QGIS源码需要从git上下载.最新的发布版是2.0,下载地址见下.https://github.com/qgis/QGIS/tree/release-2 ...
- 【嵌入式开发】C语言 内存分配 地址 指针 数组 参数 实例解析
. Android源码看的鸭梨大啊, 补一下C语言基础 ... . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/detai ...
- Spring揭秘 读书笔记 三 bean的scope与FactoryBean
本书可作为王富强所著<<Spring揭秘>>一书的读书笔记 第四章 BeanFactory的xml之旅 bean的scope scope有时被翻译为"作用域&quo ...