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的人不一定懂 ... 
随机推荐
- Cocos2D:塔防游戏制作之旅(五)
			打开HelloWorldLayer.h文件,添加以下实例变量(在@interface行的花括号之后): NSMutableArray *towerBases; 将HelloWorldLayer.m文件 ... 
- Dynamics CRM2013  定制你的系统登录后的首页面
			在2013中个性设置中又多了一个新的,更好的增强了用户体验,对于特定的用户而言只需要使用系统的一小块功能,所以很多用户进入 系统只需要显示跟自己业务相关的功能页面即可. 点右上角的齿轮进入选项,在常规 ... 
- Using mysqldump for Backups(备份还原数据库实例及参数详细说明)
			官网mysqldump命令如下: Using mysqldump for Backups https://dev.mysql.com/doc/refman/5.7/en/using-mysqldump ... 
- ECMAScript 6之变量的解构赋值
			1,数组的解构赋值 基本用法 ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring). 以前,为变量赋值,只能直接指定值. var a = 1; va ... 
- Dynamics CRM 通过OData查询数据URI中包含中文的情况
			filter条件如下"?$filter=new_name eq '采购主管' and new_entityname eq 'new_purchaseenquiry' ",如果用这个 ... 
- SpriteBuilder中如何平均拉伸精灵帧动画的距离
			首先要在Timeline中选中所有的精灵帧,可以通过如下2种的任意一种办法达成: 1按下Shift键的同时鼠标单击它们 2鼠标在Timeline空白区拖拽直到拉出的矩形包围住所有精灵帧方块后放开鼠标. ... 
- 【一天一道LeetCode】#7. Reverse Integer
			一天一道LeetCode系列 (一)题目 Reverse digits of an integer. Example1: x = 123, return 321 Example2: x = -123, ... 
- 使用swift语言进行IOS应用开发
			在Swift中能够直接使用Objective-C语言提供的api (包括系统框架与自己的定制代码),也能够在Objective-C中使用Swift提供的类和api ,还能够在一个工程中同时混合使用Sw ... 
- sql记录查询重复注意事项(经验提升),in的用法和效率
			sql查询重复记录,使用: select * from dimappnamenew as appn where id in ( select id from dimappnamenew gro ... 
- XMPP系列(四)---发送和接收文字消息,获取历史消息功能
			今天开始做到最主要的功能发送和接收消息.获取本地历史数据. 先上到目前为止的效果图: 首先是要在XMPPFramework.h中引入数据存储模块: //聊天记录模块的导入 # ... 
