【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:/ ...
随机推荐
- C#基础第一天 VS2013基本设置
1 .net能干什么 桌面应用程序 winform internet应用程序 Asp.net->京东.msdn.招聘银行 手机开发 wp8 unity3D游戏开发或者虚拟现实 2 .net两种交 ...
- 搭建CARDBOARD+ANDROID+unity3d的VR开发环境
一.下载最新unity3d(u3d官网) 二.下载最新cardboardsdkforunity(https://github.com/googlesamples/cardboard-unity) 三. ...
- bzoj 4584: [Apio2016]赛艇【dp】
参考:https://www.cnblogs.com/lcf-2000/p/6809085.html 设f[i][j][k]为第i个学校派出的赛艇数量在区间j内,并且区间j内共有k个学校的方案数 把数 ...
- 【插件开发】—— 7 SWT布局详解,不能再详细了!
前文回顾: 1 插件学习篇 2 简单的建立插件工程以及模型文件分析 3 利用扩展点,开发透视图 4 SWT编程须知 5 SWT简单控件的使用与布局搭配 6 SWT复杂空间与布局搭配 前面几篇都提到了S ...
- 在myeclipse中maven遇见的问题
An internal error occurred during: "Retrieving archetypes:". Java heap space 表示你的myeclipse ...
- [ZPG TEST 110] 多边形个数【DP】
1. 多边形个数 (polygons.pas/c/cpp) [问题描述] 给定N线段,编号1到n.并给出这些线段的长度,用这些线段组成一个K边形,并且每个线段做多使用一次.若使用了一条不同编号的线段, ...
- 题解报告:hdu 2062 Subset sequence
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2062 Problem Description 考虑集合An = {1,2,...,n}. 例如,A1 ...
- AJPFX实践 java实现快速排序算法
快速排序算法使用的分治法策略来把一个序列分为两个子序列来实现排序的思路: 1.从数列中挑出一个元素,称为“基准“2.重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面 ...
- 2556. [NOIP2016]玩具谜题
[题目描述] 小南有一套可爱的玩具小人,它们各有不同的职业.有一天,这些玩具小人把小南的眼镜藏了起来.小南发现玩具小人们围成了一个圈,它们有的面朝国内,有的面朝圈外.如下图: 这时singer告诉小南 ...
- Program received signal SIGILL, Illegal instruction
Program received signal SIGILL, Illegal instruction 这个错误,发现是直接在printf 的%s中直接使用string类型,而没有使用c字符串格式造成 ...