JAVA的反射(java.lang.reflect)机制提供了在运行时加载类,取得类信息,构造类实例对象,取得和设置静态和实例字段,取得和引发(invoke)类的静态和实例方法的一系列工具,为各种框架和应用带来了极高的动态扩展能力,并且提供了运行时改变业务逻辑的可能,这个特性不能不了解一下。
下面我分别作一些简单的例子来试试这些功能
为了方便测试 做一个测试的目标和简单输出语句
class ReflectPoint extends Rflt implements Point {
int x, y;
String comment;
int[] val;
private static int rect(int xl, int yl) {
return xl * yl;
}
@Override
public String toString() {
return "ReflectPoint [x=" + x + ", y=" + y + ", comment=" + comment
+ ", val=" + Arrays.toString(val) + "]";
}
public ReflectPoint(int x, int y, String comment, int[] val) {
super();
this.setX(x);
this.y = y;
this.comment = comment;
this.val = val;
}
@Override
public int getX() {
return x;
}
private void setX(int x) {
this.x = x;
}
@Override
public int getY() {
return y;
}
void setY(int y) {
this.y = y;
}
private static boolean not(boolean b) {
return !b;
}
@Override
protected String getComment() {
return comment;
}
}
abstract class Rflt {
abstract String getComment();
}
interface Point {
int getX();
int getY();
}
public static void sp(Object o) {
if (o == null) {
System.out.println("null");
}
if (o.getClass().isArray()) {
StringBuilder sb = new StringBuilder();
int len = Array.getLength(o);
sb.append('[');
for (int i = 0; i < len; i++) {
if (i != 0) {
sb.append(':');
}
sb.append(Array.get(o, i));
}
sb.append(']');
System.out.println(sb);
} else {
System.out.println(o);
}
}
首先试试取得类:
private static void testClass() {
// 构造一个样例
int[] val={3,4,7};
ReflectPoint rp=new ReflectPoint(12, 25, "ref test", val);
//取得类的3种常见方式 1.直接用类名.class 2.用已知类实例的.getClass()
//3.用Class的静态方法forName(String className) !!注意这种方式如果在classpath下找不到类会引发ClassNotFoundException
Class c1=ReflectPoint.class,c2=rp.getClass(),c3=null;
try {
c3=Class.forName("com.itheima.ReflectPoint");
} catch (ClassNotFoundException e) {
throw new RuntimeException("ClassNotFound");
}
//以下三个输出都是class com.itheima.ReflectPoint
sp(c1);
sp(c2);
sp(c3);
//类路径错误的例子
try {
Class.forName("com.test.IdontExist");
} catch (ClassNotFoundException e) {
//throw new RuntimeException("ClassNotFound");
sp("com.test.IdontExists not found");
}
//三种方式取得的Class实例在同一个类加载器下是单例,所以可以用==来比较,当然用.equals也行
sp(c1==c2);//true
sp(c1==c3);//true
}
那么有了类,试试构建实例对象
private static void testConstructer() {
// 构造必要的数据
int[] val = { 3, 4, 7 };
int x = 12, y = 25;
String comm = "cons test";
// 取得Constructor
// 这里使用了直接指定参数列表取得指定的构造函数的方式,当然如果参数不匹配会导致NoSuchMethodException
// 而当前运行时上下文无权限访问(修饰符限定)时,会导致SecurityException 就要改用暴力反射才能继续了
Constructor<ReflectPoint> constructor=null;
try {
constructor= ReflectPoint.class.getConstructor(int.class,int.class,String.class,int[].class);
} catch (NoSuchMethodException | SecurityException e) {
throw new RuntimeException("Constructor can not get");
}
//构造实例
//这里直接用.newInstance()方法即可,当然:参数列表必须匹配
ReflectPoint rp=null;
if(constructor!=null){
try {
rp=constructor.newInstance(x,y,comm,val);
} catch (InstantiationException | IllegalAccessException
| IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException("Construct Instance fail");
}
}
//测试一下实例
if(rp!=null){
sp(rp);
sp(rp.x);
sp(rp.y);
sp(rp.comment);
sp(rp.val);//OK 构造成功 字段都取得了
}
}
取得字段的例子,这里使用了暴力反射,而且逐个修改了传入的对象的字段:
/*
* 测试时传入的对象 int[] val = { 3, 4, 7 }; ReflectPoint rp = new ReflectPoint(12,
* 25, "ref test", val); testFields(rp);
*/
private static void testFields(Object o) {
// 现在,传入了一个Object类型对象 显然信息是极少的
// 那么就必须用反射来获取他的各种信息
// 这里测试获取他的字段并作修改
// 修改前
sp(o);
// ReflectPoint [x=12, y=25, comment=ref test, val=[3, 4, 7]]
// 这里为了取得所有的成员字段,使用了getDeclared系列方法和setAccessible强制访问,所谓的暴力反射
Field[] fields = o.getClass().getDeclaredFields();
for (Field field : fields) {
if (!field.isAccessible()) {
field.setAccessible(true);
}
// 可以根据字段类型判断
if (field.getType().isPrimitive()) {
// 也可以根据字段名称判断
switch (field.getType().getName()) {
// 简单修改一下整形内容
case "int":
int mod = 0;
switch (field.getName()) {
case "x":
mod = 7;
break;
case "y":
mod = -10;
break;
default:
break;
}
try {
// 用get方法取,用set方法写入
field.set(o, (int) (field.get(o)) + mod);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new RuntimeException("Field " + e.getMessage());
}
break;
default:
break;
}
} else {
switch (field.getType().getName()) {
// 修改String 这里类型名是完整的限定名
case "java.lang.String":
try {
field.set(o, (String) (field.get(o)) + "edited");
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new RuntimeException("Field " + e.getMessage());
}
break;
// 数组类型名为'['+元素类型名 基本类型用一个大写字符表示, I表示int
case "[I":
try {
Object arr = field.get(o);
int[] val = new int[Array.getLength(arr) + 2];
int sum = 0;
for (int i = 0; i < Array.getLength(arr); i++) {
int intValue = Array.getInt(arr, i);
sum += intValue;
val[i] = intValue;
}
val[val.length - 2] = 787;
val[val.length - 1] = sum + 787;
field.set(o, val);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new RuntimeException("Field " + e.getMessage());
}
break;
default:
break;
}
}
}
// 修改后
sp(o);
// ReflectPoint [x=19, y=15, comment=ref testedited, val=[3, 4, 7, 787,
// 801]]
// 可以看到修改成功了
}
最后 测试一下方法的反射
private static void testMethod() {
// 还是先准备一个对象
int[] val = { 3, 4, 7 };
ReflectPoint rp = new ReflectPoint(12, 25, "ref test", val);
// 还是暴力一下,拿到所有方法
Method[] mths = rp.getClass().getDeclaredMethods();
for (Method method : mths) {
if (!method.isAccessible()) {
method.setAccessible(true);
}
// 先看看相关的信息
sp(method.getName());
sp(method.getModifiers());
sp(method.getParameterTypes());
sp(method.getReturnType());
// 调用一下试试看
Object result = null;
Class<?>[] paraType = method.getParameterTypes();
int paraCount = paraType.length;
Object[] paras = new Object[paraCount];
for (int i = 0; i < paraCount; i++) {
paras[i] = defaultValue(paraType[i]);
}
switch (method.getParameterTypes().length) {
case 0:
try {
result = method.invoke(rp);
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
throw new RuntimeException("Method " + e.getMessage());
}
break;
case 1:
try {
result = method.invoke(rp, paras[0]);
} catch (IllegalAccessException
| IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException("Method " + e.getMessage());
}
break;
case 2:
try {
result = method.invoke(rp, paras[0], paras[1]);
} catch (IllegalAccessException
| IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException("Method " + e.getMessage());
}
break;
// 再多参数就不管了
default:
break;
}
sp(method);
if (result != null) {
sp(result);
}else{
sp("null|void");
}
}
}
private static Object defaultValue(Class<?> cls) {
if (cls.isPrimitive()) {
switch (cls.getName()) {
case "byte":
case "char":
case "short":
case "int":
case "long":
return (byte) 0;
case "float":
case "double":
return 0.0f;
case "boolean":
return false;
case "void":
return null;
}
} else {
try {
return cls.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
sp("unable to init default instance");
return null;
}
}
// TODO Auto-generated method stub
return null;
}
根据我校2018年硕士研究生入学考试考生成绩、招生计划安排和各学科基本要求,经学校招生工作领导小组讨论决定,对入围复试的考生初试成绩基本要求如下:一、学术学位学科门类总分政治外语业务一业务二02经济学3306055858503法学335606090900401教育学34560601900403体育学300454019005文学3606060909007理学3155050808008工学300505...
pd.read_excel sheet参数
大家好,今天给大家带来一个仿360手机卫士悬浮窗效果的教程,在开始之前请允许我说几句不相干的废话。不知不觉我发现自己接触Android已有近三个年头了,期间各种的成长少不了各位高手的帮助,总是有很多高手喜欢把自己的经验写在网上,供大家来学习,我也是从中受惠了很多,在此我深表感谢。可是我发现我却从来没有将自己平时的一些心得拿出来与大家分享,共同学习,太没有奉献精神了。于是我痛定思痛,决定从今
第一:前言用STM32 采集数据必须依据信号源设置采样频率。根据奈奎斯特定律,采样率必须是信号源最大频率的2倍以上,但是在实际的需求当中,采样率应该是Fs>3Fmax .采样周期=转换时间+读取时间 . 转换时间=采样时间+12个时钟周期(STM32F4)或者 转换时间=采样时间+12.5个时钟周期(STM32F1)采样时间是STM32采集模拟量的时间,采集的时间越长越...
输入三角型的三条边,判断三角形的形状,假设输入的三边边长均>0。判断实数相等,应该用两个数相减绝对值小于某数,如fabs(a*a+b*b-c*c)
#gitlab-ce安装指南##1、暗转必要依赖```xmlsudoyuminstall-ycurlpolicycoreutils-pythonopenssh-serverperlsudosystemctlenablesshdsudosystemctlstartsshdsudofirewall-cmd--permanent--add-service=httpsudofirewall-cmd--permanent--add-servi...
目录1、偶尔很慢1.1、数据库在刷新脏页(flush)1.2、拿不到锁2、一直这么慢2.1、没用到索引2.2、数据库选错了索引一条SQL语句执行的很慢,那是每次执行都很慢呢?还是大多数情况下是正常的,偶尔出现很慢呢?所以我觉得,我们还得分以下两种情况来讨论。1、大多数情况是正常的,只是偶尔会出现很慢的情况。2、在数据量不变的情况下,这条SQL语句一直以...
Router&gt;enable Router#configure terminal Enter configuration commands, one per line. End with CNTL/Z.Router(config)#hostname R3R3(config)#interface ethernet 0/0R3(config-if)#no shutdown R3(config-i...
嵌入式GUI ftk-0.1发布分类: 嵌入式GUI FTK 转载时请注明出处和作者联系方式文章出处:http://www.limodev.cn/blog作者联系方式:李先静 FTK最初是《系统程序员成长计划》的综合练习项目,在一些热心朋友的帮助下,从国庆到元旦,经过三个月的开发和完善,终于实现基本功能,初具现代嵌入式GUI的轮廓了。新年
注意:所有的编译、打包、部署全部是通过Jenkins完成的。公司内部有一个项目,开始做的时候已经预计到会有很多客服端。所以开发就搞了如下的结构: fft-api # 公用的API,所有的程序都必须使用fft-client-hubei # 湖北客户端fft-job # 定时任务fft-persistent # 数据库连接层fft-persi
完全不会数据结构就比较离谱A - RoadblockProblem Link题意FJ的农场由NNN个点MMM条边组成,边存在边权它每次都会沿着最短路径从点111走到点NNN现在FJ的牛想选择这张图中的任意一条边,使其边权翻倍问选择某条边翻倍后,FJ需要多走的距离的最大值是多少(最短路的最大增量)标签DijkstraSPFA思路先在原图中跑一遍SPFA,求出此时的最短路长度originalDistanceoriginalDistanceoriginalDistance并且回溯得到这条
<body> <h1>setTimeout</h1> <span id="content">时间</span> <button onclick="start()">开始</button> <script> var x = 00, y = 00, z = 00; function start () {..