前言

反射是框架设计的灵魂,使用的前提条件:必须先得到字节码的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】反射的更多相关文章

  1. 第28章 java反射机制

    java反射机制 1.类加载机制 1.1.jvm和类 运行Java程序:java 带有main方法的类名 之后java会启动jvm,并加载字节码(字节码就是一个类在内存空间的状态) 当调用java命令 ...

  2. Java反射机制

    Java反射机制 一:什么事反射机制 简单地说,就是程序运行时能够通过反射的到类的所有信息,只需要获得类名,方法名,属性名. 二:为什么要用反射:     静态编译:在编译时确定类型,绑定对象,即通过 ...

  3. java反射(基础了解)

    package cn.itcast_01; /** *Person类 */ public class Person {    /** 姓名 */    private String name;     ...

  4. java基础知识(十一)java反射机制(上)

    java.lang.Class类详解 java Class类详解 一.class类 Class类是java语言定义的特定类的实现,在java中每个类都有一个相应的Class对象,以便java程序运行时 ...

  5. java基础知识(十一)java反射机制(下)

    1.什么是反射机制? java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象都能够调用他的属性和方法,这种动态获取属性和方法的功能称为java的反射机制. ...

  6. java反射学习之二万能EXCEL导出

    一.EXCEL导出的实现过程 假设有一个对象的集合,现在需要将此集合内的所有对象导出到EXCEL中,对象有N个属性:那么我们实现的方式是这样的: 循环这个集合,在循环集合中某个对象的所有属性,将这个对 ...

  7. java反射学习之一反射机制概述

    一.反射机制背景概述 1.反射(reflection)是java被视为动态语言的一个关键性质 2.反射机制指的是程序在运行时能获取任何类的内部所有信息 二.反射机制实现功能概述 1.只要给定类的全名, ...

  8. java反射 之 反射基础

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

  9. java反射 cglib asm相关资料

    有篇文章对java反射的调用的效率做了测试,写的比较好.猛击下面地址 http://www.blogjava.net/stone2083/archive/2010/09/15/332065.html ...

  10. 超详细的java反射教程

    看技术博客时,看到关于java反射的博文,写的非常好.猛击下面的地址,开始java反射之旅 中文翻译地址:http://ifeve.com/java-reflection/ 英文原版地址:http:/ ...

随机推荐

  1. Linux - 常用命令索引

    文件和目录操作 pwd - 显示当前所在的位置 cd - 切换目录 文件过滤及内容编辑 ... 文本处理三剑客 ... 系统信息查询与搜索文件 ... 文件备份与压缩 ... 用户管理与信息查询 .. ...

  2. E20180206-E

    fundamental   adj. 基础的,基本的,根本的,重要的,原始的,主要的,十分重大的; [物] 基频的,基谐波的; [乐] 基音的; n. 原理,原则,基本,根本,基础; [乐] 基音; ...

  3. bzoj 4823: [Cqoi2017]老C的方块【最大权闭合子图】

    参考:https://www.cnblogs.com/neighthorn/p/6705785.html 并不是黑白染色而是三色染色(还有四色的,不过是一个意思 仔细观察一下不合法情况,可以发现都是特 ...

  4. bzoj 2561: 最小生成树【最小割】

    看错题了以为多组询问吓得不行-- 其实还挺好想的,就是数据范围一点都不网络流.把U作为s,V作为t,以最小生成树为例,(U,V,L)要在最小生成树上,就要求所有边权比L小的边不能连通(U,V)所在的联 ...

  5. 洛谷P3642 [APIO2016]烟火表演

    传送门 题解 fy大佬好强……我根本看不懂…… //minamoto #include<bits/stdc++.h> #define ll long long using namespac ...

  6. java启动参数一

    java启动参数共分为三类: 其一是标准参数(-),所有的JVM实现都必须实现这些参数的功能,而且向后兼容: 其二是非标准参数(-X),默认jvm实现这些参数的功能,但是并不保证所有jvm实现都满足, ...

  7. [POJ1721]Cards

    Description 剀剀和凡凡有N张牌(依次标号为1,2,--,N)和一台洗牌机.假设N是奇数.洗牌机的功能是进行如下的操作:对所有位置I(1≤I≤N),如果位置I上的牌是J,而且位置J上的牌是K ...

  8. 468 Validate IP Address 验证IP地址

    详见:https://leetcode.com/problems/validate-ip-address/description/ Java实现: class Solution { public St ...

  9. 462 Minimum Moves to Equal Array Elements II 最少移动次数使数组元素相等 II

    给定一个非空整数数组,找到使所有数组元素相等所需的最小移动数,其中每次移动可将选定的一个元素加1或减1. 您可以假设数组的长度最多为10000.例如:输入:[1,2,3]输出:2说明:只有两个动作是必 ...

  10. js点击修改按钮后修改

    <button id="click">改变内容</button> <div id="t">要改变的内容</div> ...