一、开场白
在学习java过程中,反射在java基础阶段就有接触,不过,当时也是没有理解,只是大概的了解了一下。反射也没有实际使用过,后来的学习了框架,听说很多是反射实现的。感觉反射是大神们玩的东西,作为小白就总结一点反射的基本用法吧,可能对以后的学习会有所帮助。
记住:Class类,Field类,Method类,Constructor类都是在运行期执行的 可以绕过编译期间
二、得到Class对象的三种方法
在java面向对象的学习过程中,万物皆对象”我们都听说过。在java面向对象的世界里,万物皆是对象,那么类是不是一个对象?是谁的对象?当然答案都是肯定的,类是对象,类是java.lang.Class类的实例对象。
看下面的代码,得到Class的对象。
package reflect;
public class RefelctDemo {
public static void main(String[] args) {
Person p=new Person();
Class c=Person.class; //类名.class
Class c2=p.getClass();//对象.getClass()
Class c3=null;
try {
c3=Class.forName("reflect.Person");//Class类中的方法
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(c==c2);
System.out.println(c2==c3);
}
}
class Person{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//结果当然是 true true
三、通过反射得到类中的成员变量
package reflect;
import java.lang.reflect.Field;
public class RefelctDemo {
public static void main(String[] args) {
Person p=new Person();
getClassVariables(p);
}
public static void getClassVariables(Object o){
Class c=o.getClass();
//Field[] fs=c.getFields();//只能获得public的成员变量
Field[] fs=c.getDeclaredFields();//获得该类自己声明的所有变量信息,返回的结果是Filed对象的数组
for(Field field:fs){
//得到变量的类型
String typeName=field.getType().getName();
//得到变量名字
String variableName=field.getName();
System.out.println(typeName+" "+variableName);
}
}
}
class Person{
private String name;
private int age;
public int id;
String grade;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
四、反射得到类中的方法
public static void getClassMethods(Object o){
Class c=o.getClass();
String s="";
System.out.println("类的名称是:"+c.getName()); //先获取类的名称
//获取的是该类自己声明的方法 注意:不看访问权限
//Method[] ms = c.getDeclaredMethods();
//获取所有的public的函数,也包括父类继承而来的方法 返回的结果是Method对象的数组
Method[] ms = c.getMethods();
for(Method m:ms){
//得到返回值类型 函数名称
s+=m.getReturnType().getName()+"\t"+m.getName();
s+="(";
//得到参数类型
Class[] paramTypes=m.getParameterTypes();
for(Class paramType:paramTypes){
s+=paramType.getName()+",";
}
s+=")";
System.out.println(s);
s="";
}
}
/*
类的名称是:reflect.Person
java.lang.String toString()
java.lang.String getName()
void setName(java.lang.String,)
int getAge()
void setAge(int,)
void wait(long,int,)
void wait(long,)
void wait()
boolean equals(java.lang.Object,)
int hashCode()
java.lang.Class getClass()
void notify()
void notifyAll()
*/
五、得到类的构造函数
public static void getClassConstructor(Object o){
Class c = o.getClass();
//eConstructor[] cs = c.getDeclaredConstructors(); //得到所有的构造函数
Constructor[] cs = c.getConstructors(); //获取的是所有的public的构造函数
for(Constructor constructor :cs){
System.out.print(constructor.getName()+"(");
//获取构造函数的参数列表,得到的是参数列表类型的类类型
Class[] paramType = constructor.getParameterTypes();
for(Class c1:paramType){
System.out.print(c1.getName()+",");
}
System.out.println(")");
}
}
/*
reflect.Person()
reflect.Person(java.lang.String,int,)
*/
六、反射的使用
java的反射可以绕过访问权限,访问到类的私有方法和成员。可能这点会引起安全性的讨论。反射的使用帮助解决很多复杂的问题,其运行时的类型检查,动态调用,代理的实现等,反射为我们写程序带来了很大的灵活性,很多功能都是基于反射。
public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Service service=new Service();
Class c=service.getClass();
//得到方法 public void service()
Method m=c.getDeclaredMethod("service", new Class[]{});
Object obj=m.invoke(service, new Object[]{});
//得到方法 public void service(int a,int b)
m=c.getMethod("service", new Class[]{int.class,int.class});
obj=m.invoke(service, new Object[]{10,20});
//得到方法 public void service(int a,String s)
m=c.getMethod("service", new Class[]{int.class,String.class});
obj=m.invoke(service, new Object[]{10,"我是java反射"});
//访问私有的方法 private void method()
m=c.getDeclaredMethod("method", new Class[]{});
m.setAccessible(true);//这样才能调用私有方法
obj=m.invoke(service, new Object[]{});
}
class Service{
public void service(){
System.out.println("无参数 反射");
}
public void service(int a,int b){
System.out.println("a="+a+"\tb="+b);
}
public void service(int a,String s){
System.out.println("a="+a+s);
}
private void method(){
System.out.println("我是私有的方法");
}
}
/*
无参数 反射
a=10 b=20
a=10我是java反射
我是私有的方法
*/