在我们做项目时有时为了优化开发效率通常会使用一些第三方框架,这些框架有网络请求、图片处理、json解析、注解框架等等,尤其在我们想简化代码提高开发效率时就会想到使用第三方的注解框架,比较流行的有butterknife、annotations、xutils等,在我们使用这些框架为我们带来便利的同时,总是想了解一下它们的运行原理和机制,拿butterknife来说,想要写出这样一套框架出来必定要用到一些Java知识,其中就包括注解原理、Java的反射机制。 这篇文章先初步了解一下Java的反射机制: 1. 反射机制是什么 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。 2. 反射机制能做什么 反射机制主要提供了以下功能:
3.反射机制的相关API java.lang.Class; 以下将通过具体代码实现来说明反射机制可以做哪些事情
ReflectClass 代码 package com.yd.test.javareflect;
import java.io.Serializable;
public class ReflectClass extends BaseReflectClass implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private int intValue = 0;
private String stringValue = null;
public void method01(){
System.out.println('ReflectClass_01');
}
public void method02(){
System.out.println('ReflectClass_02');
}
public void method03(int intValue, String stringValue){
System.out.println('ReflectClass_Method03' ' intValue: ' intValue ' stringValue: ' stringValue);
}
public void method04(){
System.out.println('intValue: ' intValue 'stringValue: ' stringValue);
}
}
BaseReflectClass 代码 package com.yd.test.javareflect;
public class BaseReflectClass {
int BaseClassMod = 3;
public void baseMethod(){
}
}
public static void main(String[] args) {
/** 获取类的完整包名 */
ReflectClass reflectClass = new ReflectClass();
System.out.println(reflectClass.getClass().getName());
}
输出:
/** 三种实例化Class的方法 */
Class class1 = null;
Class class2 = null;
Class class3 = null;
try {
class1 = Class.forName('com.yd.test.javareflect.ReflectClass');
// java语言中任何一个java对象都有getClass 方法
class2 = new ReflectClass().getClass();
//java中每个类型都有class 属性
class3 = ReflectClass.class;
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
以上三种实例化对象(类)的方式,一般我们用的比较多的也就是Class.forName(“xxx”)这种方式了,如果懒得去看包名,也可以用其它的方式。
/** 获取对象实现的接口和继承的类 */
System.out.println(
class1.getSuperclass().getName() ' / '
class2.getSuperclass().getName() ' / '
class3.getSuperclass().getName()
);
Class classes[] = class1.getInterfaces();
for (int i = 0; i < classes.length; i ) {
System.out.println(classes[i].getName());
}
输出:
User类代码 package com.yd.test.javareflect;
public class User {
private int age;
private String name;
public User(){}
public User(String name) {
super();
this.name = name;
}
public User(int age, String name) {
super();
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return getName() '/' getAge();
}
}
/* 实例化对象并给对象中的属性赋值 */
Class c = null;
try {
c = Class.forName('com.yd.test.javareflect.User');
// 实例化User对象
User user = (User) c.newInstance();
user.setAge(25);
user.setName('danity');
System.out.println(user.toString());
输出:
Constructor<?> constructor[] = c.getConstructors();
// 获取每个构造函数所需要的参数类型信息
for (int i = 0; i < constructor.length; i ) {
// getParameterTypes():获取构造函数参数类型
Class arrayClass[] = constructor[i].getParameterTypes();
System.out.print('cons[' i '] (');
for (int j = 0; j < arrayClass.length; j ) {
if (j == arrayClass.length - 1)
System.out.print(arrayClass[j].getName());
else
System.out.print(arrayClass[j].getName() ', ');
}
System.out.println(')');
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
输出: 以上可以看出,利用反射可以获取类构造函数的参数类型信息、对一个对象的属性进行赋值,这也是比较常用的方法。
/* 获取类的所有属性 */
try {
Class rClass = Class.forName('com.yd.test.javareflect.ReflectClass');
// Field: 获取属性,下面还会讲到获取类的方法,注意区分
Field field[] = rClass.getDeclaredFields();
for (int i = 0; i < field.length; i ) {
System.out.println(field[i].getName());
// 获取修饰权限符
int mo = field[i].getModifiers();
System.out.println('mo: ' mo);
String priv = Modifier.toString(mo);
// 属性类型
Class type = field[i].getType();
System.out.println(priv ' ' type.getName() ' ' field[i].getName());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
输出:
/* 获取父类和实现的接口的所有属性 */
Class rClass = null;
try {
rClass = Class.forName('com.yd.test.javareflect.ReflectClass');
Field field[] = rClass.getFields();
for (int j = 0; j < field.length; j ) {
System.out.println(field[j].getName());
// 获取修饰权限符
int mo = field[j].getModifiers();
System.out.println('mo: ' mo);
String priv = Modifier.toString(mo);
// 属性类型
Class type = field[j].getType();
System.out.println(priv ' ' type.getName() ' ' field[j].getName());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
package com.yd.test.javareflect;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Main2 {
/**
* @param args
*/
public static void main(String[] args) {
try {
Class fClass = Class.forName('com.yd.test.javareflect.ReflectClass');
// Method[]: 方法数组
Method method[] = fClass.getMethods();
for (int i = 0; i < method.length; i ) {
// returnType :返回类型
Class returnType = method[i].getReturnType();
System.out.println('ReturnType: ' returnType);
// 获取参数类型
Class para[] = method[i].getParameterTypes();
int temp = method[i].getModifiers();
System.out.print('Modifier.toString: ' Modifier.toString(temp) ' ');
System.out.print(returnType.getName() ' ');
System.out.print(method[i].getName() ' ');
System.out.print('(');
for (int j = 0; j < para.length; j) {
System.out.print(para[j].getName() ' ' 'arg' j);
if (j < para.length - 1) {
System.out.print(',');
}
}
// 获取异常类型
Class<?> exce[] = method[i].getExceptionTypes();
if (exce.length > 0) {
System.out.print(') throws ');
for (int k = 0; k < exce.length; k) {
System.out.print(exce[k].getName() ' ');
if (k < exce.length - 1) {
System.out.print(',');
}
}
} else {
System.out.print(')');
}
System.out.println();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
输出: 信息比较多,捡需要的信息看 下面是Java反射比较重要的用法:
ReflectClass 代码 package com.yd.test.javareflect;
import java.io.Serializable;
public class ReflectClass extends BaseReflectClass implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private int intValue = 0;
private String stringValue = null;
public void method01(){
System.out.println('ReflectClass_01');
}
public void method02(){
System.out.println('ReflectClass_02');
}
public void method03(int intValue, String stringValue){
System.out.println('ReflectClass_Method03' ' intValue: ' intValue ' stringValue: ' stringValue);
}
public void method04(){
System.out.println('intValue: ' intValue 'stringValue: ' stringValue);
}
}
public static void main(String[] args) {
/**
* 通过反射给对象类中的某个方法赋值传值
*/
try {
Class<?> fclass = Class.forName('com.yd.test.javareflect.ReflectClass');
// 调用ReflectClass的“method01方法”
Method method = fclass.getMethod('method01');
method.invoke(fclass.newInstance());
// int.class, string.class 对应方法的参数类型,位置不能写错
Method mod = fclass.getMethod('method03', int.class, String.class);
mod.invoke(fclass.newInstance(),20,'test');
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
输出:
public static void main(String[] args) {
try {
Class sClass = Class.forName('com.yd.test.javareflect.ReflectClass');
//实例化这个类赋给obj
Object obj = sClass.newInstance();
Field field = sClass.getDeclaredField('intValue');
//打破封装
//使用反射机制可以打破封装性,导致了java对象的属性不安全。
field.setAccessible(true);
//给obj对象的intValue属性赋值'3'
field.set(obj, 3);
// 打印值
System.out.println(field.get(obj));
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
输出: 以上是Java反射的基本用法,还有一些动态代理的用法有兴趣的可以自己找找资料。 |
|