java笔记反射

您所在的位置:网站首页 getdeclaredmethod参数 java笔记反射

java笔记反射

2023-03-11 14:54| 来源: 网络整理| 查看: 265

一、类的加载1.概述

​ 当程序需要使用某个类时,如果类还未被加载到内存中,系统会通过加载、连接、初始化散步来实现对 这个类进行初始化

加载 就是指将class文件读入内存,并为之创建一个Class对象。 任何类被使用时系统都会建立一个Class对象。连接 验证 : 是否有正确的内部结构,并和其他类协调一致 准备 : 负责为类的静态成员分配内存,并设置默认初始化值 解析: 把类中的符号引用转换为直接引用初始化 就是我们以前讲过的初始化步骤

2.类的加载时机

​ a.创建类的实例

​ b.访问类的静态变量,或为静态变量赋值

​ c.调用静态方法

​ d.使用反射方式来强制创建某个类或接口对应的java.lang.Class对象

​ e.初始化某个类的子类

​ f.直接使用java.exe命令来运行某个主类

3.类加载器的概述和分类A:类加载器的概述

​ 负责将.class文件加载到内在中,并为之生成对应的Class对象。

B:类加载器的分类

​ 1.Bootstrap ClassLoader 根类加载器

​ 2.Extension ClassLoader 扩展类加载器

​ 3.Sysetm ClassLoader 系统类加载器

C:类加载器的作用

1.Bootstrap ClassLoader 根类加载器

也被称为引导类加载器,负责Java核心类的加载

比如System,String等。在JDK中JRE的lib目录下rt.jar文件中

2.Extension ClassLoader 扩展类加载器

负责JRE的扩展目录中jar包的加载。

在JDK中JRE的lib目录下ext目录

3.Sysetm ClassLoader 系统类加载器

负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径

二、反射1.反射概述

​ JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;

​ 对于任意一个对象,都能够调用它的任意一个方法和属性;

​ 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

​ 通过一个类的字节码文件对象(Class)反着去剖析这个类的构成

2.获取一个类的字节码文件对象的方式

1.通过Object类的getClass()方法Student s = new Student();//Class 类的实例表示正在运行的java应用程序中的类和接口Class sc = s.getClass();2.任何一个类都有一个.class属性,通过这个属性就可以获取到该类的字节码文件对象Class scl = Student.Class;sc==scl;//true3.Class.forName();全路径:一个类带有包名 全类名ctrl+alt+空格(强制提示)Class> tc = Class.forName("java.lang.Thread");

3.类的构成

​ 构造方法:Constructor

​ 成员变量: Field

​ 成员方法: Method

4.通过反射获取构造方法并创建该类对象

​ 构造方法:Constructor

A.通过反射获取构造方法

getConstructors();getDeclaredConstructors();getConstructor();//可变参数 需要构造方法参数类型的字节码文件作为参数(如String.class) 无参就是获取无参构造 无法获取私有构造getDeclaredConstructor();//可获取私有构造

B.通过反射获取构造方法并创建该类对象

Student s = new Student();Class sc = s.getClass();1.无参构造 构造方法对象中的newInstance() 创建该类对象Object o = sc.getConstructor().newInstance();Student s = (Student)sc.getConstructor().newInstance();2.有参构造Constructor> c = sc.getDeclaredConstructor(String.class,int.class);c.setAccessible(true);//取消权限检查 可以使用私有构造方法Object o = c.newInstance("lisi",25);Student s = (Student)c.newInstance("lisi",25);

反射方式获取一个类的对象:

获取 该类字节码对象(3种方式)》字节码对象 获取 构造方法对象》构造方法对象 取消 权限检查==》构造方法对象 创建 该类对象

如果指向用空参构造创建一个类的对象,那么反射的方式有两种

1.Dog.class.getDeclaredConstructor().newInstance();2.Dog.class.newInstance();

5、通过反射获取成员变量并赋值

Field 字段类型/成员变量类型

A.通过反射获取成员变量

Class sc = Student.class;Field[] fs = sc.getFields();//获取所有公共成员变量对象的数组Field[] dfs = sc.getDeclaredFields();//获取所有成员变量对象的数组 包括私有Field n = sc.getField("name");//获取单个公共成员变量对象Field n = sc.getDeclaredField("money");//获取单个成员变量对象 包括私有

B.通过反射获取成员变量并赋值

