反射作为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反射的基本内容,谢谢
热门评论
赞自己