1,什么是反射

反射机制是java语言提供的一种基础功能,它能够赋予成语在运行时进行自省的能力。通过反射我们可以直接操作类或者对象,例如:可以通过反射去获取某个对象的类的定义,属性,方法,还可以修改类的定义。

2,反射中的包

2.1反射包

java中专门的反射包java.lang.reflect,反射包下包含了很多类,具体可以参考jdk,这里我们用到的有Field类的成员变量,Method方法,Constructor构造器。

2.2AccessibleObject

关于反射有一点需要特意注意一下,就是反射包提供的AccessibleObject类中的setAccessible方法。

他的子类很多也重写了这个方法,这里的所谓的setAccessible顾名思义,就是指的是成员变量前面的用于修饰的public、protected、private,这个方法也就意味着我们可以在运行时通过反射去修改类的成员变量的访问限制。

setAccessible的应用场景非常广泛,各种框架:开发、测试、依赖注入。例如在数据库O/R Mapping框架中,我们在加载或者持久化数据的时候,框架通常会利用反射做这个事情,而不需要开发者自己去实现。

还有个典型的应用场景,就是绕过API的访问控制。我们在开发的过程中,有时候,可能需要调用内部的API去做一些事情,比如,自定义的高性能的NIO框架需要显示的释放DirectBuffer,使用反射绕开限制是一种常见的办法。

2.2Modifier

反射包中还有一个重要的类Modifier,该类是静态类,其中的方法也是静态方法。 

Modifier.Class类中getModifiers()函数返回一个用于描述类,构造器,方法和域的修饰符的整形数值。、 

调用Modifier.toString()方法将整型数值转变成字符串,也是就我们熟悉的public,private,static,final等修饰符。

2.3代码实例

/**
* 创建一个user类
* 可不在与main方法同一个类中创建
*/
class User{ //定一个成员变量:姓名
private String name; //无参构造
public User(){}
//有参构造
public User(String name) {
this.name = name;
}
//get方法
public String getName() {
return name;
}
//set方法
public void setName(String name) {
this.name = name;
}
}
/**
* 测试Class类的函数和反射库中的函数
*/
public class TestReflectController { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException { //获得User类的Class对象
Class<?> cc = User.class; //下面这个是通过new出来的对象,并通过set给成员变量赋值
User user1 = new User();
user1.setName("hello");
//下面这个是通过构造器的方式 //1.有参构造器
//先得到有参构造器的信息,再根据构造器的信息,由newInstance()函数创建一个User对象
Constructor<?> constructor = cc.getConstructor(String.class);
//这个constructor.newInstance方法就是反射包下java.lang.reflect.Constructor类下的newInstance方法
User user2 = (User) constructor.newInstance("world");
System.out.println(user1.getName());//hello
System.out.println(user2.getName());//world //2.无参构造器
Constructor<?> constructor1 = cc.getConstructor();
//无参构造不能够像1一样赋值
//User user3 = (User) constructor1.newInstance("熊本");
User user3 = (User) constructor1.newInstance();
user3.setName("熊本");
System.out.println(user3.getName());//熊本 //由无参构造器创建对象时,可不必获得构造器,直接由Class对象调用newInstance()方法。
Class<?> cc2 = User.class;
User user4 = (User) cc2.newInstance();
user4.setName("同学");
System.out.println(user4.getName());//同学 //3.下面2个输出语句可看出cc保存类信息,输出的是“class + 类名”。cc.newInstance()是具体类的对象。
System.out.println(cc);//class com.newframe.controllers.api.User
System.out.println(cc.newInstance());//com.newframe.controllers.api.User@3a03464 //4.AccessibleObject、Field类
//首先得到有参构造函数的信息,然后根据构造函数实例化一个对象。
//由getDeclaredField()函数得到类里面的私有成员变量,访问私有成员变量要用setAccessible()函数设置访问权限。
//Field类对象得到成员变量后还可以设置该变量的值,使用set()方法。
Constructor<?> constructor2 = cc.getConstructor(String.class);
User user5 = (User) constructor2.newInstance("改变前:100");
Field field = cc.getDeclaredField("name");
field.setAccessible(true);
field.set(user5,"改变后:50");
System.out.println(user5.getName());//改变后:50 //5.Method.invoke
//首先根据获得的构造函数信息实例化一个对象
//然后由函数名获得类中的公有函数,getMethod("函数名")
//invoke()方法执行由getMethod()获得的函数,这里获得的函数是getter()
//对于获得的有参函数,invoke(对象)里只添加对象名。
Constructor<?> constructor3 = cc.getConstructor(String.class);
User user6 = (User) constructor3.newInstance("你好世界");
//getName是User实体类中的方法
System.out.println(cc.getMethod("getName").invoke(user6));//你好世界 //对于获得到的无参函数,在调用getMethod()函数时,要在getMethod()中指定被获得函数的"函数名"和"参数类型"
//并且在执行该函数(即调用invoke()函数时),要指定对象和参数类型的具体实例。
User user7 = (User) cc.newInstance();
Method method = cc.getMethod("setName", String.class);
method.invoke(user7,"你好哇,这个世界");
System.out.println(user7.getName());//你好哇,这个世界 //6.Modifier类
//Class类中getModifiers()函数返回一个用于描述类,构造器,方法和域的修饰符的整形数值。、
//调用Modifier.toString()方法将整型数值转变成字符串,也是就我们熟悉的public,private,static,final等修饰符。
System.out.println(Modifier.toString(cc.getModifiers()));//无
System.out.println(Modifier.toString(constructor.getModifiers()));//public
System.out.println(Modifier.toString(field.getModifiers()));//private
System.out.println(Modifier.toString(method.getModifiers()));//public //同时,Modifier类还有一些判断修饰符是不是某一类型的方法。
System.out.println(Modifier.isPublic(cc.getModifiers()));
System.out.println(Modifier.isPublic(constructor.getModifiers())); }
}

