反射的概述
  1、Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法。
  2、对于任意一个对象,都能调用它的任意一个方法和属性。
  3、通过动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。
  4、要解剖一个类,必须先要获取到该类的字节码文件对象。
  5、而解剖使用的就是Class类中的方法,所以先要获取到每一个字节码文件对应的Class类型对象。

Class对象获取的方法
  1、通过对象获得(getClass )
  2、通过字符串获得(Class.forName)(包名 + 类名)
  3、通过类的静态成员class获得
  4、只针对内置的基本数据类型(比如:Integer.TYPE)

对反射的总结:反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用其方法。

反射的使用(以Apple类为演示)

获取Class对象的三种方式

package fruits;

public class Apple {
private String name;
private Double price; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Double getPrice() {
return price;
} public void setPrice(Double price) {
this.price = price;
} public static void main(String[] args){ // 第一种方式获取Class对象
Apple apple = new Apple(); // 这一new 产生了一个Apple对象和一个Class对象
Class appleClass1 = apple.getClass(); // 获取Class对象
System.out.println("第一种方式获取到的Class对象:" + appleClass1.getName()); System.out.println(); // 第二种方式获取Class对象
Class appleClass2 = Apple.class;
System.out.println("第二种方式获取到的Class对象:" + appleClass2.getName()); System.out.println(); // 第三种方式获取Class对象
Class appleClass3 = null;
try {
       // 注意此字符串必须是真实路径,就是带包名的类路径,包名.类名  
appleClass3 = Class.forName("fruits.Apple");
System.out.println("第三种方式获取到的Class对象:" + appleClass3.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} System.out.println(); // 判断这三种方式 是否获取到同一个Class对象
System.out.println("appleClass1 == appleClass2 结果:" + (appleClass1 == appleClass2 ));
System.out.println("appleClass2 == appleClass3 结果:" + (appleClass2 == appleClass3 ));
System.out.println("appleClass1 == appleClass3 结果:" + (appleClass1 == appleClass3 )); } }

结果:

第一种方式获取到的Class对象:fruits.Apple

第二种方式获取到的Class对象:fruits.Apple

第三种方式获取到的Class对象:fruits.Apple

appleClass1 == appleClass2 结果:true
appleClass2 == appleClass3 结果:true
appleClass1 == appleClass3 结果:true

注:在运行期间,一个类,只有一个Class对象产生。

三种方式常用第三种。

解释:

  1、第一种对象都有了为啥还要进行反射....

  2、第二种依赖性太强,需要类才能使用

