1反射概述
2关于反射的理解
反射是动态语言的关键,反射机制允许程序在执行期间借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法
框架 = 反射+注解+设计模式
3体会反射动态性的例子
生成的随机数决定了创建哪个类的对象,在执行时并不确定会创建哪一个
public class test {
@Test
public void test3() throws InstantiationException, IllegalAccessException {
int num = 1;
String classpat ="";
switch (num) {
case 0:
classpat = "java.util.Date";
break;
case 1:
classpat = "java.lang.String";
break;
case 2:
classpat = "exer2.com.atguigu.java.Person";
break;
}
try{
Object o = getinstance(classpat);
System.out.println(o.toString());
System.out.println(o.getClass());
}catch (Exception e){
e.getMessage();
}
}
public Object getinstance(String f) throws Exception {
Class aClass = Class.forName(f);
return aClass.newInstance();
}
}
4反射机制所提供的功能
5相关API
Class类的理解
1.类的加载过程
程序经过javac.exe命令以后,会生成一个或多个字节码文件(.class)结尾。
接着我们使用java.exe命令对某个字节码文件进行解释运行。相当于把某个字节码文件加载到内存中。此过程就称为类的加载,加载到内存中的类,我们就称之为运行时类,此运行时类就作为一个Class的实例。
2.换句话说,Class的实例就对应着一个运行时类。
3.加载到内存中的运行时类,会缓存一定的时间。在此时间之内,我们可以通过不同的方式来获取此运行时类。
获取Class实例的几种方式(需要掌握)
方式一:调用运行时类的属性:.class
Class clazz1 = Person.class
方式二:通过运行时类的对象,调用getClass()
Person p1 = new Person
Class clazz2 = p1.getClass();
方式三:调用Class的静态方法:forName(String classPath)
Class clazz3 = Class.forName(com.atguigu.java.Person)
创建类的对象的几种方式?
- new + 构造器
- 要创建类的对象,可以考虑类的静态方法(构造器隐藏了)
- 通过反射
创建运行时类的对象
Class clazz = Person.class
Person obj = clazz.newInstance()
要想使用此方法正常的创建运行时类的对象,要求:
- 运行时类必须提供空参的构造器
- 空参构造器的访问权限得够,通常,设置为public
在JavaBean中提供一个public的空参构造器,因为:
- 便于通过反射,创建运行时对象
- 便于子类继承此运行时类时,默认调用super,保证父类此构造器
调用运行时类的指定结构
调用指定的属性:
public class test {
public static void main(String[] args) throws Exception {
Class<person> clazz1 = person.class;
//创建运行时类的对象
person p = clazz1.newInstance();
//1.getDeclaredField(String fieldname):获取运行时类中指定变量名的属性
Field name = clazz1.getDeclaredField("name");
//2.保证当前属性是可访问的
name.setAccessible(true);
//3.获取、设置指定对象的此属性值
name.set(p,"wq");
System.out.println(name.get(p));
/*
试一下public权限的属性
*/
Field id = clazz1.getDeclaredField("id");
//public权限不用设置能输出
id.setAccessible(true);
id.set(p,123);
System.out.println(id.get(p));
}
}
调用指定的方法:
@Test
public void test() throws Exception {
Class<person> clazz = person.class;
person p= clazz.newInstance();
//1.获取指定的某个方法
Method show1 = clazz.getDeclaredMethod("show1");
//2.设置
show1.setAccessible(true);
//3.调用invoke()方法
Object o = show1.invoke(p);
System.out.println(o);
Method show2 = clazz.getDeclaredMethod("show2");
show2.setAccessible(true);
show2.invoke(p);
//测试静态方法
Method show3 = clazz.getDeclaredMethod("show3");
/*
这里的静态方法需要注意的是,invoke方法里(),第一个参数是传入对象,
即是调用方法的对象,第二个参数是传入的参数值,对于静态来说,类加载时就已经
存在,因此可以直接传入person.class
*/
Object invoke = show3.invoke(person.class);
System.out.println("-------------");
//测试带参数的
/*
带参数的,idea会自动生成形参列表
*/
Method put = clazz.getDeclaredMethod("put", String.class, int.class);
put.invoke(p,"lya",21836965);
}
}
调用指定的构造器:
@Test
public void test2() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class<person> clazz = person.class;
Constructor<person> constructor = clazz.getDeclaredConstructor(String.class, int.class);
person wq = constructor.newInstance("wq", 0000);
System.out.println(wq);
}