我们先来看一个例子:
package venus;
public class Student {
public String name;
public Student(){
System.out.println("无参构造方法");
}
public void doHomework(){
System.out.println(name + "正在做作业~~~");
}
}
我们平常是如何调用Student
类里的方法的?
package venus;
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.name = "小白";
student.doHomework();
}
}
//结果:
无参构造方法
小白正在做作业~~~
以上这种方法是普通的方法:其中Student student = new Student()
通过new
关键字来创建对象,并调用无参构造方法;接着的student.name = "小白"
是调用的其中的成员变量;student.doHomework()
是调用普通方法。
一般情况下,我们使用某个类时是知道这个类是什么类,是用来做什么的,所以我们可以直接对这个类进行实例化,之后使用这个类的对象进行操作,就例如上面的
但反射则是一开始我们并不知道要初始化的类对象是什么,就无法通过new
关键字来创建对象了;也就是说反射是在运行时才知道要操作的类是什么,并且可以通过相应的方法可以获得这个类完整的样子!
综上所述,反射就是一种新的操作类中成员变量、构造方法和普通方法的机制,它可以将类中的各个组成部分进行剖析,可以得到每个组成部分,然后对每个组成部分进行操作!
要实现对类中的成员变量、构造方法和普通方法的操作,我们需要借助Java自身提供的
java.lang
包下的Class
类和java.lang.reflect
包下的反射API(接口)。
获取Class类实例化对象有以下六种方法:
Class.forName("包名.类名")
来获取Class类实例: try {
Class clazz = Class.forName("venus.Student");//抛出检查时异常,所以使用try-catch
System.out.println(clazz.getName()); //venus.Student
} catch (Exception e) {
e.printStackTrace();
}
类名.class
来获取Class类实例: Class clazz = Student.class;
System.out.println(clazz.getName()); //venus.Student
getClass()
方法来获取Class类实例: Student student = new Student();//已创建了引用类型的对象
Class clazz = student.getClass();
System.out.println(clazz.getName());
包装类.TYPE
来获取Class类实例,当然,也可以通过基本数据类型.class
获取Class类实例: Class clazz = Integer.TYPE;
System.out.println(clazz.getName()); //int
clazz = int.class;
System.out.println(clazz.getName()); //int
元素类型[].class
来获取数组所对应的Class类实例: clazz = String[].class;
System.out.println(clazz.getName()); //[Ljava.lang.String;
类名.class.getSuperclass()
来获取: clazz = Student.class.getSuperclass();
System.out.println(clazz.getName()); //java.lang.Object
其中getConstructor([参数类型])
只能获取由public
修饰的构造方法
Constructor[] getConstructor()
:获取 无参构造方法:
Class clazz = Student.class; //获取Class实例化对象
try {
Constructor constructor = clazz.getConstructor(); //获取无参构造方法
System.out.println(constructor.getName()); //venus.Student
System.out.println(constructor); //public venus.Student()
} catch (Exception e) {
e.printStackTrace();
}
Constructor getConstructor(Class>... parameterTypes)
:获取 对应的有参构造方法:
Class clazz = Student.class;
try {
//获取参数类型为String的有参构造方法
Constructor constructor = clazz.getConstructor(String.class);
System.out.println(constructor.getName()); //venus.Student
System.out.println(constructor); //public venus.Student(java.lang.String)
} catch (Exception e) {
e.printStackTrace();
}
其中getDeclaredConstructor([参数类型])
可以获取所有的构造方法,不区分访问权限(即使是私有的也可以):
Constructor getDeclaredConstructor()
:获取 无参构造方法
Class clazz = Student.class;
try {
//获取无参构造方法
Constructor constructor = clazz.getDeclaredConstructor();
System.out.println(constructor.getName()); //venus.Student
System.out.println(constructor); //public venus.Student()
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
Constructor
:获取 对应的有参构造方法:
Class clazz = Student.class;
try {
//获取参数类型为 int的有参构造方法
constructor = clazz.getDeclaredConstructor(int.class);
System.out.println( constructor.getName()); //venus.Student
System.out.println(constructor); //private venus.Student(int)
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
Constructor
类某些方法获取某个构造方法的的信息:Class clazz = Student.class;
try {
//获取参数类型为 String 和 int的有参构造方法
Constructor constructor = clazz.getConstructor(String.class,int.class);
} catch (Exception e) {
e.printStackTrace();
}
获取该构造方法的相关信息:
获取该构造方法的类的Class对象(Class
):
Class result = constructor.getDeclaringClass();
System.out.println(result); //class venus.Student
获取该构造方法的修饰符(int getModifiers()
):
int mod = constructor.getModifiers();
String result = Modifier.toString(mod);
System.out.println(result); //public
获取该构造方法的名称(String getName()
):
String result = constructor.getName();
System.out.println(result); //venus.Student
获取该构造方法的形参类型对应的Class对象组成的数组
Class[] clazzs = constructor.getParameterTypes();
for (Class c:clazzs) {
System.out.println(c); // {class java.lang.String , int}
}
getConstructors()
和getConstructor(Class>... parameterTypes)
方法无法获取非public类中默认无参构造方法对应的Constructor对象。getDeclaredConstructor()
和getDeclaredConstructor(Class>... parameterTypes)
方法可以获取非public类中默认无参构造方法对应的Constructor对象。操作构造方法 ---- 创建对象:
void setAccessible(boolean flag)
:如果操作的构造方法是私有的,则需要下面一行代码来忽略访问权限:
constructor.setAccessible(true);
T newInstance(Object... initargs)
:使用此Constructor对象表示的构造方法来创建声明该构造方法类的新对象。其中initargs为传入该构造方法中的参数,如果该构造方法没有参数,则可设定为null或一个长度为0的数组:
Object object = constructor.newInstance("Tom",18);
Student stu = (Student) object; //下转型
stu.doHomework();
Method[] getMethods()
:获取被public修饰的方法(不仅仅限于本类,还包括继承自父类中的public方法)
Class clazz = Student.class;
Method[] methods = clazz.getMethods();
for (Method method:methods) {
System.out.println(method.getName());
}
Method[] getMethod(String methodName, Class>... paramenterTypes)
:获取与该Class对象表示类或接口中方法名和参数类型相匹配的public方法(含继承的)的Method对象:
try {
Method method = clazz.getMethod("doHomework");
System.out.println(method.getName()); //doHomework
} catch (Exception e) {
e.printStackTrace();
}
Method[] getDeclaredMethods()
:获取一个该Class对象表示类或接口内声明定义的所有访问权限的方法(不含继承的)对应的Method对象数组:
Method [] methods = clazz.getDeclaredMethods();//(任何"访问权限"的方法)
for (Method method:methods) {
System.out.println(method.getName());
}
Method getDeclaredMethod(String methodName Class>... parameterTypes)
:获取与该Class对象表示类或接口中方法名和形参类型相匹配的方法(不含继承的)对应的Method对象。
try {
//获取方法名为cooking,参数类型为int和String的方法
Method method = clazz.getMethod("cooking", int.class, String[].class);
} catch (Exception e) {
e.printStackTrace();
}
String getName()
:获取该普通方法的方法名:String result = method.getName();//获取方法名
System.out.println(result); //cooking
Class> getDeclaringClass()
:获取该普通方法的类或接口的Class对象:Class c = method.getDeclaringClass();//获取方法的类的Class对象
System.out.println(c); //class venus.Student
int getModifiers()
:获取该普通方法的修饰符(以整数形式),应该使用Modifier类中的toString()
方法对所返回的整数进行解码:int mod = method.getModifiers(); //获取方法的修饰符
String result = Modifier.toString(mod);
System.out.println(result); //public static
Class>[] getParameterTypes()
:获取该普通方法的形参类型对应Class对象组成的数组。如果方法没有参数,则数组长度为0:Class [] zzs = method.getParameterTypes();//获取方法的参数类型组成的数组 {Integer.YPTE, String[].class}
for (Class cla :zzs) {
System.out.println(cla.getName());
}
Class> getReturnType()
:获取该普通方法的返回值类型所对应的Class对象:Class clazzs = method.getReturnType();//获取方法的返回值类型★
System.out.println(clazzs.getName());
调用该普通方法:
void setAccessible(boolean flag)
:如果该普通方法是非public的,则需要使用下一行代码来忽略访问权限,true表示忽略:
method.setAccessible(true);
Object invoke(Object obj, Object... args)
:调用该普通方法并返回Object类型结果(即返回该普通方法的【返回值】,如果没有,则返回null)。obj表示该方法所在类实例,如果方法是静态的,则obj可以指定为null;args表示传入该方法的参数,如果该方法没有参数,则args数组长度可以为0或null:
Object object = method.invoke(new Student(),1,new String []{}); //调用这个方法,并返回该方法的【返回值】,如果该方法没有【返回值】,则返回null
System.out.println(object);