3,数组的反射

public class TestReflectArray {

    public static void main(String[] args) throws ClassNotFoundException {
//新建4个不同的数组
//一维数组
int[] a = new int[3];
int[] b = new int[4];
//二维数组
int[][] c = new int[3][4];
//String类型的数组
String[] d = new String[3]; //可以对比各个数组所属的类是否相同
System.out.println(a.getClass() == b.getClass());//true
//System.out.println(a.getClass() == c.getClass());不同类型的数组不同比较
System.out.println(a.length == c.length);//但是可以比较长度,true
System.out.println(a.getClass().getName());//[I
System.out.println(d.getClass().getName());//[Ljava.lang.String;
System.out.println(a.getClass().getSuperclass().getName());//java.lang.Object //利用反射生成一个数组
int[] e = (int[]) Array.newInstance(int.class,3);
//0为数组索引下标,1为数字值
Array.set(e,0,1);
Array.set(e,1,2);
Array.set(e,2,3);
System.out.println(Array.get(e,0));
System.out.println(Array.get(e, 1));
System.out.println(Array.get(e, 2)); //利用反射获取数组类型常用的一些方式
Class<?> cc = String[].class;
Class<?> cc1 = Class.forName("[I");
Class<?> cc2 = Class.forName("[Ljava.lang.String;"); System.out.println(cc);
System.out.println(cc1);
System.out.println(cc2); //通过已有的对象获取数组的类型
Class<?> cc3 = e.getClass();
System.out.println(cc3);
//根据类型信息获取数组内成员的类型
Class<?> cc4 = cc3.getComponentType();
System.out.println(cc4);//int
}
}

