java反射主要从以下几个方面理解

  • 理解 Class 类
  • 理解 Java 的类加载机制
  • 学会使用 ClassLoader 进行类加载
  • 理解反射的机制
  • 掌握 Constructor、Method、Field 类的用法
  • 理解并掌握动态代理

1、理解Class类

Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识,即所谓的RTTI。这项信息纪录了每个对象所属的类。虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类。Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建。
简单解释上面一段话
1、Class类也是类的一种,只是名字和class关键字高度相似。Java是大小写敏感的语言。
2、Class类的对象内容是你创建的类的类型信息,比如你创建一个shapes类,那么,Java会生成一个内容是shapes的Class类的对象。
3、Class类的对象不能像普通类一样,以 new shapes() 的方式创建,它的对象只能由JVM创建,因为这个类没有public构造函数。
4、Class类的作用是运行时提供或获得某个对象的类型信息。

Class原理

所有java类都是继承了object这个类,在object这个类中有一个方法:getclass().这个方法是用来取得该类已经被实例化了的对象的该类的引用,这个引用指向的是Class类的对象。

怎么获取Class对象

1、Class类的forName方法

 Class<?> aClass = Class.forName("com.sl.reflect.Student");

2、对象的getClass()方法

 Student student = new Student();Class<? extends Student> aClass1 = student.getClass();

3、使用类名加.class

 Class classes = Student.class.getClass();

4、通过ClassLoader对象的loadClass()方法

Class<?> aClass2 = ClassLoader.getSystemClassLoader().loadClass("com.sl.reflect.Student");

Class类的常用方法

image.png

敲黑板调用newInstance()方法时,调用的是无参构造器,所以每个类中一定要声明一个无参构造器

ClassLoader加载

类装载器是用来把类(class)装载进 JVM 的。JVM 规范定义了两种类型的类装载器:启动类装载器(bootstrap)和用户自定义装载器(user-defined class loader)。 JVM在运行时会产生3个类加载器组成的初始化加载器层次结构 ,如下图所示:

image.png

        //1、获取系统类的加载器ClassLoader classLoader = ClassLoader.getSystemClassLoader();System.out.println(classLoader);//2. 获取系统类加载器的父类加载器(扩展类加载器,可以获取).classLoader = classLoader.getParent();System.out.println(classLoader);//3. 获取扩展类加载器的父类加载器(引导类加载器,不可获取).classLoader = classLoader.getParent();System.out.println(classLoader);

注意系统类加载器可以加载当前项目src目录下面的所有类,如果文件也放在src下面,也可以用类加载器来加载调用 getResourceAsStream 获取类路径下的文件对应的输入流。

       //文件夹在src下InputStream resourceAsStream = ClassLoader.getSystemClassLoader().getResourceAsStream("text1.txt");//文件夹在包名下InputStream resourceAsStream1 = ClassLoader.getSystemClassLoader().getResourceAsStream("com/sl/reflect/text2.txt");

反射

Java反射机制主要提供了以下功能

  • 在运行时构造任意一个类的对象
  • 在运行时获取任意一个类所具有的成员变量和方法
  • 在运行时调用任意一个对象的方法(属性)
  • 生成动态代理

Student测试类

/*** @author shuliangzhao* @Title: Student* @ProjectName design-parent* @Description: TODO* @date 2019/6/15 23:08*/
public class Student {private String name;private Integer age;public Student() {}public Student(String name,Integer age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}
}

