1、Java反射(Reflection)是一种新的操作类中成员变量、构造方法和普通方法的机制,为了实现对成员变量、构造方法和普通方法的操作,我们需要借助Java自身提供的java.lang包下的Class类和java.lang.reflect包下的反射API 。
2、Class类是Java 反射机制的入口,封装了一个类或接口的运行时信息,通过调用Class类的方法可以获取这些信息。
Class类的四个特点:
1、该类在java.lang包中;
2、 该类被final所修饰,即该类不可以被子类继承;
3、该类实现了Serializable接口;
4、该类的构造方法被private所修饰,即不能通过new关键字创建该类的对象;
3、获取Class类实例化对象
可以用以下六种方法获取Class类实例化对象,这里创建了一个Student类用以实验。
package com.jd;
public class ClassTest {
public static void main(String[] args) {
//反射是一种新的操作类中的属性、构造方法和普通方法的机制
Class clazz=null;
//获取Class类实例化对象的六种方法
//1、Class.forName(String classname[这个类的全名]);
try {
clazz = Class.forName("com.jd.Student");
System.out.println(clazz.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}//检查时异常
//2、类名.class
clazz = Student.class;
System.out.println(clazz.getName());
//3、对象.getClass()
clazz = new Student().getClass();
System.out.println(clazz.getName());
//4、基本数据类型对应的class对象:包装类.TYPE
clazz = Integer.TYPE;
System.out.println(clazz.getName());
//5、数组类对应的class:元素类型[].class
clazz = String[].class;
System.out.println(clazz.getName());
//6、某个类父类所对应的class对象
try {
clazz = Class.forName("com.jd.Student").getSuperclass();
System.out.println(clazz.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
运行结果
1、com.jd.Student
2、com.jd.Student
3、com.jd.Student
4、int
5、[Ljava.lang.String;
6、java.lang.Object
4、获取Class类对应类中声明的构造方法的几种方法
以Student类为例
package com.jd;
public class Student {
public String name;
public int number;
public Student(){
}
public Student(String name,int number){//private
this.name=name;
this.number = number;
}
public void doHomeWork(String name){
System.out.println(name+"正在做作业。。。");
}
}
获取构造方法
//获取某个类对应的Class类对象
Class clazz = Student.class;
//权限是public
try {
Constructor constructor = clazz.getConstructor();
System.out.println(constructor.getName());
constructor = clazz.getConstructor(String.class,Integer.TYPE);
System.out.println(constructor.getName());
} catch (Exception e) {
e.printStackTrace();
}
运行结果
无参:com.jd.Student
有参:com.jd.Student
1、Constructor[] getConstrutors():返回该Class对象表示类包含的所有public构造方法(不含继承)所对应Constructor对象数组。
2、Constructor getConstrutor(Class>... parameterTypes):返回与该Class对象表示类中参数列表相匹配的public构造函数(不含继承)对应的Constructor对象。
注意这两种的访问权限是public,若将Student中的构造方法权限改为private则会报错。这时需要另外两种方法。
1、Constructor>[] getDeclaredConstructors():返回一个该Class对象表示类中声明的所有构造方法(不区分访问权限)对应的Constructor对象数组。
2、Constructor
//无权限限制
try {
Constructor constructor = clazz.getDeclaredConstructor();
System.out.println(constructor.getName());
constructor = clazz.getDeclaredConstructor(String.class,Integer.TYPE);
System.out.println(constructor.getName());
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
运行结果
无参:com.jd.Student
有参:com.jd.Student
5、获取构造方法的信息
通过Constructor类某些方法可以获取某个构造方法的信息
Class clazz = Student.class;
try {
Constructor constructor = clazz.getDeclaredConstructor(String.class,Integer.TYPE);
//获取该构造方法来自哪一个类
clazz = constructor.getDeclaringClass();
System.out.println(clazz.getName());
//获取修饰符
int mod = constructor.getModifiers();
String result = Modifier.toString(mod);
System.out.println(result);
//获取方法名称
System.out.println(constructor.getName());
//获取参数列表(以各个参数class类的形式)
Class [] classes = constructor.getParameterTypes();
for (Class zz:classes) {
System.out.println(zz.getName());
}
} catch (Exception e) {
e.printStackTrace();
}
运行结果
来自类:com.jd.Student
修饰符:private
方法名:com.jd.Student
参数列表:java.lang.String
int
1、Class
2、int getModifiers():以整数形式返回Constructor对象表示的构造函数的修饰符。
3、String getName() :以字符串形式返回Constructor对象所表示得构造方法的名称。
4、 Class>[] getParameterTypes():返回由Constructor对象所表示的构造方法的形参类型对应Class对象组成的数组此 。如果构造方法没有参数,则数组长度为0。
通过Constructor类某些方法可以创建对象
void setAccessible(boolean flag):调用构造函数时是否忽略访问权限的影响,true表示忽略,false表示不忽略。
T newInstance(Object... initargs):使用此Constructor对象表示的构造方法来创建声明该构造方法类的新对象。initargs为传入该构造方法中的参数,如果该构造方法没有参数,则可设定为null或一个长度为0的数组。
Student类
package com.jd;
public class Student {
public String name;
public int number;
private Student(){
}
private Student(String name,int number){
this.name=name;
this.number = number;
}
public void doHomeWork(){
System.out.println(name+"正在做作业。。。"+number);
}
}
操作构造方法——创建对象
Class clazz = Student.class;
try {
Constructor constructor = clazz.getDeclaredConstructor(String.class,Integer.TYPE);
//设置权限为合法,及无视权限
constructor.setAccessible(true);//因为此处有参构造方法访问权限为private
Object object = constructor.newInstance("Tom",123);//创建对象,传入参数
Student stu = (Student)object;
stu.doHomeWork();
} catch (Exception e) {
e.printStackTrace();
}
运行结果
Tom正在做作业。。。123
6、获取Class类对应类中声明的普通方法的几种方法
a、public 不仅限于本类还包括继承自父类的public方法
1、Method[] getMethods():返回一个该Class对象表示类或接口中所有public方法(含继承的)对应的Method对象数组。
2、Method getMethod(String methodName, Class>... parameterTypes):返回与该Class对象表示类或接口中方法名和方法形参类型相匹配的public方法(含继承的)的Method对象。
示例1
//获取该对象所在类所有的public方法(含继承)
Class clazz = Student.class;
Method[] methods = clazz.getMethods();
for (Method method:methods) {
System.out.println(method.getName());
}
运行结果
doHomeWork
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAll
示例2
//获取某一个符合条件的方法
Class clazz = Student.class;
try {
Method method = clazz.getMethod("doHomeWork");
System.out.println(method.getName());//获取整个方法
} catch (Exception e) {
e.printStackTrace();
}
运行结果
doHomeWork
b、不考虑权限问题,获取“本类”中声明的方法
1、Method[] getDeclaredMethods():返回一个该Class对象表示类或接口内声明定义的所有访问权限的方法(不含继承的)对应的Method对象数组。
2、Method getDeclaredMethod(String methodName,Class>... parameterTypes) :返回与该Class对象表示类或接口中方法名和方法形参类型相匹配方法(不含继承的)对应的Method对象。
示例3
//获取某一个符合条件的方法
Class clazz = Student.class;
try {
Method [] methods = clazz.getDeclaredMethods();
for (Method method:methods) {
System.out.println(method.getName());
}
} catch (Exception e) {
e.printStackTrace();
}
运行结果
doHomeWork
6、获取Class类对应类中声明的普通方法的信息
Student类
package com.jd;
public class Student {
public static int doHomeWork(String name,int number){
System.out.println(name+"正在做作业。。。"+number);
return 1;
}
}
通过Method类某些方法可以获取某个普通方法的信息,
1、Class> getDeclaringClass():返回声明Method对象表示方法的类或接口的 Class 对象。
2、int getModifiers():以整数形式返回此Method对象所表示方法的修饰符。应该使用Modifier类中的toString方法对所返回的整数进行解码(示例见备注)。
3、 Class> getReturnType():返回Method对象所表示的方法的返回值类型所对应的Class对象。 String getName():返回方法名。
4、Class>[] getParameterTypes():返回由Method对象代表方法的形参类型对应Class对象组成的数组。如果方法没有参数,则数组长度为 0。
5、Class>[] getExceptionTypes():返回由Method对象表示方法抛出异常类型对应Class对象组成的数组。如果此方法没有在其 throws子句中声明异常,则返回长度为 0 的数组。
//获取方法信息
try {
Method method = clazz.getMethod("doHomeWork",String.class,Integer.TYPE);
System.out.println(method);//获取整个方法(不包含方法体)
System.out.println(method.getDeclaringClass());//获取方法所在的类
System.out.println(Modifier.toString(method.getModifiers()));//获取方法修饰符
clazz = method.getReturnType();
System.out.println(clazz.getName());//获取方法返回值
System.out.println(method.getName());//获取方法名称
Class [] clazzes = method.getParameterTypes();//获取方法参数类型
for (Class zz:clazzes) {
System.out.println(zz.getName());
}
} catch (Exception e) {
e.printStackTrace();
}
运行结果
整个方法:public static int com.jd.Student.doHomeWork(java.lang.String,int)
所在类:class com.jd.Student
修饰符:public static
返回类型:int
方法名:doHomeWork
参数类型:java.lang.String
int
操作普通方法——调用普通方法
1、void setAccessible(boolean flag):调用方法时是否忽略访问权限的影响,true表示忽略,false表示不忽略。
2、Object invoke(Object obj, Object... args):调用Method对象指代的方法并返回Object类型结果。obj表示该方法所在类实例,如果方法时静态的则obj可以指定为null; args表示传入该方法的参数,如果方法没有参数,则args数组长度可以为 0 或 null 。
//操作普通方法
try {
Method method = clazz.getMethod("doHomeWork",String.class,Integer.TYPE);
//反射中方法的调用不区分静态和非静态
Object object = method.invoke(new Student(),"Tom",1);
System.out.println(object);
} catch (Exception e) {
e.printStackTrace();
}
运行结果
Tom正在做作业。。。1
1