反射

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

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

1.1      Class类

获取Class对象的三种方式

package com.oracle.FanShe;

public class Demo01 {

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

//1.通过getClass方法获取,通过对象获取

Person p=new Person();

Class c1=p.getClass();

System.out.println(c1);

//2.通过类名获取

Class c2=Person.class;

System.out.println(c2);

System.out.println(c1==c2);

System.out.println(c1.equals(c2));

//3.通过完整的包名+类名

Class c3=Class.forName("com.oracle.FanShe.Person");

System.out.println(c3);

}

}

package com.oracle.FanShe;

import java.lang.reflect.Constructor;

import java.lang.reflect.InvocationTargetException;

import java.util.jar.Attributes.Name;

public class Demo02 {

//构造方法Constructor

//成员变量 Field

//方法  Method

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

//反射获取构造方法

//获取Person.class文件对象

Class c=Class.forName("com.oracle.FanShe.Person");

/*//获取所有公共的构造方法(构造方法数组)

Constructor[] cons=c.getConstructors();

//遍历

for(Constructor con:cons){

System.out.println(con);

}*/

//获取某个公共构造方法

//空参构造

/*Constructor con1=c.getConstructor();

//System.out.println(con1);

//有参构造

Constructor con2=c.getConstructor(String.class,int.class);

//System.out.println(con2);

//创建你对象

Object obj= con2.newInstance("乔治",16);

System.out.println(obj);*/

//获取 所有的构造方法数组

/*Constructor[] cons=c.getDeclaredConstructors();

for(Constructor con:cons){

System.out.println(con);

}*/

//获取某个私有构造方法

Constructor con=c.getDeclaredConstructor(String.class);

//System.out.println(con);

//暴力反射

con.setAccessible(true);

Object obj=con.newInstance("拉拉");

System.out.println(obj);

}

}

package com.oracle.FanShe;

public class Person {

private String name;

public int age;

static{

System.out.println("静态代码块");

}

public Person(){

System.out.println("空参构造");

}

public Person(String name, int age){

this.name=name;

this.age=age;

System.out.println("public Person(String name, int age)");

}

public Person(String name){

this.name=name;

System.out.println("public Person(String name)");

}

public void eat(){

System.out.println("公共空参方法");

}

public void sleep(String name){

System.out.println("公共有参方法");

}

private void smoke(){

System.out.println("私有空参构造");

}

@Override

public String toString() {

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

}

}

1.2      通过反射获取构造方法并使用

在反射机制中,把类中的成员(构造方法、成员方法、成员变量)都封装成了对应的类进行表示。      其中,构造方法使用类Constructor表示。可通过Class类中提供的方法获取构造方法:

1.2.1    通过反射方式,获取构造方法,创建对象

获取构造方法,步骤如下:

1. 获取到Class对象

2. 获取指定的构造方法

3. 通过构造方法类Constructor中的方法,创建对象

public T newInstance(Object... initargs)

package com.oracle.FanShe;

import java.lang.reflect.Constructor;

import java.lang.reflect.InvocationTargetException;

import java.util.jar.Attributes.Name;

public class Demo02 {

//构造方法Constructor

//成员变量 Field

//方法  Method

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

//反射获取构造方法

//获取Person.class文件对象

Class c=Class.forName("com.oracle.FanShe.Person");

//获取所有公共的构造方法(构造方法数组)

/*Constructor[] cons=c.getConstructors();

//遍历

for(Constructor con:cons){

System.out.println(con);

}*/

//获取某个公共构造方法

//空参构造

Constructor con1=c.getConstructor();

//System.out.println(con1);

//有参构造

Constructor con2=c.getConstructor(String.class,int.class);

//System.out.println(con2);

//创建你对象

Object obj= con2.newInstance("乔治",16);

System.out.println(obj);

}

}

运行结果:

1.2.2    通过反射方式,获取私有构造方法,创建对象

AccessibleObject 类是 Field、Method 和 Constructor 对象的父类。它提供了将反射的对象标记为在使用时取消默认 Java 语言访问控制检查的能力。

对于公共成员、默认(打包)访问成员、受保护成员和私有成员,在分别使用 Field、Method 或 Constructor 对象来设置或获取字段、调用方法,或者创建和初始化类的新实例的时候,会执行访问检查

public void setAccessible(boolean flag) throws SecurityException

参数值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。参数值为 false 则指示反射的对象应该实施 Java 语言访问检查。

