Java反射初探 ——“当类也学会照镜子”
反射的作用
好吧,我知道这听起来还是很模糊,让我们一步一步来:
类也是对象
“类”对象和“类”类型
Class a
取得Class对象的三种方式
public class MyClass { }
Class classInstance= MyClass.class;
二. 通过类创建的实例对象的getClass方法取得
MyClass myClass = new MyClass();
Class classInstance = myClass.getClass();
三.通过Class类的静态方法forName方法取得(参数是带包名的完整的类名)
Class classInstance = Class.forName("mypackage.MyClass");

try {
Class classInstance = Class.forName("mypackage.MyClass");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

利用反射API全面分析类的信息——方法,成员变量,构造器


public class MyClass {
private int value; //成员变量
public MyClass (int value) { this.value = value; } //构造函数
public int getValue() { return value; } //方法1
public void setValue(int value) { this.value = value; } //方法2
}


import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test {
public static void printClassMessage (Object obj) {
Class c = obj.getClass(); // 获取obj所属类的Class对象
Method [] methods = c.getDeclaredMethods(); // 获取方法对象列表
System.out.println("遍历MyClass类里的所有方法的名称:");
for(int i =0; i<methods.length; i++) {
System.out.println(methods[i].getName());
}
Field [] fields = c.getDeclaredFields(); // 获取成员变量对象列表
System.out.println("遍历MyClass类里的所有成员变量的名称:");
for(int i =0; i<fields.length; i++) {
System.out.println(fields[i].getName());
}
Constructor [] constructors = c.getConstructors(); // 获取构造函数对象列表
System.out.println("遍历MyClass类里的所有构造函数的名称:");
for(int i =0; i<constructors.length; i++) {
System.out.println(constructors[i].getName());
}
}
public static void main(String [] args) {
MyClass myClass = new MyClass(1); // 创建一个MyClass对象
printClassMessage(myClass); // 打印这个对象所属类的相关信息
}
}


遍历MyClass类里的所有方法的名称:
getValue
setValue
遍历MyClass类里的所有成员变量的名称:
value
遍历MyClass类里的所有构造函数的名称:
mypackage.MyClass

上面的例子仅仅是作为一个展示,Method/Field/Constructor对象的API当然不仅限于getName这样获取名称的简单操作,所以接下来我将分别介绍更具体的反射API
利用反射API分析类中方法信息
getMethods和getDeclaredMethods方法
public Method[] getDeclaredMethods()对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。当然也包括它所实现接口的方法。
getValue
setValue

import java.lang.reflect.Method;
public class Test {
public static void printMethodsMessage (Object obj) {
Class c = obj.getClass();
Method [] methods = c.getMethods();
for (Method method : methods) {
System.out.println(method.getName());
}
}
public static void main(String [] args) {
MyClass myClass = new MyClass(1);
printMethodsMessage(myClass);
}
}


getValue
setValue
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAll

通过method.getReturnType()获取方法返回值对应的Class对象

import java.lang.reflect.Method;
public class Test {
public static void printMethodsMessage (Object obj) {
Class c = obj.getClass(); // 取得obj所属类对应的Class对象
Method [] methods = c.getDeclaredMethods(); // 取得obj所属类中方法对应的Method对象组成的数组
for (Method method : methods) { // 遍历Method对象
String name = method.getName(); // 取得方法名
Class returnClass = method.getReturnType(); // 获取方法返回值对应的Class对象
String returnName = returnClass.getName(); //获取返回值所属类的类名——也即返回值类型
System.out.println(name + "方法的返回值类型是" + returnName);
}
}
public static void main(String [] args) {
MyClass myClass = new MyClass(1);
printMethodsMessage(myClass);
}
}

getValue方法的返回值类型是int
setValue方法的返回值类型是void
通过method.getParameterTypes()获取方法各参数的Class对象组成的数组
public class MyClass {
public void method1 (int a, long b) { };
public void method2 (float a, double b) { };
public void method3 (String str) { };
}

public class Test {
public static void printMethodsMessage (Object obj) {
Class c = obj.getClass(); // 取得obj所属类对应的Class对象
Method [] methods = c.getDeclaredMethods(); // 取得obj所属类中方法对应的Method对象组成的数组
for (Method method : methods) { // 遍历Method对象
String methodName = method.getName(); // 取得方法名
String paramsStr = ""; // 用于存放某个方法参数类型列表的字符串
Class [] paramsClasses = method.getParameterTypes();
for (Class pc: paramsClasses) {
String paramStr = pc.getName(); // 获取当前参数类型
paramsStr+=paramStr + " ";
}
System.out.println(methodName+ "方法的所有参数的类型列表:" + paramsStr);
}
}
public static void main(String [] args) {
MyClass myClass = new MyClass();
printMethodsMessage(myClass);
}
}

method2方法的参数类型列表:float double
method1方法的参数类型列表:int long
method3方法的参数类型列表:java.lang.String
利用反射API分析类中成员变量信息
获取成员变量类型对应的的Class对象
public class MyClass {
private int number = 123;
private String name ="彭湖湾";
}

import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test {
public static void printFieldsMessage (Object obj) {
Class c = obj.getClass(); // 取得obj所属类对应的Class对象
try {
Field field = c.getDeclaredField("name"); // 取得名称为name的field对象
field.setAccessible(true); // 这一步很重要!!!设置为true才能访问私有成员变量name的值!
String nameValue = (String) field.get(obj); // 获取obj中name成员变量的值
System.out.println("MyClass类中name成员变量的值为:" + nameValue); // 输出
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String [] args) {
MyClass myClass = new MyClass();
printFieldsMessage(myClass);
}
}

MyClass类中name成员变量的值为:彭湖湾
通过getType方法读取成员变量类型的Class对象
Field field = class1.getDeclaredField(number");
System.out.print(field.getType().getName());
int
利用反射API分析类中构造器信息
public class MyClass {
public MyClass(int a, String str){}
}

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test {
public static void printContructorsMessage (Object obj) {
Class c = obj.getClass(); // 取得obj所属类对应的Class对象
Constructor [] constructors = c.getDeclaredConstructors();
for (Constructor constructor : constructors) {
Class [] paramsClasses = constructor.getParameterTypes();
String paramsStr = "";
for (Class pc : paramsClasses) {
String paramStr = pc.getName();
paramsStr+=paramStr + " ";
}
System.out.println("构造函数的所有参数的类型列表:" + paramsStr);
}
}
public static void main(String [] args) {
MyClass myClass = new MyClass(1, "彭湖湾");
printContructorsMessage(myClass);
}
}

构造函数的所有参数的类型列表:int java.lang.String
利用反射动态加载类,并用该类创建实例对象


NotExistClass cannot be resolved to a type


Class classInstance = Class.forName("mypackage.MyClass");
MyClass myClass = (MyClass) classInstance.newInstance();
不过要注意的是,因为newInstance返回的是一个Object,所以要做强制类型转换,将其变成MyClass类型

public class Test {
public static void main(String [] args) {
try {
Class classInstance = Class.forName("mypackage.MyClass");
MyClass myClass = (MyClass) classInstance.newInstance();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

参考:利用反射实现JavaBean的自动赋值
import java.lang.reflect.Method;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import com.sns.exception.ApplicationException;
public final class ParameterUtil {
public static void setFormBean(HttpServletRequest request, Object bean) {
Class c = bean.getClass();
Method[] ms = c.getMethods();
for(int i=0; i<ms.length; i++) {
String name = ms.getName();
if(name.startsWith("set")) {
Class[] cc = ms.getParameterTypes();
if(cc.length==1) {
String type = cc[0].getName(); // parameter type
try {
// get property name:
String prop = Character.toLowerCase(name.charAt(3)) + name.substring(4);
// get parameter value:
String param = getString(request, prop);
if(param!=null && !param.equals("")) {
//ms.setAccessible(true);
if(type.equals("java.lang.String")) {
ms.invoke(bean, new Object[] {param});
}
else if(type.equals("int") || type.equals("java.lang.Integer")) {
ms.invoke(bean, new Object[] {new Integer(param)});
}
else if(type.equals("long") || type.equals("java.lang.Long")) {
ms.invoke(bean, new Object[] {new Long(param)});
}
else if(type.equals("boolean") || type.equals("java.lang.Boolean")) {
ms.invoke(bean, new Object[] { Boolean.valueOf(param) });
}
else if(type.equals("java.util.Date")) {
Date date = DateUtil.parseDateTime(param);
if(date!=null)
ms.invoke(bean, new Object[] {date});
}
}
}
catch(Exception e) {
e.printStackTrace();
}
}
}
}
}
}
每当发现JavaBean中的setXxx()方法时,便自动寻找表单的对应字段xxx,如果找到,就利用反射调用此方法,将对应的字段值赋给JavaBean。
由于表单传递的变量名和值全部是字符串,因此需要做某些转换。目前,该程序能处理的数据类型包括:boolean,Boolean,int,Integer,long,Long,Date,不被支持的数据类型被自动忽略。你也可以很方便地添加新的类型。
请 注意,只有public的set方法能够被调用。如果你希望private或protected的set方法也能被调用,请将红色标识的 getMethods()改为getDeclaredMethods(),以便获得包括private和protected在内的所有方法,并将 ms.setAccessible(true);的注释去掉,以便能正确调用private和protected方法。
反射是Java语言非常强大的功能,但是由于反射会破坏对象封装,并且反射调用的速度较慢,因此,只能在必要的工具类中使用。
Java反射初探 ——“当类也学会照镜子”的更多相关文章
- 【java】java反射初探 ——“当类也学会照镜子”
反射的作用 开门见山地说说反射的作用 1.为我们提供了全面的分析类信息的能力 2.动态加载类 我理解的“反射”的意义 (仅个人理解哈) 我理解的java反射机制就是: 提供一套完善而强 ...
- 【java】java反射初探 ——“当类也照起镜子”
反射的作用 开门见山地说说反射的作用 1.为我们提供了全面的分析类信息的能力 2.动态加载类 我理解的“反射”的意义 (仅个人理解) 我理解的java反射机制就是: 提供一套完善而强大的API ...
- JAVA反射之Class类的练习
package zhang; /** * JAVA反射之CLass类的练习 * * 在面向对象的语言里,万事万物皆对象,那么类是谁的对象呢? * 类的类型是CLass * * */ class Tes ...
- Java反射 - 1(得到类对象的几种方法,调用方法,得到包下的所有类)
通过反射获得对象的方法 准备工作: 有一个User类如下 package o1; /** * Created by yesiming on 16-11-19. */ public class User ...
- java反射 顺序输出类中的方法
java反射可以获取一个类中的所有方法,但是这些方法的输出顺序,并非代码的编写顺序. 我们可以通过自定义一个注解来实现顺序输出类中的方法. 首先,先写一个类,定义增删改查4个方法 public cla ...
- java反射之获取类的基本信息(一)
一.反射原理. Java 反射机制.通俗来讲呢,就是在运行状态中,我们可以根据“类的部分已经的信息”来还原“类的全部的信息”.这里“类的部分已经的信息”,可以是“类名”或“类的对象”等信息.“类的全部 ...
- java反射对实体类取值和赋值,可以写成通过实体类获取其他元素的数据,很方便哦~~~
项目中需要过滤前面表单页面中传过来的实体类的中的String类型变量的前后空格过滤,由于前几天看过一个其他技术博客的的java反射讲解,非常受益.于是,哈哈哈 public static <T& ...
- Java反射之Class类
接下来的几章,我们谈一谈java的反射机制. 反射就是从一个java类中映射出一个java类或是一个实例.通常在很多框架中都用到反射,比如常用的ssm框架,在配置文件中总是会写到类的全名,框架通过读取 ...
- java反射初探
java反射 反射是java的重要特性之一,java.lang.reflect 是jdk支持反射的重要包,我下面可能会对构造器Constructor,属性Filed,方法Method会用到.反射其实很 ...
随机推荐
- 【BZOJ 3451】Tyvj1953 Normal 思维题+期望概率+FFT+点分治
我感觉是很强的一道题……即使我在刷专题,即使我知道这题是fft+点分治,我仍然做不出来……可能是知道是fft+点分治限制了我的思路???(别做梦了,再怎样也想不出来的……)我做这道题的话,一看就想单独 ...
- ELK 日志分析实例
ELK 日志分析实例一.ELK-web日志分析二.ELK-MySQL 慢查询日志分析三.ELK-SSH登陆日志分析四.ELK-vsftpd 日志分析 一.ELK-web日志分析 通过logstash ...
- (转)Python中的模块循环导入问题
本文转自: https://wiki.woodpecker.org.cn/moin/MiscItems/2008-11-25 问题 cleven <shenglipang@gmail.com&g ...
- IIS发布MVC出错
一个MVC网站在发布到IIS上时,出现了这个问题: 然后解决办法: 然后应用程序池那里,自己点右键添加一个 新建完应用池之后选中点高级设置 最后,添加网站,添加网站的时候应用程序池选择自己刚刚新建的那 ...
- RESTful记录-RESTful服务
按照REST架构,一个RESTful Web服务不应该继续服务器的客户端的状态.这种限制被称为无状态.它负责客户以它的上下文传递给服务器,然后服务器可以存储这样的上下文,以处理客户端的进一步请求.例如 ...
- bzoj千题计划286:bzoj1226: [SDOI2009]学校食堂Dining
http://www.lydsy.com/JudgeOnline/problem.php?id=1226 关键点:一个人只能忍受 ‘紧跟’ 在他 后面的b个人比他先打到饭 dp[i][j][k] 前i ...
- 20155218 2006-2007-2 《Java程序设计》第5周学习总结
20155218 2006-2007-2 <Java程序设计>第5周学习总结 教材学习内容总结 java中的错误都会被包装成对象,且是可抛出的. 通常称错误处理为异常处理,程序设计本身的错 ...
- Tensorflow数据读取的方式
深度学习既然是基于数据的方法,先不管多抽象,那总归是有读取数据的方法的吧,这里的数据应该是一个统称,包含我们讲的数据集和变量tensor. tf读取数据一共有3种方法: 供给数据(Feeding): ...
- ubuntu16.04 caffe(GPU模式)安装
历时5天终于完成了,配置中出现了各种各样的Error,这里记录一下,希望能为正在安装的人提供一点帮助. 配置中主要参考博客:http://blog.csdn.net/yhaolpz/article/d ...
- 【干货】linux系统信息收集 ----检测是否被恶意程序执行了危险性命令
这些实战完全可以练习以下命令,已经找到需要观察的交互点,真实工作的时候,把数据都导入到自己U盘或者工作站内. 在kali 或者centos下训练都一样,关于kali教学,这里推荐掌控安全团队的课程:掌 ...