  3、第三种,一个字符串可以传入也可以写在配置文件中等

通过反射获取构造方法

package fruits;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; public class Apple {
private String name;
private Double price; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Double getPrice() {
return price;
} public void setPrice(Double price) {
this.price = price;
} // 无参构造函数
public Apple(){
System.out.println("调用了公有、无参构造方法执行了...");
}
// 有一个参数的构造函数
public Apple(String name){
System.out.println("调用了公有、有一个参数的构造方法 name = " + name);
}
// 有多个参数的构造函数
public Apple(String name,double price){
System.out.println("调用了公有、多个参数的构造方法 name = " + name + " price = " + price);
}
// 受保护的构造方法
protected Apple(boolean flag){
System.out.println("受保护的构造方法 flag = " + flag);
}
// 私有构造方法
private Apple(int type){
System.out.println("私有的构造方法 假如Apple的类型 = "+ type);
} public static void main(String[] args){ Class clazz = null;
try {
// 获取 Class 对象
clazz = Class.forName("fruits.Apple");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println("***************获取所有的”公有“方法*******************");
Constructor[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
System.out.println(); System.out.println("************所有的构造方法(包括:私有、受保护、默认、公有)***************");
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
for (Constructor constructor : declaredConstructors) {
System.out.println(constructor);
} System.out.println();
System.out.println("*****************获取公有、无参的构造方法*******************************");
try {
// 获取无参构造函数的类对象。
Constructor constructor = clazz.getConstructor(null);
// 调用构造函数
Object obj = constructor.newInstance();
System.out.println(" 获取公有无参构造函数的类对象: obj = " + obj);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println();
System.out.println("******************获取私有构造方法,并调用*******************************");
try {
// 获取一个参数的私有构造函数
Constructor constructor = clazz.getDeclaredConstructor(int.class);
// 忽略访问修饰符
constructor.setAccessible(true);
// 进行调用
Object obj = constructor.newInstance(9999999);
System.out.println(" 获取私有有参构造函数的类对象: obj = " + obj);
} catch (Exception e) {
e.printStackTrace();
}
}
}

结果:

***************获取所有的”公有“方法*******************
public fruits.Apple(java.lang.String,double)
public fruits.Apple()
public fruits.Apple(java.lang.String) ************所有的构造方法(包括:私有、受保护、默认、公有)***************
public fruits.Apple(java.lang.String,double)
public fruits.Apple()
protected fruits.Apple(boolean)
private fruits.Apple(int)
public fruits.Apple(java.lang.String) *****************获取公有、无参的构造方法*******************************
调用了公有、无参构造方法执行了...
获取公有无参构造函数的类对象: obj = fruits.Apple@4554617c ******************获取私有构造方法,并调用*******************************
私有的构造方法 假如Apple的类型 = 9999999
获取私有有参构造函数的类对象: obj = fruits.Apple@74a14482

获取成员变量并调用

package fruits;

import java.lang.reflect.Field;

public class Apple {
private String name;
private Double price; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Double getPrice() {
return price;
} public void setPrice(Double price) {
this.price = price;
} // 无参构造函数
public Apple(){
System.out.println("调用了公有、无参构造方法执行了...");
}
// 有一个参数的构造函数
public Apple(String name){
System.out.println("调用了公有、有一个参数的构造方法 name = " + name);
}
// 有多个参数的构造函数
public Apple(String name,double price){
System.out.println("调用了公有、多个参数的构造方法 name = " + name + " price = " + price);
}
// 受保护的构造方法
protected Apple(boolean flag){
System.out.println("受保护的构造方法 flag = " + flag);
}
// 私有构造方法
private Apple(int type){
System.out.println("私有的构造方法 假如Apple的类型 = "+ type);
} public static void main(String[] args){ Class clazz = null;
try {
// 获取 Class 对象
clazz = Class.forName("fruits.Apple");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println("************获取所有公有的字段********************");
Field[] fields = clazz.getFields();
for (Field field : fields) {
System.out.println(field);
} System.out.println();
System.out.println("************获取所有的字段(包括私有、受保护、默认的)********************");
Field[] declaredFields = clazz.getDeclaredFields();
for (Field field : declaredFields) {
System.out.println(field);
} System.out.println();
System.out.println("*************获取私有字段**并调用***********************************");
try {
// 获取一个对象
Object obj = clazz.getConstructor().newInstance();
// 获取到私有字段属性
Field field = clazz.getDeclaredField("name");
// 忽略访问修饰符
field.setAccessible(true);
// 为字段设置值
field.set(obj,"一个经过反射后的苹果...");
// 进行验证
Apple apple = (Apple) obj;
System.out.println(" 验证苹果的名称:" + apple.getName()); System.out.println();
System.out.println("*********************再设置一个私有字段的值************************************");
Field price1 = clazz.getDeclaredField("price");
price1.set(obj,1999999.0);
System.out.println(" 验证苹果的价格:" + apple.getPrice()); } catch (Exception e) {
e.printStackTrace();
}
}
}

结果:

************获取所有公有的字段********************

************获取所有的字段(包括私有、受保护、默认的)********************
private java.lang.String fruits.Apple.name
private java.lang.Double fruits.Apple.price *************获取私有字段**并调用***********************************
调用了公有、无参构造方法执行了...
验证苹果的名称:一个经过反射后的苹果... *********************再设置一个私有字段的值************************************
验证苹果的价格:1999999.0

通过反射调用方法

package fruits;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method; public class Apple {
private String name;
private Double price; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Double getPrice() {
return price;
} public void setPrice(Double price) {
this.price = price;
} // 公有的方法
public void eat(){
System.out.println("阿拉啦啦啦啦啦,吃苹果啦");
} // 私有的方法
private int add(int number, int number1){
return number + number1;
} public static void main(String[] args){ Class clazz = null;
try {
// 获取 Class 对象
clazz = Class.forName("fruits.Apple");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 获取一个无参构造类对象
Constructor constructor = null;
// 通过反射实例化一个对象
Object obj = null;
try {
constructor = clazz.getConstructor();
obj = constructor.newInstance();
} catch (Exception e) {
e.printStackTrace();
} System.out.println("**************************获取所有公有的方法********************************");
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println(method);
} System.out.println();
System.out.println("**************************调用公有的方法 eat ********************************");
try {
Method method = clazz.getMethod("eat");
method.invoke(obj);
} catch (Exception e) {
e.printStackTrace();
} System.out.println();
System.out.println("**************************调用公有的方法 set get ********************************");
try {
// 进行赋值
Method method = clazz.getMethod("setName",String.class);
method.invoke(obj,"通过 setName 进行赋值的苹果");
Method method1 = clazz.getMethod("setPrice",Double.class);
method1.invoke(obj,18888.902);
// 进行取值
Method method2 = clazz.getMethod("getName");
Method method3 = clazz.getMethod("getPrice");
System.out.println(" get ---> name:" + method2.invoke(obj) + ", price:" + method3.invoke(obj) );
Apple apple = (Apple) obj;
System.out.println("进行验证 :name " + apple.getName() + ", price " + apple.getPrice());
} catch (Exception e) {
e.printStackTrace();
} System.out.println();
System.out.println("**************************获取所有的方法,包括私有的********************************");
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
} System.out.println();
System.out.println("**************************调用私有的方法 add ********************************");
try {
Method method = clazz.getDeclaredMethod("add", int.class, int.class);
// 无视访问修饰符
method.setAccessible(true); System.out.println(" add result --》 " + method.invoke(obj,333,333));
} catch (Exception e) {
e.printStackTrace();
} } }

结果:

**************************获取所有公有的方法********************************
public static void fruits.Apple.main(java.lang.String[])
public java.lang.String fruits.Apple.getName()
public void fruits.Apple.setName(java.lang.String)
public java.lang.Double fruits.Apple.getPrice()
public void fruits.Apple.setPrice(java.lang.Double)
public void fruits.Apple.eat()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll() **************************调用公有的方法 eat ********************************
阿拉啦啦啦啦啦,吃苹果啦 **************************调用公有的方法 set get ********************************
get ---> name:通过 setName 进行赋值的苹果, price:18888.902
进行验证 :name 通过 setName 进行赋值的苹果, price 18888.902 **************************获取所有的方法,包括私有的********************************
public static void fruits.Apple.main(java.lang.String[])
private int fruits.Apple.add(int,int)
public java.lang.String fruits.Apple.getName()
public void fruits.Apple.setName(java.lang.String)
public java.lang.Double fruits.Apple.getPrice()
public void fruits.Apple.setPrice(java.lang.Double)
public void fruits.Apple.eat() **************************调用私有的方法 add ********************************
add result --》 666

通过反射越过泛型检查

    public static void main(String[] args){

        // 泛型用在编译期,编译过后泛型擦除
List<Integer> list = new ArrayList<Integer>();
// 编译器提示 类型错误
//list.add("字符串"); list.add(1);
list.add(2); // 通过 反射越过泛型检查
// 获取到 list 的 字节码对象
Class listClass = list.getClass(); try {
// 反向的调用add()方法,添加数据
Method add = listClass.getMethod("add", Object.class);
// 进行调用
add.invoke(list,"越过泛型检查");
} catch (Exception e) {
e.printStackTrace();
}
// 打印结果
for (Object obj : list) {
System.out.println( obj );
} }

结果:

1
2
越过泛型检查

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. noi openjudge 6044:鸣人和佐助

    http://noi.openjudge.cn/ch0205/6044/ 描述佐助被大蛇丸诱骗走了,鸣人在多少时间内能追上他呢? 已知一张地图(以二维矩阵的形式表示)以及佐助和鸣人的位置.地图上的每个 ...

  2. [学习笔记] 在Eclipse中导出可以直接运行的jar,依赖的jar在子目录中

    工程创建可参考前文: [学习笔记] 在Eclipse中使用Hibernate,并创建第一个工程,数据库为Oracle XE 在工程上鼠标右键: 找到java 选择 Runable JAR file N ...

  3. 在C#中简单使用gRPC

    一.引言 本文采用gRPC官方提供的一个教程例子,通过这个例子可以学习到在.proto文件中定义服务.使用protocol buffer编译器生成服务器和客户端代码.使用C#gRPC API为您的服务 ...

  4. Spring Boot 创建动态定时任务

    1,日期格式转换 //定时任务格式转换public static String convertCronTime(Date jobDate){ //https://blog.csdn.net/qq_39 ...

  5. codeforces 1251D Salary Changing (二分+贪心)

    (点击此处查看原题) 题意分析 一共有s元钱,要用这些钱给n个人发工资,发给每个人的工资si有最少和最多限制 si ∈[li,ri],在发给n个人的总工资小于s的情况下,要求发给n个人中的工资的中位数 ...

  6. dedecms发布文章时间显示多少分钟前

    /**文章发布多少时间前*/function tranTime($time) { $rtime = date("m-d H:i",$time); $htime = date(&qu ...

  7. 【Trie】L 语言

    [题目链接]: https://loj.ac/problem/10053 [题意]: 给出n个模式串.请问文本串是由多少个模式串组成的. [题解]: 当我学完AC自动机后,发现这个题目也太简单了吧. ...

  8. Go语言GOPATH详解(Go语言工作目录)

    GOPATH 是 Go语言中使用的一个环境变量,它使用绝对路径提供项目的工作目录. 工作目录是一个工程开发的相对参考目录,好比当你要在公司编写一套服务器代码,你的工位所包含的桌面.计算机及椅子就是你的 ...

  9. CCF - CCSP 2018-01 绝地求生 BFS

    BFS从安全地区方向搞一下就好了 1.还是注意每回合清空 2.posx居然开小了,可不能犯这种错误 3.地图用a和节点的dis重名了,建议其他变量禁止用a命名 4.在输入数据之前continue了,这 ...

  10. centos中拉取postgre

    新搭建好的linux服务器环境,docker也配置好了. 第一步,下载postgre docker pull postgres:11 这里的版本号自己按照自己的需要来获取. 然而实际上没那么顺利,直接 ...