java 反射

Wesley13
• 阅读 625

一、java的动态性

  • 反射机制
  • 动态编译
  • 动态执行JavaScript代码
  • 动态字节码操作

二、动态语言

  • 动态语言

   程序运行时,可以改变程序结构或变量类型,典型的语言:python、ruby、javascript等

  • C,C++,JAVA不是动态语言,java可以称之为“准动态性语言”。但java有一定的动态性,我们可以利用反射机制、字节码操作获得类似语言的特性。

三、反射机制reflection

  • 指的是可以运行加载、探知、使用编译期间完全未知的类。
  • 程序在运行状态中,可以动态加载一个只有名称的类,对于任意一个已加载的类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;

  Class c = Class.forName("com.test.User");

        //class小写是关键字,大写是类

  • 加载完类之后,在堆内存中,就产生了一个class类型的对象(一个类只有一个class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,我们形象的称之为:反射。

四、反射机制的常见作用

  • 动态加载类、动态获取类的信息(属性、方法、构造器)
  • 动态构造对象
  • 动态调用类和对象的任意方法、构造器
  • 动态调用和处理属性
  • 获取泛型信息
  • 处理注解

五、Class类介绍

  • java.lang.Class类十分特殊,用来表示java中类型(class/interface/enum/annotation/primitive type/void)
  • Class类的对象包含了某个被加载类的结构。一个被加载的类对应一个Class对象
  • 当一个class被加载,或当加载器(class loader)的defineClass()被jvm调用,jvm便自动产生一个Class对象
  • Class类是reflection的根源
  • 针对任何想动态加载,运行的类,唯有先获得相应的Class对象

六、Class类的对象如何获取

  • 运用getClass()
  • 运用Class.forName()(最常使用)
  • 运用.class语法

七、反射机制的性能问题

  • setAccessible

 

  启用和禁用访问安全检查的开关,值为true则指反射的对象在使用时应该取消java语言访问检查,值为false则指示反射的对象应该实施java语言访问检查,并不是true就能访问为false就不能访问。

  禁止安全检查,可以提高反射的运行速度

  • 可以考虑使用:cglib/javaassist字节码操作

八、反射操作泛型(Generic)

  • java采用泛型擦除的机制类引入泛型。java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换的麻烦,但是,一但编译完成,所有的和泛型有关的类型全部擦除

  • 为了通过反射操作这些类型以迎合实际开发的需要,java 新增了ParameterizedType,GenericArrayType,TypeVariable和WildcardType几种类型来代表不能被归一到Class类中的类型但是又和原始类型齐名的类型。

    package com.lkr.testReflection;/** * @AUTHOR:LKR * @DATE:2019/3/10 * @DESCRIPTION:测试各种类型(class、interface、enum、annotation、primitive type、void)对应的java.lang.Class对象的获取方式 **/@SuppressWarnings("all")public class TestClassHuoqv { public static void main(String[] args){ String path = "com.lkr.test.bean.User"; try{ Class clazz = Class.forName(path); //对象是表示或封装一些数据,一个类被加载后,JVM给创建一个对应类的class对象,类的整个结构信息会放到对应的Class对象中 //这个Class对象就像一面镜子一样,通过这面镜子可以看到对应类的全部信息 System.out.println(clazz); System.out.println(clazz.hashCode()); Class clazz2 = Class.forName(path);//一个类只对应一个Class对象 System.out.println(clazz.hashCode()); Class strClazz = String.class; Class strClazz2 = path.getClass(); System.out.println(strClazz == strClazz2); Class intClazz = int.class; int[] a = new int[10]; int[] arr2 = new int[30]; int[][] arr3 = new int[30][3]; System.out.println(a.getClass().hashCode()); System.out.println(arr2.getClass().hashCode()); System.out.println(arr3.getClass().hashCode()); double[] arr4 = new double[10]; System.out.println(arr4.getClass().hashCode()); }catch(Exception e){ e.printStackTrace(); } }}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    package com.lkr.testReflection;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;/** * @AUTHOR:LKR * @DATE:2019/3/11 * @DESCRIPTION:应用反射api获取类的信息(类的名字、属性、方法、构造器等) **/public class demo2 { public static void main(String[] args){ String path = "com.lkr.test.bean.User"; try{ Class clazz = Class.forName(path); //获取类的名字 System.out.println(clazz.getName());//获取包名+类名:com.lkr.test.bean.User System.out.println(clazz.getSimpleName());//获取类名:User //获取属性信息 Field[] fields = clazz.getFields();//只能获得public的field Field[] fields1 = clazz.getDeclaredFields();//获得所有的field Field f = clazz.getDeclaredField("uname"); System.out.println(fields.length); System.out.println(fields1.length); System.out.println(f); for (Field temp: fields1){ System.out.println("属性:"+ temp); } //获取方法信息 Method[] method = clazz.getDeclaredMethods(); Method m1 = clazz.getDeclaredMethod("getUname",null);//方法无参数 Method m2 = clazz.getDeclaredMethod("setUname", String.class);//方法有参数,则必须传递参数类型对应的class对象 System.out.println(method.length); for(Method m: method){ System.out.println("方法:"+ m); } //获取构造器信息 Constructor[] constructors = clazz.getDeclaredConstructors(); for(Constructor c: constructors){ System.out.println("构造器:"+ c); } Constructor c1 = clazz.getDeclaredConstructor(null); Constructor c2 = clazz.getDeclaredConstructor(int.class,int.class,String.class); System.out.println("获得构造器:"+c1); System.out.println("获得构造器:"+c2); }catch(Exception e){ e.printStackTrace(); } }}

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    package com.lkr.testReflection;import com.lkr.test.bean.User;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;/** * @AUTHOR:LKR * @DATE:2019/3/11 * @DESCRIPTION:通过反射api动态的操作:构造器、方法、属性 **/public class Demo3 { public static void main(String[] args) { //动态操作构造器 String path = "com.lkr.test.bean.User"; try { Class clazz = Class.forName(path); //通过反射api调用构造方法,构造对象 User u = (User) clazz.newInstance();//其实是调用了User的无参构造方法 System.out.println(u); Constructor c = clazz.getDeclaredConstructor(int.class,int.class,String.class); User u2 = (User)c.newInstance(1001,18,"lkr"); System.out.println(u2.getUname()); //通过反射api调用普通方法 User u3 = (User) clazz.newInstance(); Method m3 = clazz.getDeclaredMethod("setUname", String.class); m3.invoke(u3,"lkr3");//u3.setUname("lkr3"); System.out.println(u3.getUname()); //通过反射api操作属性 Field f = clazz.getDeclaredField("uname"); f.setAccessible(true);//这个属性不需要做安全检查了,可以直接访问 User u4 = (User) clazz.newInstance(); f.set(u4,"lkr4");//通过反射直接写属性 System.out.println(u4.getUname());//通过反射直接毒属性的值 System.out.println(f.get(u4)); }catch(Exception e){ e.printStackTrace(); } }}

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
2年前
java的特性
java的特性1、Java语言是简单的2、Java语言是面向对象的3、Java语言是分布式的4、Java语言是健壮的5、Java语言是安全的6、Java语言是可移植性的7、Java语言是解释型的8、Java语言是多线程的9、Java语言是动态的语言  Java语言是简单的: 
Wesley13 Wesley13
2年前
java中 什么是反射?
JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。JAVA反射(放射)机制:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言(https://www.oschina.net/act
Wesley13 Wesley13
2年前
java中的反射和代理
  Java反射机制可以动态地获取类的结构,动态地调用对象的方法,是java语言一个动态化的机制。java动态代理可以在不改变被调用对象源码的前提下,在被调用方法前后增加自己的操作,极大地降低了模块之间的耦合性。这些都是java的基础知识,要想成为一名合格的程序猿,必须掌握!Java反射机制 JAVA反射机制是在运行状态中,对于任意一个类,都能够知
lzy lzy
2年前
RPC框架手撕之路---java反射以及动态代理机制
在上一篇文章中,我们提到了,RPC框架所需要的java基础,第一点就是java的动态代理机制,动态代理机制的基础是反射,无论是在实际编程或者是面试时,都是java知识的重中之重。java反射:定义:在运行状态中,对于任意一个类,都能够知道这一个类的所有属性和方法,对于任意一个对象都能够通过反射机制调用一个类的任意方法,这种动态获取类信息以及动态调用类方法
Wesley13 Wesley13
2年前
java面试(反射)05
1.什么是反射JAVA反射机制是在运行状态中,对于任意一个类,都能够获取这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取类信息以及动态调用对象内容就称为java语言的反射机制。2.反射的作用在运行时判断任意一个对象所属的
桃浪十七丶 桃浪十七丶
2年前
工厂模式实例(顺便回忆反射机制的应用)
一、原理反射机制的原理JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。工厂模式自述所谓工厂模式,是说由某个产品类接口、产品实现类、工厂类、客户端(单元测试主类)构成的一个模式,大程度的降低了代码的
Wesley13 Wesley13
2年前
Java反射技术概述
1.什么是Java反射?  就是正在运行,动态获取这个类的所有信息2.反射机制的作用  a.反编译:.class.java  b.通过反射机制,访问Java对象的属性,方法,构造方法等3.反射机制的应用场景  Jdbc加载驱动  SpringIOC实现  Java框架4.创建对象的两种方式  a.直
Wesley13 Wesley13
2年前
Java提高班(六)反射和动态代理(JDK Proxy和Cglib)
反射和动态代理放有一定的相关性,但单纯的说动态代理是由反射机制实现的,其实是不够全面不准确的,动态代理是一种功能行为,而它的实现方法有很多。要怎么理解以上这句话,请看下文。一、反射反射机制是Java语言提供的一种基础功能,赋予程序在运行时<strong自省</strong(introspect,官方用语)的能力。通过反射我们可以直接
Wesley13 Wesley13
2年前
Java反射机制及适用场景
什么是Java反射机制?JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的以及动态调用对象的方法的功能称为Java的反射机制。反射的适用场景是什么?1.当你做一个软件可以安装插件的功能,你连插件的类型名称都不知道,你怎么实例化这个对象呢