Java核心反射机制
基本反射
反射是一种动态类的处理机制,通过 Class类 来实现反射机制;
Class类的基本信息:
- Module java.base
- Package java.lang
- Class Class<T>
- java.lang.Object
- java.lang.Class<T>
以下三种方式获得类的反射,三者都非常重要,牢牢掌握。
一、利用Object类中提供getClass()方法获取实例化对象
- class Member {}
- public class JavaReflectDemo {
- public static void main(String[] args) throws Exception {
- // 【操作特点】需要获取一个类的实例化对象之后才可以获取Class类实例
- Member member = new Member() ; // 实例化Member类对象
- Class<?> clazz = member.getClass() ; // 获取Class类实例化对象
- System.out.println(clazz);
- }
- }
二、使用“类.class”形式
- class Member {}
- public class JavaReflectDemo {
- public static void main(String[] args) throws Exception {
- // 【操作特点】直接通过一个类的完整名称可以获取Class类实例,需要编写import或编写完整类名称
- Class<?> clazz = Member.class ; // 获取Class类实例化对象
- System.out.println(clazz);
- }
- }
三、使用Class类内部提供的forName()方法根据类的完整名称获取实例化对象
- class Member {}
- public class JavaReflectDemo {
- public static void main(String[] args) throws Exception {
- // 【操作特点】通过名称字符串(包.类)可以获取Class类实例,可以不使用import导入
- // 获取Class类实例化对象
- Class<?> clazz = Class.forName("cn.xbhog.demo.Member");
- System.out.println(clazz);
- }
- }
反射获取实例化对象
- package com.xbhog.反射机制;
- class Member{
- public Member() { // 构造方法
- System.out.println("【构造方法】实例化Member类对象.");
- }
- @Override
- public String toString() {
- return "【toString()覆写】博客地址:http://www.cnblogs.com/xbhog";
- }
- }
- public class 反射获取对象 {
- public static void main(String[] args) throws Exception {
- // 获取Class类实例化对象
- Class<?> clazz = Class.forName("com.xbhog.反射机制.Member");
- // 反射机制可以获取任意类实例化对象(等价于关键字“new”),所以返回的类型为Object
- Object obj = clazz.getDeclaredConstructor().newInstance() ;// 实例化对象
- System.out.println(obj);
- }
- }
反射的机制可以更加方便开发者实现解耦和设计;
反射与类操作
在反射机制下,可以自动获取并调用任意一个类中的组成结构(成员属性、方法),使得代码的编写更加灵活。
反射获取类结构
- package com.xbhog.反射机制;
- interface IMessage{
- public void send();
- }
- interface IChannelService{
- public Boolean connect();
- }
- abstract class AbstractBase{}
- public class Mail extends AbstractBase implements IMessage,IChannelService{
- @Override
- public void send() {
- if(this.connect()){
- System.out.println("发送信息成功");
- }
- }
- @Override
- public Boolean connect() {
- return true;
- }
- }
- package com.xbhog.反射机制;
- public class MailTest {
- public static void main(String[] args) {
- Class<Mail> aClass = Mail.class;
- System.out.println(aClass.getPackage()); //获取类的包名
- Class<? super Mail> superclass = aClass.getSuperclass(); //获取父类对象信息
- System.out.println(superclass.getName()); //获取父类名字
- System.out.println(superclass.getSuperclass().getName()); //获取父类的父类的名字
- /*获取接口信息*/
- Class<?>[] interfaces = aClass.getInterfaces();
- for (Class<?> anInterface : interfaces) {
- System.out.println(anInterface.getName());
- }
- }
- }
反射调用构造方法
反射还可以调用构造方法,构造方法是类中的重要组成部分,也是实例化对象时必须调用的方法。
实例:
- import java.lang.reflect.Constructor;
- class Mail {
- private String msg ;
- public Mail() {}// 无参构造
- public Mail(String msg) {// 单参构造
- System.out.println("【构造方法】调用Mail类单参构造方法,实例化对象");
- this.msg = msg ;
- }
- @Override
- public String toString() { // 对象信息
- return "【toString()覆写】消息内容:" + this.msg;
- }
- }
- public class JavaReflectDemo {
- public static void main(String[] args) throws Exception {
- Class<?> cls = Mail.class ; // 获取指定类的Class对象
- Constructor<?>[] constructors = cls.getDeclaredConstructors() ; // 获取全部构造
- for (Constructor<?> cons : constructors) {
- System.out.println(cons);
- }
- // 获取单参构造并且参数类型为String的构造方法对象实例
- Constructor<?> cons = cls.getDeclaredConstructor(String.class) ;
- Object obj = cons.newInstance("www.cnblog.cn/xbhog") ;// 调用单参构造实例化对象
- System.out.println(obj);
- }
- }
反射调用方法
反射机制中除了获取类中的方法定义外,最为重要的功能就是可以利用Method类中的invoke()方法并结合实例化对象(Object类型即可)实现放射的调用。
反射调用类中的setter、getter方法【重点】
- package com.xbhog.反射机制.方法;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
- class Member{
- private String name;
- public void setName(String name){
- this.name = name;
- }
- public String getName(){
- return this.name;
- }
- }
- public class getter_Setter {
- public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
- Class<?> cls = Member.class;
- String value = "xbhog";
- //实例化Member对象
- Object obj = cls.getDeclaredConstructor().newInstance();
- //反射调用方法需要明确的知道方法的名称以及方法中的参数类型
- String setMethodName ="setName";
- Method setmethod = cls.getDeclaredMethod(setMethodName, String.class); //获取指定方法
- setmethod.invoke(obj,value); //对象.setName(value)
- String getMethodName = "getName";
- Method getMethod = cls.getDeclaredMethod(getMethodName); //get没有参数
- System.out.println(getMethod.invoke(obj));//对象.getName();
- }
- }
通过放射实现的方法调用的最大的特点是可以直接利用Object类型的实例化对象进行调用的,但是在获取对象时需要明确的知道方法名称以及方法的参数类型。
Field类的作用
在实际开发中,Field中的getType()方法使用的较多,可以通过其来确定属性的类型
示例:
- import java.lang.reflect.Field;
- class Member{
- private String name;
- public void setName(String name){
- this.name = name;
- }
- public String getName(){
- return this.name;
- }
- }
- public class FIeldDemo {
- public static void main(String[] args) throws Exception {
- //获取Member类
- Class<?> cls = Member.class;
- //实例化
- Object obj = cls.getDeclaredConstructor().newInstance();
- //成员属性name的类型
- Field name = cls.getDeclaredField("name");
- //获取详细信息
- System.out.println(name.getType().getName());
- //获取简略信息
- System.out.println(name.getType().getSimpleName());
- }
- }
结果:
- java.lang.String String