反射入门详解
引言:反射很多人说很难,其实很简单,就是一般类的应用(个人愚见),如果你对此感兴趣,请认真读完,你就会发现反射入门很简单。
反射是Java的一个特性,其实也是一种面向对象思想的一个深入体验。
类是事物的抽象,类也可以看成class文件。既然是文件那就一个事物,我们就可以把它抽象成类。换一句话说,反射(Class类)就是把类抽象成一个类。可能有点不好懂,看完下一段就懂了。
类就具有属性和方法,很好理解。那么我们做反射这个类(以后用Class类表示)。就需要有个一两个字段,Field和Method(属性和方法),属性是一个复杂的事物,它有修饰符,类型,名称。那么我们把它也抽象成一个类Field。方法同理。也有修饰符、返回值类型、方法名、方法参数。这就抽象成Method类。其中的修饰符(Modifer)、返回值类型(ReturnType)等等,这些自然也抽象成一个个类。
读到这里是不是很好理解了。
剩下的就和一般的类使用相同了,先写一个事例,来熟悉一下这里面的方法。事例目的反射出一个对象的各种东西。然后我再写一下,他们中的属性使用和方法使用。(熟悉的可以跳过这段代码)
/**
* @(#)Test.java
* Description: TODO 填写文件作用简要说明
* Version : 0.0.0
* Copyright: Copyright (c) 哈尔滨甲骨文培训基地 版权所有
* Create by: 刘东赫 2015年8月12日
*/
package com.ldh.test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* 反射——破解实例
*
* @author 刘东赫
*/
public class Test {
public static void main(String[] args) {
try {
ref();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void ref() throws Exception {
Class
clazz = Class.forName("com.ldh.domain.User");
StringBuilder sb = new StringBuilder();
if (!clazz.isInterface()) {
System.out.println("类");
// 头信息
sb.append(Modifier.toString(clazz.getModifiers())).append(" ");//获得修饰符
sb.append(clazz.getSimpleName()).append("{\n");//获得简单的类名,没有包名的
// 属性信息
Field[] fields = clazz.getDeclaredFields();//获取所有属性包括私有
//遍历属性集合,得到每个属性的类型和名称
for (Field fd : fields) {
sb.append("\t").append(Modifier.toString(fd.getModifiers()));
sb.append(" ");
sb.append(fd.getName()).append(";");
sb.append("\n");
}
//构造方法获取
Constructor
[] cs = clazz.getConstructors();
//遍历构造方法
for (Constructor
m : cs) {
sb.append("\t").append(Modifier.toString(m.getModifiers()));
sb.append(" ").append(clazz.getSimpleName());
sb.append("(");
Class
[] par = m.getParameterTypes();
int i = 0;
for (Class
p : par) {
sb.append(p.getSimpleName() + " ");
sb.append("arg" + i + ",");
i++;
}
if (par.length != 0)
sb.deleteCharAt(sb.length() - 1);
sb.append(") {}").append("\n");
}
// 获取方法
Method[] ms = clazz.getDeclaredMethods();
//遍历方法
for (Method m : ms) {
sb.append("\t").append(Modifier.toString(m.getModifiers()));
sb.append(" ").append(m.getReturnType().getSimpleName());
sb.append(" ").append(m.getName()).append("(");
Class
[] par = m.getParameterTypes();
int i = 0;
for (Class
p : par) {
sb.append(p.getSimpleName() + " ");
sb.append("arg" + i + ",");
i++;
}
if (par.length != 0)
sb.deleteCharAt(sb.length() - 1);
sb.append(")").append("\n");
}
sb.append("\n}");
System.out.println(sb.toString());
} else {
System.out.println("接口");
// 头信息
sb.append(Modifier.toString(clazz.getModifiers())).append(" ");
sb.append(clazz.getSimpleName()).append("{\n");
// 属性信息
Field[] fields = clazz.getDeclaredFields();
for (Field fd : fields) {
sb.append("\t").append(Modifier.toString(fd.getModifiers()));
sb.append(" ");
sb.append(fd.getName()).append("=").append(fd.get(fd.getName()));
sb.append(";");
sb.append("\n");
}
// 获取方法
Method[] ms = clazz.getDeclaredMethods();
for (Method m : ms) {
sb.append("\t").append(Modifier.toString(m.getModifiers()));
sb.append(" ").append(m.getReturnType().getSimpleName());
sb.append(" ").append(m.getName()).append("(");
Class
[] par = m.getParameterTypes();
int i = 0;
for (Class
p : par) {
sb.append(p.getSimpleName() + " ");
sb.append("arg" + i + ",");
i++;
}
if (par.length != 0)
sb.deleteCharAt(sb.length() - 1);
sb.append(") {}").append("\n");
}
sb.append("\n}");
System.out.println(sb.toString());
}
}
}
结果:
public User{
private static final i;
private name;
private age;
public User(int arg0) {}
public User() {}
public void find(Object arg0,String arg1)
public void setName(String arg0)
public String c()
public String getName()
public void setAge(String arg0)
public String getAge()
public static void util()
}
好了看完以上的代码,基本用法已经会了:我们在学习一下,怎么使用反射获取对象,使用方法,使用属性。
先将一下理解:方法和属性是不是有对象确定的,就像你的名字是在new了一个人之后才能知道的。方法是动作,也是这个对象(人)产生了以后才知道方法怎么用。
一句话,调用时对象调用,属性方法依赖于对象(静态方法除外)
事例:三种方法为对象设置属性值,只是了解一下方法,不是很好用。
public class Test1 {
public static void main(String[] args) {
TUser u = new TUser();
try {
new Test1().show1(u, "33");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(u.getName() + "|" + u.getAge());
}
public void show1(Object obj, String par) throws Exception {
Class
clazz = obj.getClass();
//获取属性集合
Field[] fs = clazz.getDeclaredFields();
for (Field f : fs) {
String str = f.getName();
//拼接字符串也就是set方法名
String str2 = "set" + str.substring(0, 1).toUpperCase() + str.substring(1);
//更具名字产生方法
Method m = clazz.getMethod(str2, String.class);
m.invoke(obj, par);
}
}
public void show2(Object obj, String par) throws Exception {
Class
clazz = obj.getClass();
//获得方法集合
Method[] me = clazz.getMethods();
for (Method m : me) {
//有set关键字的设置调用
if (m.getName().contains("set")) {
m.invoke(obj, par);
}
}
}
public void show3(Object obj, String par) throws Exception {
Class
clazz = obj.getClass();
Field[] fs = clazz.getDeclaredFields();
for (Field f : fs) {
//暴力破解私有属性,直接赋值
f.setAccessible(true);
f.set(obj, par);
}
}
}
后面会出文章讲解反射异常,和一些反射深入用法。