java 反射练习_JAVA反射的基础学习
反射 :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反射的基础学习相关推荐
- java 反射机制_Java反射机制原理探究
反射是Java中的一个重要的特性,使用反射可以在运行时动态生成对象.获取对象属性以及调用对象方法.与编译期的静态行为相对,所有的静态型操作都在编译期完成,而反射的所有行为基本都是在运行时进行的,这是一 ...
- java反射模式_Java反射机制详解
对于一般的开发者,很少需要直接使用Java反射机制来完成功能开发,但是反射是很多框架譬如 Spring, Mybatis 实现的核心,反射虽小,能量却很大. 本文主要介绍反射相关的概念以及API的使用 ...
- java反射类型转换_java反射(转)
反射是框架设计的灵魂 (使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码)) 一.反射的概述 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道 ...
- java 反射代价_Java反射机制
# 反射 ## 什么是反射 反射是Java提供的动态执行机制, 可以动态加载类, 动态创建对象, 动态访问属性, 动态调用方法.. 静态执行: Java代码经过编译以后就确定的执行次序, 称为静态执行 ...
- Java的反射作用_java反射机制的作用与优点
java的反射机制就是增加程序的灵活性,避免将程序写死到代码里, 例如: 实例化一个 person()对象, 不使用反射, new person(); 如果想变成 实例化 其他类, 那么必须修改源代码 ...
- java映射理解_Java反射的理解
Java反射的理解 反射之中包含了一个「反」字,所以想要解释反射就必须先从「正」开始解释. 一般情况下,我们使用某个类时必定知道它是什么类,是用来做什么的.于是我们直接对这个类进行实例化,之后使用这个 ...
- java反射方法_java反射之方法反射的基本操作方法
本文接上文"java反射之获取类的信息方法(推荐)",利用反射(invoke)来获取一个类中的方法来执行. 1.定义一个类,包含三个名称相同,参数不同的方法 class A{ pu ...
- java反射类型转换_Java反射探索研究(转)
林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankakay 摘要:本文详细深入讲解是Java中反射的机制,并介绍了如何通过反射来生成对象.调用函数.取得 ...
- 零基础学java靠谱吗_零基础学习Java靠谱吗?
零基础学习Java靠谱吗?作为信息时代的当下,我们看到太多"掌握XX技能,轻松月薪3万"."年薪30万,这个技能你必须懂得"."价值X万的写简历秘籍& ...
最新文章
- python使用numpy包编写自定义函数计算MAPE(平均绝对百分比误差)指标mean absolute percentage error (MAPE)、MAPE指标解读、MAPE指标使用的注意事项
- 寒武纪创始人兼CEO陈天石博士的公开信
- dns tunnel CC
- docker WARNING: IPv4 forwarding is disabled. 解决方法
- Swift:如何判断一个对象是否是某个类(或其子类)的实例
- Android通过透明度设置背景变暗
- python是什么 自学-你们都是怎么自学python的?
- CSS样式(一)- 基本语法
- testmarkdown
- PHP 开发者该知道的 5 个 Composer 小技巧
- mysql和php长度的漏洞_mysql和php字符长度判断
- c语言关键用法大全,c语言关键字的用法详解
- 上海计算机应用基础自考上机,上海市自学考试公共实践课程《计算机应用基础(实践)》上机考核大纲_自考资讯自考_自考报名_中国教育在线...
- 走出校门,工作4个月的工作感想
- 用java做出长方体的表面积_计算长方体、四棱锥的表面积和体积(Java)acm.sdut...
- 粉色的html 标签,22个粉色主调的网页设计欣赏
- C语言求金蝉素数,回文数 - 寂寞暴走伤的个人空间 - OSCHINA - 中文开源技术交流社区...
- 大数据实验室第一次考核
- 第二代商用计算机,紫光计算机第二代商用台式机 Unis 526S/526T G2 上市
- 教你用scratch2.0编见缝插针游戏