1.11(java高级特性)反射

反射(reflection)

万事万物皆对象:学完反射进一步体会到了。

上面的网络编程连URL都可以做对象。

概念

Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期 借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内 部属性及方法。

加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个 类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可 以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看 到类的结构,所以,我们形象的称之为:反射。

在这里插入图片描述

动态语言VS静态语言

动态语言

是一类在运行时可以改变其结构的语言:

例如新的函数、对象、甚至代码可以 被引进,已有的函数可以被删除或是其他结构上的变化。通俗点说就是在运 行时代码可以根据某些条件改变自身结构。

主要动态语言:Object-C、C#、JavaScript、PHP、Python、Erlang。

静态语言

与动态语言相对应的,运行时结构不可变的语言就是静态语言。

如Java、C、 C++。

Java不是动态语言

但Java可以称之为“准动态语言”。即Java有一定的动 态性,我们可以利用反射机制、字节码操作获得类似动态语言的特性。 Java的动态性让编程的时候更加灵活!

java反射提供的功能
  1. 在运行时判断任意一个对象所属的类
  2. 在运行时构造任意一个类的对象
  3. 在运行时判断任意一个类所具有的成员变量和方法
  4. 在运行时获取泛型信息
  5. 在运行时调用任意一个对象的成员变量和方法
  6. 在运行时处理注解
  7. 生成动态代理
反射主要的类
  1. java.lang.Class:代表一个类
  2. java.lang.reflect.Method:代表类的方法
  3. java.lang.reflect.Field:代表类的成员变量
  4. java.lang.reflect.Constructor:代表类的构造器

反射我看来都是各种API的操作

通过(Class)(Method)(Field)(构造)等的API来完成运行时的java创建对象,修改属性,运行函数等的操作。

Class类

在Object类中定义了以下的方法,此方法 将被所有子类继承:

public final Class getClass()

该方法可以获取一个Class类,可以通过找个Class类从而获取该类下的属性和方法

在这里插入图片描述

获取类实例

想要操作一个类,首先就是获取找个类的类实例

获取Class实例

java程序中获得Class实例通常有如下3中方式,可以根据实际情况灵活选择

调用类或接口实例的getClass()方法

  1. getClass()方法是java.lang.Object类中的一个方法
  2. 所有的类和接口的实例都可以调用这个方法,该方法会返回该实例的所数类型所对应的Class实例
//创建一个Student类用来作为反射的演示
public class Student {

    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

   public static void main(String[] args) {
//        创建学生类的对象
        Student student = new Student();
//        通过学生类对象获取Class实例
        Class aClass = student.getClass();
        System.out.println("我是什么类实例:"+aClass.getName());
    }

在这里插入图片描述

调用类或接口的class属性

  1. 在某些类或接口没有实例的情况下,可以通过其class属性获得对应的Class实例
  2. 这种方式需要在编译器就知道类或接口名称
 public static void main(String[] args) {

//        直接通过类的静态属性class获取类实例
        Class<Student> studentClass = Student.class;
        System.out.println("我是什么类实例:"+studentClass.getName());
    }

结果同上

使用Class.forName()方法

若编译时候无法确认具体类型,需要程序在运行时候根据情况来加载

可以使用Class类的forName()

该方法是静态方法,需要传入字符串参数,该字符串的参数是某个类的完全限定类名,包括包名(相当于路径了)

