反射
反射是什么
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
反射的用途
在开发的过程中,有时会遇到某个类的某个成员变量、方法或是属性是私有的。这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法。
反射常用类
我们对Java反射机制的学习,设计上基本就等同于对Class类的用法的学习。所以,要了解相关的类及其用法。
1. Class
Class类是java反射机制的核心,我们可以提供Class类动态的加载某个类。
Class c =Class.forName("Reflect.ReflectClass");
Class类获取对象的方式有3种。
- 运用getClass();
- .运用class语法;
- 运用Class.forName()语法(常用)
Class c1=new ReflectClass().getClass();
Class c2=ReflectClass.class;
Class c3 =Class.forName("Reflect.ReflectClass");
2. Constructor
Constructor类的对象代表"构造器",Constructor类对象我们要通过Class类对象调用方法来获取。
源码:public Constructor
getConstructor(Class<?>... parameterTypes)
Constructor[] constructor=class1.getDeclaredConstructors();//获取所有构造器
Constructor constructor1=class1.getDeclaredConstructor(null);//获取无参构造器
Constructor constructor2=class1.getConstructor(int.class,String.class);//获取相应参数的构造器
//调用构造器
ReflectClass reflectClass1=(ReflectClass) constructor1.newInstance();//调用无参构造器
ReflectClass reflectClass2=(ReflectClass) constructor2.newInstance(18,"小杨");//调用有参构造器
3. Field
Field类的对象代表”属性“,Field类对象的获取要通过Class类对象调用方法来获取。
源码: public Field getDeclaredField(String name)
Field[] field=class1.getDeclaredFields();//获取所有属性的Field对象
Field field1=class1.getDeclaredField("name");//获取name属性的Field对象
//设置属性值
field1.setAccessible(true);//跳过安全检查,可以直接访问私有属性和方法
field1.set(reflectClass1,"小杨");//参数左边是对象,右边是属性值
4. Method
Method类的对象代表”方法“,Method类对象的获取要通过Class类对象调用方法来获取。
通过指定的方法名和参数获取到Method类方法对象
源码: public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
Method[] methods=class1.getDeclaredMethods();//获得所有方法
Method method=class1.getDeclaredMethod("setName",String.class);//获得指定名字的方法,
Method method1=class1.getDeclaredMethod("sayName",null);//获取无参方法
//调用方法
method.invoke(reflectClass1,"小杨");//参数左边是对象,右边是方法所需的参数
method1.invoke(null);//调用无参方法
反射弊端
反射机制的缺点是会大大降低程序的执行效率。
public class TestReflect {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
Class class1=TestReflect.class;
long reflectStart1=System.currentTimeMillis();
TestReflect testReflect=(TestReflect) class1.newInstance();
Method method1=class1.getDeclaredMethod("fun",null);
for (int i = 0; i < 10000; i++) {
method1.invoke(testReflect,null);
}
long reflectEnd1=System.currentTimeMillis();
long reflectStart2=System.currentTimeMillis();
TestReflect testReflect2=new TestReflect();
for (int i = 0; i < 10000; i++) {
testReflect2.fun();
}
long reflectEnd2=System.currentTimeMillis();
System.out.println("反射执行时间:"+(reflectEnd1-reflectStart1));
System.out.println("普通执行时间:"+(reflectEnd2-reflectStart2));
}
public void fun(){}
}
运行结果: