咱们一起来探讨Java的反射吧
2016-06-15 本文已影响205人
墨源为水
一.为什么使用反射?反射是什么?
反射可以解决在编译时无法预知对象和类是属于那个类的,要根据程序运行时的信息才能知道该对象和类的信息的问题。在两个人协作开发时,你只要知道对方的类名就可以进行初步的开发了。
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
二.从案例学习如何使用反射
public class Man implements AnimalBaseSkill{
public int sex=-1;
private String name;
private Man(int sex, String name) {
this.sex = sex;
this.name = name;
}
public Man() {
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void eat() {}
private class Clan {
String clanName="default family";
public Clan(String familyName) {
this.clanName = familyName;
}
public Clan() {
}
public String getClanName() {
return clanName;
}
public void setClanName(String clanName) {
this.clanName = clanName;
}
}
}
1.如何通过反射获取Person对象?
- Class.forName(String clazzName)静态方法
- 调用类的class属性,Person.class返回的就是Person的class对象(推荐使用)
- 调用某个对象的getClass()方法
eg.
Class class1 = Class.forName("com.ch.java.reflect.Man");
Class class2 = Man.class;
Class class3 =Man.getClass();
但是只有方法一可以获取私有内部类:
Class class_clan=Class.forName("com.ch.java.reflect.Man$Clan");
获取Class后,然后通过Class获取构造器,通过newInstance()就可以获取该对象:
Constructor constructor=class1.getConstructor(null);
Man man= (Man) constructor.newInstance();
但是内部类的对象要像下面获取,原因会在(如何获取类构造器?)讲解
Constructor constructor=class_clan.getConstructor(Man.class, String.class);
Object family=constructor.newInstance(man, "123");
2.如何获取类构造器?
- getConstructor(Class...parameterTypes):返回此Class对象对应类的带指定形参的public构造器,返回参数:Connstructor
- getConstructors():返回此Class对象对应类的所有public构造器,返回参数:Constructor[]
- getDeclaredConstructor(Class...parameterTypes):返回此class对象对应类的带指定参数的构造器,与构造器的访问权限无关,返回参数:Constructor[]
- getDeclaredConstructors():返回此class对象对应类的所有构造器,与构造器的访问权限无关,返回参数:Constructor[]
person对象的构造器获取很简单,但是person内部类的family对象的构造器如何获取?它的坑点在哪里呢?
for (Constructor constructor1 : class_clan.getDeclaredConstructors()) {
System.out.println(constructor1.toString());
}
打印:
public com.ch.java.reflect.Man$Clan(com.ch.java.reflect.Man,java.lang.String)
public com.ch.java.reflect.Man$Clan(com.ch.java.reflect.Man)
3.获取类成员方法
- getMethod(String name,Class<?>...parameterTypes):返回此class对象对应类的带指定形参的public方法,返回参数:Method
- Method[] getMethods():返回此class对象所表示的类的所有public方法
- Method getDeclaredMethod(string name,Class<?>...parameterTypes):返回此class对象对应类的带指定形参的方法,与方法访问权限无关
- Method[] getDeclaredMethods():返回此class对象对应类的全部方法,与方法的访问权限无关
class_1.getMethods();
class_1.getDeclaredMethods();
for (Method method : methods) {
System.out.print(method.getName()+" "+method.getReturnType()+" ");
int i=0;
for (Class<?> aClass : method.getParameterTypes()) {
i++;
System.out.print("params"+i+" "+aClass.toString()+" ");
}
System.out.print("\n");
}
打印:
getName class java.lang.String
setName void params1 class java.lang.String
color void params1 int
getSex int
setSex void params1 int
Disconnected from the target VM, address: '127.0.0.1:52500', transport: 'socket'wait void
wait void params1 long params2 int
wait void params1 long
equals boolean params1 class java.lang.Object *********toString class java.lang.String
hashCode int
getClass class java.lang.Class
notify void
notifyAll void
4.获取类成员变量
- Field getField(String name):返回此class对象对应类的指定名称的public成员变量
- getFields():返回此class对象对应类的所有public成员变量,返回参数:Field[]
- getDeclaredField(String name):返回此class对象对应类的指定名称的成员变量,与成员变量访问权限无关。返回参数:Field
- getDeclaredFields():返回此class对象对应类的全部成员变量,与成员变量的访问权限无关,返回参数:Field[]
Field[] fields=class_1.getFields();
Field[] fields=class_1.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName()+" "+field.getType());
}
打印:
sex int
age int
5.其他
获取该类内部类
Class<?>[] getDeclaredClasses():返回该class队形对应类里包含的全部内部类
获取该类对象所在的外部类
Class<?> getDeclaringClass():返回该Class对象对应类所在的外部类
获取该类对象对应类所实现的接口
Class<?>[] getInterfaces():返回该Class对象对应类所实现的全部接口
获取该类对象对应类所继承的父类
Class<? super T> getSuperclass():返回该Class对象对应类的超类的Class对象
获取该类对象对应类的修饰符、所在包、类名等基本信息
int getModifiers():返回此类或接口的所有修饰符,修饰符由public、protected、private、final、static、abstract等对应的常量组成,返回的整数应使用Modifier工具类的方法来解码,才可以获取真是的修饰符
Package getPackage():获取该类的包
String getName():以字符串形式返回此CLass对象所表示的类的简称
判断该类是否为接口、枚举、注解类型
boolean isAnnotation():返回此class对象是否表示一个注解类型
boolean isAnnotationPresent(Class<? extends Annotation>annotationClass):判断此Class对象是否使用类Annotation修饰
boolean isAnonymousClass():返回此class对象是否是一个匿名类
boolean isArray():返回此class对象是否表示一个数组类
boolean isEnum():返回此class对象是否表示一个枚举
boolean isInterface():返回此class对象是否表示一个接口
boolean isInstance(Object obj):判断obj是否是此class对象的实例,该方法可以完全代替instanceof操作符