栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java反射入门

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java反射入门

反射入门

什么是反射机制?

在方法区存在这么一些对象,叫做类对象,他们表述了我们写的所有的类,当我们new对象时会根据这些类对象,并调用其构造方法为我们创建实例
首先大家应该先了解两个概念,编译期和运行期,编译期就是编译器帮你把源代码翻译成机器能识别的代码,比如编译器把java代码编译成jvm识别的字节码文件,而运行期指的是将可执行文件交给操作系统去执行。JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为ava语言的反射机制
筒单的说一个类有多个组成部分,例如:成员变量,方法,构造方法等。反射就是加载类,并解剖出类的各个组成部分。

Java反射机制主要提供了以下功能:
  • 在运行时判断任意个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时判断任意一个类所具有的成员变量和方法;
  • 在运行时调用任意一个对象成员的变量和方法;
  • #ff531a生成动态代理
  • 在运行时处理注解
  • 在运行时获取泛型信息
反射相关的主要API
API 名称代表含义
Java.lang.class代表一个类
java.lang.reflect.Method代表类的方法
java.lang.reflect.Field代表类的成员变量
java.lang.reflect.Constructor代表类的构造器
new和反射创建有什么区别呢?

new: 静态编译,在编译期就将模块编译进来,执行该字节码文件,所有的模块都被加载;
**反射:动态编译,**编译期没有加载,等到模块被调用时才加载;

获取CLASS类对象的方法

反射机制可以获取任意类实例化对象(等价于new)
1.利用Object类中提供的getClass()方法获取实例化对象

类名称 对象名称=new 类名称();
Class 另一个对象名称=对象名称.getClass(); Member member=new Member(); Class memberclass=member.getClass();

2.使用”类.class“形式获取指定类或接口的Class实例化对象。

Class 对象名称=类名称.class; Class memberclass=Member.class;

3.使用Class类内部提供的forName()方法根据类的完整名称获取实例化对象

Class 对象名称=Class.forName(“包名+类名”);
Class memberclass=Class.forName(“包名+类名”);

4.通过类的加载器ClassLoader classLoader = this.getClass().getClassLoader();
String className = “java.util.commons”;
Class claz = classLoader.loadClass(className);

T和Class以及Class的理解

单独的T 代表一个类型
而 Class和Class代表这个类型所对应的类 Class在实例化的时候,T要替换成具体类Class它是个通配泛型,?可以代表任何类型

反射Class类实例化对象 Java中什么叫做实例化
class A {
    int i;
}
//这里A就是一个类而对象就是一个类的具体的某一个,如:A a1 = new A();A a2 = new A();a1 a2都是对象而创建对象的过程就叫实例化因此有时候我们也将对象叫做一个类的实例。
//通过Class对象的方法getDeclaredConstructor()中的newInstance()获取实例化对象(通过反射来创建对象)前提:类型中必须有默认的构造方法。
package com.zsq;
class Member{
    public Member() {
        System.out.println("【构造方法】实例化Member类对象。");
    }

    @Override
    public String toString() {
        return "【toString覆写】";
    }
}
public class JavaReflectDemo {
    public static void main(String[] args)  throws Exception{
        //获取Class类实例化对象
        Class clazz= Class.forName("com.zsq.Member");
        //JDK1.9后提倡使用实例化对象
        //  Object obj=clazz.newInstance();JDK1.9前可以使用
        Object obj=clazz.getDeclaredConstructor().newInstance();
        //对象输出
        System.out.println(obj);
    }
}



本程序在获取 Member类实例化对象时并没有使用关键字new,而是基于反射机制实现了对象实例化,即按照此类结构只要设置了正确的类名称,字符串就可以自动调用无参构造方法指定类的实例化对象。
本程序中使用的反射实例化方式为 clazz.getDeclaredConstructor().newInstance(),这段代码的核心意义在于:获取指定类提供的无参构造方法并进行对象实例化,得到的对象是一个Object对象。,但是需要注意的是,这类操作是从JDK1.9后提倡使用的,而在JDK1.9前可以直接使用Class类内部提的 **new Instance()得到对象类型已经弃用(只能调用无参构造函数)**方实例化对象.

反射获取类结构信息

在反射机制的处理之中不仅仅只是一个实例化对象的处理操作,更多的情况下还有类的组成结构操作(父类、父接口、包、属性、方法)。

变量和类型方法描述
软件包getPackage()获取此类的包。
getSuperclass()获取继承父类
[]getInterfaces()返回由此对象表示的类或接口直接实现的接口。
//定义父接口
interface IMessageService {
    public void send();
}

//定义父接口
interface IChannelService {
    public boolean connect();
}

//定义抽象类
abstract class AbstractBase {

}

class Mail extends AbstractBase implements IMessageService, IChannelService {
    //信息发送
    @Override
    public void send() {
        if (this.connect()) {
            System.out.println("【信息发送】");
        }
    }

    //获取连接状态
    @Override
    public boolean connect() {
        return true;
    }
}

public class JavaReflectDemo {
    public static void main(String[] args) {
        //获取指定类的Class对象
        Class cls = Mail.class;
        //获取指定类的包定义
        Package pack = cls.getPackage();
        //获取包名称
        System.out.println(pack.getName());
        //获取父类对象
        Class parent = cls.getSuperclass();
        //父类信息
        System.out.println(parent.getName());
        //父类信息
        System.out.println(parent.getSuperclass().getName());
        //获取接口信息
        Class[] clazz = cls.getInterfaces();
        for (Class temp : clazz) {
            System.out.println(temp.getName());
        }
    }
}

运行结果:

反射调用构造方法

构造方法是类的重要组成部分,也是实例化对象时必须调用的方法,在Class类可以通过下表获取构造方法的相关信息

变量和类型方法描述
Constructor[]getDeclaredConstructors()返回构造器对象的数组,获取指定类中的所有构造函数。
ConstructorgetDeclaredConstructor(类… parameterTypes)返回一个构造器对象,获取指定参数类型所表示的类或接口的指定构造函数。
Constructor[]getConstructors()返回一个包含构造器对象的数组,获取类中所有的public权限的构造函数。
ConstructorgetConstructor(类… parameterTypes)返回一个包含构造器对象的数组,获取指定参数类型并且访问权限为public的构造方法

使用Class类获取的所有构造方法都是通过java.lang.reflect.Constructor类的对象来表示。它常有的方法有如下表
构造器Constructor类常用的方法

变量和类型方法描述
TnewInstance(Object… initargs)调用构造方法传入指定参数进行对象实例化
StringgetName()获取构造方法名称(类,接口,数组类,基本类型或void)
Type[]getGenericInterfaces()获取接口的泛型类型
TypegetGenericSuperclass()得到父类的泛型类型
[]getInterfaces()返回由此对象表示的类或接口直接实现的接口。
AgetAnnotation(类 annotationClass)获取全部生命的注解
TnewInstance()**已过时。**可以根据传入的参数,调用 任意构造构造函数。
package com.zsq;

import java.lang.reflect.Constructor;

class Mail{
    private String msg;

    public Mail() {
    }

    public Mail(String msg) {
        this.msg=msg;
        System.out.println("【构造方法】调用Mail类单参构造方法,实例化对象");
    }

    @Override
    public String toString() {
        return "【toString()覆写】消息内容:"+this.msg;
    }
}
public class JavaReflectDemo {
    public static void main(String[] args)throws Exception {
        //获取指定类的Class对象
        Class cls = Mail.class;
        //获取该类全部public权限的构造方法
      Constructor[] constructors=cls.getConstructors();
      for(Constructorcons:constructors){
          System.out.println(cons);
      }
        //获取单参构造方法并且参数类型为String的构造方法对象实例
        Constructorcons=cls.getDeclaredConstructor(String.class);
        //调用单参构造实例化对象
        Object object=cons.newInstance("嘻嘻");
        
        System.out.println(object);
    }
}

反射调用方法

每个类都有不同的功能,所有的功能都可以通过方法进行定义。在Java中除了通过具体的实例化对象实现方法调用外(即new ),也可以利用反射基于实例化对象的形式实现方法调用。在 Class类中提供如下表所示的方法获取类中的方法信息。

