什么是反射:
对于任何一个类,我们都能知道他有哪些方法。对于任何一个对象我们都可以调用他的任意一个方法和属性,这种动态的获取信息以及动态的调用对象的方法就称为java的反射机制。形象一点说,任何一个类或者对象,对我们来说都是透明的,想要啥直接拿就可以。
首先列出我们要反射的类:
public class Person {
int age;
String name;
private String email;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public Person(int age){};
public Person(){};
private String getEmail() {
System.out.println("我是getEmail");
return email;
}
private void setEmail(String email) {
this.email = email;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("我是setName");
this.name = name;
}
}
要想对一个类进行反射,就必须获取他的字节码字节码。有三种形式:
//第一种
Class<?> c1 =new Person().getClass();
//第二种
Class<?> c2 = Person.class;
//第三种,要加包名
try {
Class<?> c3 = Class.forName("one.Person");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
通过反射获取类中的所有构造器
//获取类中的所有构造器
Constructor<?>[] con = c1.getConstructors();
System.out.println("共"+con.length+"构造器");
for (int i = 0; i < con.length; i++) {
System.out.println("第"+i+"个构造参数");
//获取构造器参数类型
Class[] paramenter = con[i].getParameterTypes();
for (int j = 0; j < paramenter.length; j++) {
//打印构造器参数
System.out.print(paramenter[j].getName()+" ");
}
System.out.println();
}
结果如下:
共3构造器
第0个构造参数
第1个构造参数
int
第2个构造参数
int java.lang.String
一个无参,还有两个有参构造。
通过获取的构造器进行实例化
try {
Person per1 = (Person) con[0].newInstance();
Person per2 = (Person) con[1].newInstance(20);
Person per3 = (Person) con[2].newInstance(19,"lv");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
通过反射获取类中的属性
Person per1 = null,per2 = null,per3= null;
try {
per1 = (Person) con[0].newInstance();
per2 = (Person) con[1].newInstance(20);
per3 = (Person) con[2].newInstance(19,"lv");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//获取某个对象内的某个字段
try {
Field f = c1.getDeclaredField("email"); //或取私有属性
//对私有字段的访问取消检查
f.setAccessible(true);
//修改该对象的emal字段
f.set(per3, "emal@qq.com");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//获取当前类的所有属性类型和值
Field[] field = c1.getDeclaredFields();
//对私有字段的访问取消检查
Field.setAccessible(field, true);
for (int i = 0; i < field.length; i++) {
try {
System.out.println("属性名:"+field[i].getName()+"属性类型:"
+field[i].getType()+"属性值:"+field[i].get(per3));
} catch (Exception e) {
e.printStackTrace();
}
}
结果如下:
属性名:age属性类型:int属性值:19
属性名:name属性类型:class java.lang.String属性值:lv
属性名:email属性类型:class java.lang.String属性值:emal@qq.com
注意:取消安全性检查后才可以访问私有属性
通过反射获取类中的方法并运行
//获取全部方法
Method[] methods = c1.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
System.out.println("方法名称:"+methods[i].getName()+
" 返回值类型 :"+methods[i].getReturnType()+
" 方法参数:"+methods[i].getParameterTypes());
}
//获取无参私有方法
try {
Method method = c1.getDeclaredMethod("getEmail");
//对私有字段取消安全检查
method.setAccessible(true);
System.out.println("私有方法名称:"+method.getName()+" 返回值类型:"
+method.getReturnType().getName());
//调用无参的私有方法
method.invoke(per3);//即getEmail方法
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//获取有参方法
try {
Method meth = c1.getDeclaredMethod("setName", String.class);
//调用有参方法
meth.invoke(per3, "我是Name");//即setName方法
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
结果如下:
方法名称:main 返回值类型 :void 方法参数:[Ljava.lang.Class;@6d06d69c
方法名称:getName 返回值类型 :class java.lang.String 方法参数:[Ljava.lang.Class;@7852e922
方法名称:setName 返回值类型 :void 方法参数:[Ljava.lang.Class;@4e25154f
方法名称:setEmail 返回值类型 :void 方法参数:[Ljava.lang.Class;@70dea4e
方法名称:getAge 返回值类型 :int 方法参数:[Ljava.lang.Class;@5c647e05
方法名称:setAge 返回值类型 :void 方法参数:[Ljava.lang.Class;@33909752
方法名称:getEmail 返回值类型 :class java.lang.String 方法参数:[Ljava.lang.Class;@55f96302
私有方法名称:getEmail 返回值类型:java.lang.String
我是getEmail
我是setName
总结一下:
这些 只是最基本的反射,更多的使用方法还是需要去查api。其实反射是非常重要的。我们还是有必要去掌握它。
若有错误,还请指出,谢谢