精华内容
下载资源
问答
  • 主要介绍了Java 反射和反射的应用场景的相关资料,帮助大家更好的理解和学习Java反射的相关知识,感兴趣的朋友可以了解下
  • 主要介绍了Java反射获取class对象方式解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • NULL 博文链接:https://zouwu85.iteye.com/blog/801921
  • JAVA反射PPT,,简单介绍反射的实现和机制,
  • JAVA反射参数传递概略

    2019-05-25 02:31:39
    NULL 博文链接:https://xwood.iteye.com/blog/472428
  • Java反射调用工具类

    2019-04-26 01:24:07
    NULL 博文链接:https://shulinshulinzi.iteye.com/blog/2372372
  • 文章目录一、Java反射定义二、Java反射机制实现1、Class对象获取2、获取class对象的摘要信息3、获取class对象的属性、方法、构造函数等三、反射的应用场景1、动态代理2、自定义注解实现日志管理 写在前面:Java反射...
  • NULL 博文链接:https://1064319393.iteye.com/blog/2114611
  • java反射基本方法测试

    2017-06-01 15:09:54
    Java基本的反射方法
  • Java反射机制修改私有成员变量的实现_Reflection,普通方式无法修改私有成员变量的值,但通过反射机制可以实现。
  • java反射调用封装接口

    2016-09-01 12:57:24
    万能的反射封装接口,值得下载参考,当成util
  • 使用JAVA反射机制动态调用 计算器对象的加法,减法函数。 使用JAVA反射机制修改一个学生对象 的私有数据成员(不允许调用setters) 使用的类有Class, Method, Field
  • java 反射 调用私有方法(有参数私有方法)获取私有属性值
  • java反射以及复制一个bean的值到另一个bean中。
  • java反射机制和动态代理的原理,熟悉反射机制和动态代理
  • 思考:在讲反射之前,先思考一个问题,java中如何创建一个对象,有哪几种方式? Java中创建对象大概有这几种方式: 1、使用new关键字:这是我们最常见的也是最简单的创建对象的方式 2、使用Clone的方法:无论何时...

    视频功能审核通过了,可以看视频啦!

    建议一定要花十几分钟时间把视频看完,然后再结合博客里的内容来理解

    看完后,相信对你了解Java中的反射一定会有所帮助!

    注意:因为网络原因,视频前一两分钟可能会比较模糊,过一会儿就好了

    记得点关注啊,视频里的wx二维码失效了,wx搜索:“聊5毛钱的java 或 扫码关注公众号,欢迎一起学习交流

    快扫码关注啦!关注可领取博主的Java学习视频+资料,保证都是干货

    用最通俗易懂的话来说一说Java中的反射机制

    思考:在讲反射之前,先思考一个问题,java中如何创建一个对象,有哪几种方式?

    Java中创建对象大概有这几种方式:

    1、使用new关键字:这是我们最常见的也是最简单的创建对象的方式

    2、使用Clone的方法:无论何时我们调用一个对象的clone方法,JVM就会创建一个新的对象,将前面的对象的内容全部拷贝进去

    3、使用反序列化:当我们序列化和反序列化一个对象,JVM会给我们创建一个单独的对象

    上边是Java中常见的创建对象的三种方式,其实除了上边的三种还有另外一种方式,就是接下来我们要讨论的 “反射”

    1、反射概述

    1.1什么是反射

    反射就是把Java类中的各个组成部分进行解剖,并映射成一个个的Java对象,拿到这些对象后可以做一些事情。

    既然说反射是解剖Java类中的各个组成部分,所以说咱们得知道一个类中有哪些部分?

    例如,一个类有:构造方法,方法,成员变量(字段),等信息,利用反射技术咱们可以把这些组成部分映射成一个个对象

    拿到映射后的构造方法,可以用它来生成对象;拿到映射后的方法,可以调用它来执行对应的方法;拿到映射后的字段,可以用它来获取或改变对应字段的值;

    1.2、反射能干什么

    说完反射的概念后,咱们说一下反射能干什么?

    一般来说反射是用来做框架的,或者说可以做一些抽象度比较高的底层代码,反射在日常的开发中用到的不多,但是咱们还必须搞懂它,因为搞懂了反射以后,可以帮助咱们理解框架的一些原理。所以说有一句很经典的话:反射是框架设计的灵魂。现在说完这个可能还不太能理解,不急,等下说完一个快速入门的例子后,应该会稍微有点感觉

    1.3、怎么得到想反射的类

    刚才已经说过,反射是对一个类进行解剖,想解剖一个东西,前提是首先你得拿到这个东西,那么怎么得到咱们想解剖的类呢?

    首先大家要明白一点,咱们写的代码是存储在后缀名是 .java的文件里的,但是它会被编译,最终真正去执行的是编译后的 .class文件。Java是面向对象的语言,一切皆对象,所以java认为 这些编译后的 class文件,这种事物也是一种对象,它也给抽象成了一种类,这个类就是Class,大家可以去AIP里看一下这个类

    所以拿到这个类后,就相当于拿到了咱们想解剖的类,那怎么拿到这个类?

    看API文档后,有一个方法forName(String className); 而且是一个静态的方法,这样咱们就可以得到想反射的类了

    到这里,看Class clazz = Class.forName("com.cj.test.Person");这个应该有点感觉了吧

    Class.forName("com.cj.test.Person");因为这个方法里接收的是个字符串,字符串的话,我们就可以写在配置文件里,然后利用反射生成我们需要的对象,这才是我们想要的。很多框架里都有类似的配置

    2、解剖类

    我们知道一个类里一般有构造函数、方法、成员变量(字段/属性)这三部分组成

    翻阅API文档,可以看到

    Class对象提供了如下常用方法:

    public Constructor getConstructor(Class<?>…parameterTypes)

    public Method getMethod(String name,Class<?>… parameterTypes)

    public Field getField(String name)

    public Constructor getDeclaredConstructor(Class<?>…parameterTypes)

    public Method getDeclaredMethod(String name,Class<?>… parameterTypes)

    public Field getDeclaredField(String name)

    这些方法分别用于帮咱们从类中解剖出构造函数、方法和成员变量(属性)。

    然后把解剖出来的部分,分别用Constructor、Method、Field对象表示。

    2.1反射构造方法

    2.1.1反射无参的构造函数

    可以看到 默认的无参构造方法执行了

    从上边的例子看出,要想反射,首先第一步就是得到类的字节码

    所以简单说一下得到类的字节码的几种方式

    (1)、Class.forName("com.cj.test.Person"); 这就是上边我们用的方式

    (2)、对象.getClass();

    (3)、类名.class;

    2.1.2反射“一个参数”的构造函数

    2.1.3反射“多个参数”的构造函数

    2.1.4反射“私有”的构造函数

    注意:在反射私有的构造函数时,用普通的clazz.getConstructor()会报错,因为它是私有的,所以提供了专门反射私有构造函数的方法 clazz.getDeclaredConstructor(int.class);//读取私有的构造函数,用这个方法读取完还需要设置一下暴力反射才可以

    c.setAccessible(true);//暴力反射

    2.1.5反射得到类中所有的构造函数

    2.2反射类中的方法

    package com.cj.test;
    
    import java.util.Date;
    
    public class Person {
    	
    	public Person(){
    		System.out.println("默认的无参构造方法执行了");
    	}
    
    	public Person(String name){
    		System.out.println("姓名:"+name);
    	}
    	
    	public Person(String name,int age){
    		System.out.println(name+"="+age);
    	}
    	
    	private Person(int age){
    		System.out.println("年龄:"+age);
    	}
    	
    	public void m1() {
    		System.out.println("m1");
    	}
    	
    	public void m2(String name) {
    		System.out.println(name);
    	}
    	
    	public String m3(String name,int age) {
    		System.out.println(name+":"+age);
    		return "aaa";
    	}
    	
    	private void m4(Date d) {
    		System.out.println(d);
    	}
    	
    	public static void m5() {
    		System.out.println("m5");
    	}
    	
    	public static void m6(String[] strs) {
    		System.out.println(strs.length);
    	}
    
            public static void main(String[] args) {
    		System.out.println("main");
    	}
    
    }
    
    
    
    
    
    package com.cj.test;
    
    import java.lang.reflect.Method;
    import java.util.Date;
    import org.junit.Test;
    
    public class Demo2 {
    
    	@Test//public void m1()
    	public void test1() throws Exception{
    		Class clazz = Class.forName("com.cj.test.Person");
    		Person p = (Person)clazz.newInstance();
    		Method m = clazz.getMethod("m1", null);
    		m.invoke(p, null);
    	}
    	@Test//public void m2(String name)
    	public void test2() throws Exception{
    		Class clazz = Person.class;
    		Person p = (Person) clazz.newInstance();
    		Method m = clazz.getMethod("m2", String.class);
    		m.invoke(p, "张三");
    	}
    	@Test//public String m3(String name,int age)
    	public void test3() throws Exception{
    		Class clazz = Person.class;
    		Person p = (Person) clazz.newInstance();
    		Method m = clazz.getMethod("m3", String.class,int.class);
    		String returnValue = (String)m.invoke(p, "张三",23);
    		System.out.println(returnValue);
    	}
    	@Test//private void m4(Date d)
    	public void test4() throws Exception{
    		Class clazz = Person.class;
    		Person p = (Person) clazz.newInstance();
    		Method m = clazz.getDeclaredMethod("m4", Date.class);
    		m.setAccessible(true);
    		m.invoke(p,new Date());
    	}
    	@Test//public static void m5()
    	public void test5() throws Exception{
    		Class clazz = Person.class;
    		Method m = clazz.getMethod("m5", null);
    		m.invoke(null,null);
    	}
    	@Test//private static void m6(String[] strs)
    	public void test6() throws Exception{
    		Class clazz = Person.class;
    		Method m = clazz.getDeclaredMethod("m6",String[].class);
    		m.setAccessible(true);
    		m.invoke(null,(Object)new String[]{"a","b"});
    	}
    	@Test
    	public void test7() throws Exception{
    		Class clazz = Person.class;
    		Method m = clazz.getMethod("main",String[].class);
    		m.invoke(null,new Object[]{new String[]{"a","b"}});
    	}
    }
    

    *****注意:看下上边代码里test6和test7的invoke方法里传的参数和其他的有点不一样

    这是因为 jdk1.4和jdk1.5处理invoke方法有区别

    1.5:public Object invoke(Object obj,Object…args)

    1.4:public Object invoke(Object obj,Object[] args)

    由于JDK1.4和1.5对invoke方法的处理有区别, 所以在反射类似于main(String[] args) 这种参数是数组的方法时需要特殊处理

    启动Java程序的main方法的参数是一个字符串数组,即public static void main(String[] args),通过反射方式来调用这个main方法时,如何为invoke方法传递参数呢?按jdk1.5的语法,整个数组是一个参数,而按jdk1.4的语法,数组中的每个元素对应一个参数,当把一个字符串数组作为参数传递给invoke方法时,javac会到底按照哪种语法进行处理呢?jdk1.5肯定要兼容jdk1.4的语法,会按jdk1.4的语法进行处理,即把数组打散成为若干个单独的参数。所以,在给main方法传递参数时,不能使用代码mainMethod.invoke(null,new String[]{“xxx”}),javac只把它当作jdk1.4的语法进行理解,而不把它当作jdk1.5的语法解释,因此会出现参数个数不对的问题。

    上述问题的解决方法:

    (1)mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});

    这种方式,由于你传的是一个数组的参数,所以为了向下兼容1.4的语法,javac遇到数组会给你拆开成多个参数,但是由于咱们这个Object[ ] 数组里只有一个元素值,所以就算它拆也没关系

    (2)mainMethod.invoke(null,(Object)new String[]{"xxx"});

    这种方式相当于你传的参数是一个对象,而不是数组,所以就算是按照1.4的语法它也不会拆,所以问题搞定

    编译器会作特殊处理,编译时不把参数当作数组看待,也就不会数组打散成若干个参数了

    对上边的描述进行一下总结:在反射方法时,如果方法的参数是一个数组,考虑到向下兼容问题,会按照JDK1.4的语法来对待(JVM会把传递的数组参数拆开,拆开就会报参数的个数不匹配的错误)
    解决办法:防止JVM拆开你的数组
        方式一:把数组看做是一个Object对象
        方式二:重新构建一个Object数组,那个参数数组作为唯一的元素存在。

    2.3反射类中的属性字段

    package com.cj.test;
    
    import java.util.Date;
    
    public class Person {
    	
    	public String name="李四";
    	private int age = 18;
    	public static Date time;
    	
    	public int getAge() {
    		return age;
    	}
    	
    	public Person(){
    		System.out.println("默认的无参构造方法执行了");
    	}
    
    	public Person(String name){
    		System.out.println("姓名:"+name);
    	}
    	
    	public Person(String name,int age){
    		System.out.println(name+"="+age);
    	}
    	
    	private Person(int age){
    		System.out.println("年龄:"+age);
    	}
    	
    	public void m1() {
    		System.out.println("m1");
    	}
    	
    	public void m2(String name) {
    		System.out.println(name);
    	}
    	
    	public String m3(String name,int age) {
    		System.out.println(name+":"+age);
    		return "aaa";
    	}
    	
    	private void m4(Date d) {
    		System.out.println(d);
    	}
    	
    	public static void m5() {
    		System.out.println("m5");
    	}
    	
    	public static void m6(String[] strs) {
    		System.out.println(strs.length);
    	}
    	
    	public static void main(String[] args) {
    		System.out.println("main");
    	}
    	
    }
    
    
    
    
    
    package com.cj.test;
    
    import java.lang.reflect.Field;
    import java.util.Date;
    import org.junit.Test;
    
    public class Demo3 {
    	//public String name="李四";
    	@Test
    	public void test1() throws Exception{
    		Class clazz = Person.class;
    		Person p = (Person)clazz.newInstance();
    		Field f = clazz.getField("name");
    		String s = (String)f.get(p);
    		System.out.println(s);
    		
    		//更改name的值
    		f.set(p, "王六");
    		System.out.println(p.name);
    	}
    	@Test//private int age = 18;
    	public void test2() throws Exception{
    		Class clazz = Person.class;
    		Person p = (Person)clazz.newInstance();
    		Field f = clazz.getDeclaredField("age");
    		f.setAccessible(true);
    		int age = (Integer)f.get(p);
    		System.out.println(age);
    		
    		f.set(p, 28);
    		age = (Integer)f.get(p);
    		System.out.println(age);
    	}
    	@Test//public static Date time;
    	public void test3() throws Exception{
    		Class clazz = Person.class;
    		Field f = clazz.getField("time");
    		f.set(null, new Date());
    		System.out.println(Person.time);
    	}
    }
    

    以上就是自己对Java中反射的一些学习总结,欢迎大家留言一起学习、讨论

    看完上边有关反射的东西, 对常用框架里的配置文件是不是有点思路了

    上边是Spring配置文件里的常见的bean配置,这看起来是不是可以用反射很轻易的就可以实现:解析xml然后把xml里的内容作为参数,利用反射创建对象。

    拓展:

    1、除了上述的Spring配置文件里会用到反射生成bean对象,其他常见的MVC框架,比如Struts2、SpringMVC等等一些框架里还有很多地方都会用到反射。

    前端夜页面录入的一些信息通过表单或者其他形式传入后端,后端框架就可以利用反射生成对应的对象,并利用反射操作它的set、get方法把前端传来的信息封装到对象里。

    感兴趣的话可以看下这篇:利用Java反射模拟一个Struts2框架 Struts2主要核心设计 手动实现Struts2核心代码,这篇里边包含了XML解析、反射的东西,模拟了一个Struts2的核心代码

    2、框架的代码里经常需要利用反射来操作对象的set、get方法,来把程序的数据封装到Java对象中去。

    如果每次都使用反射来操作对象的set、get方法进行设置值和取值的话,过于麻烦,所以JDK里提供了一套API,专门用于操作Java对象的属性(set/get方法),这就是内省

    关于内省相关的内容我也整理了一篇文章,感兴趣可以点击:Java反射——内省(Introspector)以及BeanUtils内省框架

    3、平常用到的框架,除了配置文件的形式,现在很多都使用了注解的形式。

    其实注解也和反射息息相关:使用反射也能轻而易举的拿到类、字段、方法上的注解,然后编写注解解析器对这些注解进行解析,做一些相关的处理

    所以说不管是配置文件还是注解的形式,它们都和反射有关。注解和自定义注解的内容,最近也抽时间大概整理了一下,感兴趣的小可爱可以点击了解:Java中的注解以及自定义注解

    写在最后:反射是框架的灵魂,具备反射知识和思想,是看懂框架的基础。希望看完文章后对你能有所帮助。

    铁子们,如果觉得文章对你有所帮助,可以点关注,点赞

    也可以关注下公众号:扫码 或 wx搜索:“聊5毛钱的java ,欢迎一起学习交流,关注公众号可领取博主的Java学习视频+资料,保证都是干货

    3Q~

    纯手敲原创不易,如果觉得对你有帮助,可以打赏支持一下,哈哈,感谢~

               

    展开全文
  • Java反射技术详解

    万次阅读 多人点赞 2019-04-14 23:11:32
    相信很多人都知道反射可以说是Java中最强大的技术了,它可以做的事情太多太多,很多优秀的开源框架都是通过反射完成的,比如最初的很多注解框架,后来因为java反射影响性能,所以被运行时注解APT替代了,java反射有...

    前言

      相信很多人都知道反射可以说是Java中最强大的技术了,它可以做的事情太多太多,很多优秀的开源框架都是通过反射完成的,比如最初的很多注解框架,后来因为java反射影响性能,所以被运行时注解APT替代了,java反射有个开源框架jOOR相信很多人都用过,不过我们还是要学习反射的基础语法,这样才能自己写出优秀的框架,当然这里所讲的反射技术,是学习Android插件化技术、Hook技术等必不可少的!

    一、基本反射技术

          1.1 根据一个字符串得到一个类

            getClass方法

     String name = "Huanglinqing";
     Class c1 = name.getClass();
     System.out.println(c1.getName());
    

         打印结果如下:

        

        Class.forName

        比如我们获取java.lang.String的类名 

       String name = "java.lang.String";
       Class c1 = null;
       try {
              c1 = Class.forName(name);
              System.out.println(c1.getName());
          } catch (ClassNotFoundException e) {
      }
    

        这里也通过捕获异常,因为我们传的这个字符串可能不合法,字符串合法命名是类的命名空间和类的名称组成

        打印结果如下:

        
       我们还可以通过c1.getSuperclass()获取到他的父类

       Type属性

        基本类型都有type属性,可以得到这个基本类型的类型,比如:

    Class c1 = Boolean.TYPE;
    Class c2 = Byte.TYPE;
    Class c3 = Float.TYPE;
    Class c4 = Double.TYPE;
    
     停停停!这些东西有啥子用,如此鸡肋! 别急,一切都是为后续做准备。

    二、获取类的成员

             当类中方法定义为私有的时候我们能调用?不能!当变量是私有的时候我们能获取吗?不能!但是反射可以,比如源码中有你需要用到的方法,但是那个方法是私有的,这个时候你就可以通过反射去执行这个私有方法,并且获取私有变量。

           获取类的构造函数

           为了便于测试,我们定义一个Test类,Test类如下:(省略get和set方法)

           Test类中我们定义是三个私有变量,生成两个公有的含参构造方法和一个私有的含参构造方法以及一个公有的无参构造方法。

    public class Test {
    
        private int age;
        private String name;
        private int testint;
    
        public Test(int age) {
            this.age = age;
        }
    
        public Test(int age, String name) {
            this.age = age;
            this.name = name;
        }
    
        private Test(String name) {
            this.name = name;
        }
    
        public Test() {
        }
    

          下面我们通过反射获取这些构造方法

           获取类的所有构造方法

     Test test = new Test();
     Class c4 = test.getClass();
     Constructor[] constructors ;
     constructors = c4.getDeclaredConstructors();
    

          通过getDeclaredConstructors可以返回类的所有构造方法,返回的是一个数组因为构造方法可能不止一个,通过getModifiers可以得到构造方法的类型,getParameterTypes可以得到构造方法的所有参数,返回的是一个Class数组,所以我们如果想获取所有构造方法以及每个构造方法的参数类型,可以有如下代码:

      for (int i = 0; i < constructors.length; i++) {
            System.out.print(Modifier.toString(constructors[i].getModifiers()) + "参数:");
            Class[] parametertypes = constructors[i].getParameterTypes();
            for (int j = 0; j < parametertypes.length; j++) {
                 System.out.print(parametertypes[j].getName() + " ");
           }
          System.out.println("");
      }
    

        运行结果如下所示:

        

        这样我们就得到了类中所有构造方法和构造方法中的参数,那么我们如何获取特定的构造方法呢?

        获取类中特定的构造方法

        我们可以通过getConstructors方法获取类中 所有的public类型的构造方法,代码和上面一样就不演示了。

        我们可以通过getDeclaredConstructor()方法传参获取特定参数类型的构造方法,这里注意是getDeclaredConstructor()不是  getDeclaredConstructors() ,所以返回的是一个Class对象而不是一个Class数组。

        获取无参构造方法直接不传参数,如下所示:

       try {
              constructors = c4.getDeclaredConstructor();
              System.out.print(Modifier.toString(constructors.getModifiers()) + );
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
          }
    

        这里要进行异常捕获,因为可能不存在对应的构造方法,打印结果如下:  

        

       如果我们想获取有两个参数分别为int和String类型的构造方法,代码如下:

      Class[] p = {int.class,String.class};
      try {
           constructors = c4.getDeclaredConstructor(p);
           System.out.print(Modifier.toString(constructors.getModifiers()) + "参数:");
           Class[] parametertypes = constructors.getParameterTypes();
           for (int j = 0; j < parametertypes.length; j++) {
                System.out.print(parametertypes[j].getName() + " ");
              }
           } catch (NoSuchMethodException e) {
                e.printStackTrace();
         }
    

      这里我们同样打印出构造方法的参数:


      

      调用构造方法

       从这里开始慢慢到了关键的一步,得到类的实例,我们主要借助于newInstance方法,为了方便演示我们将测试类的两个构造方法打印出来. 

       public Test(int age, String name) {
            this.age = age;
            this.name = name;
            System.out.println("hello" + name + "i am" + age);
        }
    
    
        private Test(String name) {
            this.name = name;
            System.out.println("My Name is" +
                    name);
        }
    

       我们先来调用public的方法,如下所示:

     Class[] p = {int.class,String.class};
     constructors = c4.getDeclaredConstructor(p);
     constructors.newInstance(24,"HuangLinqing");
    

     运行打印结果如下:


      

     那么调用私有构造方法呢,和上面一样,只是我们要设置constructors.setAccessible(true);代码如下:

      Class[] p = {String.class};
      constructors = c4.getDeclaredConstructor(p);
      constructors.setAccessible(true);
      constructors.newInstance("HuangLinqing");
    

      打印结果如下:


       

    调用类的私有方法

      如何调用类中的私有方法呢,我们先在测试类中编写一个测试的私有方法 如下:

      private void welcome(String tips){
            System.out.println(tips);
        }
    

      我们知道如果我们要正常的调用类的方法都是通过类.方法调用,所以我们调用私有方法也需要得到类的实例,而我们上面newInstace已经得到了类的实例,这样就好办了。

       Class[] p4 = {String.class};
       Method method = c4.getDeclaredMethod("welcome",p4);
       method.setAccessible(true);
    

       我们首先通过 getDeclaredMethod方法获取到这个私有方法,第一个参数是方法名,第二个参数是参数类型

       然后通过invoke方法执行,invoke需要两个参数一个是类的实例,一个是方法参数。

         Class[] p4 = {String.class};
         Method method = c4.getDeclaredMethod("welcome",p4);
         method.setAccessible(true);
         Object arg1s[] = {"欢迎关注代码男人技术公众号"};
         method.invoke(test,arg1s);
    

         test类的实例当不能new 获取的时候我们也可以通过反射获取,就是上面的newInstance方法。打印结果如下:


        

     获取类的私有字段并修改值

      看到这里你可能会说,有了set方法,什么私有不私有,test.set不就可以了,但是这里要注意我们是没有办法得到这个类的实例的,要不然都可以得到实例就没有反射一说了。我们在通过反射得到类的实例之后先获取字段:

    Field field = c4.getDeclaredField("name");
    field.setAccessible(true);
    field.set(o,"代码男人");
    

       o是我们上面通过反射构造方法获取的实例,  打印field.get(o).toString()的值如下:
      

       

       不过要注意的是我们修改了name的值只对当前的实例对象有效。

       Java的基本反射语法就是这样了,欢迎加入技术群一起探讨!

      最后反射封装类如下:

    package jnidemo.hlq.com.hookdemo;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    /**
     * @author Huanglinqing
     * @date 2019/4/28
     */
    
    public class Reflex {
    
        /**
         * 获取无参构造函数
         * @param className
         * @return
         */
        public static Object createObject(String className) {
            Class[] pareTyples = new Class[]{};
            Object[] pareVaules = new Object[]{};
    
            try {
                Class r = Class.forName(className);
                return createObject(r, pareTyples, pareVaules);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
    
            return null;
        }
    
        /**
         * 获取无参构造方法
         * @param clazz
         * @return
         */
        public static Object createObject(Class clazz) {
            Class[] pareTyple = new Class[]{};
            Object[] pareVaules = new Object[]{};
    
            return createObject(clazz, pareTyple, pareVaules);
        }
    
        /**
         * 获取一个参数的构造函数  已知className
         *
         * @param className
         * @param pareTyple
         * @param pareVaule
         * @return
         */
        public static Object createObject(String className, Class pareTyple, Object pareVaule) {
    
            Class[] pareTyples = new Class[]{pareTyple};
            Object[] pareVaules = new Object[]{pareVaule};
    
            try {
                Class r = Class.forName(className);
                return createObject(r, pareTyples, pareVaules);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
    
            return null;
        }
    
    
        /**
         * 获取单个参数的构造方法 已知类
         *
         * @param clazz
         * @param pareTyple
         * @param pareVaule
         * @return
         */
        public static Object createObject(Class clazz, Class pareTyple, Object pareVaule) {
            Class[] pareTyples = new Class[]{pareTyple};
            Object[] pareVaules = new Object[]{pareVaule};
    
            return createObject(clazz, pareTyples, pareVaules);
        }
    
        /**
         * 获取多个参数的构造方法 已知className
         * @param className
         * @param pareTyples
         * @param pareVaules
         * @return
         */
        public static Object createObject(String className, Class[] pareTyples, Object[] pareVaules) {
            try {
                Class r = Class.forName(className);
                return createObject(r, pareTyples, pareVaules);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
    
            return null;
        }
    
    
        /**
         * 获取构造方法
         *
         * @param clazz
         * @param pareTyples
         * @param pareVaules
         * @return
         */
        public static Object createObject(Class clazz, Class[] pareTyples, Object[] pareVaules) {
            try {
                Constructor ctor = clazz.getDeclaredConstructor(pareTyples);
                ctor.setAccessible(true);
                return ctor.newInstance(pareVaules);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            return null;
        }
    
    
        /**
         * 获取多个参数的方法
         * @param obj
         * @param methodName
         * @param pareTyples
         * @param pareVaules
         * @return
         */
        public static Object invokeInstanceMethod(Object obj, String methodName, Class[] pareTyples, Object[] pareVaules) {
            if (obj == null) {
                return null;
            }
    
            try {
                //调用一个private方法 //在指定类中获取指定的方法
                Method method = obj.getClass().getDeclaredMethod(methodName, pareTyples);
                method.setAccessible(true);
                return method.invoke(obj, pareVaules);
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            return null;
        }
    
        /**
         * 获取一个参数的方法
         * @param obj
         * @param methodName
         * @param pareTyple
         * @param pareVaule
         * @return
         */
        public static Object invokeInstanceMethod(Object obj, String methodName, Class pareTyple, Object pareVaule) {
            Class[] pareTyples = {pareTyple};
            Object[] pareVaules = {pareVaule};
    
            return invokeInstanceMethod(obj, methodName, pareTyples, pareVaules);
        }
    
        /**
         * 获取无参方法
         * @param obj
         * @param methodName
         * @return
         */
        public static Object invokeInstanceMethod(Object obj, String methodName) {
            Class[] pareTyples = new Class[]{};
            Object[] pareVaules = new Object[]{};
    
            return invokeInstanceMethod(obj, methodName, pareTyples, pareVaules);
        }
    
    
        /**
         * 无参静态方法
         * @param className
         * @param method_name
         * @return
         */
        public static Object invokeStaticMethod(String className, String method_name) {
            Class[] pareTyples = new Class[]{};
            Object[] pareVaules = new Object[]{};
    
            return invokeStaticMethod(className, method_name, pareTyples, pareVaules);
        }
    
        /**
         * 获取一个参数的静态方法
         * @param className
         * @param method_name
         * @param pareTyple
         * @param pareVaule
         * @return
         */
        public static Object invokeStaticMethod(String className, String method_name, Class pareTyple, Object pareVaule) {
            Class[] pareTyples = new Class[]{pareTyple};
            Object[] pareVaules = new Object[]{pareVaule};
    
            return invokeStaticMethod(className, method_name, pareTyples, pareVaules);
        }
    
        /**
         * 获取多个参数的静态方法
         * @param className
         * @param method_name
         * @param pareTyples
         * @param pareVaules
         * @return
         */
        public static Object invokeStaticMethod(String className, String method_name, Class[] pareTyples, Object[] pareVaules) {
            try {
                Class obj_class = Class.forName(className);
                return invokeStaticMethod(obj_class, method_name, pareTyples, pareVaules);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            return null;
        }
    
        /**
         * 无参静态方法
         * @param method_name
         * @return
         */
        public static Object invokeStaticMethod(Class clazz, String method_name) {
            Class[] pareTyples = new Class[]{};
            Object[] pareVaules = new Object[]{};
    
            return invokeStaticMethod(clazz, method_name, pareTyples, pareVaules);
        }
    
        /**
         * 一个参数静态方法
         * @param clazz
         * @param method_name
         * @param classType
         * @param pareVaule
         * @return
         */
        public static Object invokeStaticMethod(Class clazz, String method_name, Class classType, Object pareVaule) {
            Class[] classTypes = new Class[]{classType};
            Object[] pareVaules = new Object[]{pareVaule};
    
            return invokeStaticMethod(clazz, method_name, classTypes, pareVaules);
        }
    
        /**
         * 多个参数的静态方法
         * @param clazz
         * @param method_name
         * @param pareTyples
         * @param pareVaules
         * @return
         */
        public static Object invokeStaticMethod(Class clazz, String method_name, Class[] pareTyples, Object[] pareVaules) {
            try {
                Method method = clazz.getDeclaredMethod(method_name, pareTyples);
                method.setAccessible(true);
                return method.invoke(null, pareVaules);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            return null;
        }
    
    
        public static Object getFieldObject(String className, Object obj, String filedName) {
            try {
                Class obj_class = Class.forName(className);
                return getFieldObject(obj_class, obj, filedName);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return null;
        }
    
        public static Object getFieldObject(Class clazz, Object obj, String filedName) {
            try {
                Field field = clazz.getDeclaredField(filedName);
                field.setAccessible(true);
                return field.get(obj);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            return null;
        }
    
    
        public static void setFieldObject(Class clazz, Object obj, String filedName, Object filedVaule) {
            try {
                Field field = clazz.getDeclaredField(filedName);
                field.setAccessible(true);
                field.set(obj, filedVaule);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public static void setFieldObject(String className, Object obj, String filedName, Object filedVaule) {
            try {
                Class obj_class = Class.forName(className);
                setFieldObject(obj_class, obj, filedName, filedVaule);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    
    
        public static Object getStaticFieldObject(String className, String filedName) {
            return getFieldObject(className, null, filedName);
        }
    
        public static Object getStaticFieldObject(Class clazz, String filedName) {
            return getFieldObject(clazz, null, filedName);
        }
    
        public static void setStaticFieldObject(String classname, String filedName, Object filedVaule) {
            setFieldObject(classname, null, filedName, filedVaule);
        }
    
        public static void setStaticFieldObject(Class clazz, String filedName, Object filedVaule) {
            setFieldObject(clazz, null, filedName, filedVaule);
        }
    }
    
     
    展开全文
  • Java反射调用方法

    2014-11-13 15:47:38
    通过Java反射调用方法,适合初级自学者,通俗易懂
  • Java 反射详解(包含私有方法属性的调用)
  • java 反射机制

    2018-05-09 13:40:08
    java 反射机制深入理解,java 反射机制深入理解,java 反射机制深入理解,
  • 利用java反射机制实现Object转json.
  • java反射总结

    2017-10-27 17:36:44
    个人学习总结,java反射,思维导图 个人学习总结,java反射,思维导图
  • Java动态代理和Java反射的Demo演示,通俗易懂。
  • java反射机制测试代码

    2018-11-23 15:03:26
    java反射机制测试代码 反射获取private类型的属性,方法,构造器 利用反射,多态实现动态编译
  • java反射实例

    2017-07-31 10:00:15
    java反射实例
  • 实现java反射和分发的原理,给需要使用的人下载
  • 该工具类下载后拷贝到你要用的包,只需该包名即可
  • java 反射

    千次阅读 2016-07-28 16:50:30
    不管咋样,学java的,了解java反射非常有必要!什么是反射反射定义java官方文档给出了解释: Reflection is the ability of a program to query and modify its state during the execution. 意为:反射是在程序运行...

    使用场景

    web中我不太清楚,android中,热修复时的原理,其实就是用的java反射,但不管咋样,学java的,了解java反射非常有必要!

    什么是反射

    反射定义

    java官方文档给出了解释:

    Reflection is the ability of a program to query and modify its state during the execution.

    意为:反射是在程序运行时,能动态查看和修改它的状态。
    在java中,我们能在程序运行时,获取它的属性,方法,修饰符,以及此类的父类。我们也能够在程序运行时,创建一个未知类的实例,并且设置或获取它的属性方法。
    但是,在java中,我们不能在运行时改变它的数据结构,比如说,我们不能在程序运行时,往一个类或者对象里添加新的方法,也不能改变类中方法的代码。

    反射API

    反射中经常用到的几个类,如下所示:

    类名 描述
    java.lang.Class 表示在JVM中被类加载器加载的类。
    java.lang.reflect.Field 表示一个类或者接口的属性。
    java.lang.reflect.Constructor 表示一个类中的构造方法。
    java.lang.reflect.Method 表示一个类或者接口中的方法。
    java.lang.reflect.Modifier 解码一个类及其成员的访问修饰符。
    java.lang.reflect.Array 程序运行时创建数组。

    具体用途

    1. 获取对象类名;
    2. 获取包名,修饰符等等;
    3. 获取类中定义的方法,返回类型,修饰符,参数类型,参数名等等;
    4. 获取所有构造函数;
    5. 用它其中一个构造方法创建类;
    6. 通过方法名和方法参数类型调用方法;
    7. 在运行时动态创建数组,并动态操作此数组元素。

    反射相关类的使用

    java.lang.Class

    先上代码:

    package com.lxh;
    
    public class MyClass {
        static {
            System.out.println("Loading class MyClass...");
        }
    }
    package com.lxh;
    public class Main {
        public static void main(String[] args) {
            try {
                String className = "com.lxh.MyClass";
                boolean initialize = false;
    
                ClassLoader cLoader = Main.class.getClassLoader();
                Class c = Class.forName(className, initialize, cLoader);
                className = "com.lxh.MyClass";
                System.out.println("about to load");
                // Will load and initialize the class
                c = Class.forName(className, true, cLoader);
            } catch (ClassNotFoundException e) {
                System.out.println(e.getMessage());
            }
        }
    }

    log如下:

    about to load
    Loading class MyClass...

    Class.forName(String name, boolean initialize, ClassLoader loader)如果布尔值为false,表示不初始化名为name的类,当为true时,就会初始化。Class.forName(String name)其实也是调用的Class.forName(String name, boolean initialize, ClassLoader loader),只不过它中间默认的布尔值为true。当调用名为name的类时,name类中的静态代码块被加载。
    注意:这里第一个参数name,必须是类的全名,包含包名,否则将调用不到该类。

    java.lang.reflect.Field

    反射类Field表示类中的属性,Field中有如下几种方法:

    Field[] getFields()
    Field[] getDeclaredFields()
    Field getField(String name)
    Field getDeclaredField(String name)

    getFields()表示所有该类所有修饰符为public的属性,以及该类所继承的父类所有修饰符为public的属性。
    getDeclaredFields()表示该类任何修饰符的所有属性,但不包括父类中属性。
    上代码:

    class MySuperClass {
        public int super_id = -1;
        private String super_name = "Unknown";
    }
    
    class MyClass extends MySuperClass{
        private int id = -1;
        public String name = "Unknown";
    }
    
    public class Main {
        public static void main(String[] args) {
            Class<MyClass> c = MyClass.class;
    
            // 获取MyClass类中所有的属性
            ArrayList<String> fieldsDesciption = getDeclaredFieldsList(c);
    
            System.out.println("Declared Fields for " + c.getName());
            for (String desc : fieldsDesciption) {
                System.out.println(desc);
            }
            //获取MyClass类中修饰符为public,及其父类中属性
            fieldsDesciption = getFieldsList(c);
    
            System.out.println("\nAccessible Fields for " + c.getName());
            for (String desc : fieldsDesciption) {
                System.out.println(desc);
            }
        }
    
        public static ArrayList<String> getFieldsList(Class c) {
            Field[] fields = c.getFields();
            ArrayList<String> fieldsList = getFieldsDesciption(fields);
            return fieldsList;
        }
    
        public static ArrayList<String> getDeclaredFieldsList(Class c) {
            Field[] fields = c.getDeclaredFields();
            ArrayList<String> fieldsList = getFieldsDesciption(fields);
            return fieldsList;
        }
    
        public static ArrayList<String> getFieldsDesciption(Field[] fields) {
            ArrayList<String> fieldList = new ArrayList<>();
    
            for (Field f : fields) {
                int mod = f.getModifiers() & Modifier.fieldModifiers();
                //获取该属性的修饰符 public,int等等
                String modifiers = Modifier.toString(mod);
                //获取该属性的类型 int,String等等
                Class<?> type = f.getType();
                String typeName = type.getSimpleName();
                // 获取该属性名
                String fieldName = f.getName();
                //拼接后加到集合中
                fieldList.add(modifiers + "  " + typeName + "  " + fieldName);
            }
            return fieldList;
        }
    }

    打印的log如下:

    Declared Fields for com.lxh.MyClass
    private  int  id
    public  String  name
    
    Accessible Fields for com.lxh.MyClass
    public  String  name
    public  int  super_id

    说明getDeclaredFields()
    获取到了指定类中所有属性,而getFields()获取的是指定类及其父类中修饰符为public的属性。而我们在具体情境下,一般是用getDeclaredFields()方法比较多~

    java.lang.reflect.Method

    Method中有如下方法:

    Method[]  getMethods()
    Method[]  getDeclaredMethods()
    Method getMethod(String name,  Class...  parameterTypes)
    Method getDeclaredMethod(String name,  Class...  parameterTypes)

    跟Field类似,getMethods()返回该类中任何修饰符的方法,getDeclaredMethods()返回该类及其父类中修饰符为public的方法
    上代码:

    class MyClass<T> {
    
      public MyClass(int i, int j, String s) {
    
      }
    
      public MyClass(T t) {
    
      }
    
      public int getInt(String a) {
        return 0;
      }
    }
    
    public class Main {
      public static void main(String[] args) {
        Class<MyClass> c = MyClass.class;
    
        ArrayList<String> methodsDesciption = getDeclaredMethodsList(c);
        System.out.println("Declared Methods  for " + c.getName());
        for (String desc : methodsDesciption) {
          System.out.println(desc);
        }
        methodsDesciption = getMethodsList(c);
        System.out.println("\nMethods for  " + c.getName());
        for (String desc : methodsDesciption) {
          System.out.println(desc);
        }
    
      }
    
      public static ArrayList<String> getMethodsList(Class c) {
        Method[] methods = c.getMethods();
        ArrayList<String> methodsList = getMethodsDesciption(methods);
        return methodsList;
      }
    
      public static ArrayList<String> getDeclaredMethodsList(Class c) {
        Method[] methods = c.getDeclaredMethods();
        ArrayList<String> methodsList = getMethodsDesciption(methods);
        return methodsList;
      }
    
      public static ArrayList<String> getMethodsDesciption(Method[] methods) {
        ArrayList<String> methodList = new ArrayList<>();
    
        for (Method m : methods) {
          String modifiers = getModifiers(m);
    
          Class returnType = m.getReturnType();
          String returnTypeName = returnType.getSimpleName();
    
          String methodName = m.getName();
    
          String params = getParameters(m).toString();
    
          String throwsClause = getExceptionList(m).toString();
    
          methodList.add(modifiers + "  " + returnTypeName + "  " + methodName
              + "(" + params + ") " + throwsClause);
        }
    
        return methodList;
      }
    
      public static ArrayList<String> getParameters(Executable exec) {
        Parameter[] parms = exec.getParameters();
        ArrayList<String> parmList = new ArrayList<>();
        for (int i = 0; i < parms.length; i++) {
    
          int mod = parms[i].getModifiers() & Modifier.parameterModifiers();
          String modifiers = Modifier.toString(mod);
          String parmType = parms[i].getType().getSimpleName();
          String parmName = parms[i].getName();
          String temp = modifiers + "  " + parmType + "  " + parmName;
          if (temp.trim().length() == 0) {
            continue;
          }
          parmList.add(temp.trim());
        }
        return parmList;
      }
    
      public static ArrayList<String> getExceptionList(Executable exec) {
        ArrayList<String> exceptionList = new ArrayList<>();
        for (Class<?> c : exec.getExceptionTypes()) {
          exceptionList.add(c.getSimpleName());
        }
        return exceptionList;
      }
    
      public static String getModifiers(Executable exec) {
        int mod = exec.getModifiers();
        if (exec instanceof Method) {
          mod = mod & Modifier.methodModifiers();
        } else if (exec instanceof Constructor) {
          mod = mod & Modifier.constructorModifiers();
        }
        return Modifier.toString(mod);
      }
    }

    log打印如下:
    这里写图片描述

    java.lang.reflect.Constructor

    跟Method和Field类似~

    通过反射给方法赋值

    直接上代码:

    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    class MyClass {
        public MyClass() {
        }
    
        private String name;
    
        public void setName(String name) {
            this.name = name;
            System.out.println("setName():"+name);
        }
    
        public String getName(){
            return name;
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            Class<MyClass> myClass = MyClass.class;
            try {
                //通过class.newInstance()实例化对象
                MyClass p = myClass.newInstance();
                //给对象中方法赋值
                Method setName = myClass.getMethod("setName", String.class);
                setName.invoke(p, "luoxiaohui");
                //获取赋值后getName()中的返回值,不需要参数.
                Method getName = myClass.getMethod("getName");
                System.out.println(getName.invoke(p));
            } catch (InstantiationException | IllegalAccessException
                    | NoSuchMethodException | SecurityException | IllegalArgumentException
                    | InvocationTargetException e) {
                System.out.println(e.getMessage());
            }
        }
    }

    注意:getMethod(String methodName,Class… parameterType),第一个参数表示方法名,后面范型表示方法的需要传的值,这里一定要跟原来方法相匹配,有参数就传参数。比如setName()方法需要传字符串型,参数则为String.class,而getName()不需要传。如果多传或者少传参数,将对应不上类中的方法。

    通过反射给属性赋值

    前面我们提到的Field的方法getField()和getDeclaredField(),只是获取属性的修饰符,属性类型,属性名,这里来说说给属性具体赋值。
    上代码:

    import java.lang.reflect.Field;
    class MyClass {
      private String name = "Unknown";
    
      public MyClass() {
      }
    
      public String toString() {
        return "name=" + this.name;
      }
    }
    
    public class Main {
      public static void main(String[] args) {
        Class<MyClass> my = MyClass.class;
        try {
          MyClass p = my.newInstance();
          Field nameField = my.getDeclaredField("name");
          //Field.setAccessible()方法要注意
          nameField.setAccessible(true);
          String nameValue = (String) nameField.get(p);
          System.out.println("Current name is " + nameValue);
          nameField.set(p, "luoxiaohui");
          nameValue = (String) nameField.get(p);
          System.out.println("New name is " + nameValue);
        } catch (InstantiationException | IllegalAccessException
            | NoSuchFieldException | SecurityException | IllegalArgumentException e) {
          System.out.println(e.getMessage());
        }
      }
    }

    注意:在获取到Class的Field属性后,记得调用方法Field.setAccessible(true),这样能保证不管该属性是public,private,还是缺省,都能修改它,如果没调用此方法,则只能修改修饰符为public的属性。

    通过反射扩展数组

    java.lang.reflect.Array中有两个方法

    Object newInstance(Class<?> componentType,  int  arrayLength)
    Object newInstance(Class<?> componentType,  int... dimensions)

    前者表示实例化一个长度为arrayLength的数组,后者表示实例化一个数组矩阵,后者此篇暂时不讲。以前在书上看到说数组实例化后,是不能改变起长度的,不过,通过反射,还是可以滴~
    上代码:

    import java.lang.reflect.Array;
    import java.util.Arrays;
    
    public class Main {
    
        private static int[] ids = new int[2];
    
        public static void main(String[] args) {
            ids = new int[2];
            System.out.println(ids.length);
            System.out.println(Arrays.toString(ids));
            //将已经实例化的数组ids扩展两个单位长度
            ids = (int[]) expandBy(2);
            //给数组中某个对象赋值
            ids[2] = 3;
            ids[0] = 5;
            System.out.println(ids.length);
            System.out.println(Arrays.toString(ids));
        }
    
        public static Object expandBy(int increment) {
            Object newArray = null;
            //获取数组ids的长度
            int oldLength = Array.getLength(ids);
            //定义新的长度
            int newLength = oldLength + increment;
            Class<?> c = ids.getClass();
            //此方法很重要,对实例化数组通过反射扩展其长度
            newArray = Array.newInstance(c.getComponentType(), newLength);
            return newArray;
        }
    }

    log打印如下:

    2
    [0, 0]
    4
    [5, 0, 3, 0]

    数组成功扩展!

    关于java中反射已经讲完,欢迎各位交流指教!

    展开全文
  • java反射ppt

    2016-04-25 11:19:35
    java反射的ppt帮助大家学习java反射
  • java反射原理详解

    2017-08-10 11:32:26
    java反射原理详解

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 413,933
精华内容 165,573
关键字:

java反射

java 订阅