获取私有构造方法,步骤如下:

1. 获取到Class对象

2. 获取指定的构造方法

3. 暴力访问, 通过setAccessible(boolean flag)方法

4. 通过构造方法类Constructor中的方法,创建对象

public T newInstance(Object... initargs)

package com.oracle.FanShe;

import java.lang.reflect.Constructor;

import java.lang.reflect.InvocationTargetException;

import java.util.jar.Attributes.Name;

public class Demo02 {

//构造方法Constructor

//成员变量 Field

//方法  Method

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

//反射获取构造方法

//获取Person.class文件对象

Class c=Class.forName("com.oracle.FanShe.Person");

//获取所有公共的构造方法(构造方法数组)

/*Constructor[] cons=c.getConstructors();

//遍历

for(Constructor con:cons){

System.out.println(con);

}*/

//获取某个公共构造方法

//空参构造

//Constructor con1=c.getConstructor();

//System.out.println(con1);

//有参构造

/*Constructor con2=c.getConstructor(String.class,int.class);

//System.out.println(con2);

//创建你对象

Object obj= con2.newInstance("乔治",16);

System.out.println(obj);*/

//获取 所有的构造方法数组

/*Constructor[] cons=c.getDeclaredConstructors();

for(Constructor con:cons){

System.out.println(con);

}*/

//获取某个私有构造方法

Constructor con=c.getDeclaredConstructor(String.class);

//System.out.println(con);

//暴力反射

con.setAccessible(true);

Object obj=con.newInstance("拉拉");

System.out.println(obj);

}

}

运行结果:

1.3      通过反射获取成员方法并使用

1.3.1        通过反射,创建对象,获取指定的成员变量,进行赋值与获取值操作

获取成员变量,步骤如下:

1. 获取Class对象

2. 获取构造方法

3. 通过构造方法,创建对象

4. 获取指定的成员变量(私有成员变量,通过setAccessible(boolean flag)方法暴力访问)

5. 通过方法,给指定对象的指定成员变量赋值或者获取值

public void set(Object obj, Object value)

在指定对象obj中,将此 Field 对象表示的成员变量设置为指定的新值

public Object get(Object obj)

返回指定对象obj中,此 Field 对象表示的成员变量的值

1.4      通过反射获取成员方法并使用

在反射机制中,把类中的成员变量使用类Field表示

返回一个成员变量

public Field getField(String name) 获取指定的 public修饰的变量

public Field getDeclaredField(String name) 获取指定的任意变量

返回多个成员变量

public Field[] getFields() 获取所有public 修饰的变量

public Field[] getDeclaredFields() 获取所有的 变量 (包含私有)

1.4.1    通过反射,创建对象,调用指定的方法

获取成员方法,步骤如下:

1. 获取Class对象

2. 获取构造方法

3. 通过构造方法,创建对象

4. 获取指定的方法

5. 执行找到的方法

u  public Object invoke(Object obj,  Object... args)

执行指定对象obj中,当前Method对象所代表的方法,方法要传入的参数通过args指定。

package com.oracle.FanShe;

import java.lang.reflect.Constructor;

import java.lang.reflect.InvocationTargetException;

import java.util.jar.Attributes.Name;

public class Demo02 {

//构造方法Constructor

//成员变量 Field

//方法  Method

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

//反射获取构造方法

//获取Person.class文件对象

Class c=Class.forName("com.oracle.FanShe.Person");

//获取某个公共构造方法

//空参构造

Constructor con1=c.getConstructor();

//System.out.println(con1);

//有参构造

Constructor con2=c.getConstructor(String.class,int.class);

//System.out.println(con2);

//创建你对象

Object obj= con2.newInstance("乔治",16);

System.out.println(obj);

}

}

运行结果:

1.4.2    通过反射,创建对象,调用指定的private 方法

获取私有成员方法,步骤如下:

1. 获取Class对象

2. 获取构造方法

3. 通过构造方法,创建对象

4. 获取指定的方法

5. 开启暴力访问

6. 执行找到的方法

u  public Object invoke(Object obj,  Object... args)

执行指定对象obj中,当前Method对象所代表的方法,方法要传入的参数通过args指定。

Person类

package com.oracle.FanShe;

