Day29
今天专注学习时间大于五个小时,加油OVO,快要把基础看完了,还剩两天的内容了,下周可以往高阶的迈进,明天早上要是起不来的话,明天就放周六假期好了,真的好累。加油OVO
Day29
反射
通过反射创建运行时类的对象
体现了为什么需要用到反射。
package com.sorrymaker.reflection;
import org.junit.Test;
import java.util.Random;
/**
* 通过反射创建对应的运行时类的对象
*/
public class NewInstanceTest {
@Test
public void test1() throws IllegalAccessException, InstantiationException {
Class<Person> clazz =Person.class;
//这里获得的是Person类的对象
/**
* newInstance():调用此方法,创建对应的运行时类的对象,内部调用了运行时类空参的构造器
* 要想此方法正常的创建运行时类的对象,要求:
* 1.运行时类必须提供空参的构造器
* 2.空参的构造器的访问权限得够,通常设置为public
*
* 在javabean中要求提供一个public的空参构造器,
* 原因:
* 1.便于通过反射,创建运行时类的对象
* 2.便于子类继承此运行时类时,默认调用super()时,保证父类有此构造器。
*
* 造对象就得用构造器造,
*/
Person obj =(Person) clazz.newInstance();
System.out.println(obj);
}
/**
* 下面这个代码,就说明,假如一开始确定好了,代码就不能动态的决定生成的对象。
* 一开始不确定需要生成哪个类的对象,所以需要反射的动态决定我等等需要生成的对象。
* 反射的动态性体会出来了,
*/
@Test
public void test2(){
for (int i = 0; i < 100; i++) {
int num = new Random().nextInt(3);
String classPath ="";
switch (num){
case 0:
classPath ="java.util.Date";
break;
case 1:
//java.sql.Date没有空参构造器,所以报错了
// classPath="java.sql.Date";
classPath ="java.lang.Object";
break;
case 2:
classPath="com.sorrymaker.reflection.Person";
break;
}
Object obj = null;
try {
obj = getInstance(classPath);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(obj);
}
}
/**
* 创建一个指定类的对象
* classPath:指定类的全类名
*/
public Object getInstance(String classPath) throws Exception {
Class clazz =Class.forName(classPath);
return clazz.newInstance();
}
}
获取运行时类的属性
package com.sorrymaker.reflection;
import org.junit.Test;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/**
* 获取当前运行时类的属性结构
*/
public class FieldTest {
@Test
public void test1(){
Class clazz =Person1.class;
//获取内部属性
//.getFields():获取当前运行时类及其所有父类中声明为public访问权限的属性。
Field[] fields = clazz.getFields();
for(Field f:fields){
System.out.println(f);
}
//.getDeclaredFields():获取当前运行时类当中声明的所有属性(不包含父类中声明的属性)。
Field[] declaredFields = clazz.getDeclaredFields();
for(Field f1:declaredFields){
System.out.println(f1);
}
}
/**
* 权限 + 修饰符 + 数据类型 + 变量名
*/
@Test
public void test2(){
Class clazz = Person1.class;
Field[] declaredFields = clazz.getDeclaredFields();
for(Field f:declaredFields){
//1.权限修饰符
int modifier = f.getModifiers();
String str = Modifier.toString(modifier);
System.out.print(str+"\t");
//2.数据类型
Class type = f.getType();
System.out.print(type.getTypeName()+"\t");
//3.变量名
String fName = f.getName();
System.out.println(fName);
}
}
}
获取运行时类的方法结构
package com.sorrymaker.reflection;
import org.junit.Test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* 获取运行时类的方法结构
*/
public class MethodTest {
@Test
public void test1() {
Class clazz = Person1.class;
//.getMethods()获取当前运行时类及其所有父类当中声明为public的方法。
Method[] methods = clazz.getMethods();
for (Method m : methods) {
System.out.println(m);
}
System.out.println();
//.getDeclaredMethods()获取当前运行时类当中声明的所有方法。(不包含父类中声明的)
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method dm : declaredMethods) {
System.out.println(dm);
}
}
/**
* @Xxx 权限修饰符 返回值类型 方法名(参数类型1 形参名1,...)thorows XxxException{}
*/
@Test
public void test2() {
//1.获取方法声明的注解
Class clazz = Person1.class;
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method dm : declaredMethods) {
//1.获取方法声明的注解
//注解可以写很多个,所以是个数组
Annotation[] annotations = dm.getAnnotations();
for (Annotation a : annotations) {
System.out.println(a);
}
//2.权限修饰符
System.out.print(Modifier.toString(dm.getModifiers()) + "\t");
//3.返回值类型
System.out.print(dm.getReturnType().getName() + "\t");
//4.方法名
System.out.print(dm.getName());
System.out.print("(");
//5.形参列表
Class[] parameterTypes = dm.getParameterTypes();
if (!(parameterTypes == null && parameterTypes.length == 0)) {
for (int i = 0; i < parameterTypes.length; i++) {
if (i == parameterTypes.length - 1) {
System.out.print(parameterTypes[