今天早上、在群里闲聊。群友A说道叫群友B拉几个妹纸进群来聊天。
B说道:"凡是我认识的妹子,我都会标注为private,怎么可能有public的"。
A说道:"你妹,伙计们,用反射获取他的private属性"。
于是闲的蛋疼的我就去写代码去了、在写代码的过程中、我的疑惑渐渐的多了起来。好多以前学习过的内容都忘记了、于是乎Google百度什么的开始忙了起来。
String classPath = "com.test.hzw.bean.test_user"; //B君的类路径
Class cls = Class.forName(classPath);
Field[] fieldlist = cls.getDeclaredFields();
for (int i = 0; i < fieldlist.length; i++) {
Field fld = fieldlist[i];
System.out.println("妹纸的属性名称 = " + fld.getName());
System.out.println("妹纸的类型名称 = " + fld.getType());
}
Java的反射机制、能够在java运行时根据类的路径去获取与路径对应的Class对象。在根据这个类对象去获取类的成员变量、方法、构造这些东西、哪怕他们是私有的。获取到这些东西来做什么?你可以用他们来判断、也可以调用他们去完成某些功能。
Class:类
既然一切的前提就是要获取到Class对象。那么就得看看java.lang.Class这个类。继续Google了一下、发现有前辈写了一篇文章:
http://blog.csdn.net/hzw2312/article/details/8637199
文章很OK、我这里借用一下、就在不多加描述了。
Field:类的成员变量
Field类、提供有关类或接口的单个字段的信息,以及对它的动态访问权限。可以通过Class的四个静态方法来获得Field对象跟数组:
第一个getField方法返回一个Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明的public字段(包含继承字段)。
第二个方法getDeclaredField返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段(不包含继承字段)。name 参数是一个 String,它指定所需字段的简称。
Class class1 = null;
try {
//com.test.hzw.bean.test_user为类的全路径名
class1 = Class.forName("com.test.hzw.bean.test_user");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
//getField方法就不写了
Field ff = class1.getDeclaredField("name");
System.out.println(ff.getName());
System.out.println(ff.getType());
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
第三个方法getFields则返回Class对象所表示的类或接口的所有可访问公共字段(包括继承字段)。
第四个getDeclaredFields方法返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。包括公共、保护、默认(包)访问和私有字段,但不包括继承的字段。返回数组中的元素没有排序,也没有任何特定的顺序。如果该类或接口不声明任何字段,或者此 Class 对象表示一个基本类型、一个数组类或 void,则此方法返回一个长度为 0 的数组。
Class class1 = null;
try {
//com.test.hzw.bean.test_user为类的全路径名
class1 = Class.forName("com.test.hzw.bean.test_user");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Field[] f = class1.getDeclaredFields();
for (int i = 0; i < f.length; i++) {
Field field = f[i];
System.out.println("属性名称:"+field.getName());
System.out.println("属性类型:"+field.getType());
}
Method:类的方法
Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。 跟Field一样通过Class的四个静态方法来获得Method对象跟数组:
第一个getMethod 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。name 参数是一个 String,用于指定所需方法的简称。parameterTypes 参数是按声明顺序标识该方法形参类型的 Class 对象的一个数组。如果 parameterTypes 为 null,则按空数组处理。
第二个getDeclaredMethod返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。name 参数是一个 String,它指定所需方法的简称,parameterTypes 参数是 Class 对象的一个数组,它按声明顺序标识该方法的形参类型。如果在某个类中声明了带有相同参数类型的多个方法,并且其中有一个方法的返回类型比其他方法的返回类型都特殊,则返回该方法;否则将从中任选一个方法。如果名称是 "<init>” 或 “<clinit>",则引发一个 NoSuchMethodException。
Class class1 = null;
try {
//com.test.hzw.bean.test_user为类的全路径名
class1 = Class.forName("com.test.hzw.bean.test_user");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Method m = null;
try {
m = class1.getDeclaredMethod("getPass"); //参数填写类中任意方法的方法名称
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
System.out.println("方法名称:"+m.getName());
System.out.println("方法返回类型:"+m.getReturnType());
第三个getMethods返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。数组类返回从 Object 类继承的所有(公共)member 方法。返回数组中的元素没有排序,也没有任何特定的顺序。如果此 Class 对象表示没有公共成员方法的类或接口,或者表示一个基本类型或 void,则此方法返回长度为 0 的数组。
第四个getDeclaredMethods返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。返回数组中的元素没有排序,也没有任何特定的顺序。如果该类或接口不声明任何方法,或者此 Class 对象表示一个基本类型、一个数组类或 void,则此方法返回一个长度为 0 的数组。类初始化方法 <clinit> 不包含在返回数组中。如果该类声明带有相同参数类型的多个公共成员方法,则它们都包含在返回的数组中。
Class class1 = null;
try {
//com.test.hzw.bean.test_user为类的全路径名
class1 = Class.forName("com.test.hzw.bean.test_user");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Method[] ms = class1.getDeclaredMethods();
for (int i = 0; i < ms.length; i++) {
Method m = ms[i];
System.out.println("方法名称:"+m.getName());
System.out.println("方法返回类型:"+m.getReturnType());
}
Constructor:类的构造
提供关于类的单个构造方法的信息以及对它的访问权限。构造跟上面的两个类一样、通过Class的四个静态方法来获取Constructor 对象跟数组:
第一个getConstructor返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
第二个getDeclaredConstructor返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。
第三个getConstructors 返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。
第四个返回 getDeclaredConstructors 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。
import java.io.IOException;
import java.lang.reflect.Constructor;
/**
* 获取指定类的构造器相关信息
* @author 胡汉三
*/
public class ConstructorTest {
private int i;
private double j;
//默认的构造器
public ConstructorTest(){}
//重载的构造器
public ConstructorTest(int i , double j) throws IOException{
this.i=i;
this.j=j;
}
/**
* @param args
*/
public static void main(String[] args)throws Exception {
//得到本类的类对象
Class cls = Class.forName("com.test.hzw.f.ConstructorTest");
//取得所有在本类声明的构造器
Constructor[] cs = cls.getDeclaredConstructors();
//遍历
for (Constructor c : cs) {
//构造器名称
System.out.println("构造器名="+c.getName());
//构造器声明所在的类
System.out.println("其声明的类="+c.getDeclaringClass());
//取得参数的类型集合
Class[] ps = c.getParameterTypes();
//遍历参数类型
for (int i = 0; i < ps.length; i++) {
System.out.println("参数类型"+i+"="+ps[i]);
}
//取得异常类型集合
Class[] es =c.getExceptionTypes();
//遍历异常类型
for (int i = 0; i < es.length; i++) {
System.out.println("异常类型"+i+"="+es[i]);
}
//结束一层循环标志
System.out.println("-------------------------");
}
}
}
我的com.test.hzw.bean.test_user类代码
/**
* 用户类
* @author 胡汉三
*
*/
public class test_user extends Test{
private int id ; //用户编号(自增)
private String name; //用户名
private String pass; //密码
private int type; //类型
public String s="";
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String getPass() {
return pass;
}
public void setPass(String pass) {
this.pass = pass;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}
下一篇继续学习反射的实际应用、比如利用反射构建JDBC、利用反射构建JSON格式数据等!
欢迎QQ群交流:138986722