()
9.1概念JAVA反射机制在运行状态下可以知道任何类的所有属性和方法; 可以对任何对象调用其任何方法和属性; 公共、受保护、私有。
面向对象(OO )、专用、不可访问。 动态获取这些信息并动态调用对象方法的功能称为java语言反射机制。 **
反射是将java类的各种组件映射到单个java对象。 例如,类包含成员变量、方法、生成方法和包等信息。 反射技术允许您解剖类并将每个组件映射到单个对象。
物理:有通过镜子可以知道物体存在的反射概念。 看镜像和名字等,知道物体在哪里。
(实际上,一个类中描述了这些成员方法、生成方法和参与类中的一个类)图是类的常规加载过程。 反射的原理在class对象中。 熟悉加载时: Class对象的来源是将Class文件导入内存并为其创建Class对象。
Student.java---Student.class已编译成字节码文件。
9.2在日常第三方APP复制开发过程中,如果某个类的成员变量、方法或属性是专用的,或者只对系统APP应用开放,则可以使用Java反射机制进行反射所需的专用当然,并不是一切都适合反射。 从以前开始,通过反射得到的结果就遇到了与预想不同的情况。 阅读源代码后,在分层调用后,在最终返回结果的位置验证APP应用程序的权限,对未经授权的APP应用程序返回值是没有意义的默认值,否则返回实际值是为了保护用户的隐私
反射是框架设计的灵魂
(使用前提条件:必须先获得代表性字节码的Class,Class类用于表示. Class文件(字节码) )
9.2.1反编译:class--.java
9.2.2通过反射机制访问java对象的属性、方法、构建方法等;
用户用户=new user (; -”创建的java文件--XXX.class
将来分配值时,是不是报告错了,而不是User类? 有紧密耦合的状态,我们做OO的目的是高凝聚、松散耦合,简言之,就是在模块内部实现特定的功能,模块和模块之间的关联度不是很高。
该方式是编译时
我们接下来写程序,应该经常在运行时给出值。
9.3反射机制的相关类别
与Java反射相关的类包括: 类名用途Class类表示类的实体,在运行的Java APP应用程序中表示类和接口
Field类表示类的成员变量。 成员变量也称为类的属性
Method类表示类的方法
构造器类表示如何构建类
9.3.1在Java中查看Class类的api
Class类的实例表示正在运行的Java APP应用程序中的类和接口。 也就是说,jvm具有n个或更多实例,每个类都有其Class对象。 Class (包括基本数据类型)没有公共生成方法。 加载类后,类对象由Java虚拟机自动生成,并通过调用类加载器的defineClass方法自动生成。 也就是说,我们不需要自己处理创建,JVM已经为我们创建了。
没有公共机制。 方法一共64个太多了。 接下来详细调查一下使用哪个吧
从9.3.2字符串中获取类名方法的含义的StringgetClass表示此对象的运行时类的Class对象
ClassforName具有指定名称的类的Class对象
包类没有属性Type
参考代码: Stringstr='今天是反射路线'; Classclz=str.getClass (; //获得当前正在运行的类; system.out.println(clz; Classclz2=Integer.TYPE; //包装类型,不同; 包装类. typesystem.out.println(clz2); 系统. out.println (boolean.type; system.out.println(double.type ); 系统. out.println (character.type;
9.3.3获取class对象的三种方法Object:getClass
任何数据类型(包括基本数据类型)都具有“静态”class属性,此时可以通过类名.属性访问。
类Class的静态方法: forname (字符串类名称路径) )。
引用代码//1.1使用第一种方法获取User的Class对象的Useruser=newUser (; 得到User对象,在内存中; Classclz1=user.getClass (; //对象. getclass system.out.println (clz 1; //clz1:是什么类型的? C
om.aaa.chapter07.User;路径+类名;//2.使用第二种方式;Class clz2=User.class; //类名.class 这个静态属性.System.out.println(clz2);//这时候,我们是不是考虑一下,之前讲的那个原理图。证明原理图,里面,正在运行的Class是一个。System.out.println(clz1==clz2);//3.Class.forName(类路径方式)try {Class clz3=Class.forName("com.aaa.chapter07.User");System.out.println(clz3);System.out.println(clz2==clz3);} catch (ClassNotFoundException e) {e.printStackTrace();}提问?最常用哪种?一般用第三个。松耦合方式。
9.3.4 通过反射来获取构造方法
调用方法:
1.获取构造方法:
1).批量的方法: public Constructor[] getConstructors():所有"公有的"构造方法 public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
2).获取单个的方法,并调用: public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法: public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;
例如:
调用构造方法: Constructor-->newInstance(Object... initargs)package com.aaa.chapter07;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.sql.Connection;/** * Created by djzg on 2020/3/10 10:24 */public class Constructors {public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {Class clz=Class.forName("com.aaa.chapter07.User");//2.获取所有公共字段;// Field[] fields = clz.getFields();// for(Field f:fields){// System.out.println(f);// }//2.获取所有共有 私有字段;// Field[] fields = clz.getDeclaredFields();// for(Field f:fields){// System.out.println(f);// }Field field=clz.getField("country");System.out.println(field);Object obj=clz.getConstructor().newInstance();field.set(obj,"中国");User u=(User)obj;System.out.println(u.getCountry());}}
2、newInstance是 Constructor类的方法(管理构造函数的类) api的解释为: newInstance(Object... initargs) 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。 它的返回值是T类型,所以newInstance是创建了一个构造方法的声明类的新实例对象。并为之调用
package com.aaa.chapter07;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;/** * Created by djzg on 2020/3/10 22:29 */public class InstanceDemo {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {Class clz=Class.forName("com.aaa.chapter07.User");//1.调用第一个默认构造方法,没有参数,创建实例之后,再次使用setter赋值。// Constructor constructor = clz.getConstructor();//Alt+Enter,// Object obj=constructor.newInstance();// User user=(User)obj;// user.setName("csdwg");// System.out.println(obj);//2.调用第二个有3个参数的构造方法,公共的构造方法,注意里面参数的使用方式.// Constructor constructor2 = clz.getConstructor(String.class,char.class,Integer.class);// Object obj2=constructor2.newInstance("djzg",'男',18);//类似于之前的构造方法,填充值;// User user2=(User)obj2;// System.out.println(user2);//3.调用第三个私有构造方法,这个构造方法,我们说外部无法访问.Constructor declaredConstructor = clz.getDeclaredConstructor(String.class);//设置私有构造方法,可以访问,强制(暴力)访问.declaredConstructor.setAccessible(true);Object obj=declaredConstructor.newInstance("nrdhn");User user3=(User)obj;System.out.println(user3);}}
9.3.5 获取成员变量并调用
获取成员变量并调用:
1.批量的
1).Field[] getFields():获取所有的"公有字段"
2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
2.获取单个的:
1).public Field getField(String fieldName):获取某个"公有的"字段;
2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)
设置字段的值:
Field --> public void set(Object obj,Object value):
参数说明:
1.obj:要设置的字段所在的对象;
2.value:要为字段设置的值;