day22Java-Reflect-反射
博客 |
---|
Java-(高级) |
文章目录
- 类加载器
- 反射
- 反射-获取class文件对象的方式
- 反射-通过反射获取构造方法对象相关方法
- 反射-通过反射获取无参构造方法对象
- 反射-通过反射获取带三个参数构造方法对象
- 反射-通过反射获取私有构造方法对象
- 反射-通过反射获取成员变量对象相关方法
- 反射-通过反射获取不同修饰符的成员变量对象
- 反射-通过反射获取成员方法对象相关方法
- 反射-通过反射获取不同修饰符的成员方法对象
- 反射练习-通过配置文件运行类中的方法
- 反射练习-ArrayList\的一个对象,在这个集合中添加一个字符串数据,如何实现呢?
- 反射练习-public void setProperty(Object obj, String propertyName, Object value){}此方法可将obj对象中名为propertyName的属性的值设置为value。
类加载器
在写反射时,先介绍类加载器,因为反射都是在操作运行时Class文件对象,一个java文件,首先要编译成class文件,在使用类加载器加载到内存中。
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。
加载 1.就是指将class文件读入内存,并为之创建一个Class对象。2.任何类被使用时系统都会建立一个Class对象。
连接1.验证 是否有正确的内部结构,并和其他类协调一致2.准备 负责为类的静态成员分配内存,并设置默认初始化值3.解析 将类的二进制数据中的符号引用替换为直接引用
初始化 就是我们以前讲过的初始化步骤
1.类加载器图解
2.类加载器的组成
1)BootStrap:引导类加载器:加载都是最基础的文件 也被称为引导类加载器,负责Java核心类的加载。比如System,String等。在JDK中JRE的lib目录下rt.jar文件中。2)ExtClassLoader:扩展类加载器:加载都是基础的文件负责JRE的扩展目录中jar包的加载。在JDK中JRE的lib目录下ext目录。3)AppClassLoader:应用类加载器:三方jar包和自己编写java文件负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径。
3.类初始化时机
1.创建类的实例2.访问类的静态变量,或者为静态变量赋值3.调用类的静态方法4.使用反射方式来强制创建某个类或接口对应的java.lang.Class对象5.初始化某个类的子类6.直接使用java.exe命令来运行某个主类
反射
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象。
反射:就是通过class文件对象,去使用该文件中的成员变量,构造方法,成员方法。
要想这样使用,首先你必须得到class文件对象,其实也就是得到Class类的对象。
Class类:成员变量 Field构造方法 Constructor成员方法 Method
反射-获取class文件对象的方式
获取class文件对象的方式:
A:Object类的getClass()方法
B:数据类型的静态属性class
C:Class类中的静态方法
public static Class forName(String className)
一般我们到底使用谁呢?A:自己玩 任选一种,第二种比较方便B:开发 第三种为什么呢?因为第三种是一个字符串,而不是一个具体的类名。这样我们就可以把这样的字符串配置到配置文件中。
代码演示
public class ReflectDemo {public static void main(String[] args) throws ClassNotFoundException {//A:Object类的getClass()方法Person p = new Person();Class c = p.getClass();Person p2 = new Person();Class c1 = p2.getClass();System.out.println(p==p2);//falseSystem.out.println(c==c1);//true//B:数据类型的静态属性classClass c2 = Person.class;System.out.println(c1==c2);//true//C:Class类中的静态方法Class c3 = Class.forName("com.ginger.demo01.Person");System.out.println(c2==c3);//true}
}
结果
false
true
true
true
反射-通过反射获取构造方法对象相关方法
Class类中的方法:
Constructor[] getConstructors():获取公共构造方法对象
Constructor<?>[] getDeclaredConstructors():获取所有构造方法对象(包括私有)
Constructor getConstructor(Class<?>… parameterTypes):获取单个公共构造方法对象
Constructor getDeclaredConstructor(Class<?>… parameterTypes): 获取单个公共构造方法对象(包括私有)
Constructor类中的方法:
public void setAccessible(boolean flag):值为true,取消 Java 语言访问检查。
T newInstance(Object… initargs):使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
反射获取构造方法共用的Person类
public class Person {private String name;int age;public String address;public Person() {}private Person(String name) {this.name = name;}public Person(String name, int age) {this.name = name;this.age = age;}public Person(String name, int age, String address) {this.name = name;this.age = age;this.address = address;}public void show() {System.out.println("show");}public void method(String s) {System.out.println("method" + s);}public String getString(String s, int i) {return s + "--" + i;}private void function() {System.out.println("function");}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", address='" + address + '\'' +'}';}
}
反射-通过反射获取无参构造方法对象
代码演示
public class RefletcDemo {public static void main(String[] args) throws Exception {//获取class文件对象Class c = Class.forName("com.ginger.demo02.Person");//Constructor[] getConstructors():获取公共构造方法Constructor[] consArr1 = c.getConstructors();for (Constructor cons1 : consArr1) {System.out.println(cons1);}System.out.println("----------------------------------------------");//Constructor<?>[] getDeclaredConstructors():返回所有构造方法包括私有Constructor[] consArr2 = c.getDeclaredConstructors();for (Constructor cons2 : consArr2) {System.out.println(cons2);}System.out.println("----------------------------------------------");//获取无参构造方法//Constructor<T> getConstructor(Class<?>... parameterTypes):获取单个构造//参数表示的是:你要获取的构造方法的构造参数个数及数据类型的class字节码文件对象Constructor cons3 = c.getConstructor();//返回构造方法对象//T newInstance(Object... initargs):使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。Object o = cons3.newInstance();//等价于//Person p = new Person();System.out.println(o);Person p2 = (Person) o;p2.show();}
}
结果:
public com.ginger.demo02.Person(java.lang.String,int,java.lang.String)
public com.ginger.demo02.Person(java.lang.String,int)
public com.ginger.demo02.Person()
----------------------------------------------
public com.ginger.demo02.Person(java.lang.String,int,java.lang.String)
public com.ginger.demo02.Person(java.lang.String,int)
private com.ginger.demo02.Person(java.lang.String)
public com.ginger.demo02.Person()
----------------------------------------------
Person{name='null', age=0, address='null'}
show
反射-通过反射获取带三个参数构造方法对象
需求:通过反射去获取该构造方法并使用:
public Person(String name, int age, String address)
Person p = new Person(“亚索”,33,“艾欧尼亚”);
System.out.println§;
代码演示
public class RefletcDemo {public static void main(String[] args) throws Exception {//获取Class对象Class c1 = Class.forName("com.ginger.demo03.Person");//获取带参构造方法对象//Constructor<T> getConstructor(Class<?>... parameterTypes)Constructor cons = c1.getConstructor(String.class, int.class, String.class);//通过带参的构造方法对象,创建对象。//T newInstance(Object... initargs)Object o = cons.newInstance("亚索", 33, "艾欧尼亚");//等价于Person p = new Person("亚索",33,"艾欧尼亚");System.out.println(o);Person p = (Person) o;p.show();}
}
结果:
Person{name='亚索', age=33, address='艾欧尼亚'}
show
反射-通过反射获取私有构造方法对象
需求:通过反射获取私有构造方法并使用
private Person(String name)
Person p = new Person(“影流之主”);
System.out.println§;
代码演示
public class ReflectDemo {public static void main(String[] args) throws Exception {//获取Class对象Class c1 = Class.forName("com.ginger.demo04.Person");//获取私有带参构造方法对象//NoSuchMethodException:没有这样的方法//Constructor cons = c1.getConstructor(String.class);//只能获取公共方法,所以就报错了。Constructor cons = c1.getDeclaredConstructor(String.class);//可以获取私有构造方法//public void setAccessible(boolean flag):值为true,取消 Java 语言访问检查。//设置为true就可以访问私有构造方法cons.setAccessible(true);//IllegalAccessException:非法异常Object o = cons.newInstance("影流之主");//因为是私有方法不能访问所以报错了。System.out.println(o);Person p = (Person)o;p.show();}
}
结果:
Person{name='影流之主', age=0, address='null'}
show
反射-通过反射获取成员变量对象相关方法
Class类中的方法:
Field[] getFields():获取公共成员变量对象
Field[] getDeclaredFields():获取所有成员变量对象(包括私有)
Field getField(String name):获取单个公共成员变量
Field getDeclaredField(String name):获取单个成员变量对象(包括私有)
Field类中的方法:
void set(Object obj,Object value):将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
void setAccessible(boolean flag):值为true,取消 Java 语言访问检查。
反射获取构造方法共用的Person类
public class Person {private String name;int age;public String address;public Person() {}private Person(String name) {this.name = name;}public Person(String name, int age) {this.name = name;this.age = age;}public Person(String name, int age, String address) {this.name = name;this.age = age;this.address = address;}public void show() {System.out.println("show");}public void method(String s) {System.out.println("method" + s);}public String getString(String s, int i) {return s + "--" + i;}private void function() {System.out.println("function");}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", address='" + address + '\'' +'}';}
}
反射-通过反射获取不同修饰符的成员变量对象
代码演示
public class ReflectDemo {public static void main(String[] args) throws Exception {//获取Class对象Class c1 = Class.forName("com.ginger.demo05.Person");//获取多个成员变量对象//Field[] getFields():获取公共成员变量对象//Field[] fields1 = c1.getFields();//获取公共成员变量对象//for (Field field : fields1) {// System.out.println(field);//}//System.out.println("---------------------------------------");//Field[] getDeclaredFields():获取所有成员变量对象(包括私有)//Field[] field2 = c1.getDeclaredFields();//获取所有成员变量对象//for (Field field : field2) {// System.out.println(field);//}//System.out.println("---------------------------------------");/*Person p = new Person(); p.address="艾欧尼亚"; System.out.println(p);*///通过无参构造创建对象Constructor cons = c1.getConstructor();Object obj = cons.newInstance();//获取单个成员变量对象//获取address字段并赋值//Field getField(String name):获取单个公共成员变量Field field3 = c1.getField("address");// public void set(Object obj,Object value):将指定对象变量上此 Field 对象表示的字段设置为指定的新值。field3.set(obj, "艾欧尼亚");//把obj对象的addressField字段设置为"艾欧尼亚"。System.out.println(obj);System.out.println("---------------------------------------");//获取name字段并赋值//NoSuchFieldException//Field field4 = c1.getField("name");//Field getDeclaredField(String name):获取单个成员变量对象(包括私有)Field field4 = c1.getDeclaredField("name");//获取单个私有成员变//void setAccessible(boolean flag):值为true,取消 Java 语言访问检查。field4.setAccessible(true);field4.set(obj, "影流之主");System.out.println(obj);System.out.println("---------------------------------------");//获取age字段并赋值//NoSuchFieldException//Field file5 = c1.getField("age");Field file6 = c1.getDeclaredField("age");file6.set(obj,33);System.out.println(obj);}
}
结果:
Person{name='null', age=0, address='艾欧尼亚'}
---------------------------------------
Person{name='影流之主', age=0, address='艾欧尼亚'}
---------------------------------------
Person{name='影流之主', age=33, address='艾欧尼亚'}
反射-通过反射获取成员方法对象相关方法
Class类中的方法:
Method[] getMethods():获取公共成员方法对象(包括从父类继承的公共方法)
Method[] getDeclaredMethods():获取自己所有成员方法对象(包括私有)
Method getMethod(String name, Class<?>… parameterTypes):获取单个公共成员方法对象
Method getDeclaredMethod(String name, Class<?>… parameterTypes):获取单个公共成员方法对象(包括私有)
Method类中的方法:
Object invoke(Object obj, Object… args):对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
void setAccessible(boolean flag):值为true,取消 Java 语言访问检查。
反射获取构造方法共用的Person类
public class Person {private String name;int age;public String address;public Person() {}private Person(String name) {this.name = name;}public Person(String name, int age) {this.name = name;this.age = age;}public Person(String name, int age, String address) {this.name = name;this.age = age;this.address = address;}public void show() {System.out.println("show");}public void method(String s) {System.out.println("method" + s);}public String getString(String s, int i) {return s + "--" + i;}private void function() {System.out.println("function");}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", address='" + address + '\'' +'}';}
}
反射-通过反射获取不同修饰符的成员方法对象
代码演示
public class ReflectDemo {public static void main(String[] args) throws Exception {//创建class对象Class c1 = Class.forName("com.ginger.demo06.Person");//Method[] getMethods():获取公共成员方法对象(包括从父类继承的公共方法)/*Method[] methods1 = c1.getMethods();for (Method method : methods1) {System.out.println(method);}System.out.println("------------------------------------");*///Method[] getDeclaredMethods():获取自己所有成员方法对象(包括私有)/*Method[] methods2 = c1.getDeclaredMethods();for(Method method:methods2){System.out.println(method);}System.out.println("------------------------------------");*///通过无参创建对象Constructor cons = c1.getConstructor();Object obj = cons.newInstance();//获取单个成员方法对象//Method getMethod(String name, Class<?>... parameterTypes):获取单个公共成员方法对象//第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型Method m1 = c1.getMethod("show");//执行方法// obj.m1(); 错误//第一个参数表示对象是谁,第二参数表示调用该方法的实际参数//invoke()方法返回值是,obj对象调用方法(这里是show)的返回值。show()方法没有返回值,这里返回是null。Object o = m1.invoke(obj);//调用obj对象的m1方法System.out.println(o);//nullSystem.out.println("------------------------------------");Method m2 = c1.getMethod("method", String.class);m2.invoke(obj, "-影流之主");System.out.println("------------------------------------");Method m3 = c1.getMethod("getString", String.class, int.class);Object s = m3.invoke(obj, "格雷福斯-", 45);System.out.println(s);System.out.println("------------------------------------");//NoSuchMethodException:未发现该方法//Method m4 = c1.getMethod("function");//Method getDeclaredMethod(String name, Class<?>... parameterTypes):获取单个公共成员方法对象(包括私有)Method m4 = c1.getDeclaredMethod("function");//IllegalAccessException:非法的访问异常m4.setAccessible(true);//取消 Java 语言访问检查。m4.invoke(obj);}
}
结果:
show
null
------------------------------------
method-影流之主
------------------------------------
格雷福斯---45
------------------------------------
function
反射练习-通过配置文件运行类中的方法
class.txt文件内容:
通过修改className的值,实现了我不需要修改代码,只用修改配置文件就可以实现调用不同类的work方法。
className=com.ginger.demo01.Teacher
method=work
Student类
public class Studnet {public void work(){System.out.println("学生要学习");}
}
Teacher类
public class Teacher {public void work(){System.out.println("老师要教书");}
}
测试
public class ReflectTest {public static void main(String[] args) throws Exception {//没使用反射前//如果我有一个需求,随着实际的变化我需要老师、学生、工程师、或者医生类,每个类中都有一个work//方法,不同的对象做不同的工作。//Student s = new Student(); 某个时间我又不要学生对象//work();//Teacher t = new Teacher();//work();//Doctor d = new Doctor();//work();//或者某个时间我需要工程师对象,这时候就得要改代码,一般情况下代码是不能改的。可能会牵扯很多的代码。//使用反射后Properties p = new Properties();//读取数据p.load(new FileReader("class.txt"));//通过建获取值String className = p.getProperty("className");String method = p.getProperty("method");//获取class文件对象Class c1 = Class.forName(className);//通过无参构造创建对象Constructor cons = c1.getConstructor();Object obj = cons.newInstance();//获取方法对象Method m1 = c1.getMethod("work");m1.invoke(obj);}
}
结果:
老师要教书
反射练习-ArrayList<Integer>的一个对象,在这个集合中添加一个字符串数据,如何实现呢?
首先要明白的是集合的泛型,其实是编译器器看的,在java文件编译成class文件的时候,是根本没有泛型的,这个问题就是绕过编译器就可以实现。
通过反编译查看创建的一个ArrayList集合,根本没有泛型。
public class ArrayListDemo{public ArrayListDemo(){}public static void main(String args[]){ArrayList list = new ArrayList();}
}
代码实现
public class ArrayListDemo {public static void main(String[] args) throws Exception {//创建集合对象ArrayList<Integer> list = new ArrayList<>();//其实就是通过反射获取到list集合字节码文件对象,在使用add方法添加一个字符串即可。Class c1 = list.getClass();//获取list集合的add方法对象Method m1 = c1.getMethod("add", Object.class);//执行方法m1.invoke(list,"hello");System.out.println(list);}
}
结果:
[hello]
反射练习-public void setProperty(Object obj, String propertyName, Object value){}此方法可将obj对象中名为propertyName的属性的值设置为value。
代码演示
public class ToolDemo {public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {Student s = new Student();Tool.setProperty(s, "name", "疾风剑豪");System.out.println(s);Tool.setProperty(s, "age", 35);System.out.println(s);}
}
class Student {private String name;public int age;@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}
Tool工具类
public class Tool {public static void setProperty(Object obj, String propertyName, Object value) throws NoSuchFieldException, IllegalAccessException {//获取class文件对象Class c1 = obj.getClass();//获取字段对象//防止是私有成员Field field = c1.getDeclaredField(propertyName);//取消Java的访问检查field.setAccessible(true);//设置obj对象属性值field.set(obj,value);}
}
结果:
Student{name='疾风剑豪', age=0}
Student{name='疾风剑豪', age=35}
day22Java-Reflect-反射相关推荐
- Proxy代理 和 Reflect反射(反射的是obj)的概念
1. Proxy代理 // 供应商(原始对象)let obj = {time:'2018-01-03',name:'net',_r: "123"}// 创建代理商,传入obj数据l ...
- Proxy(代理,拦截器),Reflect(反射)
Proxy(代理,拦截器),Reflect(反射) Proxy: 代理: var duixaing = {"name":"小胖","age" ...
- GO语言reflect反射篇
1.1 reflect反射是什么,为什么需要反射 GO 反射的意义:Go 语言的 ORM 库离不开它,Go 语言的 json 序列化库离不开它, fmt包字符串格式化离不开它,Go 语言的运行时更是离 ...
- 利用 Proxy 代理与 Reflect 反射实现 mv 模型视图,实现一个 打怪升级 的小游戏“勇士之战”
利用 Proxy 代理与 Reflect 反射实现 mv 模型视图,多层数据动态渲染页面,模仿 vue3 双向绑定中 viewModel 核心功能,实现一个 打怪升级 的小游戏"勇士之战&q ...
- GO语言基础之reflect反射
反射reflection 1. 反射可以大大的提高程序的灵活性,使得 interface{} 有更大的发挥余地 2. 反射使用 TypeOf 和 ValueOf 函数从接口中获取目标对象信息 3. 反 ...
- Go 语言编程 — reflect 反射机制
目录 文章目录 目录 为什么需要反射? reflect 包 通过 reflect.TypeOf() 获取对象的反射类型 reflect.Type 通过 reflect.Elem() 获取指针所指向的对 ...
- golang reflect 反射 简介
和Java语言一样,Go也实现运行时反射,这为我们提供一种可以在运行时操作任意类型对象的能力.比如我们可以查看一个接口变量的具体类型,看看一个结构体有多少字段,如何修改某个字段的值等等. TypeOf ...
- Java —— Reflect反射机制
JAVA反射机制是在运行时,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java的反射机制. ...
- Go语言类库-reflect(反射)
概述 什么是反射? 反射是计算机程序在运行时可以访问,检查和修改本身状态或者行为的一种能力,大多数编程语言都支持反射.Go语言中,使用反射可以在程序执行过程中更新变量和检查对象的属性,调用对象的方法. ...
- (十)reflect反射
文章目录 1 反射的基本概念 2 example 2.1 exa1 2.2 exa2 2.4 exa3 2.3 exa4 2.5 exa5 2.6 exa6 2.7 exa7 3 注意事项 1 反射的 ...
最新文章
- Python学习札记(二)
- 【Netty】NIO 选择器 ( Selector ) 通道 ( Channel ) 缓冲区 ( Buffer ) 网络通信案例
- 语言nomogram校准曲线图_预测模型的概率校准
- 有多少种 “图片格式”?
- java线程下载文件_Java多线程下载文件实例详解
- ps3存档是php文件,PS3存档修改图文详细全教程
- 打表法判断素数 c语言,素数打表(4种方法)
- PostgreSQL 10.1 手册
- 给C盘释放五个G的空间
- 使用OpenCV对物体搜索检测与识别
- 【小萝莉说Crash】第一期:Unrecognized selector sent to instance xxxx
- bcs转10 c语言,ARM汇编转C语言 - ARM技术论坛-ARM嵌入式论坛-人气最火爆ARM学习论坛 - 21ic电子技术开发论坛...
- x265 1.8版本更新
- 魔法诗~~~一套基于Vue开发的实用、高端、炫酷的响应式前端网页!!!
- 计算机主机能上网玩游戏吗,为什么现在人人都有电脑,还要去网吧玩游戏?
- 飞蛾逐月优化算法(Matlab实现)
- JMeter基本使用
- 跟着源码一起学:手把手教你用WebSocket打造Web端IM聊天
- 关于人生,理想和抉择的对话
- Linux服务器环境安装MySQL8.0.30(通用二进制文件-Generic Binaries)记录
热门文章
- PDF文本格式转换器下载免费版
- Spring Boot Admin系列(3)-Spring Boot Admin添加登录认证
- 2019计算机一级考试题库及答案,2019年全国计算机一级考试题库及答案
- 「Adobe国际认证」优秀的设计团队,需要了解的 9 种“设计类型“
- 我发现陌生人社交赛道最大的秘密,就是它根本不存在
- 如何划分音节并区分重读和非重读
- 注册制可能对我们带来的影响-读《三十年股票投资心得》
- 推荐一款家庭投影仪?投影仪什么品牌好
- 一致性成本和非一致性成本
- 上古卷轴 5 :不能与瑟拉娜交换装备的问题