Class sc = Student.class;Field n = sc.getField("name");//成员变量名称Constructor scc = sc.getConstructor();scc.setAccessible(true);Student s = scc.newInstance();n.setAccessible(true);n.set(s,"张三");//需要一个该类对象和成员变量值 给哪个对象的那个成员变量赋值Object o = n.get(s);//需要set()方法的该类对象s 返回该成员变量对象System.out.println(o);//打印对象 即是设置的成员变量的值

通过反射方法设置成员变量的值:

获取该类字节码对象==》字节码对象 获取 成员变量对象 ==》成员变量对象设置具体该类对象的成员变量值

6、通过反射获取成员方法并使用

Method 成员方法对象

A.通过反射获取成员方法

Class sc = Student.class;Constructor scc = sc.getDeclaredConstructor();scc.setAccessible(true);Student s = scc.newInstance();Method[] ms = sc.getMethods();//获取所有公共成员方法对象,包括父类的公共方法Method[] dms = sc.getDeclaredMethods();//获取所有的私有成员方法对象,不包括父类sc.getMethod();//需要成员方法名和成员方法参数类型的class类型(可变参数)Method show = sc.getMethod("show",String.class,int.class);sc.getDeclaredMethod();

B.通过反射获取成员方法并使用

Class sc = Student.class;Constructor scc = sc.getDeclaredConstructor();scc.setAccessible(true);Student s = scc.newInstance();Method show = sc.getDeclaredMethod("show");show.invoke(s);//参1:类对象 参2(可变参数):成员方法需要的具体参数Method sho = sc.getDeclaredMethod("sho",String.class,int.class);sho.invoke(s,"张三",23);Method how = sc.getDeclaredMethod("how",double.class);how.setAccessible(true);Object o = how.invoke(s,3.2);//有返回值的成员方法 会返回该方法返回值System.out.println(o);//该方法返回值

反射机制读取配置文件

//peizhi.propertiesclassname=org.westos.demo.Dogmethodname=sleep//Dog类public class Dog { public void eat() { System.out.println("狗吃骨头"); } public void sleep() { System.out.println("狗睡觉"); }}//读取配置文件Properties properties = new Properties();properties.load(new FileReader("peizhi.properties"));Class> classname = Class.forName(properties.getProperty("classname"));Object o = classname.getDeclaredConstructor().newInstance();Method eat = classname.getMethod(properties.getProperty("methodname"));eat.invoke(o);

反射机制越过泛型检查

// 我给你ArrayList 的一个对象,我想在这个集合中添加一个字符串数据,如何实现呢? ArrayList list = new ArrayList(); list.add(100); //list.add("abc"); 报错 //泛型:泛型只在编译期,运行期就擦除了。 Class extends ArrayList> aClass = list.getClass(); //获取add方法对象 Method add = aClass.getDeclaredMethod("add", Object.class); add.invoke(list,"abc"); System.out.println(list);

反射

动态代理:在不修改某个类的情况下对该类中的方法进行增强的一种手段

A:动态代理概述

代理:本来应该自己做的事情,却请了别人来做,被请的人就是代理对象。

举例:春季回家买票让人代买

动态代理:在程序运行过程中产生的这个对象

而程序运行过程中产生对象其实就是我们刚才反射讲解的内容,所以,动态代理其实就是通过反射来生成一个代理

在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,必须要有接口,没有接口使用cglib 可以代理通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口做代理。我们有更强大的代理cglib,Proxy类中的方法创建动态代理类对象 public static Object newProxyInstance(ClassLoader loader,Class>[] interfaces,InvocationHandler h)最终会调用InvocationHandler的方法 InvocationHandler Object invoke(Object proxy,Method method,Object[] args)

被代理对象(目标对象)

代理对象==运行期生成

动态生成代理人的类 Proxy java.lang.reflectstatic Object newProxyInstance(Classloader loader,Class>[]interfaces,InvocationHandler h); //返回一个指定接口的代理类实例 1.Classloader loader类加载器,负责加载代理对象的字节码文件,根被代理对象使用的是同一个类加载器,固定写法 被代理对象.getClass().getClassLoader() 2.Class>[]interfaces 被代理对象实现的所有接口的class数组 固定写法 被代理对象.getClass().getInterfaces() 3.InvocationHandler h 用于提供增强的代码 new InvocationHandler(){增强代码} new InvocationHandler(){ @Override /**proxy 代理对象 * method 方法对象 * args 方法上的参数数组 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //System.out.println("权限校验"); //Object invoke = method.invoke(userDao); //System.out.println("记录日志"); Object invoke=null; if(method.getName().equals("update")){ System.out.println("权限校验"); invoke= method.invoke(userDao); System.out.println("记录日志"); } return invoke; } } Proxy.newProxyInstance();



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3