17.Java 反射机制

1.反射的定义

反射之中包含了一个“反”的概念,所以要想解释反射就必须先从“正”开始解释,一般而言,当用户使用一个类的时候,应该先知道这个类,而后通过这个类产生实例化对象,但是“反”指的是通过对象找到类。                                                            

2.Class对象

2.1 概述

Class对象是反射的起点,可以利用类的Class对象创建类的实例(newInstance),同时提供了操作类的工具,可以获取类的详细信息,并且使用特殊的技术实现类的加载(运行时加载,在编译的时候还没有该类的class文件)。

2.2 Class对象的获取方式

  • a.使用类的字面常量

      • Class<Integer> c=Class.forName("Integer");     备注:编译时会进行检查,不需要捕获ClassNotFoundException,Class对象的类型也是明确的。
  • b.使用forName函数
      • Class<?> c=Class.forName("Integer");              备注:需要捕获异常,而且Class对象的类型是Class<?>,类型不明确,可以使用asSubClass进行转换,但是只能转换到Class<? extends Integer>。
      • Class<? extends Integer> u=c.asSubClass(Integer.class);
      • Class<? exnteds Integer> u1=c.getClass(new Integer(10).getClass());
  • c.使用getClass()函数
      • Integer integer=new Integer(10);
      • Class<? extends Integer> c=intger.getClass();   备注:使用对象实例获取Class对象。

3.类型检查

3.1概述

Class对象提供了很多获取类信息的工具,可以获取类的方法,属性,进行类型判断,创建类的对象实例等等。

3.2 相关API介绍

  • a.获取类的构造函数
  • public class Main {
        public static void main(String[] atgs) throws ClassNotFoundException {
            printTypeInfo("MyClass");
        }
       /**   获取类的构造函数    */
        public static void printTypeInfo(String className){
            try {
                Class<?> c = Class.forName(className);
                Constructor<?>[] constructors=c.getConstructors();
                for(Constructor<?> constructor:constructors){
                    System.out.println(constructor);
                }
            }catch(ClassNotFoundException e){
                e.printStackTrace();
            }
        }
    }
    
    class MyClass {
        private int num=10;
        public MyClass(int num){
            this.num=num;
        }
    
        public MyClass(){
        }
    
        @Override
        public String toString(){
            return String.format("%d",num);
        }
    } 
  • 备注:1.使用反射创建类的实例,Class.newInstance(),类中必须又一个无参数的构造函数,否则会报错。
  • 2.输出:public MyClass(int)

                     public MyClass()
  • 利用构造函数获取相关的对象
  • 用带参数构造函数,创建实例
  • Constructor<?> constructor=c.getConstructor(int.class);
    MyClass myClass=(MyClass)constructor.newInstance(5);
    System.out.println(myClass); 
  • 备注:1.上述的代码没有捕获异常,不能直接执行
  • 2.Class.newInstance()其实也就是获取类的无参构造函数,然后创建对象。
  • b.获取类的一般函数
  • public static void printTypeInfo(String className) {
        try {
             Class<?> c=Class.forName(className);
             for(Method method:c.getMethods()){
                System.out.println(method);
             }
        } catch (ClassNotFoundException e) {
             e.printStackTrace();
        }
    } 
  • 备注:
  • 只能获取构造函数之外的函数,但是还包括从父类中继承来的函数
  • 获取特定的函数
  • getMethod(String methodName,Class<?> ...);
  • 例子:获取特定函数并执行Method.invoke(Obj,Class<?>...)---------动态执行Java的函数
  • public static void main(String[] args){
        Class<?> c=Class.forName(className);
        Method method=c.getMethod("getInfo",String.class);
        System.out.println(method.invoke(c.newInstance(),new String("123")));
    }
    
    class MyClass {
        private int num=10;
        public MyClass(int num){
            this.num=num;
        }
    
        public MyClass(){
        }
    
        public String getInfo(String string){
            return String.format("get : %s",string);
        }
    
        @Override
        public String toString(){
            return String.format("%d",num);
        }
    }
  • 备注:不能直接执行,没有捕获异常,为了看一来比较清楚
  • c.获取类的属性
  • public static void printTypeInfo(String className) {
            try {
                Class<?> c=Class.forName(className);
                Field[] fields=c.getDeclaredFields();
                for(Field field:fields){
                    System.out.println(field);
                }
    
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }} 
  • 备注:还可以获取制定的属性 :field = c.getDeclaredField("num");
  • 操作类的属性,赋值-取值
  • 可能会有访问权限的问题,比如private的属性就不能进行操作,此时可以使用field.setAccessible(true)进行“破坏”面向对象的封装。
  • field.setAccessible(true);
    field.set(myClass,123);
    
  • d.备注
  • 反射还有很所用处,例如获取泛型的参数化类型,操作注解等等。

