1、反射的原理
*应用在一些通用性比较高的代码中
*学到的框架,大多数都是使用反射来实现的
*在框架的开发中,都是使用配置文件开发的
-在配置文件中配置了类,可以通过反射得到类中的所有内容,可以让类中的某个方法来执行
*类中的所有内容:属性、没有参数构造方法,有参数构造方法,普通方法
*画图分析反射的原理
-首先需要把java文件保存到本地硬盘
-编译java文件,成.class文件
-使用jvm把class文件加载进内存
-万物皆对象,class文件在内存中使用Class类表示’
-当使用反射时候,首先需要获取到Class类,得到了这个类之后,就可以得到class文件里面的所有内容
--包括属性,构造函数,方法
-属性通过一个类 Field
-构造方法通过类 Constructor
-普通方法通过类 Method
*Constructor对象方法
- T newInstance(Object... initargs)
使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
-public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。
*Field对象方法
-Field f = getDeclaredField(String name)
根据名称返回属性
- void set(Object obj, Object value)
将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
-public void setAccessible(boolean flag)
将此对象的 accessible 标志设置为指示的布尔值。
*Method对象方法
-public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。
-Object invoke(Object obj, Object... args)
对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
*获取Class类
//获取Class类
//第一种方法
Class clazz1 = ReflectDemo.class;
//第二种方法
Class clazz2 = new ReflectDemo().getClass();
//第三种方法
Class clazz3 = Class.forName("com.ayit.reflect.ReflectDemo");
*使用反射操作类里面的构造方法
//操作有参数的构造方法
@Test
public void TestCon2() throws Exception
{
//得到class类
Class c3 = Class.forName("com.ayit.reflect.ReflectDemo");
//使用有参数的构造方法
//c3.getConstructors();//获取所有的构造方法
//传递是有参数的构造方法里面参数类型,类型使用class形式传递
Constructor cs = c3.getConstructor(String.class,String.class);
//通过有参数的构造方法设置值
ReflectDemo r = (ReflectDemo)cs.newInstance("lisi",30);
System.out.println("name:"+r.getName()+"id:"+r.getId());
}
//操作无参数的构造方法
@Test
public void TestCon() throws Exception
{
//得到Class类
Class c3 = Class.forName("com.ayit.reflect.ReflectDemo");
//得到ReflectDemo实例,即操作了无参数构造方法
ReflectDemo r = (ReflectDemo) c3.newInstance();
//设置值
r.setName("zhangsan");
System.out.println("Name:"+r.getName());
}
*使用反射操作类里面的属性
//操作属性
@Test
public void testField()
{
try {
//得到Class类
Class c3 = Class.forName("com.ayit.reflect.ReflectDemo");
//通过无参数构造函数获取对象
ReflectDemo r = (ReflectDemo) c3.newInstance();
//得到name属性
//Field[] declaredFields = c3.getDeclaredFields();//获取所有属性
Field f1 = c3.getDeclaredField("name");
Field f2 = c3.getDeclaredField("id");
//因为属性是私有的,需设置可以操作私有属性。
f1.setAccessible(true);
f2.setAccessible(true);
//设置name属性
f1.set(r, "wangwu");
f2.set(r, "200");
System.out.println("name:"+r.getName()+" id:"+r.getId());
} catch (Exception e) {
e.printStackTrace();
}
}
*使用反射操作类里面的普通方法
//操作普通方法,比如setName
@Test
public void testMethod()
{
try{
//得到class类
Class c1 = ReflectDemo.class;
//得到ReflectDemo实例
ReflectDemo r = (ReflectDemo) c1.newInstance();
//c1.getDeclaredMethods();//得到所有方法
//得到普通方法
Method method = c1.getDeclaredMethod("setName", String.class);
//设置setName方法执行,执行设置值
method.invoke(r, "xiayujie");
System.out.println("name:"+r.getName());
}
catch(Exception e)
{
e.printStackTrace();
}
}
*当我们操作的方法是静态方法时候,因为静态方法调用方式是 类名.方法名 不需要实例
-使用反射操作静态方法时候,也是不需要实例
-在invoke方法的第一个参数里面,写一个null
//操作静态方法
public static void testStaticMethod() throws Exception{
//得到Class类
Class c3 = Class.forName("com.ayit.reflect.ReflectDemo");
//获取方法
Method method = c3.getDeclaredMethod("print");
//执行
method.invoke(null);
}