JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象
总之,反射就是把java类中的各种成分映射成一个个的Java对象。例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象
反射的用法
先定义一个Student类,该类有四个属性,两个方法(不包括get和set方法)
package com.fs.reflect;
public class
Student {
private String name;
private String gender;
private int age;
private int sno;
public Student(String name, String gender, int age, int sno) {
this.name = name;
this.gender = gender;
this.age = age;
this.sno = sno;
}
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getSno() {
return sno;
}
public void setSno(int sno) {
this.sno = sno;
}
public void walk(){
System.out.println("走路");
}
public void eat(){
System.out.println("吃饭");
}
}
获取Class对象
获取Class对象总共有三种方法
1)通过类名.class获取Class对象
2)通过Class提供的方法获取Class对象
3)通过Object提供的方法获取Class对象
示例代码如下:
//获取Class对象的三种方法
Class c1= Student.class;//通过类名.class获取Class对象
System.out.println(c1.getName());//全限定名
System.out.println(c1.getSimpleName());//类名:Student
Class c2 = Class.forName("com.fs.reflect.Student");//通过Class提供的方法获取Class对象
Student student = new Student();
Class c3 = student.getClass();//通过Object提供的方法获取Class对象
获取构造方法
构造方法可以指定获取或者全部获取
获取所有构造方法(不包括private修饰的方法)
Constructor[] cons = cls.getConstructors();
for(int i=0;i<cons.length;i++){
System.out.println(cons[i]);
}
获取所有构造方法(不包括private修饰的方法)
Constructor[] constructors = cls.getDeclaredConstructors();//获取类的全部构造器
for (Constructor constructor: constructors) {
System.out.println(constructor.getName() + "------"+constructor.getParameterCount());//获取构造器名字和构造器参数个数
}
获取指定构造方法
//得到指定的构造 方法,如果有多个参数,中间用","隔开
Constructor con = cls.getDeclaredConstructor(String.class,Integer.class);
//也可以使用另一种方式来获得:cls.getConstructor(parameterTypes)
根据Class创建对象
1)调用无参构造,来获得对象
2)先获得指定的构造,然后利用这个构造方法,来获得对象,这里指定的构造属性要和创建的类属性一致
示例代码如下
//先获取Student类的类对象
Class<Student> stuClass = Student.class;
//Class创建对象的两种方法
//1)调用无参构造
Student student = stuClass.newInstance();
//2)先获得指定的构造,然后利用这个构造方法,来获得对象
Constructor<Student> con = stuClass.getDeclaredConstructor(String.class, String.class, int.class, int.class);
Student student1 = con.newInstance("张三","男",18,1111);
获取属性
获得本类所有的属性(继承自父类的属性不能获得),private修饰的属性也能获得
Field[] fields = stu.getDeclaredFields();
for (Field field : fields) {
System.out.println("获取当前属性的信息:"+field);
System.out.println("获取当前属性的信息:"+field.getName());
System.out.println("获取当前属性存在的类:"+field.getDeclaringClass());
System.out.println("获取当前属性的修饰符"+field.getModifiers());
}
获得所有的public修饰的属性(继承自父类的属性也能获得),private修饰的属性不能获得
Field [] fs = cls.getFields();
for(int i=0;i<fs.length;i++){
System.out.println(fs[i]);
}
获得某个指定的属性:
这里获取Student类的sno属性
Field sno = stu.getDeclaredField("sno");
sno.setAccessible(true);//当属性为私有时使用,解除私有属性的封装
System.out.println(sno);
获取方法
获取所有方法,包括继承自父类的方法,但私有方法不能获取:
Class stu = Student.class;
Method[] methods = stu.getMethods();
for (Method method : methods) {
System.out.println(method.getName());//获得方法名
System.out.println(method.getParameterCount());//参数个数
System.out.println(method.getReturnType());//返回参数类型
System.out.println(method);
}
获取所有方法,包括私有方法,可以如下(但继承的方法不能得到):
Class stu = Student.class;
Method[] methods = stu.getDeclaredMethods();//获取所有方法
for (Method method : methods) {
System.out.println(method.getName());//获得方法名
System.out.println(method.getParameterCount());//参数个数
System.out.println(method.getReturnType());//返回参数类型
System.out.println(method);
}
获取某一个指定的方法,如下:
获得指定方法(无参)
Method walk = stu.getMethod("walk");
System.out.println(walk);
获得指定方法(有参)
Method eat = stu.getMethod("eat", String.class);
System.out.println(eat);
调用方法
通过invoke调用方法,obj表示在哪个对象里调用方法,后续的参数都是方法的传入的参数
//创建对象
Class<Student> stu = Student.class;
Student student = stu.newInstance();
//获取方法
Method walk = stu.getMethod("walk");
System.out.println(walk);
Method eat = stu.getMethod("eat", String.class);
System.out.println(eat);
//方法调用
walk.invoke(student);
eat.invoke(student,"张三");
其他方法
穿插在以上方法使用
String getName()
//获取全限定名(完整包名+类名)
Class [] getInterfaces() //确定此对象所表示的类或接口实现的接口
Class getSuperclass() //返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class
Field类的方法:
String getName() 获取字段名
int getModifiers() 用于返回Field的修饰符
void setAccessible(true); 设置该属性能否被访问,如果属性为private,必须设置为true才能访问
void set(Object obj, Object value) 将指定对象obj上此 Field 对象表示的字段设置为指定的新值value。
Method类的方法:
String getName() 获取方法名
int getModifiers() 用于返回Method的修饰符
Class getReturnType() 获取返回值类型
Class [] getExceptionTypes() 获取声明抛出的异常类型
Class [] getParameterTypes() 返回方法中各个参数的类型
Constructor类的方法:
int getModifiers() 用于返回Method的修饰符
Class [] getExceptionTypes() 获取声明抛出的异常类型
Class [] getParameterTypes() 返回方法中各个参数的类型