有关反射的异常:
- InstantiationException 实例化异常:通常由没有构造方法,或没有public构造方法产生的异常,有此异常也会有IllegalAccessException 该异常。
- IllegalAccessException 非法访问异常:通常由访问修饰符不是public产生
- ClassNotFoundException 找不到类异常:通常由路径写错或类名写错产生
一:反射的作用
- 动态的创建一个对象,不需要new创建一个对象(更灵活,忽略访问权限)
- 操作的是运行编译后的对象
在java.lang包下有Reflec类
反射的api
invoke调用
二:反射的运行流程
- 第一步:由Java编译器进行源代码编译,得到相应类的字节码.class文件。
- 第二步:生成class文件之后,通过ClassLoader类加载器加载进内存,Java字节码由JVM执行解释给目标计算机。
- 第三步,目标计算机将结果呈现给我们计算机用户;因此,Java并不是编译机制,而是解释机制.class文件才可以在不同平台上运行加载。
三:利用反射机制获取类的三种方式
第一种:new一个对象,使用如下方式获取
Person person01=new Person();
Class clazz=person01.getClass();
第二种:直接获取
Class clazz=类名.class;
第三种:使用Class.forName(“”)方法
Class clazz=Class.forName("包名.类名");
第四种:使用类加载器的方式获取
ClassLoader classLoader = RelfectTest.class.getClassLoader();
Class<?> clazz = classLoader.loadClass("com.java.Person");
四:利用反射机制获取一个类的构造方法和属性
Class的 newInstance()方法创建对象 创建对象的前提条件:必须要有构造方法,权限必须为public
package com.java;
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class RelfectTest {
@Test
public void Test() {
Person person = new Person("hanmeimei", 20);
person.showAge(161);
System.out.println(person.toString());
}
@Test
public void Test01() throws Exception {
Class clazz = Person.class;
/*通过反射创建对象*/
Constructor cons = clazz.getConstructor(String.class, Integer.class);
//创建运行时实例
Person person = (Person) cons.newInstance("tom", 12);
System.out.println(person.toString());
/*通过反射调用对象指定的属性,方法*/
//调用age属性,调用公共的属性
Field age = clazz.getDeclaredField("age");
//允许调用私有属性和方法
age.setAccessible(true);
age.set(person, 23);
//调用name属性
System.out.println(person.toString());
/*调用公共方法*/
Method showAge = clazz.getDeclaredMethod("showAge", Integer.class);
/*调用方法,invoke调用的意思*/
showAge.invoke(person, 20);
/*调用私有的构造器*/
Constructor cons1 = clazz.getDeclaredConstructor(String.class);
//允许调用私有的属性和方法
cons1.setAccessible(true);
Object person1 = cons1.newInstance("lili");
System.out.println(person1.toString());
//调用私有方法
Method showName = clazz.getDeclaredMethod("showName");
showName.setAccessible(true);
showName.invoke(person1);
}
}
1. 反射动态创建一个对象的应用
public Object getNewInstance(String path) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Class<?> aClass = Class.forName(path);
Object newInstance = aClass.newInstance();
return newInstance;
}
@Test
public void Test04() {
for (int i = 1; i < 100; i++) {
Random random = new Random();
int num = random.nextInt(3);
String path = " ";
switch (num) {
case 0:
path = "java.util.Date";
break;
case 1:
path = "com.java.Person";
break;
case 2:
path = "java.lang.Object";
default:
break;
}
Object newInstance = null;
try {
newInstance = getNewInstance(path);
System.out.println(newInstance);
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.通过反射获取一个类的所有信息(包含private,但不包含父类和实现类)和他的父类实现类的public信息
@Test
public void Test05() {
Class<Person> clazz = Person.class;
//获取所有公共的属性
Field[] fields = clazz.getFields();
for (Field field : fields) {
System.out.println(field);
}
}
@Test
public void Test06() {
Class<Person> clazz = Person.class;
//获取当前实例中所有属性(私有公有全部获取),不包含父类的
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
}
@Test
public void Test07() {
Class<Person> clazz = Person.class;
//获取当前实例中所有属性(私有公有全部获取),不包含父类的
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
//获取权限修饰符
int modifiers = field.getModifiers();
System.out.println(Modifier.toString(modifiers));
//获取数据类型
Class<?> type = field.getType();
System.out.println(type);
//获取变量名
String name = field.getName();
System.out.println(name);
}
}
@Test
public void Test08() {
Class<Person> clazz = Person.class;
//获取当前类的所有公共的方法(包含父类的,实现类的)
Method[] methods = clazz.getMethods();
for (Method method : methods) {
Parameter[] parameters = method.getParameters();
for (Parameter parameter : parameters) {
System.out.println(parameter.getName());
}
}
//获取当前类的所有方法(不包含继承的,实现的,忽略访问权限)
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
}
@Test
public void Test09() {
Class<Person> clazz = Person.class;
//获取当前类的所有方法(不包含继承的,实现的,忽略访问权限)
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
//获取访问修饰符
int modifiers = declaredMethod.getModifiers();
System.out.print(Modifier.toString(modifiers) + "\t");
//获取返回值类型
Class<?> returnType = declaredMethod.getReturnType();
System.out.print(returnType + "\t");
//获取方法名
String name = declaredMethod.getName();
System.out.print(name);
System.out.print("(");
//获取参数类型
Class[] parameterTypes = declaredMethod.getParameterTypes();
String parameterName = "";
Parameter[] parameters = declaredMethod.getParameters();
if (!(parameterTypes == null && parameterTypes.length == 0)) {
for (int i = 0; i < parameterTypes.length; i++) {
for (int j=0;j<parameters.length;j++) {
parameterName = parameters[j].getName();
System.out.print(parameterName);
}
if (i == parameterTypes.length - 1) {
System.out.print(parameterTypes[i].getName() +" "+ parameterName);
break;
}
System.out.print(parameterTypes[i].getName()+" "+parameterName + ",");
}
System.out.print(")");
}
//获取异常
Class<?>[] exceptionTypes = declaredMethod.getExceptionTypes();
if (exceptionTypes.length > 0) {
System.out.print(" throws ");
for (int i = 0; i < exceptionTypes.length; i++) {
String name1 = exceptionTypes[i].getName();
if (i == exceptionTypes.length - 1) {
System.out.print(name1);
break;
}
System.out.print(name1 + ",");
}
}
System.out.println();
}
}
五:Class类的运用(对对象的描述的类)
六:加载配置文件的两种方式
@Test
public void Test02() throws IOException {
/**
* 读取配置文件的方式一,默认在moudle下
* 通过流的方式读取文件
* 优点:只要路径对,可以加载任意位置的文件
*/
//创建配置文件对象
Properties properties=new Properties();
//获取配置文件流
InputStream inputStream = new FileInputStream("src\\main\\resources\\jdbc1.properties");
//加载配置文件
properties.load(inputStream);
/**
* 读取配置文件的方式二
* 使用ClassLoader
* 缺点:默认加载的是src下的文件
*/
ClassLoader classLoader = RelfectTest.class.getClassLoader();
InputStream resourceAsStream = classLoader.getResourceAsStream("jdbc1.properties");
properties.load(resourceAsStream);
//获取配置文件的内容并打印
String user = properties.getProperty("password");
System.out.println(user);
}