1.Java反射机制概述

  • Java Reflection允许允许程序在执行期间借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性和方法;(属于动态语言的关键)

  • 反射主要的API:java.lang.Class(代表一个类);java.lang.reflect.Method(代表一个方法);等等

  • 反射可以调用类私有的构造器,方法,属性,当然是通过部分方法进行调用,后面介绍;

  • 使用反射时,最开始的就是要先创建一个Class对象,但是这个对象并非是new 出来的,它的对象是加载到内存中的类(运行时类),这个运行时类就可以作为Class的对象,比如有一个类Person,那么创建一个Class的对象的方式;

     public static void main(String[] args) throws ClassNotFoundException {// 创建Class类对象的第一种方式;Class clazz1 = Person.class;//第二种方式,通过对象创建Person p = new Person("神秘的天");Class clazz = p.getClass();//第三种方式,通过Class.forName创建;会出现异常;但是比较灵活,因为它传入的是字符串,不会再编译的时候就肯定,也就是可以进行修改;Class name = Class.forName("cn.dxs.Person");//第四种方式,通过ClassLoader实现,这个属于系统类加载器;主要用来加载自定义的类;ClassLoader classLoader = TextUDP.class.getClassLoader();Class aClass = classLoader.loadClass("cn.dxs.Person");
    }
    
  • 上面讲到,使用反射时,开始就要创建一个Class的对象,前面也介绍如何通过一个普通的类,创建Class的对象,接下来就记录一下,到底有多少的结构可以创建Class对象;
    (1)class:各种类(如:匿名内部类、外部类等)
    (2)interface(接口)
    (3)数组
    (4)enum(枚举类)
    (5)annotation(注解)
    (6)primitive(基本数据类型)
    (7) void

    public void text(){//class类Class clazz1 = study.class;//interfaceClass clazz2 = Closeable.class;//数组Class clazz3 = int[].class;//枚举类,这个state是Thread中的一个枚举类,主要表示线程生命周期;Class clazz4 = Thread.State.class;//注解;Class clazz5 = Override.class;//基本类型Class clazz6 = int.class;//void也可以创建Class对象;Class class7 = void.class;
    }
    
  • 除了系统类加载器,还有扩展类加载器和引导类加载器,其中第一个可以用来加载自定义的类;第二个用于加载jre的扩展目录,lib/ext中的jar包;第三个是用于加载Java的核心类;

  • 通过反射去创建需要的类的对象;

    public void test() throws IllegalAccessException, InstantiationException {//先创建一个class的对象;Class<Person> clazz = Person.class;//然后再通过这个创建的对象clazz去创建person的对象;会抛出异常Person p = clazz.newInstance();
    }
    

    在上面程序中的两个异常,IllegalAccessException表示非法接入,意思就是指你想要创建的类的对象必须要有一个可以使用的构造方法,如果构造方法是私有的,那么就会出现这个异常;InstantiationException 表示要有构造器,否则抛异常;

  • 通过反射可以获得类中的很多结构,比如:构造器,属性,方法,注解,等;都是通过Class对象调用的方法实现;
    有的时候,就比如属性,可能是被private修饰的,那么就算反射可以取到属性也是不能直接修改的,那么就需要用到setAccessible(boolean)方法,使其能被使用;(boolean设置成true即可)

  • 在使用sevlet时,有一种叫做servlet抽取(详情可百度)的方法,这种方法,主要就是将一些servlet综合在一起,这样可以避免写过多的servelet,它实现的核心就是通过反射,下面简单介绍一下,它的核心实现模式;

    首先要先创建一个所有类的父类,这个父类继承了HttpServlet类,就相当于一个servlet了,然后在这个主类中,使用一个反射创建当前类的Class对象clazz,然后通过clazz调用method方法,当然你在该子类里面必须要将名字确定好,这样父类通过getMethod(方法名,参数)取到子类中的方法之后,就可以直接通过invoke(对象,参数)调用该方法; getMethod()中的参数,是需要(.class)的比如String就应该是String.class作为参数,具体例子如下:

    Method md = clazz.getMethod(method, HttpServletRequest.class, HttpServletResponse.class);

  • 通过反射的方式读取配置文件,这里我是通过IDEA中运行的,一开始一直报空指针错误,如果不希望出现空指针错误,最好是将这个配置文件放在src同级;当然如果通过文件流读取就不会出现这种错误,随便配置文件放在哪里;

      public static void main(String[] args) {ClassLoader classLoader = TextUDP.class.getClassLoader();//直接通过ClassLoader对象加载文件;InputStream input = classLoader.getResourceAsStream("mything.properties");Properties pro = new Properties();try {pro.load(input);String name = pro.getProperty("Name");String password = pro.getProperty("Password");System.out.println(name + "\t" + password);} catch (IOException e) {e.printStackTrace();}
    }
    