4.代理

  • a.一般的代理设计模式
  • public class Main {
        public static void main(String[] atgs) {
            proxy proxy=new ProxyServer(new RealServer());
            proxy.doSomthing();
        }
    }
    
    interface proxy{
        void doSomthing();
    }
    
    class RealServer implements proxy{
        @Override
        public void doSomthing(){
            System.out.println("doSomething from RealServer");
        }
    }
    
    class ProxyServer implements proxy{
        private proxy realServer;
        public ProxyServer(proxy realServer){
            this.realServer=realServer;
        }
    
        @Override
        public void doSomthing(){
            realServer.doSomthing();
        }
    }
    
  • b.利用反射的动态代理设计模式
  • import java.lang.reflect.*;
    
    /**
     * Created by yangyun on 2016/11/30.
     */
    public class Main {
        public static void main(String[] atgs) {
            myProxy myProxyInterface=(myProxy) Proxy.newProxyInstance(
                    RealServer.class.getClassLoader(),
                    RealServer.class.getInterfaces(),
                    new ProxyHandler(new RealServer())
            );
            myProxyInterface.doSomthing();
        }
    }
    
    interface myProxy{
        void doSomthing();
    }
    
    class RealServer implements myProxy{
    
        public RealServer(){
        }
    
        @Override
        public void doSomthing(){
            System.out.println("from RealServer doSomething()");
        }
    }
    
    class ProxyHandler implements InvocationHandler{
        private Object realProxy;
        public ProxyHandler(Object realProxy){
            this.realProxy=realProxy;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("before invoke()");
            Object result=method.invoke(realProxy,args);
            System.out.println("after invoke()");
            return result;
        }
    }
    
  • 有什么意义?
  • 1.如果需要在调用代理服务器的函数之前或者之后做一些别的工作,可以不修改服务器端的代码,只需要修改InvocationHandler的invloke()函数就可以。
  • 2.动态代理还是AOP(Spring 面向切面编程的基础)
  • 3.静态代理每增加一个服务类就应该添加一个代理类,动态代理的话只需要一个InvokationHandler就可以了
  • 备注:
  • System.out.println(myProxyInterface.getClass().getName());//$Proxy0
  • 通过 Proxy.newProxyInstance 创建的代理对象是在jvm运行时动态生成的一个对象,它并不是我们的InvocationHandler类型,也不是我们定义的那组接口的类型,而是在运行是动态生成的一个对象,并且命名方式都是这样的形式,以$开头,proxy为中,最后一个数字表示对象的标号
  • 我自己的理解可能会有错
  • proxy.newProxyInstance()产生的其实是代理对象,这个代理对象会实现被“代理类RealServer”的所有接口,这里我们把它转型为proxy接口。
  • 当我通过代理对象来调用方法的时候,起实际就是委托由其关联到的 handler 对象的invoke方法中来调用,并不是自己来真实调用,而是通过代理的方式来调用的,输出method可以看到其实就是doSomething函数。
  • 这就是我们的java动态代理机制,代理对象执行函数全部都通过InvokationHandler的invoke()函数。

参考文献

https://www.zhihu.com/question/24304289

http://blog.csdn.net/xu__cg/article/details/52882023

http://blog.csdn.net/liujiahan629629/articzle/details/18013523

http://www.cnblogs.com/xiaoluo501395377/p/3383130.html

时间: 2024-12-31 23:04:41

17.Java 反射机制的相关文章

java反射机制分析

