博客
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-反射相关推荐

  1. Proxy代理 和 Reflect反射(反射的是obj)的概念

    1. Proxy代理 // 供应商(原始对象)let obj = {time:'2018-01-03',name:'net',_r: "123"}// 创建代理商,传入obj数据l ...

  2. Proxy(代理,拦截器),Reflect(反射)

    Proxy(代理,拦截器),Reflect(反射) Proxy: 代理: var duixaing = {"name":"小胖","age" ...

  3. GO语言reflect反射篇

    1.1 reflect反射是什么,为什么需要反射 GO 反射的意义:Go 语言的 ORM 库离不开它,Go 语言的 json 序列化库离不开它, fmt包字符串格式化离不开它,Go 语言的运行时更是离 ...

  4. 利用 Proxy 代理与 Reflect 反射实现 mv 模型视图,实现一个 打怪升级 的小游戏“勇士之战”

    利用 Proxy 代理与 Reflect 反射实现 mv 模型视图,多层数据动态渲染页面,模仿 vue3 双向绑定中 viewModel 核心功能,实现一个 打怪升级 的小游戏"勇士之战&q ...

  5. GO语言基础之reflect反射

    反射reflection 1. 反射可以大大的提高程序的灵活性,使得 interface{} 有更大的发挥余地 2. 反射使用 TypeOf 和 ValueOf 函数从接口中获取目标对象信息 3. 反 ...

  6. Go 语言编程 — reflect 反射机制

    目录 文章目录 目录 为什么需要反射? reflect 包 通过 reflect.TypeOf() 获取对象的反射类型 reflect.Type 通过 reflect.Elem() 获取指针所指向的对 ...

  7. golang reflect 反射 简介

    和Java语言一样,Go也实现运行时反射,这为我们提供一种可以在运行时操作任意类型对象的能力.比如我们可以查看一个接口变量的具体类型,看看一个结构体有多少字段,如何修改某个字段的值等等. TypeOf ...

  8. Java —— Reflect反射机制

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

  9. Go语言类库-reflect(反射)

    概述 什么是反射? 反射是计算机程序在运行时可以访问,检查和修改本身状态或者行为的一种能力,大多数编程语言都支持反射.Go语言中,使用反射可以在程序执行过程中更新变量和检查对象的属性,调用对象的方法. ...

  10. (十)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 反射的 ...

最新文章

  1. Python学习札记(二)
  2. 【Netty】NIO 选择器 ( Selector ) 通道 ( Channel ) 缓冲区 ( Buffer ) 网络通信案例
  3. 语言nomogram校准曲线图_预测模型的概率校准
  4. 有多少种 “图片格式”?
  5. java线程下载文件_Java多线程下载文件实例详解
  6. ps3存档是php文件,PS3存档修改图文详细全教程
  7. 打表法判断素数 c语言,素数打表(4种方法)
  8. PostgreSQL 10.1 手册
  9. 给C盘释放五个G的空间
  10. 使用OpenCV对物体搜索检测与识别
  11. 【小萝莉说Crash】第一期:Unrecognized selector sent to instance xxxx
  12. bcs转10 c语言,ARM汇编转C语言 - ARM技术论坛-ARM嵌入式论坛-人气最火爆ARM学习论坛 - 21ic电子技术开发论坛...
  13. x265 1.8版本更新
  14. 魔法诗~~~一套基于Vue开发的实用、高端、炫酷的响应式前端网页!!!
  15. 计算机主机能上网玩游戏吗,为什么现在人人都有电脑,还要去网吧玩游戏?
  16. 飞蛾逐月优化算法(Matlab实现)
  17. JMeter基本使用
  18. 跟着源码一起学:手把手教你用WebSocket打造Web端IM聊天
  19. 关于人生,理想和抉择的对话
  20. Linux服务器环境安装MySQL8.0.30(通用二进制文件-Generic Binaries)记录

热门文章

  1. PDF文本格式转换器下载免费版
  2. Spring Boot Admin系列(3)-Spring Boot Admin添加登录认证
  3. 2019计算机一级考试题库及答案,2019年全国计算机一级考试题库及答案
  4. 「Adobe国际认证」优秀的设计团队,需要了解的 9 种“设计类型“
  5. 我发现陌生人社交赛道最大的秘密,就是它根本不存在
  6. 如何划分音节并区分重读和非重读
  7. 注册制可能对我们带来的影响-读《三十年股票投资心得》
  8. 推荐一款家庭投影仪?投影仪什么品牌好
  9. 一致性成本和非一致性成本
  10. 上古卷轴 5 :不能与瑟拉娜交换装备的问题