java中的反射整理的更多相关文章

  1. Java中的反射和注解

    前言 在Java中,反射机制和注解机制一直是一个很重要的概念,那么他们其中的原理是怎么样呢,我们不仅仅需要会使用,更要知其然而之所以然. 目录 反射机制 反射如何使用 注解定义 注解机制原理 注解如何 ...

  2. java中的反射机制在Android开发中的用处

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反 ...

  3. 浅说Java中的反射机制(二)

    写过一篇Java中的反射机制,不算是写,应该是抄了,因为那是别人写的,这一篇也是别人写的,摘抄如下: 引自于Java基础--反射机制的知识点梳理,作者醉眼识朦胧.(()为我手记) 什么是反射? 正常编 ...

  4. 浅说Java中的反射机制(一)

    在学习传智播客李勇老师的JDBC系列时,会出现反射的概念,由于又是第一次见,不免感到陌生.所以再次在博客园找到一篇文章,先记录如下: 引用自java中的反射机制,作者bingoideas.(()为我手 ...

  5. java中动态反射

    java中动态反射能达到的效果和python的语法糖很像,能够截获方法的实现,在真实方法调用之前和之后进行修改,甚至能够用自己的实现进行特别的替代,也可以用其实现面向切片的部分功能.动态代理可以方便实 ...

  6. 第89节:Java中的反射技术

    第89节:Java中的反射技术 反射技术是动态的获取指定的类,和动态的调用类中的内容(没有类前就可以创建对象,将对象的动作完成,这就是动态的获取指定的类). 配置文件把具体实现的类名称定义到配置文件中 ...

  7. java笔记十:java中的反射

    Java中,反射是一种强大的工具.它使您能够创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代表链接.反射允许我们在编写与执行时,使我们的程序代码能够接入装载到JVM中的类的内部信息,而 ...

  8. 【Java基础】java中的反射机制与动态代理

    一.java中的反射机制 java反射的官方定义:在运行状态下,可以获取任意一个类的所有属性和方法,并且可通过某类任意一对象实例调用该类的所有方法.这种动态获取类的信息及动态调用类中方法的功能称为ja ...

  9. java中使用反射获取pojo(实体)类的全部字段值

    说起反射.不得不说它实在是太强大了,通过反射就能够轻轻松松拿到各种东东,假设你想在项目中解除对某个类的依赖,能够考虑用反射. 今天跟大家分享的是通过java中的反射,获取pojo类的全部字段值. 为什 ...

随机推荐

  1. java基础 关于转换流

    转换流有两种:InputStreamReader:将字节流转换为字符流 OutputStreamWriter:将字符流转换为字节流 什么时候使用转换流?由以下分析: 流对象很多,首先要明确那个流对象. ...

  2. python双端队列-collection模块

    双端队列(double-ended queue,或者称deque)在需要按照元素增加的顺序来移除元素时非常有用.其中collection模块,包括deque类型. 使用实例:

  3. 动态解析xml,并生成excel,然后发邮件。

    直接贴代码了! DECLARE @CurrentServer NVARCHAR(100)DECLARE @CurrentDatabase NVARCHAR(100)DECLARE @CurrentLo ...

  4. eclipse搭建elastic-job

    1.官网下载eclipse----面向Java EE企业级开发的Eclipse IDE for Java EE Developers:2.官网下载maven,并配置环境变量---MAVEN_HOME: ...

  5. day 24-1 继承

    继承 什么是继承: 继承是一种创建新类的方式,在 python 中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类 父类必须在子类上面 一个类 可以被多个类继承 一个 ...

  6. [转载]在termux上安装Kali Linux

    最近在手机上下了个Termux,然后想装个kali,就找到了这篇文章. 不过其中的命令有一处错误(在我进行配置的时候报错了): 命令应该是 ./atilo install kali

  7. git知识总结-3.gitignore文件说明

    1.前言 一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表. 通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等. 在这种情况下,我们可以创建一个名 ...

  8. WPF入门之一APP.XAML

    WPF运行之后,App.xaml是应用的声明起始点. 一.指定入口 通过指定Application 的StartupUri属性,指示了启动应用的时候,加载哪个窗口或网页. 最常见的就是将默认的Main ...

  9. 删除Win10资源管理器中的3D对象/音乐/视频文件夹

    Win10如何删除资源管理器中的3D对象/音乐/视频等文件夹?使用Win10系统的用户都知道,打开此电脑之后,资源管理上面会显示文档/音乐/视频等7个文件夹,一些用户认为很少使用到它们,想要除之而后快 ...

  10. SpringBoot相关错误

    1.org.springframework.boot.builder.SpringApplicationBuilder.<init>([Ljava/lang/Object;)V 搭建spr ...