什么是反射?
定义一 :JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
定义二 :把java类中的各种成分映射成一个个的Java对象,这个比较好理解~~~
怎么使用反射?
Java反射常用类:
1、Class类—可获取类和类的成员信息
Class类的常用方法:
方法名 | 功能说明 |
---|---|
forName(String name) | 返回指定类名 name 的 Class 对象 |
newInstance() | 调用缺省构造函数,返回该Class对象的一个实例 |
newInstance(Object []args) | 调用当前格式构造函数,返回该Class对象的一个实例 |
getName() | 返回此Class对象所表示的实体(类、接口、数组类、基本类型或void名称 |
getSuperclass() | 返回表示此Class所表示的实体的超类的Class |
getField(String name) | 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。 |
getFields() | 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。 |
getDeclaredField(String name) | 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。 |
getDeclaredFields() | 返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。 |
getMethod(String name, Class<?>... parameterTypes) | 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。 |
getMethods() | 返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。 |
getDeclaredMethod(String name, Class<?>... parameterTypes) | 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。 |
getDeclaredMethods() | 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。 |
getConstructor(Class<?>... parameterTypes) | 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。 |
getConstructors() | 返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。 |
getDeclaredConstructor(Class<?>... parameterTypes) | 返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。 |
getDeclaredConstructors() | 返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。 |
2、Field类—可访问类的属性
2.1 如何获取 Field:
1).getField()
2).getDeclaredField()
.....
2.2 如何获取 Field 的值:
1). setAccessible(true) 如果方法时 private 修饰的,使其变为可访问权限
2). field.get(Object obj)
2.3 如何设置 Field 的值:
field.set(Obejct obj, Object val)
方法名 | 功能说明 |
---|---|
get(Object obj) | 返回指定对象上此 Field 表示的字段的值。 |
getAnnotation(Class<T> annotationClass) | 如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。 |
set(Object obj, Object value) | 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。 |
getGenericType() | 返回一个 Type 对象,它表示此 Field 对象所表示字段的声明类型。 |
3、Method—可调用类的方法
3.1 如何获取 Method:
1) . getDeclaredMethods: 得到 Method 的数组.
2) . getMethod(String methondName, Class ... parameterTypes)
......
3.2 如何调用 Method
1) .setAccessible(true) 如果方法时 private 修饰的,使其变为可访问
2). method.invoke(obj, Object ... args);
方法名 | 功能说明 |
---|---|
getAnnotation(Class<T> annotationClass) | 如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。 |
getName() | 以 String 形式返回此 Method 对象表示的方法名称。 |
invoke(Object obj, Object... args) | 对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。 |
4、Constructor—可调用类的构造方法
4.1 如何获取 Constructor:
1). getConstructors(): 得到 Constructor的数组.
2). getDeclaredConstructors()
4.2 如何调用 Constructor
1) .setAccessible(true) 如果方法时 private 修饰的,使其变为可访问
2) .newInstance(Object... initargs)
方法名 | 功能说明 |
---|---|
newInstance(Object... initargs) | 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。 |
getName() | 以字符串形式返回此构造方法的名称。 |
getAnnotation(Class<T> annotationClass) | 如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。 |
更多方法,查看 java 的 api 在线文档: http://tool.oschina.net/apidocs/apidoc?api=jdk-zh
使用反射的步骤 :
1、获取想要的类的class对象
2、调用类中的方法
3、使用反射API来操作这些信息
好了~~~上代码。。。。。
先定义一个反射的类:(和我上一篇注解是同一个类哦~~~)
public class McyTest {
private String name;
private String sex;
private int age;
private int phoneNum;
public McyTest(String name, String sex, int age, int phoneNum) {
this.name = name;
this.sex = sex;
this.age = age;
this.phoneNum = phoneNum;
}
@Test(id = "_01", description = "好好好")
public String getDescription() {
return "马春燕";
}
private void aaaa(String b){
System.out.println("aaaa = "+b);
}
@Override
public String toString() {
return "McyTest{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
", age=" + age +
", phoneNum=" + phoneNum +
'}';
}
}
开始反射:
public class Main {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
McyTest mcyTest = new McyTest("mcy", "女", 20, 123456);
//获取属性以及他们的值和方法名称
System.out.println("1、获取属性以及他们的值和方法名称");
Field[] declaredFields = mcyTest.getClass().getDeclaredFields();
System.out.println("属性+值:---");
for (Field declaredField : declaredFields) {
declaredField.setAccessible(true);//第一步,必须先打开权限!!!
System.out.println(declaredField.getName() + " : " + declaredField.get(mcyTest));
}
System.out.println("方法:---");
Method[] methods = mcyTest.getClass().getDeclaredMethods();
for (Method method : methods) {
System.out.println(method.getName());
}
System.out.println("----------------------------");
//使用反射的方式修改字段的值
System.out.println("2、使用反射的方式修改字段的值");
for (Field declaredField : declaredFields) {
declaredField.setAccessible(true);//第一步,必须先打开权限!!!
if (declaredField.getName().equals("name")) {
declaredField.set(mcyTest, "哒哒哒");
}
System.out.println(declaredField.getName() + ":" + declaredField.get(mcyTest));
}
System.out.println("----------------------------");
//调用方法
System.out.println("3、使用反射调用方法");
Method aaaa = mcyTest.getClass().getDeclaredMethod("aaaa", String.class);
aaaa.setAccessible(true);
aaaa.invoke(mcyTest, "AAAAAAAA");
//调用构造方法
System.out.println("4、使用反射调用构造方法");
Constructor<? extends McyTest> constructor = mcyTest.getClass().getDeclaredConstructor(String.class, String.class, int.class, int.class);
McyTest mcyTest1 = constructor.newInstance("大鱼", "女", 22, 987654);
System.out.println(mcyTest1.toString());
}
}
网友评论