public class Person {

private String name;

public int age;

static{

System.out.println("静态代码块");

}

public Person(){

System.out.println("空参构造");

}

public Person(String name, int age){

this.name=name;

this.age=age;

System.out.println("public Person(String name, int age)");

}

public Person(String name){

this.name=name;

System.out.println("public Person(String name)");

}

public void eat(){

System.out.println("公共空参方法");

}

public void sleep(String name){

System.out.println("公共有参方法");

}

private void smoke(){

System.out.println("私有空参构造");

}

@Override

public String toString() {

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

}

}

package com.oracle.FanShe;

import java.lang.reflect.Constructor;

import java.lang.reflect.InvocationTargetException;

import java.util.jar.Attributes.Name;

public class Demo02 {

//构造方法Constructor

//成员变量 Field

//方法  Method

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

//反射获取构造方法

//获取Person.class文件对象

Class c=Class.forName("com.oracle.FanShe.Person");

//获取某个私有构造方法

Constructor con=c.getDeclaredConstructor(String.class);

//System.out.println(con);

//暴力反射

con.setAccessible(true);

Object obj=con.newInstance("拉拉");

System.out.println(obj);

}

}

运行结果:

反射练习

2.1      泛型擦除

其实程序编译后产生的.class文件中是没有泛型约束的,这种现象我们称为泛型的擦除。那么,我们可以通过反射技术,来完成向有泛型约束的集合中,添加任意类型的元素

//Person类:

package com.oracle.demo01;

public class Person {

private String name;

public int age;

static{

System.out.println("静态代码块");

}

public Person(){

System.out.println("空参构造");

}

public Person(String name,int age){

this.name=name;

this.age=age;

System.out.println("Person(String name,int age)");

}

private Person(String name){

this.name=name;

System.out.println("Person(String name)");

}

public void eat(){

System.out.println("公共空参方法");

}

public void sleep(String name){

System.out.println("公共有参方法");

}

private void smoke(){

System.out.println("私有空参构造");

}

@Override

public String toString() {

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

}

}

//测试类:

package com.oracle.demo01;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

import java.util.ArrayList;

public class Demo02 {

public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

//泛型擦除

ArrayList<Integer> arr=new ArrayList<Integer>();

arr.add(1);

//arr.add("aaa");

//获取ArrayList的字节码文件对象

Class c=arr.getClass();

//通过反射的方式获取add方法

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

//调用方法

add.invoke(arr,"aaa");

System.out.println(arr);

}

}

运行结果:

2.2      反射配置文件

通过反射配置文件,运行配置文件中指定类的对应方法

读取Peoperties.txt文件中的数据,通过反射技术,来完成Person对象的创建

Peoperties.txt文件内容如下:

className=cn.oracle_01_Reflect.Person

methodName=method5

读取配置文件,调用指定类中的对应方法

public class ReflectTest2 {

public static void main(String[] args)

throws FileNotFoundException, IOException, ClassNotFoundException, NoSuchMethodException, SecurityException,

InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

// 通过Properties集合从文件中读取数据

Properties prop = new Properties();

// 读取文件中的数据到集合中

prop.load(new FileInputStream("properties.txt"));

// 获取键所对应的值

String className = prop.getProperty("className");

System.out.println(className);

// 1,获取Person.class 字节码文件对象

Class c = Class.forName(className);

// 2,获取构造方法

// public Person(String name, int age, String address)

Constructor con = c.getConstructor(String.class, int.class, String.class);

// 3,创建对象

Object obj = con.newInstance("小明", 20, "中国");

System.out.println(obj);

// 4,获取指定的方法

// private void method5(){}

String methodName = prop.getProperty("methodName");

Method m5 = c.getDeclaredMethod(methodName, null);

// 5,开启暴力访问

m5.setAccessible(true);

// 6,执行找到的方法

m5.invoke(obj, null);

}

}

