java反射(概念)
反射的一些概述:
—什么是反射机制:
反射机制是java动态性之一,而说到动态性首先得了解动态语言。那么何为动态语言
–什么是动态语言
是指程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化。比如常见的javaScript就是动态语言,除此之外Ruby,python等也属于动态语言,而c、c++则不属于动态语言。
–java是动态语言吗
从动态语言能在运行时改变程序结构或则变量上看,Java和c、c++一样都不属于动态语言。但是java却又有一个非常突出的与动态相关的机制:反射机制。java通过反射机制,可以在程序运行时加载,探知和使用编译期间完全未知的类,并且可以生成相关类对象实例,从而可以调用其方法或则改变某个属性值。所有Java也可以算得上是一个半动态的语言
–什么是反射机制
在java中的反射机制是指在运行状态中,对任意一个类都能知道这个类所有的属性和方法;并且对任意一个对象,都能够调用它的任意一个方法;这种动态获取信息以及动态调用对象方法的功能成为java语言的反射机制。
一句话概述:反射就是把java类中的各种成分映射成一个个的Java对象
反射的应用场合
在编译时根本无法知道该对象或类可能属于哪些类,程序只依靠运行时信
息来发现该对象和类的真实信息
反射的作用
通过反射可以使程序代码访问装载到JVM 中的类的内部信息
获取已装载类的属性信息
获取已装载类的方法
获取已装载类的构造方法信息
反射技术的引入
在JDK中,主要由以下类来实现Java反射机制,这些类都位于
java.lang.reflect 包中
Class类:代表一个类
Field 类:代表类的成员变量(属性)
Method类:代表类的成员方法
Constructor 类:代表类的构造方法
Array类:提供了动态创建数组,以及访问数组的元素的静态方法
反射技术的入口类Class
- Class类是Java 反射机制的起源和入口
用于获取与类相关的各种信息
提供了获取类信息的相关方法
Class类继承自Object类
-
Class类是所有类的共同的图纸
每个类有自己的对象,好比图纸和实物的关系
每个类也可看做是一个对象,有共同的图纸Class,存放类的结构信息,
能够通过相应方法取出相应信息
类的名字 属性 方法
构造方法
父类和接口
class常用方法:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3XLVC94E-1574769376392)(D:\学习文件\博课\img\反射class.png)]
使用反射可以在编译和运行期间动态获取类的信息
1.获取类class对象
获取方式:①、通过类对象获取类的Class
②、通过类的名称、类名.class
③、通过完整路径字符串获取
Class c=Class.forName(“类的路径”);
2.获取类中属性Field
①、获取类中所有public属性
Field[] f=Class.getFields();
a.getName(), a.getType().getSimpleName()//取成员类型
–getFields(); //获得所有public属性
–getField(String name);//获得指定public属性
Field | getDeclaredField(String name) 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。 |
---|---|
Field[] | getDeclaredFields() 返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。 |
3.获取类中方法methods
①、获取类中所有的public的方法、不仅时当前类的,还能获取到所有继承类的public的方法
Method m[]=class.getMethods();
–getMethods(); //获得所有public方法
–getMethod(String name,Class[] args);//获得指定public方法
参数传递的是Class类型,基本数据类型的class与它封装类的class是不一样的 例:int.class;
Method | getDeclaredMethod(String name, Class<?>… parameterTypes) 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。 |
---|---|
Method[] | getDeclaredMethods() 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。 |
获取方法的参数 Parameter
m.getName(); 方法名 m.getReturnType(); 方法返回值 类型
Parameter[] p=m.getParameters(); 方法所有参数
4.类的基本信息(包路径Package)
①、Package age=类名.getPackage;
在反射中,java将类中所有的信息都封装成了对象
类–>Class
T | newInstance() 创建此 Class 对象所表示的类的一个新实例。 类似于调用该类的无参构造方法 |
---|---|
Field[] | getDeclaredFields 返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段 |
Method[] | getDeclaredMethods() 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。 |
Constructor<T> | getConstructor(Class<?>… parameterTypes) 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。 |
---|---|
Constructor<?>[] | getConstructors() 返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。 |
包–>Package
属性–>Field
返回值 | 方法 描述 |
---|---|
String | getName() 返回此 Field 对象表示的字段的名称 |
Class<?> | getType() 返回一个 Class 对象,它标识了此 Field 对象所表示字段的声明类型。 .getSimpleName()//取成员类型 |
Class.getField(String)方法可以获取类中的指定字段(可见的), 如果是私有的可以用getDeclaedField(“name”)方法获取,通过set(obj, “李四”)方法可以设置指定对象上该字段的值, 如果是私有的需要先调用setAccessible(true)设置访问权限,用获取的指定的字段调用get(obj)可以获取指定对象中该字段的值
方法–>Mothod
Class.getMethod(String, Class…) 和 Class.getDeclaredMethod(String, Class…)方法可以获取类中的指定方法,
如果为私有方法,则需要打开一个权限。setAccessible(true);
用invoke(Object, Object…)可以调用该方法,
跟上面同理,也能一次性获得所有的方法
参数–>Parameter
构造方法–>Constructor
T | newInstance(Object… initargs) 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。 |
---|---|
getConstructor(String.class,int.class)方法获取一个指定的构造函数然后再调用Constructor类的newInstance(“张三”,20)方法创建对象
接口–>interfaces()
Class[] getInterfaces():确定此对象所表示的类或接口实现的接口
返回值:接口的字节码文件对象的数组
2.6、获取指定资源的输入流
InputStream getResourceAsStream(String name)
return:一个 InputStream 对象;如果找不到带有该名称的资源,则返回null
参数:所需资源的名称,如果以"/“开始,则绝对资源名为”/"后面的一部分。
2.7、动态代理的概述和实现
动态代理:一种设计模式,其非常简单,很容易理解,你自己可以做这件事,但是觉得自己做非常麻烦或者不方便,所以就叫一个另一个人(代理)来帮你做这个事情,而你就不用管了,这就是动态代理。举个例子,买火车票叫人代买。
在程序运行过程中产生的这个对象,而程序运行过程中产生对象其实就是我们刚才反射讲解的内容,所以,动态代理其实就是通过反射来生成一个代理
在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口做代理。我们有更强大的代理cglib,Proxy类中的方法创建动态代理类对象
分三步,但是注意JDK提供的代理正能针对接口做代理,也就是下面的第二步返回的必须要是一个接口。
1、new出代理对象,通过实现InvacationHandler接口,然后new出代理对象来。
2、通过Proxy类中的静态方法newProxyInstance,来将代理对象假装成那个被代理的对象,也就是如果叫人帮我们代买火车票一样,那个代理就假装成我们自己本人
3、执行方法,代理成功
反射总结(简单运用)
—获取字节码 Class.forname(“包名.文件名”);
–获取构造方法 getConstructor(String.class,int.class)方法获取一个指定的构造函数然后再调用Constructor类的 newInstance(“张三”,20)方法创建对象
0、通过反射创建对象的方式
1、Class对象的newInstances()
2、通过构造函数对象的newInstances()
1、对属性值的操作
Filed对象.getXXX(Object obj) : obj表示当前反射的类的对象
.setXXX(Object obj)
2、执行方法操作
通过method对象的invoke(Object obj,Object… param)调用方法
3、Array用于操作数组
创建数组:Array.newInstance(String.class, 3);
往数据里存入数据:Array.set(arr, 0, “100”);
取出指定下标的数据:Array.get(arr0, 1)
ect obj) : obj表示当前反射的类的对象
.setXXX(Object obj)
2、执行方法操作
通过method对象的invoke(Object obj,Object… param)调用方法
3、Array用于操作数组
创建数组:Array.newInstance(String.class, 3);
往数据里存入数据:Array.set(arr, 0, “100”);
取出指定下标的数据:Array.get(arr0, 1)