转载: https://blog.csdn.net/a724888/article/details/80160662
//注解类,可可用于表示方法,可以通过反射获取注解的内容。
//Java注解的实现是很多注框架实现注解配置的基础
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Invoke {
}
public class UserBean extends PersonBean implements User{
@Override
public void login() {
}
class B {
}
public String userName;
protected int i;
static int j;
private int l;
private long userId;
public UserBean(String userName, long userId) {
this.userName = userName;
this.userId = userId;
}
public String getName() {
return userName;
}
public long getId() {
return userId;
}
@Invoke
public static void staticMethod(String devName,int a) {
System.out.printf("Hi %s, I'm a static method", devName);
}
@Invoke
public void publicMethod() {
System.out.println("I'm a public method");
}
@Invoke
private void privateMethod() {
System.out.println("I'm a private method");
}
}
获取类的成员变量(字段)信息
主要是这几个方法,在此不再赘述:
getFiled: 访问公有的成员变量
getDeclaredField:所有已声明的成员变量。但不能得到其父类的成员变量
getFileds和getDeclaredFields用法同上(参照Method)
public class 打印成员变量 {
public static void main(String[] args) {
Class userBeanClass = UserBean.class;
//获得该类的所有成员变量,包括static private
Field[] fields = userBeanClass.getDeclaredFields();
for(Field field : fields) {
//private属性即使不用下面这个语句也可以访问
// field.setAccessible(true);
//因为类的私有域在反射中默认可访问,所以flag默认为true。
String fieldString = "";
fieldString += Modifier.toString(field.getModifiers()) + " "; // `private`
fieldString += field.getType().getSimpleName() + " "; // `String`
fieldString += field.getName(); // `userName`
fieldString += ";";
System.out.println(fieldString);
//打印结果
// public String userName;
// protected int i;
// static int j;
// private int l;
// private long userId;
}
}
}
调用方法
当我们从类中获取了一个方法后,我们就可以用invoke()方法来调用这个方法。invoke方法的原型为:
public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
public class 使用反射调用方法 {
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException {
Class userBeanClass = UserBean.class;
//获取该类所有的方法,包括静态方法,实例方法。
//此处也包括了私有方法,只不过私有方法在用invoke访问之前要设置访问权限
//也就是使用setAccessible使方法可访问,否则会抛出异常
// // IllegalAccessException的解释是
// * An IllegalAccessException is thrown when an application tries
// * to reflectively create an instance (other than an array),
// * set or get a field, or invoke a method, but the currently
// * executing method does not have access to the definition of
// * the specified class, field, method or constructor.
// getDeclaredMethod*()获取的是类自身声明的所有方法,包含public、protected和private方法。
// getMethod*()获取的是类的所有共有方法,这就包括自身的所有public方法,和从基类继承的、从接口实现的所有public方法。
//就是说,当这个类,域或者方法被设为私有访问,使用反射调用但是却没有权限时会抛出异常。
Method[] methods = userBeanClass.getDeclaredMethods(); // 获取所有成员方法
for (Method method : methods) {
//反射可以获取方法上的注解,通过注解来进行判断
if (method.isAnnotationPresent(Invoke.class)) { // 判断是否被 @Invoke 修饰
//判断方法的修饰符是是static
if (Modifier.isStatic(method.getModifiers())) { // 如果是 static 方法
//反射调用该方法
//类方法可以直接调用,不必先实例化
method.invoke(null, "wingjay",2); // 直接调用,并传入需要的参数 devName
} else {
//如果不是类方法,需要先获得一个实例再调用方法
//传入构造方法需要的变量类型
Class[] params = {String.class, long.class};
//获取该类指定类型的构造方法
//如果没有这种类型的方法会报错
Constructor constructor = userBeanClass.getDeclaredConstructor(params); // 获取参数格式为 String,long 的构造函数
//通过构造方法的实例来进行实例化
Object userBean = constructor.newInstance("wingjay", 11); // 利用构造函数进行实例化,得到 Object
if (Modifier.isPrivate(method.getModifiers())) {
method.setAccessible(true); // 如果是 private 的方法,需要获取其调用权限
// Set the {@code accessible} flag for this object to
// * the indicated boolean value. A value of {@code true} indicates that
// * the reflected object should suppress Java language access
// * checking when it is used. A value of {@code false} indicates
// * that the reflected object should enforce Java language access checks.
//通过该方法可以设置其可见或者不可见,不仅可以用于方法
//后面例子会介绍将其用于成员变量
//打印结果
// I'm a public method
// Hi wingjay, I'm a static methodI'm a private method
}
method.invoke(userBean); // 调用 method,无须参数
}
}
}
}
}
利用反射创建数组
数组在Java里是比较特殊的一种类型,它可以赋值给一个Object Reference。下面我们看一看利用反射创建数组的例子:
public class 用反射创建数组 {
public static void main(String[] args) {
Class<?> cls = null;
try {
cls = Class.forName("java.lang.String");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Object array = Array.newInstance(cls,25);
//往数组里添加内容
Array.set(array,0,"hello");
Array.set(array,1,"Java");
Array.set(array,2,"fuck");
Array.set(array,3,"Scala");
Array.set(array,4,"Clojure");
//获取某一项的内容
System.out.println(Array.get(array,3));
//Scala
}
}
其中的Array类为java.lang.reflect.Array类。我们通过Array.newInstance()创建数组对象.