反射可以解决在编译时无法预知对象和类是属于那个类的,要根据程序运行时的信息才能知道该对象和类的信息的问题。
在两个人协作开发时,你只要知道对方的类名就可以进行初步的开发了。
获取类对象
Class.forName(String clazzName)静态方法
调用类的class属性,Person.class返回的就是Person的class对象(推荐使用)
-
调用某个对象的getClass()方法
立即学习“Java免费学习笔记(深入)”;
具体使用还是要根据实际来选择,第一种方式是比较自由的,只要知道一个类名就可以了,其不会做该类是否存在的校验,第二种、第三种则会做校验
获取类的信息
获取类构造器
Connstructor:返回此Class对象对应类的带指定形参的public构造器getConstructor(Class>...parameterTypes) Constructor>[] getConstructors():返回此Class对象对应类的所有public构造器Constructor:返回此class对象对应类的带指定参数的构造器,与构造器的访问权限无关[] getDeclaredConstructor(Class>...parameterTypes) Constructor>[] getDeclaredConstructors():返回此class对象对应类的所有构造器,与构造器的访问权限无关
获取类成员方法
Method getMethod(String name,Class>...parameterTypes):返回此class对象对应类的带指定形参的public方法Method[] getMethods():返回此class对象所表示的类的所有public方法Method getDeclaredMethod(string name,Class>...parameterTypes):返回此class对象对应类的带指定形参的方法,与方法访问权限无关Method[] getDeclaredMethods():返回此class对象对应类的全部方法,与方法的访问权限无关
获取类成员变量
Field getField(String name):返回此class对象对应类的指定名称的public成员变量Field[] getFields():返回此class对象对应类的所有public成员变量Field getDeclaredField(String name):返回此class对象对应类的指定名称的成员变量,与成员变量访问权限无关Field[] getDeclaredFields():返回此class对象对应类的全部成员变量,与成员变量的访问权限无关
获取类注解
A getDeclaredAnnotation(ClassannotationClass):以字符串形式返回此CLass对象所表示的类的简称
判断该类是否为接口、枚举、注解类型
Annotation[] getAnnotations():返回此class对象是否表示一个注解类型Annotation[] getDeclaredAnnotations():判断此Class对象是否使用类Annotation修饰A[] getAnnotationByType(ClassannotationClass):返回此class对象是否是一个匿名类A[] getDeclaredAnnotationByType(ClassannotationClass):返回此class对象是否表示一个数组类Class>[] getDeclaredClasses():返回此class对象是否表示一个枚举Class> getDeclaringClass():返回此class对象是否表示一个接口Class>[] getInterfaces():判断obj是否是此class对象的实例,该方法可以完全代替instanceof操作符
public interface Colorable {
public void value();
}public class ClassInfo {
public static void main(String[] args) throws NoSuchMethodException, SecurityException {
Class cls=Colorable.class;
System.out.println(cls.getMethod("value"));
System.out.println(cls.isAnnotation());
System.out.println(cls.isInterface());
}
} Class super T> getSuperclass()
public abstract void com.em.Colorable.value() false true
Java8中新增的方法参数反射
int getModifiers():获取该构造器或方法的形参个数Package getPackage():获取该构造器或方法的所有形参String getName():获取修饰该形参的修饰符boolean isAnnotation():获取形参名boolean isAnnotationPresent(Class extends Annotation>annotationClass):获取带泛型的形参类型boolean isAnonymousClass():获取形参类型boolean isArray():该方法返回该类的class文件中是否包含了方法的形参名信息boolean isEnum():该方法用于判断该参数是否为个数可变的形参
public class Test {
public void getInfo(String str,Listlist){
System.out.println("成功");
}
} public class ClassInfo {
public static void main(String[] args) throws NoSuchMethodException, SecurityException {
Class cls=Test.class;
Method med=cls.getMethod("getInfo", String.class,List.class);
System.out.println(med.getParameterCount());
Parameter[] params=med.getParameters();
System.out.println(params.length);
for(Parameter par:params){
System.out.println(par.getName());
System.out.println(par.getType());
System.out.println(par.getParameterizedType());
}
}
} boolean isInterface()
2 2 arg0 class java.lang.String class java.lang.String arg1 interface java.util.List java.util.List
反射生成对象
使用Class对象的newInstance()方法创建Class对象的实例,该方法要求要有默认构造器(比较常用)
先使用Class对象获取指定的Constructor对象,在调用Constructor对象的newInstance()方法来创建该Class对象对应类的实例
反射调用方法
boolean isInstance(Object obj):该方法中的obj是执行该方法的主调,后面的args是执行该方法时传入该方法的实参
public class Test {
public Test(String str) {
System.out.println(str);
}
public void getInfo(String str){
System.out.println(str);
}
}public class ClassInfo {
public static void main(String[] args) throws Exception {
Class cls=Test.class;
Constructorconstruct=cls.getConstructor(String.class);
Test test=construct.newInstance("初始化");
Method med=cls.getMethod("getInfo", String.class);
med.invoke(test, "调用方法成功");
}
} 结果
初始化 调用方法成功
接下来看官仔细看下面的栗子
public class Test {
public Test(String str) {
System.out.println(str);
}
//私有方法
private void getInfo(String str){
System.out.println(str);
}
}public class ClassInfo {
public static void main(String[] args) throws Exception {
Class cls=Test.class;
Constructorconstruct=cls.getConstructor(String.class);
Test test=construct.newInstance("初始化");
//为啥使用这个方法呢?
Method med=cls.getDeclaredMethod("getInfo", String.class);
//为啥使用这个方法呢?
med.setAccessible(true);
med.invoke(test, "调用方法成功");
}
} int getParameterCount()
初始化 调用方法成功
setAccessible(boolean flag):将值设为true,指示该Method在使用是应该取消Java语言的访问权限检查
访问成员变量值
Parameter[] getParameters():获取obj对象的该成员变量的值。此处的Xxx对应8种基本类型,如果该成员变量的类型是引用类型的,则去掉Xxx部分getModifiers():将obj对象的该成员变量设置为val值。此处的Xxx对应8中基本类型,如果该成员变量的类型是引用类型,则取消set后面的Xxx
以上两个方法可以方法所有的成员变量,包括private的私有成员变量
public class Test {
private int num;
public Test(String str) {
System.out.println(str);
}
private void getInfo(String str){
System.out.println(str);
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
}public class ClassInfo {
public static void main(String[] args) throws Exception {
Class cls=Test.class;
Constructorconstruct=cls.getConstructor(String.class);
Test test=construct.newInstance("初始化");
Method med=cls.getDeclaredMethod("getInfo", String.class);
med.setAccessible(true);
med.invoke(test, "调用方法成功");
Field fld=cls.getDeclaredField("num");
fld.setAccessible(true);
fld.setInt(test, 12);
System.out.println(fld.getInt(test));
}
} String getName()
初始化 调用方法成功 12
操作数组
java.lang.reflect包下有一个Array类,其可以动态创建数组
Type getParameterizedType():创建一个具有指定的元素类型、指定维度的新数组
Class>getType():返回array数组中第index个元素。其中xxx是各种基本数据类型,如果数组元素是引用类型,则该方法变为get()
boolean isNamePresent():将array数组中低index 个元素的值设为val,其中xxx是各种基本数据类型,如果数组元素是引用类型,则该方法变为set()
public class ArrayInfo {
public static void main(String[] args) {
Object arrays=Array.newInstance(String.class, 3);
Array.set(arrays, 0, "第一个");
Array.set(arrays, 1, "第二个");
Array.set(arrays, 2, "第三个");
System.out.println(Array.get(arrays, 2));
}
}










