java基础总结(反射详解)

这里我单独拎出来总结反射,反射很重要,后面的底层框架源码中非常多使用反射,这里是鄙人浅薄之见,有错误希望大家指出!!!

十、反射

1、何谓反射?

反射就是通过Class类对象获取class的信息的方法

反射赋予了我们在运行是分析类以及执行类中方法成员的能力

通过反射我们可以获取任意一个类的属性和方法,也可以使用这个类的方法和属性。

2、#反射的优缺点?

优点:提高了灵活性和,为各种框架提供开箱即用的方法提供了便利(动态的创建和使用对象)

缺点:降低了安全性,因为它可以避过泛型的类型安全检查(泛型类型安全检查是在编译的阶段,而反射可以在运行阶段,因此可以避过),降低安全性,同时反射的性能相对差一点(解释型语言)。

3、反射的应用场景

反射在各类框架和底层原理中使用的非常多,框架中有需要使用了动态代理的功能,而动态代理机制的实现还需要以来反射,

同时注解也使用了反射。

这是因为可以基于反射去分析类,我们可以获取类上,方法上,属性上的注解。

4、反射详解(Class类和class解析,获取Class的四种方式)

1)Class类和class解析

首先说一下这个Class是什么,Class是类,当jvm加载一个类时,会在内存中创建这个类的Class对象,一个类在堆内存中只有一个对应的Class类对象,而这个类对象包含了这个类的所有信息,我们可以通过这个Class获取这个类的所有信息,因此在操作反射的时候都是先获取类,然后再进行相应的操作。

类加载和反射机制

反射机制是java实现动态语言的关键,也就是使用反射实现类的动态加载

静态加载:指的是在编译期间就加载相关的类,如果不存在相关的类就报错

动态加载:指的是在运行期间加载相关的类,如果运行时未使用到该类也不会报错

类加载的时机:

静态加载时机:

1、使用new新创建一个对象时,该类会被加载

2、当调用类中的静态成员时,会加载该类

3、当子类被加载时,超类也会被加载

动态加载的时机:

1、使用反射时,在程序运行中使用到哪个类,哪个类才会被加载

类加载过程

在这里插入图片描述

准备阶段会给静态成员赋默认值,到了初始化阶段会赋初值。

Class类的一些注意点:

1、Class类也是一个类(class),他的名字就叫Class

2、Class类对象时jvm在加载类的时候自动创建的

3、在堆内存中,一个类的Class类对象最多只会有一个,因为类只加载一次

4、每个类实例对象都会知道自己的Class类对象

5、每个Class类对象都知道对应类的所有的信息

6、存放在方法区域中

这里需要注意除了int等基本的数据类型,其他都属于类(包括接口interface)

因此类和接口本质上都是数据类型

而每个class都是动态加载的,当jvm第一次读取到class的时候,才会加载到内存

每加载一种class,此时jvm都会为其创建一个Class类对象,将两者关联起来,注意这里的Class其实是一个名字为Class的类(class)。

public final class Class {

private Class() {}

}

每个Class都指向一个数据类型(class或者接口)

┌───────────────────────────┐ │ Class Instance │──────> String ├───────────────────────────┤ │name = "java.lang.String" │ └───────────────────────────┘ ┌───────────────────────────┐ │ Class Instance │──────> Random ├───────────────────────────┤ │name = "java.util.Random" │ └───────────────────────────┘ ┌───────────────────────────┐ │ Class Instance │──────> Runnable ├───────────────────────────┤ │name = "java.lang.Runnable"│ └───────────────────────────┘

并且每一个Class包含了对应的class的全部信息

因此要使用反射,获取class的全部信息,首先需要获取class对应的Class类

2)获取Class的四种方式

1、对应已知类名的类或者基本数据类型的类,可以直接使用静态成员变量class来获取

Class cls = String.class;// class 是 String 类中的一个静态变量

2、对于类的实例对象,可以使用getClass()来获取Class类对象

String s = "Hello"; Class cls = s.getClass();// 调用 String类对象 s的 getClass() 方法获取

3、如果知道类的路径名,可以使用Class.forName(路径名)来获取Class类

Class cls = Class.forName("java.lang.String");// java.lang.String 是 String 类的完整类名

4、可以通过类的加载器来获取Class类,传入类路径

ClassLoader.getSystemClassLoader().loadClass("cn.javaguide.TargetObject");

5、如何操作类

1)字段:获取字段值、设置字段值

如果需要访问字段有以下四种方法:

Field getField(name):根据字段名获取某个 public 的 field(包括父类)

Field getDeclaredField(name):根据字段名获取当前类的某个 field(不包括父类)

Field[] getFields():获取所有 public 的 field(包括父类)

Field[] getDeclaredFields():获取当前类的所有 field(不包括父类)

一个Field对象包含了以下信息:

1、字段的名称,通过getName()来获取

2、字段的类型,通过getType()来获取

3、字段的修饰符,通过getModifers()来获取

如果要获取字段值,首先需要获取Class类对象,然后通过以上四种之一的方法获取字段Field,然后在通过get(Object object)来设置字段值(object指的是对象,即获取指定对象的字段值),通过set(Object object,Object value)(第一个object是指定对象,第二个object是值,即设置指定对象的指定字段值)来设置值。

注意如果是设置和获取私有字段的值,此时需要先使用Field.setAccessible(True),来暴力反射,获取权限。

2)成员方法

同上,访问方法有以下四种方法:

Method getMethod(name, Class...):获取某个public的Method(包括父类) Method getDeclaredMethod(name, Class...):获取当前类的某个Method(不包括父类) Method[] getMethods():获取所有public的Method(包括父类) Method[] getDeclaredMethods():获取当前类的所有Method(不包括父类) 一个Method对象中包含了以下信息:

1、方法的名字,getName()

2、方法的返回值类型,getReturnType()

3、方法的参数类型,getParameterType()

4、方法的修饰符,getmodifiers()

调用方法的话则是使用Method.invoke(Object object,xxx.class),第一个object指的是要在哪个实例对象是调用方法,后面是方法参数的类型,如果是调用静态方法,则object为null,即invoke(null,xxx.class),如果调用的是私有的方法,则需要先使用setAcccessible(True)。

如果在多态中,此时调用的方法,应该是子类重写后的方法,这里其实与多态规则相同。

3)构造器

如果单纯使用newInstance()创建实例对象,调用的是public的无参构造方法,因此有极大的限制

因此可以先获得类的构造器,然后再创建对象。

获取构造器的方法同上:

getConstructor(Class...):获取某个public的Constructor; getDeclaredConstructor(Class...):获取某个Constructor; getConstructors():获取所有public的Constructor; getDeclaredConstructors():获取所有Constructor。 因为构造器不能被重写,因此不存在多态的问题。

此时再使用newInstance(Object... parameters)来创建对象就可以使用私有的无参/有参构造器了。

但是如果使用私有的构造器,同样需要先setAccessible(True)。

4)继承方法

通过Class对象可以获取继承关系:

Class getSuperclass():获取父类类型;

Class[] getInterfaces():获取当前类实现的所有接口。

通过Class对象的isAssignableFrom()方法可以判断一个向上转型是否可以实现。

  • 20
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值