下面总结下Class常用的几种方法:
1.类中的方法:
1.int result = clazz.getModifiers(); // 获取类的修饰符(权限 特征)
每一个修饰符 用一个整数来进行表示
从0开始 ---0 1 2 4 8 16 32 64 129 256 512
0表示默认不写 1表示public 2表示private 4表示protected 8表示static 16表示final 32表示synchronized 64volatile
128表示transient 256表示native 512表示interface 1024表示abstract
2.String name = clazz.getName(); // 获取到的是包名.类名如testReflect.Person
3.String simpleName = clazz.getSimpleName();// 获取到的是类名Person
4.Package p = clazz.getPackage(); // 获取到的是包名 testReflect
5.Class sclazz = clazz.getSuperClass(); // 获取超类(父类)
6.Class[] classes = clazz.getModifiers();
7.Object obj = clazz.newInstance(); // 默认调用无参构造方法创建对象,如testReflect.Person@2a139a55
------------------------------------------------
2.Field类中的常用方法:
可以获取到属性的修饰符,返回值类型,属性名以及
8.属性值如以下这两个方法只能获取公有的属性,其中可以包含继承过来的父类属性:
Field f = clazz.getField("属性名);
Fields[] fs = clazz.getFields();
------------------------------
9.获取到的公有的和私有的属性方式,只能获取本类中的属性属性如:
Field f = clazz.getDeclaredField("name");
Fields[] f = clazz.getDeclaredFields();
获取到的私有属性进行操作该属性的方式如:
f.setAccessible(true); // 表示私有属性可以直接被修改。
获取私有的属性方式如:
创建java类如下:
public class Person {
public String name; // public修饰表示该属性是公有的
public int age; // public修饰表示该属性是公有
public String toString() { return "{" + name + "," + age + "}"; } }
如图:

为什么需要通过clazz.getField()获取到属性?
答:需要操作属性,一方面向里面存值或者另一方面从里面取值。
-------------------------
对比:
传统操作属性中的值的方式是:
对象 = new(); // 先创建对象空间,有了对象之后,对象空间里就有自己的一套元素(属性,方法)
于是就可以是使用对象.属性 = 值;
而我们使用反射机制创建对象方式是:
第一步:属性 = 类.getField();
第二步:属性.赋值(哪个对象,值);
总结:反射机制操作对象的步骤就好像跟传统方式的步骤相反似的。
例子如:
try {
Class clazz = Class.forName("testReflect.Person");
Person p = (Person)clazz.newInstance();
Field nameField = clazz.getField("name");
// 赋值
nameField.set(p, "小蔡"); // p表示哪个对象要设置值,小蔡这个参数表示设置的值是什么
System.out.println(p);
} catch (Exception e) {
e.printStackTrace();
}
传统访问属性中的值的方式是:
值 = 对象.属性
而反射机制中访问属性的方式是:
值 = 属性.取值(哪个对象)
如图效果:

最后看下例子:
想要修改String类里面的值,也就是数组里面的值的实现方式:
代码如下:
public static void main(String[] args) {
// 通过一个Class对象来操作Person.class类,
// String里面的属性是private final char value[],也就是
// String里面的属性是private final char[] value = {'a','b','c'}
String str = new String("abc");
System.out.println(str);
// 反射的技术可以获取私有属性,可以操作私有属性,虽然不合理
// 1.获取String类对应的那个Class
Class clazz = str.getClass();
// 2.通过claszz获取类中的value属性
try {
Field field = clazz.getDeclaredField("value");
// 3.直接操作属性的值不可以设置私有属性,所以需要设置这个值为true
field.setAccessible(true);
// 4.获取value属性里面的值(内存地址)
//String里面的属性是private final char[] value = {'a','b','c'},
//注意:final表示是地址不让修改,而不是里面的值不让修改,我们可以找到地址找到真实的内容进行修改
char[] temp = (char[])field.get(str);
// 通过temp的地址引用 找到真实的String对象中的数组进行修改数组内的每一个元素
temp[0] = '小';
temp[1] = '菜';
temp[2] = '好';
System.out.println(temp);
} catch (Exception e) {
e.printStackTrace();
}
}
输出:abc
小菜好
-----------------------------------------------------------------------------------
3.类中的方法:
int mm = m.getModifiers(); // 获取方法的修饰符(权限+特征)
Class mrt = m.getReturnType(); // 获取返回值数据类型
String mm = m.getName(); // 获取方法的名字
Class[] mpts = m.getParameterTypes(); // 获取方法参数列表的数据
Class[] mets = m.getExceptionTypes(); // 获取方法抛出异常的类型
同样如果该方法是private修饰的,则需要设置:
setAccessible(true); // 表示私有属性可以直接被修改。
获取到方法之后,如果操作方法呢?
使用方法.invoke(对象,执行方法需要传递的所有参数);
如:
// 获取Person对应的Class
Class clazz = Person.class;
Person p = (Person)clazz.newInstance();
// 通过clazz获取其中的方法,第一个参数是方法名,第二个是参数类型即Class<?>...
Method m = clazz.getMethod("eat", String.class);
m.invoke(p,"测试"); // 调用带参数地方法
首先创建Person类如下:
public class Person {
public String name;
public int age;
public void eat() {
System.out.println("我是吃的方法");
}
public void eat(String s, Integer a) {
System.out.println("我是带参数的吃的方法");
}
public String toString() {
return "{" + name + "," + age + "}";
}
}
然后实现如下:
// 获取Person对应的Class
Class clazz = Person.class;
// 通过clazz获取其中的方法,第一个参数是方法名,第二个是参数类型即Class<?>...
try {
Method m = clazz.getMethod("eat", String.class, Integer.class);
int result = m.getModifiers(); // 方法修饰符(权限+特征)
System.out.println(result); // 打印结果为1
Class cl = m.getReturnType(); // 返回值数据类型
System.out.println(cl); // 打印结果为void
String name = m.getName(); // 获取方法的名字
System.out.println(name); // 打印结果为eat
Class[] mpts = m.getParameterTypes(); // 获取方法参数列表的类型
for (Class mpt : mpts) {
System.out.println(mpt.getName()); // 打印结果java.lang.String和java.lang.Integer
}
} catch (Exception e) {
e.printStackTrace();
}
其中getMethod实现如下:
@CallerSensitive
public Method getMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
Method method = getMethod0(name, parameterTypes, true);
if (method == null) {
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
}
return method;
}
------------------------------------------------------------------------------------------------------
构造方法(clazz.getConstructor(Class...参数类型)):
作用:因为
Class class = Class.forName(className);
Object object = class.newInstance(); // 只能调用无参构造函数
当一个对象中没有无参构造方式时,如果再想通过class.newInstance这样的方式是不行的,所以需要通过
Constructor conn = clazz.getConstructor(Class...参数类型)获取到有参构造函数,然后使用conn.newInstance()构造对象
浙公网安备 33010602011771号