Method类

  public static void testMethod() throws Exception {Class<Student> aClass = (Class<Student>) Class.forName("com.sl.reflect.Student");//1.获取方法// 获取取clazz对应类中的所有方法--方法数组(一)// 不能获取private方法,并且获取从父类继承来的所有方法Method[] methods = aClass.getMethods();for (Method method:methods) {System.out.println(method);}System.out.println("================================");//2.获取方法// 获取取clazz对应类中的所有方法--方法数组(一)// 不能获取private方法,不获取从父类继承来的所有方法Method[] declaredMethods = aClass.getDeclaredMethods();for (Method method:declaredMethods) {System.out.println(method);}System.out.println("=================================");//  1.3.获取指定的方法//  需要参数名称和参数列表,无参则不需要写//  对于方法public void setName(String name) {  }Method method = aClass.getDeclaredMethod("setName", String.class);System.out.println(method);//  而对于方法public void setAge(int age) {  }method = aClass.getDeclaredMethod("setAge", Integer.class);System.out.println(method);//  这样写是获取不到的,如果方法的参数类型是int型//  如果方法用于反射,那么要么int类型写成Integer: public void setAge(Integer age) {  }//  要么获取方法的参数写成int.class//2.执行方法//  invoke第一个参数表示执行哪个对象的方法,剩下的参数是执行方法时需要传入的参数Object obje = aClass.newInstance();method.invoke(obje,2);//如果一个方法是私有方法,第三步是可以获取到的,但是这一步却不能执行//私有方法的执行,必须在调用invoke之前加上一句method.setAccessible(true);}/***  把类对象和类方法名作为参数,执行方法**  把全类名和方法名作为参数,执行方法*  可变参数可以放数组* @param obj: 方法执行的那个对象.* @param methodName: 类的一个方法的方法名. 该方法也可能是私有方法.* @param args: 调用该方法需要传入的参数* @return: 调用方法后的返回值**/public Object invoke(Object obj, String methodName, Object ... args) throws Exception{//1. 获取 Method 对象//   因为getMethod的参数为Class列表类型,所以要把参数args转化为对应的Class类型。Class [] parameterTypes = new Class[args.length];for(int i = 0; i < args.length; i++){parameterTypes[i] = args[i].getClass();System.out.println(parameterTypes[i]);}Method method = obj.getClass().getDeclaredMethod(methodName, parameterTypes);//如果使用getDeclaredMethod,就不能获取父类方法,如果使用getMethod,就不能获取私有方法////2. 执行 Method 方法//3. 返回方法的返回值return method.invoke(obj, args);}

Field类

public static void testField() throws Exception {Class<Student> aClass = (Class<Student>) Class.forName("com.sl.reflect.Student");//1.获取字段//  1.1 获取所有字段 -- 字段数组//     可以获取公用和私有的所有字段,但不能获取父类字段Field[] declaredFields = aClass.getDeclaredFields();for (Field field:declaredFields) {System.out.println(field);}System.out.println("=============================");//  1.2获取指定字段Field field = aClass.getDeclaredField("name");System.out.println(field.getName());System.out.println("==============================");Student student = new Student();//如果字段是私有的,不管是读值还是写值,都必须先调用setAccessible(true)方法field.setAccessible(true);student.setAge(1);student.setName("张三");//2.使用字段//  2.1获取指定对象的指定字段的值Object o = field.get(student);System.out.println(o);System.out.println("==========================");//  2.2设置指定对象的指定对象Field值field.set(student, "DEF");System.out.println(student.getName());}

Constructor类

 public static void testConstructor() throws Exception{Class<Student> aClass = (Class<Student>) Class.forName("com.sl.reflect.Student");//1. 获取 Constructor 对象//   1.1 获取全部Constructor<?>[] constructors = aClass.getConstructors();for (Constructor constructor:constructors) {System.out.println(constructor);}System.out.println("============================");//  1.2获取某一个,需要参数列表Constructor<Student> constructor = aClass.getConstructor(String.class, Integer.class);System.out.println(constructor);System.out.println("============================");//2. 调用构造器的 newInstance() 方法创建对象Object obj = constructor.newInstance("zhagn", 1);}

Annotation

@Retention(RetentionPolicy.RUNTIME)
@Target(value={ElementType.METHOD})
public @interface AgeValidator {public int min();public int max();
}public static void testAnnotation() throws Exception{Class<?> aClass = Class.forName("com.sl.reflect.Student");Object o = aClass.newInstance();Method method = aClass.getDeclaredMethod("setAge", Integer.class);int val = 6;AgeValidator annotation = method.getAnnotation(AgeValidator.class);if (annotation != null) {if (annotation instanceof AgeValidator) {AgeValidator ageValidator =  annotation;if (val < ageValidator.min() || val > ageValidator.max()) {throw new RuntimeException("年龄非法");}}}method.invoke(o,20);System.out.println(o);}

小结

  1. Class: 是一个类; 一个描述类的类.
      封装了描述方法的 Method,
    描述字段的 Filed,
    描述构造器的 Constructor 等属性.
  2. 如何得到 Class 对象:
      2.1 Person.class
      2.2 person.getClass()
      2.3 Class.forName("com.atguigu.javase.Person")
  3. 关于 Method:
      3.1 如何获取 Method:
        1). getDeclaredMethods: 得到 Method 的数组.
        2). getDeclaredMethod(String methondName, Class ... parameterTypes)
      3.2 如何调用 Method
        1). 如果方法时 private 修饰的, 需要先调用 Method 的 setAccessible(true), 使其变为可访问
        2). method.invoke(obj, Object ... args);
  4. 关于 Field:
      4.1 如何获取 Field: getField(String fieldName)
      4.2 如何获取 Field 的值:
        1). setAccessible(true)
        2). field.get(Object obj)
      4.3 如何设置 Field 的值:
        field.set(Obejct obj, Object val)
  5. 了解 Constructor 和 Annotation
  6. 反射和泛型.
      6.1 getGenericSuperClass: 获取带泛型参数的父类
      6.2 Type 的子接口: ParameterizedType
      6.3 可以调用 ParameterizedType 的 Type[] getActualTypeArguments() 获取泛型参数的数组.

