本人学习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反射机制,以及对反射机制的了解,如有差池欢迎点评(初学者勿喷)的更多相关文章

  1. 【代码笔记】Java——远程监控、反射、代理、内省机制

    远程控制的基本原理 远程控制(RemoteControl)拥有控制端和被控端双方. 控制方通过请求,取得对远端的操作,实现远端的事件回放功能,同时,应该看得到远端桌面的画面.而被控方必须在建立Serv ...

  2. Java程序语言的后门-反射机制

    在文章JAVA设计模式-动态代理(Proxy)示例及说明和JAVA设计模式-动态代理(Proxy)源码分析都提到了反射这个概念. // 通过反射机制,通知力宏做事情 method.invoke(obj ...

  3. 深入理解java:1.1.1. 反射机制

    反射 到底什么是反射(Reflection)呢? 反射有时候也被称为内省(Introspection),事实上,反射,就是一种内省的方式, Java不允许在运行时改变程序结构或类型变量的结构,但它允许 ...

  4. 【转】Java之 内存区域和GC机制

    转自:Leo Chin 目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage ...

  5. Java运行时环境---ClassLoader类加载机制

    背景:听说ClassLoader类加载机制是进入BAT的必经之路. ClassLoader总述: 普通的Java开发其实用到ClassLoader的地方并不多,但是理解透彻ClassLoader类的加 ...

  6. Java学习点滴——Class和反射

    基于<Java编程思想>第四版 前言 我们要操作一个类实例对象时,一般都要先知道这个类有哪些方法或者成员变量.反射就是在我们不知道这个类有哪些方法或成员变量时,使用特定方式得到类的这些信息 ...

  7. 【Java】利用注解和反射实现一个"低配版"的依赖注入

    在Spring中,我们可以通过 @Autowired注解的方式为一个方法中注入参数,那么这种方法背后到底发生了什么呢,这篇文章将讲述如何用Java的注解和反射实现一个“低配版”的依赖注入. 下面是我们 ...

  8. 转 Java虚拟机5:Java垃圾回收(GC)机制详解

    转 Java虚拟机5:Java垃圾回收(GC)机制详解 Java虚拟机5:Java垃圾回收(GC)机制详解 哪些内存需要回收? 哪些内存需要回收是垃圾回收机制第一个要考虑的问题,所谓“要回收的垃圾”无 ...

  9. JAVA中的糕富帅技术——反射(一)

    前言 突然发现好久没写博客了,前面写的都是关于Android的东西,今天心血来潮突然有一种冲动想写一篇基于JAVA技术的博客,别问我为什么?有钱.任性! 今天就来谈谈反射机制:学过JAVA的人不一定懂 ...

随机推荐

  1. Cocos2D:塔防游戏制作之旅(十四)

    塔之战:炮塔的攻击 炮塔就位了?检查.敌人前进中?再次检查 - 它们看起来就是如此!看起来到了击溃这些家伙的时候了!这里我们将智能置入炮塔的代码中去. 每一个炮塔检查是否有敌人在其攻击范围.(炮塔一次 ...

  2. Leetcode_8_String to Integer

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/41521063 Implement atoi to conv ...

  3. Java单例模式之饿汉模式与懒汉模式

    单例模式是我们在开发软件的过程中经常用到的23中常用的java模式之一,主要的功能就是保证我们所使用的对象只有一个,这也在一方面减少了出错的可能性,增强了代码的健壮.单例模式一般来说有两种实现的方式, ...

  4. 敦泰FT6X06单层自容调屏

    总的概括来说,自电容调屏在配置好通道个数和顺序后,只需调整AFE相关的设置参数使各通道的Raw Data和CI值符合定义的标准即可.– AFE是模拟前端的缩写-Analog Front End• Ra ...

  5. Linux环境编程导引

    计算机系统硬件组成 总线 贯穿整个系统的一组电子管道称为总线, 分为: 片内总线 系统总线 数据总线DB 地址总线AB 控制总线CB 外部总线 I/O设备 I/O设备是系统与外界联系的通道 键盘鼠标是 ...

  6. html5学习之旅-html5的简易数据库开发(18)

    实际上是模拟实现html5的数据库功能,用键值对的方式. !!!!!!废话不多说 ,代码 index.html的代码 <!DOCTYPE html> <html lang=" ...

  7. android MVP框架

    原文地址:http://blog.csdn.net/guxiao1201/article/details/40147209 在开发Android应用时,相信很多同学遇到和我一样的情况,虽然项目刚开始构 ...

  8. android 之ViewStub

    在开发应用程序的时候,经常会遇到这样的情况,会在运行时动态根据条件来决定显示哪个View或某个布局.那么最通常的想法就是把可能用到的View都写在上面,先把它们的可见性都设为View.GONE,然后在 ...

  9. PS 滤镜——平面坐标变换到极坐标

    %%% orthogonal coordinate to polar coordinate %%% 平面坐标转极坐标 clc; clear all; close all; addpath('E:\Ph ...

  10. 【Android 应用开发】BluetoothSocket详解

    一. BluetoothSocket简介 1. 简介 客户端与服务端 : BluetoothSocket 和 BluetoothServerSocket 类似于Java中的套接字的 Socket 和 ...