反射作为java高级的一个知识点。虽然一般开发情况下不会用到,但是也算是必须知道的知识点
如下则是java的反射包 java.lang.reflect
在开始我们建立一个父类 Anmion (名字我瞎起的,只作为展示代码效果来看,主要测试某些方法):
public class Anmion { protected int aaa; private int bbb; public int ccc; public int getAaa() { return aaa; } public void setAaa(int aaa) { this.aaa = aaa; } public int getBbb() { return bbb; } public void setBbb(int bbb) { this.bbb = bbb; } public int getCcc() { return ccc; } public void setCcc(int ccc) { this.ccc = ccc; } @Override public String toString() { return "Anmion{" + "aaa=" + aaa + ", bbb=" + bbb + ", ccc=" + ccc + '}'; }}
建立好了父类,我们再建立子类,以便于继承父类
public class People extends Anmion{ private String name; private int sex; public int old; public People(String name, int sex, int old) { this.name = name; this.sex = sex; this.old = old; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getSex() { return sex; } public void setSex(int sex) { this.sex = sex; } public int getOld() { return old; } public void setOld(int old) { this.old = old; } private void showName(){ System.out.println("sfdsa" + name); } public void showOld(){ System.out.println("sfdsa"+old); } @Override public String toString() { return super.toString()+"People{" + "name='" + name + '\'' + ", sex=" + sex + ", old=" + old + '}'; }}
如上两个类,我都将tostring()方法重新写了一下,目的在于,方便测试(细节就不要在意了,你也可以不重写)
一般情况下,你想创建一个对象,你会采用,如下策略
People people = new People();
为了测试反射,我们将改变产出的方式:
如下
Class clazz = Class.forName("People");People people = (People) clazz.newInstance();
Class.forName 在jvm中查找并加载该class,
注意:以上的方式是无参数构造,如果没有无参构造器,则不能使用如上方式产出people
有参数构造方式
Class clazz = Class.forName("People");Constructor constructor = clazz.getConstructor(String.class, int.class,int.class); People people = (People) constructor.newInstance("test", 1,2);
还有一点要注意 int.class 和Integer.class 是不同的两个东西。
如下则是获取字段和方法的代码,看我一一介绍一下:
clazz.getName():获取该class的名字。clazz.getDeclaredFields():获取该class里的字段(包括public private protected)clazz.getFields():获取该class里的字段(仅仅包括 public 继承的public)clazz.getMethods():获取该class里方法(仅仅包括public 继承的public)clazz.getDeclaredMethods():获取该class里的字段(包括public private protected)
于是我们就可以进行一些不可告人的事情了
//遍历该类的所有字段for(Field field:getDeclaredFields()){ field.setAccessible(true); Class t = field.getType(); if(t.isAssignableFrom(String.class)){ System.out.println( field.get(people)); }else if(t.isAssignableFrom(int.class)){ System.out.println( field.getInt(people)); } }
如上代码我解释一下field.setAccessible(true); 设置true的作用很大,如果不设置的话,是不能够访问受保护的字段和私有字段,(同样方法也是)
isAssignableFrom是个比较两个类型是否相同,或者是否是某个类的子类,与 instanceof 作用差不多,但是是比较类型的。
如果类型相同,毋庸置疑就能拿出该类的值,我只是复杂的写了一下,简单写法如下:
for(Field field:getDeclaredFields()){ field.setAccessible(true);System.out.println( field.get(people));}
设置字段的值:
//循环去设置值for(Field field:fields){ String n = field.getName(); System.out.print(n); if(n.equalsIgnoreCase("name")){ field.set(people, "嚣张"); } if(n.equalsIgnoreCase("sex")){ field.set(people,14231); } if(n.equalsIgnoreCase("old")){ field.set(people,32); } }//直接设置值Field f1 = clazz.getDeclaredField("sex"); f1.setAccessible(true); f1.setInt(people,14);
获取方法也是一样:如下代码
Method[] methods = clazz.getDeclaredMethods(); for(Method method:methods){ method.setAccessible(true); System.out.println(Modifier.toString(method.getModifiers())+" "+ method.getReturnType().getName() +" " + method.getName()); } for(Method m:methods){ String n = m.getName(); if(n.equalsIgnoreCase("setName")){ if(m.getParameterTypes().length == 1){ m.invoke(people,"呢"); } } } System.out.println(people.toString());//直接设置名字 Method m1 = clazz.getMethod("setName", String.class); m1.invoke(people, "赵文");
解释如下
Modifier.toString(method.getModifiers())是获取当前方法的类型,如public private
method.getReturnType().getName()获取方法返回值类型名
如上就是java反射的基本内容,谢谢
网友评论