java 反射 Constructor、Method、Field 基本用法相关推荐

  1. Java反射 Constructor类

    Java反射 Constructor类 Java通过反射可以获取构造方法,和使用构造方法创造对象. 在网上找了一个比较好理解的例子来弄清楚Constructor类. public Constructo ...

  2. 反射机制----Method,Field,Constructor

    public class ClassUtil {/** 打印类的信息,包括类的成员函数,成员变量*/public static void printClassMessage(Object obj){/ ...

  3. java short字段_Java Field setShort()用法及代码示例

    java.lang.reflect.Field的setShort()方法用于将字段的值设置为指定对象的缩写.当您需要将对象的字段值设置为短时,可以使用此方法在对象上设置值. 用法: public vo ...

  4. java boolean例子_Java Field setBoolean()用法及代码示例

    java.lang.reflect.Field的setBoolean()方法用于将字段的值设置为指定对象上的布尔值.当需要将对象的字段的值设置为布尔值时,可以使用此方法在对象上设置值. 用法: pub ...

  5. Java反射使用的Field类介绍

    一.Field类的作用 Field是一个类,位于java.lang.reflect包下.在Java反射中Field类描述的是类的属性信息,功能包括 (1)获取当前对象的成员变量的类型 (2)对成员变量 ...

  6. JAVA反射系列之Field,java.lang.reflect.Field使用获取方法。

    2019独角兽企业重金招聘Python工程师标准>>> 首先必须明一点 Field类主要是用来辅助获取和操作类的属性的! 1.怎么通过反射获取类的属性 先来看JDK提供的方法有如下几 ...

  7. java 反射获取字段field

    为了下面测试先建对象 package com.sakyoka.test.person;import java.lang.reflect.Field;public class Person {priva ...

  8. Java 反射机制[Field反射]

    Java 反射机制[Field反射] 1.  反射概念及功能 反射就是把Java类中的各种成分映射成对应的Java类.比如一个Java类中用一个Class类的对象来表示. 一个类中的组成部分分为成员变 ...

  9. Java反射08 : 成员方法Method学习示例

    超级通道: Java泛型学习系列-绪论 java.lang.reflect.Method类提供了用于获取和操作成员方法的静态方法. 1.通过Method可以做什么 通过Method可以做以下事情: 如 ...

最新文章

  1. Linux 2 的 Windows 子系统上发布 CUDA
  2. python 获取 程序运行时间
  3. 在Java中,采用类的默认构造函数构造对象的方法!
  4. oracle用户登录的认证方式
  5. hdu 5497 Inversion(树状数组)
  6. log4j.xml配置文件
  7. php mysql 正则_MySQL 正则表达式
  8. 判断 iframe 是否加载完成的完美方法(转)
  9. Ubuntu下安装LXR
  10. MySQL学习笔记—复制表
  11. K8s与Docker
  12. tab页签切换----bootstrap
  13. 一张图告诉你各地高考成绩查询时间
  14. 记录一次elastic-job分片查询及基础概念理解
  15. 用计算机算cos1,cos计算器(数学三角函数计算器)
  16. linux应用程序开发指南-开发工具介绍
  17. java八大排序算法详解
  18. 电力电子课设日志(已完结)
  19. 任正非的艰难时刻的启示
  20. java面试问题与心得

热门文章

  1. carsim学习笔记5——carsim与simulink联合仿真
  2. Web基础:记录简单个人网站建站过程
  3. 工业用微型计算机(6)-指令系统(3)
  4. access开发精要(12)-文本 和 备注 数据类型格式(1)
  5. 趣学python3(40)--TCP服务器和客户端(socketserver类)
  6. Kaggle知识点:对比学习基础
  7. Python业务分析实战|共享单车数据挖掘
  8. 【竞赛相关】特征/模型存储的5种方法
  9. 温州大学《机器学习》课程课件和视频(四)朴素贝叶斯
  10. 盘点2020国内本科开设人工智能专业高校