一、什么是反射
1、概述
- JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制
2、获取反射class对象的三种方式
- 获取反射对象代码演示
public class 反射对象的创建方式 {
public static void main(String[] args) throws ClassNotFoundException {
Person person = new Student();
//方式一:通过类名获得class对象
Class<Student> c1 = Student.class;
//方式二:通过对象获得class对象
Class<? extends Person> c2 = person.getClass();
//方式三:通过类的全路径获得class对象
Class<?> c3 = Class.forName("com.lc.反射.Student");
//获得父类的类型
Class<? super Student> c5 = c1.getSuperclass();
System.out.println(c5);
}
}
- 运行结果
二、反射操作类的所有信息
- 代码演示
public class 获得类的信息 {
public static void main(String[] args) throws Exception {
//获得类的class对象
Class<?> c1 = Class.forName("com.lc.entity.User");
//获得类的名称(包名+类名)
System.out.println("获得类的名称(包名+类名)------>"+c1.getName());
System.out.println("======================");
//获得类的简单名称(类名)
System.out.println("获得类的简单名称(类名)------>"+c1.getSimpleName());
System.out.println("======================");
//只能获得public属性
Field[] fields = c1.getFields();
for (Field field : fields) {
System.out.println("public属性------>"+field);
}
System.out.println("======================");
//获得所有的属性
Field[] declaredFields = c1.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println("获得所有的属性------>"+declaredField);
}
System.out.println("======================");
//获取指定的属性
Field name = c1.getDeclaredField("name");
System.out.println("获取指定的属性------>"+name);
System.out.println("======================");
//获取本类及其父类的所有的public方法
Method[] methods = c1.getMethods();
for (Method method : methods) {
System.out.println("获取本类及其父类的所有的public方法------->"+method);
}
System.out.println("======================");
//获得本类的所有的方法
Method[] declaredMethods = c1.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println("获得本类的所有的方法-------->"+declaredMethod);
}
System.out.println("======================");
//获取指定的方法
Method getName = c1.getMethod("getName", null);
System.out.println("获取指定的方法------->"+getName);
System.out.println("======================");
//获得public的构造器
Constructor<?>[] constructors = c1.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println("获得public的构造器----->"+constructor);
}
System.out.println("======================");
//获得所有的构造器
Constructor<?>[] declaredConstructors = c1.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println("获得所有的构造器------->"+declaredConstructor);
}
System.out.println("======================");
//获取指定的构造器
Constructor<?> constructor = c1.getConstructor(String.class, int.class, int.class);
System.out.println("获取指定的构造器------->"+constructor);
}
}
- 运行结果
三、反射获取泛型
- 代码演示
//通过反射获取泛型
public class 反射获取泛型 {
public void test01(Map<String, User> map, List<User> list){
System.out.println("test01");
}
public Map<String,User> test02(){
System.out.println("test02");
return null;
}
public static void main(String[] args) throws Exception {
Class c1 = 反射获取泛型.class;
Method method1 = c1.getMethod("test01", Map.class, List.class);
Type[] genericParameterTypes = method1.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.out.println("test01泛型外部类型---->"+genericParameterType);
if (genericParameterType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println("test01泛型内部类型---->"+actualTypeArgument);
}
}
}
Method method2 = c1.getMethod("test02", null);
Type genericParameterTypes1 = method2.getGenericReturnType();
if (genericParameterTypes1 instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericParameterTypes1).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println("test02返回值泛型类型---->"+actualTypeArgument);
}
}
}
}
- 运行结果
四、反射动态的操作对象
- 代码演示
//,通过反射动态的创建对对象
public class 动态的操作对象 {
public static void main(String[] args) throws Exception {
//获得class对象
Class<?> c1 = Class.forName("com.lc.entity.User");
//构造一个对象,本质是调用了类 一个无参构造器
System.out.println("==============================================");
//通过构造器创建对象
Constructor<?> declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
User u = (User) declaredConstructor.newInstance("廖常", 11, 24);
System.out.println("通过构造器创建对象------>"+"姓名:"+u.getName()+"年龄:"+u.getAge()+" ID:"+u.getId());
System.out.println("==============================================");
//通过反射获取方法
User user = (User) c1.newInstance();
Method setName = c1.getMethod("setName", String.class);
setName.invoke(user,"廖常哈哈");
System.out.println("通过反射获取方法------->"+user.getName());
System.out.println("==============================================");
//通过反射操作属性
User user1 = (User) c1.newInstance();
Field name = c1.getDeclaredField("name");
//不能直接操作私有属性,需要关闭程序的安全检测,或者name.setAccessible(true)
name.setAccessible(true);
name.set(user1,"小常常");
System.out.println("反射操作私有属性------->"+user1.getName());
}
}
- 运行结果
五、new对象和反射操作 对象性能测试
- 代码演示
//分析性能问题
public class 性能测试 {
public static void main(String[] args) throws Exception {
test01();
test02();
test03();
}
//普通方式
public static void test01(){
User user = new User();
long start = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
user.getName();
}
long end = System.currentTimeMillis();
System.out.println("普通方式执行10亿次需要----->"+(end-start)+"毫秒");
}
//反射不关闭检测方式
public static void test02() throws Exception {
User user = new User();
long start = System.currentTimeMillis();
Class<? extends User> c1 = user.getClass();
Method getName = c1.getDeclaredMethod("getName", null);
for (int i = 0; i < 1000000000; i++) {
getName.invoke(user,null);
}
long end = System.currentTimeMillis();
System.out.println("反射不关闭检测方式执行10亿次需要----->"+(end-start)+"毫秒");
}
//反射关闭检测方式
public static void test03() throws Exception {
User user = new User();
long start = System.currentTimeMillis();
Class<? extends User> c1 = user.getClass();
Method getName = c1.getDeclaredMethod("getName", null);
getName.setAccessible(true);
for (int i = 0; i < 1000000000; i++) {
getName.invoke(user,null);
}
long end = System.currentTimeMillis();
System.out.println("反射关闭检测方式执行10亿次需要----->"+(end-start)+"毫秒");
}
}
- 运行结果
六、反射操作注解
- 创建一个Stu类
@Table("db_stu")
public class Stu{
@Field(columnName = "db_id",type = "int",length = 10)
private int id;
@Field(columnName = "db_name",type = "varchar",length = 10)
private String name;
@Field(columnName = "db_age",type = "varchar",length = 3)
private int age;
public Stu() {
}
public Stu(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Stu{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
- 创建一个Table注解
//类名注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table{
String value();
}
- 创建一个Field注解
//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Field{
String columnName();
String type();
int length();
}
- 测试
//通过 反射操作注解
public class 反射操作注解 {
public static void main(String[] args) throws Exception {
Class<?> c1 = Class.forName("com.lc.entity.Stu");
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println("获取注解---->"+annotation);
}
//获取注解value的值
Table table = c1.getAnnotation(Table.class);
System.out.println("获取注解value的值----->"+table.value());
//获得指定属性上的注解的值
java.lang.reflect.Field name = c1.getDeclaredField("id");
Field annotation = name.getAnnotation(Field.class);
System.out.println("获得指定属性上的注解的值---->"+annotation.columnName());
System.out.println("获得指定属性上的注解的值---->"+annotation.length());
System.out.println("获得指定属性上的注解的值---->"+annotation.type());
}
}
- 运行结果
七、类加载器
1、什么是类加载器
- Java类加载器是Java运行时环境的一部分,负责动态加载Java类到Java虚拟机的内存空间中。类通常是按需加载,即第一次使用该类时才加载。由于有了类加载器,Java运行时系统不需要知道文件与文件系统
2、类加载器是干什么的
- 类加载器它是在虚拟机中完成的,负责动态加载Java类到Java虚拟机的内存空间中,在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class类的一个实例
3、类加载器的类型
1.启动类加载器,没有父类
2.拓展类加载器由Java语言实现,父类加载器为null
3.系统类加载器,由Java语言实现
4.自定义类加载器,父类加载器肯定为AppClassLoader
4、获取类加载器
- 代码演示
public class 获取类加载器 {
public static void main(String[] args) throws ClassNotFoundException {
//获取系统类的加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println("系统类的加载器------>"+systemClassLoader);
//获取系统类加载器的父类加载器--->扩展类加载器
ClassLoader parent = systemClassLoader.getParent();
System.out.println("父类加载器--->"+parent);
//获取扩展类的父类加载器----->根加载器(c/c++)
ClassLoader grandParent = parent.getParent();
System.out.println("根加载器---->"+grandParent);
//获取当前类的类加载器
ClassLoader classLoader = Class.forName("com.lc.内存分析.获取类加载器").getClassLoader();
System.out.println("当前类的类加载器----->"+classLoader);
}
}
- 运行结果