Java反射、反射练习整理的更多相关文章

  1. java中反射学习整理

    转载请注明:http://blog.csdn.net/j903829182/article/details/38405735 反射主要是指程序能够訪问.检測和改动它本身的状态或行为的一种能力. jav ...

  2. 反射(学习整理)----Class类和加载器ClassLoader类的整理

    1.学习反射的时整理的笔记!Class类和ClassLoader类的简单介绍 反射机制中的Class Class内部到底有什么呢?看下图! 代码: Class cls=Person.class; .C ...

  3. java梳理-反射

    本文属于面试题梳理系列:问题:java反射类的訪问私有方法与普通方法相比,须要多处理什么?  之前梳理类载入的时候,介绍到初始化的时机之中的一个:用java.lang.reflect包的方法对类进行反 ...

  4. JAVA的反射理解

    1----------------------------反射的概念----------------------------------------------- JAVA的反射机制是在运行状态中,对 ...

  5. java的反射

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

  6. iOS运行时编程(Runtime Programming)和Java的反射机制对比

    运行时进行编程,类似Java的反射.运行时编程和Java反射的对比如下:   1.相同点   都可以实现的功能:获取类信息.属性设置获取.类的动态加载(NSClassFromString(@“clas ...

  7. Java 类反射机制分析

    Java 类反射机制分析 一.反射的概念及在Java中的类反射 反射主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.在计算机科学领域,反射是一类应用,它们能够自描述和自控制.这类应用通过某 ...

  8. java的反射机制

    一.java的反射机制浅谈 最近研究java研究得很给力,主要以看博文为学习方式.以下是我对java的反射机制所产生的一些感悟,希望各位童鞋看到失误之处不吝指出.受到各位指教之处,如若让小生好好感动, ...

  9. Java:反射

    初识Java反射机制: 从上面的描述可以看出Java的反射机制使得Java语言可以在运行时去认识在编译时并不了解的类/对象的信息,并且能够调用相应的方法或修改属性的值.Java反射机制的核心就是允许在 ...

  10. Java中反射机制和Class.forName、实例对象.class(属性)、实例对象getClass()的区别

    一.Java的反射机制   每个Java程序执行前都必须经过编译.加载.连接.和初始化这几个阶段,后三个阶段如下图:   其中

随机推荐

  1. 利用ZYNQ SOC快速打开算法验证通路(4)——AXI DMA使用解析及环路测试

    一.AXI DMA介绍 本篇博文讲述AXI DMA的一些使用总结,硬件IP子系统搭建与SDK C代码封装参考米联客ZYNQ教程.若想让ZYNQ的PS与PL两部分高速数据传输,需要利用PS的HP(高性能 ...

  2. 010 Editor v8.0.1(32 - bit) 算法逆向分析、注册机编写

    010 Editor 的逆向分析整体算下来还是比较简单的,将程序拖入OD,通过字符串搜索定位到核心代码,经过分析,主要是如下图所示的两个关键函数,返回正确的值,才算是注册成功. 00409C9B 这个 ...

  3. table 的宽度设置无效

    1.在table 标签添加样式 table-layout: fixed; 必须设置width的值:<table style="table-layout: fixed"> ...

  4. 二叉搜索树的最近公共祖先的golang实现

    给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p.q,最近公共祖先表示为一个结点 x,满足 x 是 p.q 的祖先且 x ...

  5. Spark的性能调优杂谈

    下面这些关于Spark的性能调优项,有的是来自官方的,有的是来自别的的工程师,有的则是我自己总结的. 基本概念和原则 <1>  每一台host上面可以并行N个worker,每一个worke ...

  6. A. Points in Segments(cf a题, 水题)

    没什么好说的 #include<iostream> using namespace std; ], x, y,n, m, ans; int main(){ cin>>n> ...

  7. C# — 调用dll出现试图加载不正确格式的程序问题

    今天在调用百度dll包时,运行项目出现了如下警告: 修改:鼠标右击项目名称----选择属性----生成-----平台目标-----X64(由于我调用的是X64的dll包,所以这里选择X64,网上许多说 ...

  8. Svn 安装、配置、使用指南

    Svn 安装.配置.使用指南 Svn 是 Subversion 的简称,是一个开放源代码的版本控制系统,它采用了分支管理系统. 1. 安装配置 1.1. 安装 svn 1.2. 创建 svn 仓库 1 ...

  9. FineUIPro/Mvc/Core/JS v4.2.0 发布了(老牌ASP.NET控件库,WebForms,ASP.NET MVC,Core,JavaScript)!

    还记得 10 年前那个稍微青涩的 ExtAspNet 吗,如今她已脱胎换骨,变成了如下 4 款产品: FineUIPro:基于jQuery的经典款ASP.NET WebForms控件,之前的FineU ...

  10. 在 .NET Core 中结合 HttpClientFactory 使用 Polly(下篇)

    译者:王亮作者:Polly 团队原文:http://t.cn/EhZ90oq声明:我翻译技术文章不是逐句翻译的,而是根据我自己的理解来表述的(包括标题).其中可能会去除一些不影响理解但本人实在不知道如 ...