反射 :reflection

程序的一种内省机制

程序可以在运行期间动态的创建对象,获取对象类型,调用对象行为

内省机制在java和.net语言中有,在早期的C,C++,delphi,vb这些语言都没有内省机制。

//方法的可变参数

public void playDisc(Class... cl) {

}

反编译后,可变参数的本质就是数组

public transient void playDisc(Class aclass[])

{

}

Class

Class类的类表示正在运行的Java应用程序中的类和接口

1 类的加载概述和加载时机

A:类的加载概述

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

加载:就是指将class文件读入内存,并为之创建一个class对象,任何类被使用时系统都会建立一个class对象。

连接:(三步:验证、准备、解析)

验证 是否有正确的内部结构,并和其他类协调一致

准备 负责为类的静态成员分配内存,并设置默认初始化值

解析 将类的二进制数据中的符号引用替换为直接引用

初始化 就是以前常用的初始化步骤(创建一个对象时字节码文件加载进来的过程

B加载时机

创建类的实例

访问类的静态变量,或者为静态变量赋值

调用类的静态方法

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

初始化某个类的子类

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

2 类加载器的概述和分类

A类加载器的概述

负责将。class文件加载到内存中并为之生成对应的class对象。类加载机制可以不用关心,但是此处的了解有利于更好地理解程序的运行

B类加载器的分类

Bootstrap classloader 根类加载器

Extension classloader 扩展类加载器

system classloader 系统类加载器

C类加载器的作用

Bootstrap classloader 根类加载器

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

比如system,string类等,在JDK中JRE放入lib目录下rt.jar文件中

Extension classloader 扩展类加载器

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

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

system classloader 系统类加载器

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

3 反射概述

A 反射概述

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

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

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

想要解剖一个类,必须先要获取到该类的字节码文件对象。

而解剖使用的就是Class类中的方法,所以要先获取到每一个字节码文件对应的class类型的对象。

B 获取对象类型的方法:(三种)

1:类名.class 静态属性class,锁对象

Class aa = Dog.class; //通过xxx.class的方式获取数据类型

2:对象.getclass(); Object类的个体class()方法,判断两个对象是否在同一个字节码文件

Dog dog = new Dog("旺财");

Class bb = dog.getClass();//在程序运行期,动态湖区

System.out.println(bb);

3:class.forname()需要抛出异常; class类中静态方法forname(),读取配置文件 可以只改配置文件获取不同的.class文件

Class.forname(“oracle.jdbc.driver.OracleDriver”);

//作用1、检查驱动是否存在

2. 通过静态代码块,给静态变量defaultDriver赋值并做了初始化操作

3. 在DriverManager.getConnection中调用前面的静态变量

Class.forName("oracle.jdbc.driver.OracleDriver");

Connection connection = DriverManager.getConnection("xxx","aa","123456");

//1. 检查数据类型是否存在

2. 通过静态代码块给静态变量初始化 -----静态变量存储与JVM的方法区

3. ClassLoader ,把数据类型加载到JVM的方法区

4. 返回Class对象

C 三种获取对象类型的方式实例

public class Test1_reflect { //三种获取class的方式实例

/**

*

* @param args

* @throws ClassNotFoundException

*/

public static void main(String[] args) throws ClassNotFoundException {

Class clazz1= Class.forName("bean.Person");

Class clazz2= Person.class;

Person p=new Person();

Class clazz3=p.getClass();

System.out.println(clazz1==clazz2);

System.out.println(clazz2==clazz3);

}

}

4 Class,forname()读取配置文件举例

榨汁机:

public class Test2_reflect {

/*

* 用forname获取对象,在使用时只需要更改配置文件即可以完成操作

*/

public static void main(String[] args) throws Exception {

/*没用到反射

* Juicer j=new Juicer(); //购买榨汁机

* j.run(new Apple()); //榨汁机中放苹果

* j.run(new Orange()); //榨汁机中放橘子*/

//用反射和配置文件

BufferedReader br=new BufferedReader(new FileReader("config.properties"));

Class clazz =Class.forName(br.readLine());

Fruit f= (Fruit) clazz.newInstance(); //父类引用指向子类对象,水果的引用指向了苹果对象

//clazz.newInstance();根据配置文件创建了一个Object类型的对象,使用时需要强转

Juicer j=new Juicer();

j.run(f);

}

}

interface Fruit{

public void squeeze();

}

class Apple implements Fruit{

public void squeeze() {

System.out.println("榨出一杯苹果汁");

}

}

class Orange implements Fruit{

public void squeeze() {

System.out.println("榨出一杯橘子汁");

}

}

class Juicer{

public void run(Fruit f) {

f.squeeze();

}

/*public void run(Apple a) {

a.squeeze();

}

public void run(Orange o) {

o.squeeze();

}*/

}

5 通过反射获取带参构造方法并使用

constructor

Class类的newinstance()方法时使用该类无参的构造函数和创建对象,如果一个类没有无参构造函数,就不能这样创建了,可以调用Class类的getConstructor(String。class,int.class)方法获取一个指定的构造函数然后再调用Constructor类的newInstan(“张三”20)方法创建对象。

public class Test3_reflect {

/*

* Class类的newinstance()方法时使用该类无参的构造函数和创建对象,如果一个类没有无参构造函数,就不能这样创建了,

* 可以调用Class类的getConstructor(String。class,int.class)方法获取一个指定的构造函数

* 然后再调用Constructor类的newInstan(“张三”20)方法创建对象。

*/

public static void main(String[] args) throws Exception {

Class clazz=Class.forName("bean.Person");

//Person p=(Person) clazz.newInstance(); 通过无参构造创建对象

//System.out.println(p);

//void.class

Constructor c=clazz.getConstructor(String.class,int.class); //反射阶段操作字节码,给的是字节码(获取有参构造)

Person p =(Person) c.newInstance("张三",23); //通过有参构造创建对象

System.out.println(p);

}

}

6 通过反射获取成员变量并使用

Field

Class.getFiled(String)方法可以获取类中指定字段(可见的),如果是私有的可以用getDeclaedField("name")方法获取,通过set(obj,"李四")方法可以设置指定对象上该字段的值,如果是私有的需要先调用setAccessible(ture)设置访问权限,用获取的指定字段调用get(obj)可以获取指定对象中该字段的值

public class Test4_reflect {

/**

* Class.getFiled(String)方法可以获取类中指定字段(可见的),如果是私有的可以用getDeclaedField("name")方法获取,

* 通过set(obj,"李四")方法可以设置指定对象上该字段的值,如果是私有的需要先调用setAccessible(ture)设置访问权限,

* 用获取的指定字段调用get(obj)可以获取指定对象中该字段的值

* @throws Exception

*/

public static void main(String[] args) throws Exception {

Class clazz=Class.forName("bean.Person");

Constructor c=clazz.getConstructor(String.class,int.class); //反射阶段操作字节码,给的是字节码(获取有参构造)

Person p =(Person) c.newInstance("张三",23); //通过有参构造创建对象

//Field f=clazz.getField("name");//获取name字段

//f.set(p, "李四"); //修改P的姓名的值

Field f=clazz.getDeclaredField("name");//暴力反射获取字段(可以获取私有的字段)

f.setAccessible(true); //去除私有权限

f.set(p, "李四");

System.out.println(p);

}

}

7 通过反射获取方法并使用

Method

Class.getMethod(String,Class...)和Class。getDeclaredMethod(String,Class...)方法可以获取类中的指定方法,调用invoke(Object,Object...)可以调用该方法,Class。getMethod(“eat")invoke(obj)Class.getMethod("eat",int.class)invoke(obj,10)

public class Test5_Method {

/**

* Class.getMethod(String,Class...)和Class。getDeclaredMethod(String,Class...)方法可以获取类中的指定方法,

* 调用invoke(Object,Object...)可以调用该方法,

* Class。getMethod(“eat")invoke(obj)Class.getMethod("eat",int.class)invoke(obj,10)

* @param args

* @throws Exception

*/

public static void main(String[] args) throws Exception {

Class clazz=Class.forName("bean.Person");

Constructor c=clazz.getConstructor(String.class,int.class); //反射阶段操作字节码,给的是字节码(获取有参构造)

Person p =(Person) c.newInstance("张三",23); //通过有参构造创建对象

Method m=clazz.getMethod("eat"); //获取无参eat方法

m.invoke(p); //执行无参方法

Method m1=clazz.getMethod("eat",int.class); //获取有参eat方法

m1.invoke(p,10); //执行有参方法

}

}

8 通过反射越过泛型检查

A案例演示

ArrayList的一个对象,在这个集合中添加一个字符串数据。

public class Test1 {

/**

* @param args

* ArrayList的一个对象,在这个集合中添加一个字符串数据

* 泛型只在编译期有效,在运行期会被擦除掉

* @throws Exception

*/

public static void main(String[] args) throws Exception {

ArrayList list=new ArrayList<>();

list.add(111);

list.add(222);

Class clazz =Class.forName("java.util.ArrayList"); //获取字节码对象

Method m=clazz.getMethod("add", Object.class);

m.invoke(list, "abc");

System.out.println(list); //泛型被擦除掉了所添加进去的内容是新的类型

}

}

9 通过反射写一个通用的设置某个对象的某个属性为指定的值

A案例演示

public void setProperty(object obj,String propertyName,Object value){},此方法可将obj对象中名为propertyName的属性值设置为value。

public class Test2 {

/**

* public void setProperty(object obj,String propertyName,Object value){},

* 此方法可将obj对象中名为propertyName的属性值设置为value。

* @param args

* @throws Exception

*/

public static void main(String[] args) throws Exception {

Student s=new Student("张三",23);

System.out.println(s);

Tools t=new Tools();

t.setProperty(s, "name", "李四");

System.out.println(s);

}

}

class Student{

private String name;

private int age;

public Student() {

super();

}

public Student(String name,int age) {

super();

this.name=name;

this.age=age;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

@Override

public String toString() {

return "Student [name=" + name + ", age=" + age + "]";

}

}

import java.lang.reflect.Field;

public class Tools {

public void setProperty(Object obj,String propertyName,Object value) throws Exception{

Class clazz =obj.getClass(); //获取字节码对象

Field f=clazz.getDeclaredField(propertyName); //暴力反射获取字段

f.setAccessible(true); //去除权限

f.set(obj, value);

}

}

练习:

已知一个类定义如下

package cn;

public class DenoCLass{

public void run(){

system.out.println("welcome to china!);

}

}

(1)写一个Properties格式配置文件,配置类的完整名称

(2)写一个程序,读取这个Properties配置文件,获得类的完整名称并加载这个类,用反射的方式运行run方法。

作业:

自定义日志系统,在系统运行目录按日期建立文件夹和日志文件(Error文件单独存储)

IO流,反射

java 反射练习_JAVA反射的基础学习相关推荐

  1. java 反射机制_Java反射机制原理探究

    反射是Java中的一个重要的特性,使用反射可以在运行时动态生成对象.获取对象属性以及调用对象方法.与编译期的静态行为相对,所有的静态型操作都在编译期完成,而反射的所有行为基本都是在运行时进行的,这是一 ...

  2. java反射模式_Java反射机制详解

    对于一般的开发者,很少需要直接使用Java反射机制来完成功能开发,但是反射是很多框架譬如 Spring, Mybatis 实现的核心,反射虽小,能量却很大. 本文主要介绍反射相关的概念以及API的使用 ...

  3. java反射类型转换_java反射(转)

    反射是框架设计的灵魂 (使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码)) 一.反射的概述 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道 ...

  4. java 反射代价_Java反射机制

    # 反射 ## 什么是反射 反射是Java提供的动态执行机制, 可以动态加载类, 动态创建对象, 动态访问属性, 动态调用方法.. 静态执行: Java代码经过编译以后就确定的执行次序, 称为静态执行 ...

  5. Java的反射作用_java反射机制的作用与优点

    java的反射机制就是增加程序的灵活性,避免将程序写死到代码里, 例如: 实例化一个 person()对象, 不使用反射, new person(); 如果想变成 实例化 其他类, 那么必须修改源代码 ...

  6. java映射理解_Java反射的理解

    Java反射的理解 反射之中包含了一个「反」字,所以想要解释反射就必须先从「正」开始解释. 一般情况下,我们使用某个类时必定知道它是什么类,是用来做什么的.于是我们直接对这个类进行实例化,之后使用这个 ...

  7. java反射方法_java反射之方法反射的基本操作方法

    本文接上文"java反射之获取类的信息方法(推荐)",利用反射(invoke)来获取一个类中的方法来执行. 1.定义一个类,包含三个名称相同,参数不同的方法 class A{ pu ...

  8. java反射类型转换_Java反射探索研究(转)

    林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankakay 摘要:本文详细深入讲解是Java中反射的机制,并介绍了如何通过反射来生成对象.调用函数.取得 ...

  9. 零基础学java靠谱吗_零基础学习Java靠谱吗?

    零基础学习Java靠谱吗?作为信息时代的当下,我们看到太多"掌握XX技能,轻松月薪3万"."年薪30万,这个技能你必须懂得"."价值X万的写简历秘籍& ...

最新文章

  1. python使用numpy包编写自定义函数计算MAPE(平均绝对百分比误差)指标mean absolute percentage error (MAPE)、MAPE指标解读、MAPE指标使用的注意事项
  2. 寒武纪创始人兼CEO陈天石博士的公开信
  3. dns tunnel CC
  4. docker WARNING: IPv4 forwarding is disabled. 解决方法
  5. Swift:如何判断一个对象是否是某个类(或其子类)的实例
  6. Android通过透明度设置背景变暗
  7. python是什么 自学-你们都是怎么自学python的?
  8. CSS样式(一)- 基本语法
  9. testmarkdown
  10. PHP 开发者该知道的 5 个 Composer 小技巧
  11. mysql和php长度的漏洞_mysql和php字符长度判断
  12. c语言关键用法大全,c语言关键字的用法详解
  13. 上海计算机应用基础自考上机,上海市自学考试公共实践课程《计算机应用基础(实践)》上机考核大纲_自考资讯自考_自考报名_中国教育在线...
  14. 走出校门,工作4个月的工作感想
  15. 用java做出长方体的表面积_计算长方体、四棱锥的表面积和体积(Java)acm.sdut...
  16. 粉色的html 标签,22个粉色主调的网页设计欣赏
  17. C语言求金蝉素数,回文数 - 寂寞暴走伤的个人空间 - OSCHINA - 中文开源技术交流社区...
  18. 大数据实验室第一次考核
  19. 第二代商用计算机,紫光计算机第二代商用台式机 Unis 526S/526T G2 上市
  20. 教你用scratch2.0编见缝插针游戏

热门文章

  1. 精彩网络生活从中国电信百兆宽带开首
  2. 苹果开发证书导入电脑不受信任解决办法
  3. 试行非24小时营业 7-11“老了”还是“困了”
  4. BI报表是什么,BI报表的好处,BI和报表的区别
  5. cocos2d-x学习--游戏菜单CCMenu
  6. 亚信科技、清华AIR、英特尔成功举办WAIC智能算网与绿色计算论坛
  7. Java学习(Day 9)
  8. 终极解码-不错的解码器包
  9. 用手机打 CTF 是什么样的体验
  10. 第四部分:特殊用途的句子——第三章:虚拟