变量和类型方法描述
Method[]getDeclaredMethods()获取一个类中所有定义的方法(包括public,protected,default(package)访问和私有方法但不包括继承的方法)
MethodgetDeclaredMethod(String name, 类… parameterTypes)获取一个类中指定名称与指定参数类型的方法
Method[]getMethods()获取一个类中所有public类型的方法
MethodgetMethod(String name, 类… parameterTypes)获取类中指定名称与指定参数类型的public方法

通过 Class类获取的每一个方法信息都使用 Java. lang. reflect. Method类实例描述,通过该类实例可以获取方法的相关信息,也可以实现方法的反射调用。 Method类常用方法如下表所示。

变量和类型方法描述
Objectinvoke(Object obj, Object… args)方法调用,obj -从中调用底层方法的对象(简单的说就是调用谁的方法用谁的对象)。args - 用于方法调用的参数。等价于“实例化对象.方法“
getReturnType()args - 用于方法调用的参数获取方法返回值类型
StringgetName()获取构造方法名称
Type[]getGenericParameterTypes()获取构造方法的参数类型
Type[]getGenericExceptionTypes()获取构造方法抛出的异常类型
intgetParameterCount()获取构造方法的参数个数
TgetAnnotation(类 annotationClass)获取全部声明的Annotation
package com.zsq;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

class Member{
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class JavaReflectDemo {
    public static void main(String[] args)throws Exception {
        //获取指定类的Class对象
        Class cls = Member.class;
        //设置内容
        String value="大胆刁民";
        //获取所有无参构造方法
        Constructorcons=cls.getDeclaredConstructor();
        //调用无参构造并实例化对象
        Object object=cons.newInstance();
        //反射调用方法需要明确知道方法的名称以及方法的参数类型
        String setMethodName="setName";                 //方法名称
        //获取指定名称以及类型的方法
        Method setMethod=cls.getDeclaredMethod(setMethodName,String.class);
        //等价于对象。对象.setName(value)
        setMethod.invoke(object,value);
        String getMethodName="getName";                 //方法名称
        //获取指定的方法
        Method getMethod=cls.getDeclaredMethod(getMethodName);
        //等价于  System.out.println(对象.getName)
        System.out.println(getMethod.invoke(object));
    }
}

反射调用成员属性

字段(field),通常叫做“类成员”,或 "类成员变量”,有时也叫“域”,理解为“数据成员”,用来承载数据的
Class获取成员属性操作的方法

变量和类型方法描述
Field[]getDeclaredFields()获取本类全部成员信息
FieldgetDeclaredField(String name)获取指定成员属性信息
Field[]getFields()获取父类中全部public成员信息
FieldgetField(String name)获取父类中定义的全部public成员信息

反射中成员通过java.lang.reflect.Field实例描述,Field类常用方法如下:

变量和类型方法描述
getType()获取成员属性类型
voidset(Object obj, Object value)设置成员属性内容 obj - 应修改其字段的对象,value -用于领域的新值 obj被修改
Objectget(Object obj)获取成员属性内容
intgetModifiers)获取成员属性修饰符
voidsetAccessible(boolean flag)设置成员属性可见性,让我们在用反射时访问私有变量
package com.zsq;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

class Member {
    private String name;
}

public class JavaReflectDemo {
    public static void main(String[] args) throws Exception {
        //获取指定类的Class对象
        Class cls = Member.class;
        //获取无参构造方法的构造方法对象实例
        Constructor cons=cls.getDeclaredConstructor();
        //调用无参构造实例化对象
        Object object=cons.newInstance();
        //获取指定名称成员属性
        Field nameField=cls.getDeclaredField("name");         
        
        nameField.setAccessible(true);         //设置属性内容
        nameField.set(object,"还不下跪");         //获取属性内容
        System.out.println(nameField.get(object));
        // 本程序直接进行 Member类中name成员属性的操作,由于name属性使用 private封装,所以在进行属性内容设置相取得前需要使用 setAccessible (true) 方法设置其为可见.
    }
}


在实际项目开发中很少直接通过反射来进行成员属性操作,而一般都会通过相应的setr、getr方法来操成员属性,所以以上的代码只作为Field类的使用特点进行说明。但是需要注意的是,Field类中获取成员属性类型的 get Type()方法在实际开发中使用较多,可以通过其来确定属性类型。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/855538.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号