Java反射基础总结
1.前言Java语言特性中,最经常的一个就是反射机制,最近开发有用到,所以再这里整理一篇学习笔记。简单理解反射就是在运行时获得程序中每一个类型的成员和成员的信息,即使是private修饰的也是可以获取到的。2.基础使用基本API//java.lang.Class类中://1.根据类全限定名获取类的Class对象public static Class<?> forName...
·
1.前言
反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
2.基础使用
测试类如下:
//User.java
public class User extends BaseUser implements Serializable {
protected static final long serialVersionUID = 1L;
private int userId;
public String userName;
public boolean isMale;
public User(int userId, String userName, boolean isMale) {
this.userId = userId;
this.userName = userName;
this.isMale = isMale;
}
@Override
public String toString() {
return "userId=" + userId + ",userName=" + userName + ", isMale=" + isMale;
}
private void print(String userName) {
System.out.println(toString());
}
}
- 1.获取类的Class对象
public static Class<?> forName(String className)
- 2.获取所有的构造函数:getConstructors()
//获取当前类的public修饰的构造方法
public Constructor<T> getConstructor(Class<?>... parameterTypes)
public Constructor<?>[] getConstructors()
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
//Returns an array of {@code Constructor} objects reflecting all the constructors declared by the class represented by this
//{@code Class} object.These are public, protected, default (package) access, and private constructors.
////获取当前类的所有构造方法
public Constructor<?>[] getDeclaredConstructors()
- 3.创建实例:newInstance()
//相当于调用无参的默认构造器new一个对象
public T newInstance()
- 4.获取所有的属性:getDeclaredFields();
//获取当前类的public成员变量,包含父类或接口中的成员变量
public Field getField(String name)
public Field[] getFields()
//获取当前类所有的成员变量,没有父类或接口中的成员变量
public Field getDeclaredField(String name)
public Field[] getDeclaredFields()
- 5.获取类的方法:getMethods()
//获取当前类的方法信息,当前类自己和继承父类或接口的public方法
public Method getMethod(String name, Class<?>... parameterTypes)
public Method[] getMethods()
//获取当前类的所有方法,不包括父类的
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
public Method[] getDeclaredMethods()
- 6.获取所有实现的接口:getInterfaces()
public Class<?>[] getInterfaces()
- 7.获取父类:getSuperclass()
public native Class<? super T> getSuperclass()
3.实例
- 反射调用私有方法:
private static void callPrivateMethod() {
try {
//先获取类的Class实例
Class<?> aClass = Class.forName("main.serializabletest.User");
//根据方法名和参数列表获取对应的Method实例
Method print = aClass.getDeclaredMethod("print", String.class);
//通过构造方法获取类实例
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(int.class, String.class, boolean.class);
Object userObj = declaredConstructor.newInstance(18, "123", true);
//invoke()传入对象实例和参数调用私有方法
if (print != null) {
print.setAccessible(true);
print.invoke(userObj, "print test");
}
} catch (Exception e) {
e.printStackTrace();
}
}
这种适用于,某些系统API是公开的,但是因为要实现一些功能必须要调用,可以采用上面的方式调用。注意调用private方法时,一定要先调用setAccessible(true),否则会报IllegalAccessException异常,无法正常调用。
- 另外反射常用在动态代理中,举例如下:
/**
* Sell接口,代理类和被代理类都应该实现这个方法
*
* @author Mr.torto
*/
public interface Sell {
void sell();
void ad();
}
/**
* 生产厂家,被代理类
*
* @author Mr.torto
*/
public class Vendor implements Sell {
public void sell() {
System.out.println("Has been called sell() method");
}
public void ad() {
System.out.println("Has been ad() method");
}
}
/**
* @author Mr.torto
* 测试动态代理
*/
public class Main {
public static void main(String[] args) {
Sell realObj = new Vendor(); //被代理者,主题类
Sell proxyObj = (Sell) Proxy.newProxyInstance(realObj.getClass().getClassLoader(),
new Class[]{Sell.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Call realSubject before");
//调用被代理者真正的业务实现方法,这里具体就会转调到Vendor::sell(),Vendor::ad()方法
Object result = method.invoke(realObj, args);
System.out.println("Call realSubject after");
return result;
}
});
//转调到InvocationHandler的invoke方法中
proxyObj.sell();
proxyObj.ad();
}
}
输出:
Call realSubject before
Has been called sell() method
Call realSubject after
Call realSubject before
Has been ad() method
Call realSubject after
相对于动态,以为不管是静态代理还是动态代理 ,理论上是一定要调用被代理者实现真实业务逻辑的,所以代理本质上是在被代理类的基础上加些业务,或者说更偏业务逻辑的东西。在代码上就表现为在调用被代理者的前后,加一些预处理,或是加些后续处理。
更多推荐



所有评论(0)