本文转自:http://www.cnblogs.com/gulvzhe/archive/2012/01/27/2330001.html 浅显易懂,值得收藏 Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象, 都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制.反射的概念是由Smith在1982年 首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.这一概念的提出很快引发了

【转载】Java反射机制详解

转自:http://baike.xsoftlab.net/view/209.html#3_8 1反射机制是什么 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 2反射机制能做什么 反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类: 在运行时构造任意一个类的对象: 在运行时判断任意一个类所具有的成员变量和方法: 在运行时调用任意一个

Java反射机制(Reflection)

Java反射机制(Reflection) 一.反射机制是什么 Java反射机制是程序在运行过程中,对于任意一个类都能够知道这个类的所有属性和方法;对于任意一个对象都能够调用它的任意一个方法和属性,这种动态获取类信息以及动态调用对象方法的功能就是JAVA语言的反射机制. 二.反射机制能干什么 (1)在运行时判断任意一个对象所属的类 (2)在运行时构造任意一个类的对象 (3)在运行时判断任意一个类所具有的成员变量和方法 (4)在运行时调用任意一个对象的方法 (PS:注意反射机制都是在程序运行时,而不

Java知识总结:Java反射机制(用实例理解)

概念理解: 反射是指一类应用,它们能够自描述和自控制.也就是说,这类应用通过采用某种机制来 实现对自己行为的描述( self-representation )和检测( examination) ,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义. Java中的反射是一个强大的工具,他能够创建灵活的代码,这些 代码可以在运行时装配,无需在组件之间进行链接,发射允许在编写和执行时,使程序代码能够接入装载到 JVM 中的类的内部信息 .而不是源代码中选定的类协作的代码.这使发射

Java 反射机制(包括组成、结构、示例说明等内容)

http://www.cnblogs.com/skywang12345/p/3345205.html 第1部分 Java 反射机制介绍 Java 反射机制.通俗来讲呢,就是在运行状态中,我们可以根据"类的部分已经的信息"来还原"类的全部的信息".这里"类的部分已经的信息",可以是"类名"或"类的对象"等信息."类的全部信息"就是指"类的属性,方法,继承关系和Annotation

java反射机制(转)

一.什么是反射机制         简单的来说,反射机制指的是程序在运行时能够获取自身的信息.在java中,只要给定类的名字,     那么就可以通过反射机制来获得类的所有信息. 二.哪里用到反射机制         有些时候,我们用过一些知识,但是并不知道它的专业术语是什么,在刚刚学jdbc时用过一行代码,     Class.forName("com.mysql.jdbc.Driver.class").newInstance();但是那时候只知道那行代码是生成     驱动对象实例

java 反射机制 Demo 练习

最近在研究java 反射机制,看网上视频,并抄了下来研究,用到Servlet 注解,绝不亚于SpringMVC 的注解使用,特此记录分享,Servlet 再也不用为传递参数而判断担忧了,专注业务! 1. 首先定义一个父类,所有的业务操作全部继承之. 1 package controller; 2 3 import java.io.IOException; 4 import java.lang.reflect.Method; 5 6 import javax.servlet.ServletExce

Java反射机制1

一.什么是反射机制         简单的来说,反射机制指的是程序在运行时能够获取自身的信息.在java中,只要给定类的名字,     那么就可以通过反射机制来获得类的所有信息. 二.哪里用到反射机制         有些时候,我们用过一些知识,但是并不知道它的专业术语是什么,在刚刚学jdbc时用过一行代码,     Class.forName("com.mysql.jdbc.Driver.class").newInstance();但是那时候只知道那行代码是生成     驱动对象实例

java 反射机制的概念

java 反射 定义 功能 示例 概要: Java反射机制详解 | |目录 1反射机制是什么 2反射机制能做什么 3反射机制的相关API ·通过一个对象获得完整的包名和类名 ·实例化Class类对象 ·获取一个对象的父类与实现的接口 ·获取某个类中的全部构造函数 - 详见下例 ·通过反射机制实例化一个类的对象 ·获取某个类的全部属性 ·获取某个类的全部方法 ·通过反射机制调用某个类的方法 ·通过反射机制操作某个类的属性 ·反射机制的动态代理 4反射机制的应用实例 ·在泛型为Integer的Arr