【thinking in java】反射
前言
反射是框架设计的灵魂,使用的前提条件:必须先得到字节码的Class,Class类用于表示字节码,字节码即是.class文件
概述
JAVA反射机制:在程序运行的过程中,对于任意一个类,都可以知道这个类的所有信息,比如:成员变量、方法、构造方法、包等信息;要想用反射机制,首先要获取到
该类的字节码文件对象Class,然后用Class类中的方法把各种成分映射成Java对象,关于.class文件,在我们new对象的时候,本地IDE自动编译,然后jvm会自动的从硬盘
读取到.class文件,并创建一个该类的Class文件,但是,如果我们new了多个该类的实例,内存中只会有一份该类的字节码文件。
API
Class 类与 java.lang.reflect 类库一起对反射的概念进行了支持,该类库包含了 Field、Method、Constructor 类 (每个类都实现了 Member 接口)该接口反映单个成员
(字段或方法)或构造方法的标识信息,正因为实现了该接口,因此可以反射相关变量、方法信息,这些类型的对象时由 JVM 在运行时创建的,用以表示未知类里对应的成员
反射
获取字节码
在 Java 中可以通过三种方法获取类的字节码 (Class) 对象,如下:
package com.oxygen.bean;
public class ReflectTest {
public static void main(String[] args) throws ClassNotFoundException {
Student student = new Student();
Class<?> clazz1 = student.getClass(); //方式1
Class<?> clazz2 = Student.class; //方式2
Class clazz3 = Class.forName("com.oxygen.student");//方式3
}
}
获取类信息
Student类如下
package com.oxygen.bean; import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; public class Student {
private String name;
private Integer age;
private Car car; public void init() {
System.out.println("init...");
} public void destroy() {
System.out.println("destroy...");
} public Student() { // 无参构造
} public Student(String name, Integer age, Car car) {
super();
this.name = name;
this.age = age;
this.car = car;
} private Student(String name) {
this.name = name;
} public void show1(String s) {
System.out.println("调用了:公有的,String参数的show1(): name = " + s);
} protected void show2() {
System.out.println("调用了:受保护的,无参的show2()");
} void show3() {
System.out.println("调用了:默认的,无参的show3()");
} private String show4(int age) {
System.out.println("调用了,私有的,并且有返回值的,int参数的show4(): age = " + age);
return "oxygen";
}
}
1. 通过构造函数对象Constructor创建对应类的实例
package com.oxygen.bean;
import java.lang.reflect.Constructor;
public class ReflectTest {
public static void main(String[] args) throws Exception {
Student student = new Student(); //Student的带参构造函数依赖另外一个类Car
Class<?> clazz1 = student.getClass(); //方式1
func1(clazz1); //通过无参构造函数反射Student实例
func2(clazz1);//通过有参构造函数反射Student实例
func3(clazz1);//获取所有的构造函数反射Student实例
func4(clazz1); // 反射私有构造函数
}
private static void func4(Class<?> clazz1) throws Exception {
Constructor<?> declaredConstructor = clazz1.getDeclaredConstructor(String.class);
declaredConstructor.setAccessible(true);//设置为可以访问
System.out.println(declaredConstructor.newInstance("zhangsan"));
}
private static void func3(Class<?> clazz1) throws Exception {
Constructor<?>[] constructors = clazz1.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println("func3: " + constructor);
}
}
/**
* 因为Student的带参构造函数依赖另外一个类Car,因为必须保证JVM能获取到Car的字节码
* @param clazz1
* @throws Exception
*/
public static void func2(Class<?> clazz1) throws Exception {
Car car = new Car();//保证
Constructor<?> constructor = clazz1.getConstructor(String.class, Integer.class, Car.class);
Student student = (Student) constructor.newInstance("张三", 18, new Car());
System.out.println(student);
}
public static void func1(Class<?> clazz1) throws Exception {
Constructor<?> constructor = clazz1.getConstructor();
Student student = (Student) constructor.newInstance();
System.out.println(student);
}
}
2. 获取成员方法
package com.oxygen.bean; import java.lang.reflect.Constructor;
import java.lang.reflect.Method; public class ReflectTest {
public static void main(String[] args) throws Exception {
Student student = new Student();
Class<?> clazz1 = student.getClass();
m1(clazz1);
m2(clazz1);
m3(clazz1);
m4(clazz1);
} /**
* 获取所有的方法,包括私有的,不包括继承Object类的9个方法
* @param clazz1
*/
public static void m4(Class<?> clazz1) {
Method[] declaredMethods = clazz1.getDeclaredMethods();
} /**
* 获取所有的”公有“方法,包括继承Object类的9个方法
* @param clazz1
*/
public static void m3(Class<?> clazz1) {
Method[] methods = clazz1.getMethods();
} /**
* 获取私有的show4()方法
* @param clazz1
* @throws Exception
*/
public static void m2(Class<?> clazz1) throws Exception {
Method method;
method = clazz1.getDeclaredMethod("show4", int.class);
Student stu = func1(clazz1); // 实例化一个Student对象
method.setAccessible(true);
method.invoke(stu, 20);//反射私有方法show4(),第一个参数是实例,第二个参数是被反射方法的参数
} /**
* 获取公有的show1()方法
* @param clazz1
* @throws Exception
*/
public static void m1(Class<?> clazz1) throws Exception {
Method method = clazz1.getMethod("show1", String.class); //第一个参数是方法名称,第二个参数是形参类型
Student stu = func1(clazz1); // 实例化一个Student对象
method.invoke(stu, "lisi"); //反射公有方法show1(),第一个参数是实例,第二个参数是被反射方法的参数
} public static Student func1(Class<?> clazz1) throws Exception {
Constructor<?> constructor = clazz1.getConstructor();
Student student = (Student) constructor.newInstance();
return student;
}
}
【thinking in java】反射的更多相关文章
- 第28章 java反射机制
java反射机制 1.类加载机制 1.1.jvm和类 运行Java程序:java 带有main方法的类名 之后java会启动jvm,并加载字节码(字节码就是一个类在内存空间的状态) 当调用java命令 ...
- Java反射机制
Java反射机制 一:什么事反射机制 简单地说,就是程序运行时能够通过反射的到类的所有信息,只需要获得类名,方法名,属性名. 二:为什么要用反射: 静态编译:在编译时确定类型,绑定对象,即通过 ...
- java反射(基础了解)
package cn.itcast_01; /** *Person类 */ public class Person { /** 姓名 */ private String name; ...
- java基础知识(十一)java反射机制(上)
java.lang.Class类详解 java Class类详解 一.class类 Class类是java语言定义的特定类的实现,在java中每个类都有一个相应的Class对象,以便java程序运行时 ...
- java基础知识(十一)java反射机制(下)
1.什么是反射机制? java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象都能够调用他的属性和方法,这种动态获取属性和方法的功能称为java的反射机制. ...
- java反射学习之二万能EXCEL导出
一.EXCEL导出的实现过程 假设有一个对象的集合,现在需要将此集合内的所有对象导出到EXCEL中,对象有N个属性:那么我们实现的方式是这样的: 循环这个集合,在循环集合中某个对象的所有属性,将这个对 ...
- java反射学习之一反射机制概述
一.反射机制背景概述 1.反射(reflection)是java被视为动态语言的一个关键性质 2.反射机制指的是程序在运行时能获取任何类的内部所有信息 二.反射机制实现功能概述 1.只要给定类的全名, ...
- java反射 之 反射基础
一.反射 反射:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为 ...
- java反射 cglib asm相关资料
有篇文章对java反射的调用的效率做了测试,写的比较好.猛击下面地址 http://www.blogjava.net/stone2083/archive/2010/09/15/332065.html ...
- 超详细的java反射教程
看技术博客时,看到关于java反射的博文,写的非常好.猛击下面的地址,开始java反射之旅 中文翻译地址:http://ifeve.com/java-reflection/ 英文原版地址:http:/ ...
随机推荐
- asp.net 中的事务
ASP.NET开发过程中的事务处理 http://www.cnblogs.com/georgeHeaven/p/3766609.html
- yield示例分析
yield示例分析 public class TestYield { private static final Object lock = new Object(); public static vo ...
- 洛谷 P2593 [ZJOI2006]超级麻将【dp】
设f[i][j][k][0/1]表示选到i时,i-1选j张,i选k张,之前选的所有牌是否选择了对子 然后分情况讨论转移即可 #include<iostream> #include<c ...
- bzoj 4951: [Wf2017]Money for Nothing【分治】
参考:https://blog.csdn.net/herobrine_tkj/article/details/78404426?locationNum=8&fps=1 为什么从1开始存就挂了, ...
- bzoj 3206: [Apio2013]道路费用【最小生成树+并查集】
参考:http://hzwer.com/6888.html 把k条道路权值设为0,和其他边一起跑MST,然后把此时选中的其他边设为必选,在新图中加上必选变缩成k个点,把所有边重标号,枚举k跳边的选取情 ...
- 从Oracle9i RMAN全库备份迁移到 Oracle10g
1. 创建以下目录: mkdir -pv $ORACLE_BASE/admin/$ORACLE_SID/{{a,b,c,dp,u}dump,pfile} mkdir -pv $ORACLE_BASE/ ...
- Qt - 锁屏界面加虚拟小键盘
一.实现效果 鼠标点击"密码输入栏",弹出虚拟键盘,输入锁屏密码后,点击虚拟键盘外部区域,则会隐藏虚拟键盘,再点击登录,成功进入主界面. 二.虚拟键盘-程序设计 2.1 frmNu ...
- 循环队列 分类: c/c++ 2014-10-10 23:28 605人阅读 评论(0) 收藏
利用线性表实现队列,为了有效利用空间,将其设计为循环结构,防止假溢出:牺牲一个存储单元以区分队空.队满. 设front队头,rear队尾,N为顺序表大小 队空:rear==front 队满:(rear ...
- 16-2 基于localStorage或sessionStorage的计数器
localStorage 方法 localStorage 方法存储的数据没有时间限制.第二天.第二周或下一年之后,数据依然可用. <!doctype html> <html> ...
- python 字符串的split()函数详解(转)
作者:宋桓公 出处:http://www.cnblogs.com/douzi2/ 如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同 ...