  public static void main(String[] args) {

        try {
//            通过Class类静态方法指定类路径获取指定Student类实例
            Class aClass = Class.forName("Reflection.Student");
            System.out.println("我是什么类实例:"+aClass.getName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

获取到类实例之后,可以调用Class方法进行获取类实例的信息

Class的常用方法

方法返回值说明
getName()String以字符串形式返回类型的名称(类名)
getSimpleName()String一字符串形式返回该类的简称
getPackage()Package获取该类所在包
getSuperclass()Class返回该类的父类
getInterfaces()Class[]返回该类实现的接口
getModifiers()int返回该类型所有修饰符 由public,private,protected等对应的int常量组成 返回整数使用Modifier工具进行解码,判断访问修饰符的组成
getDeclaredClasses()Class[]返回该类型中包含的全部内部类的Class实例
getDeclaringClass()class返回该类型中的外部类的Class实例
newInstanceObject通过类实例创建对象

动态创建对象的两种方式

  1. 通过类实例的newInstance
  2. 通过构造函数的newInstance

Modifier(修饰符类)

该类表示的是修饰符类。

每个修饰符都对应Modifier的一个静态常量属性

在这里插入图片描述

根据其他反射API的getModifiers()来判断访问修饰符

Constructor(构造函数)

想要创建一个类的对象离不开构造函数。

获取构造函数

我们可以通过Class实例来获取构造函数对象,从而创建对象

返回值方法名说明
ConstructorgetConstructor(Class…params)返回该类型指定参数列表的public构造函数 构造函数的参数列表为params eg:Constructor co = 类实例.getConstructor(String name,list.class)
Constructor[]getConstructors()返回该类型的所有public构造方法
ConstructorgetDeclaredConstructor(Class…params)返回该类型指定参数列表的构造函数,返回类型不限
Constructor[]getDeclaredConstructors()返回该类型的所有构造函数访问级别不限

Constructor的常用方法

方法描述
public int getModifiers()//得到构造方法的修饰符
public String getName()//得到构造方法的名称
public Class<?>[] getParameterTypes()//得到构造方法中参数的类型
public String toString()//返回此构造方法的信息
public T newInstance(Object.class…initargs)//向构造方法中传递参数,实例化对象

示例

 public static void main(String[] args) throws Exception {

//        通过Student类的class属性获取指定的类实例
        Class studentClass = Student.class;


//            通过类实例获取构造函数
        Constructor constructor = studentClass.getConstructor();
        System.out.println("构造函数名字:" + constructor.getName());
        System.out.println("构造函数的访问修饰符:" + constructor.getModifiers());

//        通过Constructor创建对象
        Object stu = constructor.newInstance();
        System.out.println("该对象是否属于Student类型"+ (stu instanceof Student));

    }

在这里插入图片描述

Field(属性类)

获取对应类型包括的属性的方法,通过反射获取类实例的属性信息

获取属性

返回值方法名描述
FieIdgetFieId(String name)返回该类型中指定名称为public属性,name参数为指定属性名称、 eg:类实例.getFieId(“age”) 获得类的age属性
FieId[]getFieIds()返回该类型中所有的publi修饰的
FieIdgetDeclaredFieId(String name)返回该类型中指定名称的属性,与访问修饰符无关
FieId[]getDeclaredFieIds()返回该类型中全部属性,与属性访问修饰符无关

Field常用的方法

返回值方法名描述
StringgetName()获取属性的名
StringgetType()获取属性的数据类型(int,String等)

示例

 public static void main(String[] args) throws Exception {
        //        通过Student类的class属性获取指定的类实例
        Class studentClass = Student.class;

//        获取指定的属性
//        不加上DeclareField的就是找public修饰的
        Field name = studentClass.getDeclaredField("name");

        System.out.println("属性的名字是:"+name.getName());
        System.out.println("属性的类型是:"+name.getType());
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lOoijajj-1637986761777)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20211127114225257.png)]

Field的操作属性API

返回值方法名描述
xxxgetXXX(Object obj)xxx表示8中基本数据类型之一 obj表示该属性所在类的实例(对象)
Objectget(Object obj)以Object类型返回obj中相关属性的值
voidsetXxx(Object obj,xxx val)将Obj中相关属性的值设置为val,Xxx为8中基本数据类型之一
voidset(Object obj,Object val)将Obj中相关属性的值设置为val
voidsetAccessible(boolean flag)对相关属性设置访问权限,设置为true可以禁止java语言访问检查(就是可以访问)

Method(方法类)

获取方法

返回值方法名描述
MethodgetMethod(String name,Class params)返回该实例中指定public方法,name参数用于指定方法的名称,params表示的指定的参数列表
Method[]getMethods()返回该类实例中的public方法
MethodgetDeclaredMethod(String name,Class params)返回该类实例指定方法,与方法访问修饰符无关
Method[]getDeclaredMethods()返回该类实例中的全部方法

Method常见的方法

返回值方法名描述
StringgetName()获取方法名
StringgetReturnType()获取返回值类型
Class[]getParameterTypes()获取参数列表
intgetModifiers()获取访问修饰符
ClassgetDeclaringClass()获取方法所属与的接口或方法
Class[]getExceptionTypes()获取该方法抛出的异常

示例

下面都是基本的API调用。

只要思想不滑坡,利用这些API就可以做很多java动态代码

Method调用函数

Objectinvoke(Object obj ,Object args)
  1. obj是执行该方法的对象,表示的就是实例(对象)
  2. args是执行时候带入的参数
  3. 调用者就是方法,表示obj调用这个方法带入arge参数
  4. 若Method是静态方法,则obj可以为null
  5. args也可以是null

这一篇文章没有安装硅谷的写,是自己学习中的总结。

反射这一章节讲述的就是API。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值