专栏名称: 老马说编程
从入门到高级, 深入浅出, 老马和你一起探索编程及计算机技术的本质, 篇篇原创, 用心写作。
目录
相关文章推荐
蚂蚁技术AntTech  ·  论文秀Live#21 ICSE 2025 ... ·  19 小时前  
OSC开源社区  ·  Gitee ... ·  3 天前  
蚂蚁技术AntTech  ·  “切面融合智能在威胁检测的应用”获评BCS2 ... ·  2 天前  
程序员的那些事  ·  AI 编程工具 Windsurf 突遭 ... ·  4 天前  
51好读  ›  专栏  ›  老马说编程

(84) 反射 / 计算机程序的思维逻辑

老马说编程  · 公众号  · 程序员  · 2017-04-25 08:31

正文

请到「今天看啥」查看全文



public Field getDeclaredField(String name)


Field也有很多方法,可以获取字段的信息,也可以通过Field访问和操作指定对象中该字段的值,基本方法有:

//获取字段的名称
public String getName()

//判断当前程序是否有该字段的访问权限

public boolean isAccessible()

//flag设为true表示忽略Java的访问检查机制,以允许读写非public的字段
public void setAccessible(boolean flag)
//获取指定对象obj中该字段的值
public Object get(Object obj)
//将指定对象obj中该字段的值设为value
public void set(Object obj, Object value)


在get/set方法中,对于静态变量,obj被忽略,可以为null,如果字段值为基本类型,get/set会自动在基本类型与对应的包装类型间进行转换,对于private字段,直接调用get/set会抛出非法访问异常IllegalAccessException,应该先调用setAccessible(true)以关闭Java的检查机制。


看段简单的示例代码:

List obj = Arrays.asList(new String[]{"老马","编程"});
Class> cls = obj.getClass();
for(Field f : cls.getDeclaredFields()){
f.setAccessible(true);
System.out.println(f.getName()+" - "+f.get(obj));
}


代码比较简单,就不赘述了。我们在 ThreadLocal一节 介绍过利用反射来清空ThreadLocal,这里重复下其代码,含义就比较清楚了:

protected void beforeExecute(Thread t, Runnable r) {
try {
//使用反射清空所有ThreadLocal
Field f = t.getClass().getDeclaredField("threadLocals");
f.setAccessible(true);
f.set(t, null);
} catch (Exception e) {
e.printStackTrace();
}
super.beforeExecute(t, r);
}


除了以上方法,Field还有很多别的方法,比如:

//返回字段的修饰符
public int getModifiers()
//返回字段的类型
public Class> getType()
//以基本类型操作字段
public void setBoolean(Object obj, boolean z)
public boolean getBoolean(Object obj)
public void setDouble(Object obj, double d)
public double getDouble(Object obj)

//查询字段的注解信息
public T getAnnotation(Class annotationClass)
public Annotation[] getDeclaredAnnotations()


getModifiers返回的是一个int,可以通过Modifier类的静态方法进行解读,比如,假定Student类有如下字段:

public static final int MAX_NAME_LEN = 255;


可以这样查看该字段的修饰符:

Field f = Student.class.getField("MAX_NAME_LEN");
int mod = f.getModifiers();
System.out.println(Modifier.toString(mod));
System.out.println("isPublic: " + Modifier.isPublic(mod));
System.out.println("isStatic: " + Modifier.isStatic(mod));
System.out.println("isFinal: " + Modifier.isFinal(mod));
System.out.println("isVolatile: " + Modifier.isVolatile(mod));


输出为:

public static final
isPublic: true
isStatic: true
isFinal: true
isVolatile: false


关于注解,我们下节再详细介绍。


方法信息
类中定义的静态和实例方法都被称为方法,用类Method表示,Class有四个获取方法信息的方法:

//返回所有的public方法,包括其父类的,如果没有方法,返回空数组
public Method[] getMethods()
//返回本类声明的所有方法,包括非public的,但不包括父类的
public Method[] getDeclaredMethods()
//返回本类或父类中指定名称和参数类型的public方法,找不到抛出异常NoSuchMethodException
public Method getMethod(String name, Class>... parameterTypes)
//返回本类中声明的指定名称和参数类型的方法,找不到抛出异常NoSuchMethodException
public Method getDeclaredMethod(String name, Class>... parameterTypes)


Method也有很多方法,可以获取方法的信息,也可以通过Method调用对象的方法,基本方法有:

//获取方法的名称
public String getName()
//flag设为true表示忽略Java的访问检查机制,以允许调用非public的方法
public void setAccessible(boolean flag)
//在指定对象obj上调用Method代表的方法,传递的参数列表为args
public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException


对invoke方法,如果Method为静态方法,obj被忽略,可以为null,args可以为null,也可以为一个空的数组,方法调用的返回值被包装为Object返回,如果实际方法调用抛出异常,异常被包装为InvocationTargetException重新抛出,可以通过getCause方法得到原异常。


看段简单的示例代码:

Class> cls = Integer.class;
try {
Method method = cls.getMethod("parseInt", new Class[]{String.class});
System.out.println(method.invoke(null, "123"));
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}


Method还有很多方法,可以获取方法的修饰符、参数、返回值、注解等信息,比如:

//获取方法的修饰符,返回值可通过Modifier类进行解读
public int getModifiers()
//获取方法的参数类型
public Class>[] getParameterTypes()
//获取方法的返回值类型
public Class> getReturnType()
//获取方法声明抛出的异常类型
public Class>[] getExceptionTypes()
//获取注解信息
public Annotation[] getDeclaredAnnotations()
public T getAnnotation(Class annotationClass)
//获取方法参数的注解信息
public Annotation[][] getParameterAnnotations()


创建对象和构造方法
Class有一个方法,可以用它来创建对象:

public T newInstance() throws InstantiationException, IllegalAccessException







请到「今天看啥」查看全文