2. 动态代理

  1. 动态代理:通过代理类来调用其它对象的方法,并且是在程序运行时根据需要动态创建目标类的对象;
  2. 静态代理,简单的理解就是已经规定好了某些特定类,无法直接在程序上进行修改;我发现静态代理和装饰器模式有点像,仔细比较了一下,发现在装饰器模式中,并没有像静态代理中的代理类一样创建对象;
    //这个作为运行类;
    public class StaticAgent {public static void main(String[] args) {//先创建一个被代理类的对象;LOLGame lolGame = new LOLGame();//创建一个代理类的对象;将被代理类的对象放入;GameDesign gameDesign = new GameDesign(lolGame);//这个对象实际是GameDesign的。所以可以调用GameDesign    的produce方法;gameDesign.produce();}
    }//这个是最开始的原始接口,
    interface GameFactory {//定义一个抽象方法
    void produce();
    }//定义一个代理的类
    class GameDesign implements GameFactory {//定义一个这样的对象(这个对象属于GameFactory的实现类即可),方便使用多态;
    private GameFactory gameFactory;//定义一个构造方法,将被代理类的对象作为参数放进来;方便在 后面的方法中调用;public GameDesign(GameFactory gameFactory) {this.gameFactory = gameFactory;}@Overridepublic void produce() {//这里只是简单介绍,就不写过多的逻辑了;System.out.println("开始设计游戏!");//在这里运行被代理类的对象;gameFactory.produce();System.out.println("游戏设计完成!");}
    }//创建一个被代理类;实现原始的接口;
    class LOLGame implements GameFactory {//在代理类中重写接口方法;@Overridepublic void produce() {System.out.println("LoL设计中");}
    }
    
  3. 动态代理,和上面的静态代理相比,动态的更加灵活,也就是只要你创建那个被代理,而不需要一直创建代理类,在我看来;这就是动态和静态的区别;以下是动态代理的基本结构;
        public class DynamicAgent {//运行主类public static void main(String[] args) {//创建一个被代理类的实例;Student stu = new Student();//然后就是获得代理类的对象;Person per = (Person) AgentPer.ProxyThis(stu);String doing = per.doing();System.out.println(doing);per.sing();}
    }//首先准备一个接口,在其中写好可以使用方法;
    interface Person {void sing();String doing();
    }//要准备与代理类类似功能的类,比如获得一个代理类的对象;
    class AgentPer {//从静态代理就可以知道,我们需要一个代理类的对象调用方法;//定义一个Static方法,这样用于获取代理类对象;这里之所以返回Object类是由于不确定会得到什么类;public static Object ProxyThis(Object obj) {//这里的obj是指被代理类的对象;//由于下面要用到实现接口InvocationHandler的类,所以下面创建它的对象;MyInvocation handler = new MyInvocation(obj);/*    handler.bind(obj);*///这里必须要用这个方法创建代理类的对象;第三个参数需要接口InvocationHandler的实现类,所以要自定义一下;return Proxy.newProxyInstance(AgentPer.class.getClassLoader(), obj.getClass().getInterfaces(), handler);}
    }class MyInvocation implements InvocationHandler {//定义一个对象;private Object obj;public MyInvocation() {}//这里是直接调用一个构造参数将被代理对象放进来;也可以用下面的那个方法bind;用方法的话,就需要调用一下;public MyInvocation(Object obj) {this.obj = obj;}/*  //定义一个方法,为这个对象赋值public void bind(Object obj) {this.obj = obj;}*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws     Throwable {//这里面重新写一下需要调用的方法,obj是指被代理类的对象;args是参    数;Object thisobj = method.invoke(obj, args);return thisobj;}
    }//定义一个测试的被代理类,方便验证代码的正确性;
    class Student implements Person {@Overridepublic void sing() {System.out.println("I can sing");}@Overridepublic String doing() {return "do homework";}
    }
    

运行结果:

3. Java杂记(学到什么记录什么)

  1. 如何读取配置文件(properties后缀)

     public static void main(String[] args)  {//定义一个Properties对象Properties pro = new Properties();try {//通过文件路径,定义文件输入流FileInputStream in = new FileInputStream("src\\cn\\dxs\\net\\mything.properties");//通过properties对象加载文件输入流pro.load(in);//通过键值对取值String name = pro.getProperty("Name");String password = pro.getProperty("Password");System.out.println(name+"****\t"+password);} catch (IOException e) {e.printStackTrace();}
    }
    

2.Interface中的方法为抽象方法,默认修饰为public abstract;变量默认为public static final;

Java基础(22)-Java反射总览(把反射基本了解一遍)相关推荐

  1. java基础总结-java技术栈快速复习

    java基础 java基础概念 java概述和语言背景 java语言是没有sun公司(Stanford University Network:斯坦福大学网络)在1995年推出的计算机语言 java之父 ...

  2. Java基础:Java抽象接口

    在Java中,一个没有方法体的方法应该定义为抽象方法,而如果一个类中含有抽象方法,则该类必须定义为一个抽象类.接口是功能的集合,同样可看做是一种特殊的数据类型,是比抽象类更为抽象的类,接口只描述所应该 ...

  3. 黑马程序员:Java基础总结----Java语言编程规范

       黑马程序员:Java基础总结        Java语言编程规范:参考自SUN公司文档  ASP.Net+Android+IO开发..Net培训.期待与您交流!  I.   排版规范 A.  规 ...

  4. Java 基础-01 Java语言入门

    文章目录 Java 基础-01 Java语言入门 1.计算机基本概念 1.1 计算机概述 1.2 计算机组成 1.3 CPU.内存与硬盘 2.软件基本概念 2.1 软件概述 2.2 人机交互方式 2. ...

  5. java基础之java中的基本数据类型

    java基础之java中的基本数据类型 学习java一段时间了,使用java也差不多一年多了,可是对于后续的java的学习真的是后劲不足,或者是说懒惰吧,回想一下这一年多,用java最多的就是Andr ...

  6. java基础之----java常见异常及代码示例

    java基础之----java常见异常及代码示例 参考文章: (1)java基础之----java常见异常及代码示例 (2)https://www.cnblogs.com/gunduzi/p/1203 ...

  7. 【Java基础】· Java基本语法:程序流程控制习题总结

    写在前面 Hello大家好, 我是[麟-小白],一位软件工程专业的学生,喜好计算机知识.希望大家能够一起学习进步呀!本人是一名在读大学生,专业水平有限,如发现错误或不足之处,请多多指正!谢谢大家!!! ...

  8. java基础:Java七大外企经典面试精讲视频

    java基础:Java七大外企经典面试精讲视频 对于很多应聘java程序员的求职者来说,全面掌握java面试技巧,确实是自己找到一个好工作的敲门砖.今天小编在这里给大家分享一个关于java基础的Jav ...

  9. java基础之java类型

    系列文章目录 java基础之java类型 文章目录 系列文章目录 基本类型 自动类型提升 引用类型 基本类型 整型 Byte 8位 -2^7~2^7-1 默认值0 Short 16位 -2^15~2^ ...

  10. Java 基础学习-Java语言概述

    Java 基础学习 第一章 Java语言概述 回顾java基础知识,进行整理记录. 文章目录 Java 基础学习 前言 一. Java语言发展史(了解) 二.Java语言跨平台原理(理解) 三.JRE ...

最新文章

  1. linux maps,linux下/proc/pid/maps和pmap命令详解
  2. 读取properties文件
  3. boost::geometry::transform用法的测试程序
  4. Ghost的相关问题
  5. [置顶] NoSQl mongodb数据库 配置篇
  6. python逻辑运算符or的短路求值特性_[Python]计算闰年时候出现的and和or优先级的问题以及短路逻辑...
  7. 全国计算机等级考试题库二级C操作题100套(第20套)
  8. java 守护进程 linux_Java使用appache deamon实现linux守护进程
  9. 计算机网络的硬盘组成,大卸八块!编辑为你揭秘硬盘的内部结构
  10. Maven跳过antrun打包
  11. java 构建_Java入门环境构建
  12. php导出excel出现乱码,完美解决phpexcel导出到xls文件出现乱码的问题
  13. 阿里编码规范认证考试题库(免费版)
  14. 搜索引擎算法大全(吐血整理)
  15. linux中rcf命名管道,RCF-进程间为C通讯
  16. 【论坛】交通需求管理政策与实践——中国城市交通发展论坛第十一次研讨会讨论精选...
  17. 使用GI Agent(XAG)实现GoldenGate的高可用性(二)
  18. android博学谷布局,《Android项目实战-博学谷》设置部分
  19. C语言实现两个整数相除的四舍五入和进一法
  20. 串口232,485转以太网模块 TCP/IP 串口协议转换模块

热门文章

  1. 【有利可图网】PS教程:巧用PS设计制作3D金属铆钉字体效果
  2. java设计模式(3)
  3. 思科华为厂家为什么要推出自己的CCIE/HCIE认证
  4. 易购网上线 苏宁转身电子商务
  5. NKOJ【USACO OCT09】双数还是单数?
  6. 【Pytorch】读取model中的module和name
  7. HTML聊天框特效,利用jQuery实现响应式聊天窗口界面特效
  8. oracle执行报错ora-00955,Oracle:ORA-00955: name is already used by an existing object
  9. 这几款图片转PDF软件推荐给你
  10. proxmox VE minimal 配置openbox自启动