Java学习篇之反射

一、认识反射

1.1 反射的概念

1.2 Class对象的三种实例化方式

二、反射与类操作

2.1 取得父类与父接口信息

2.2 调用类中的构造方法

2.3 调用普通方法

2.4 调用类中的属性

三、Java类加载器

3.1 Java类加载器定义

3.2 JDK中内置的3大类加载器

3.3 双亲委派模型

1、双亲委派模型的定义

2、执行流程

3、意义:

4、如果我们自己写一个java.lang.Object类会怎么样呢???


 

一、认识反射

1.1 反射的概念

在Java中,正常情况下,我们要获取一个对象,首先是导入包,然后通过类来创建一个对象的实例,而所谓的反射,就是和正常情况反着类,通过实例化对象,来获取该对象的来源信息

反射操作的核心是Object类中的一个getClass()方法:这个方法返回的是一个Class类的对象,这个对象描述的就是一个类

在反射的世界中,我们看重的不再是一个对象,而是一个对象背后的组成(类,构造方法,普通方法,成员等)

1.2 Class对象的三种实例化方式

  • 任何一个类的Class对象由JVM加载类后产生,用户只能调用指定方法取得该对象(JVM加载类时产生的类的Class对象全局我唯一)
  1. 任何类的对象都可以通过Object类提供的getClass( )对象取得该类的Class对象
  2. "类名称 . class" 可以直接获取该类的Class对象
  3. 调用Class类的静态方法 Class.forName(“包名 .  类名”) 来取得其Cass对象

取得一个类的Class对象后,我们可以通过反射来实例化对象。在Class类中有如下方法:

public T newInstance() throws InstantionException, IllegalAccessException;
// 只能调用该类的无参构造且无参构造的权限必须是public

下面就来看看怎么通过一个对象,获取该对象背后的一些信息...

二、反射与类操作

这里我首先定义了一个People类,对以下方法进行使用,People类结构如下:

2.1 取得父类与父接口信息

  • 取得包名称:getPackage();
  • 取得父类的class对象 getSuperClass();
  • 取得实现的父接口信息:getInterface();

2.2 调用类中的构造方法

  • Construct类提供了实例化对象的方法:newInstance(Object  ... initargs ) ;
  • 取得类中指定参数类型的构造方法
  1. 取得权限为public的构造方法:getConstruct(参数类型);
  2. 取得所有权限的构造方法:getDeclareConstruct(参数类型);

  • 获取所有的构造方法:
  1. 获取权限为public的构造方法:getConstructs() ;
  2. 获取所有权限的构造方法:getDeclaredConstructs() ;

2.3 调用普通方法

  • Method提供了调用类中普通方法的API:invoke(一个Object对象, 方法参数) ;

     invoke的两个参数解释:

  1. 第一个是一个Object类的对象,它是表示用该类的哪一个实例去调用这个方法,传入的参数是一个实例化对象
  2. 第二个参数是一个可变参数,表示的是调用的方法的应该传入的参数
  • 取得类中指定名称的普通方法
  1. 取得权限为public的普通方法:getMethod(方法名);
  2. 取得所有普通方法:getDeclaredMethod(方法名);
  • 取得类中所有普通方法
  1. 取得权限为public的普通方法:getMethods() ;
  2. 取得所有权限的普通方法:getDeclaredMethods() ;

使用案例:

2.4 调用类中的属性

  • 取得类中指定属性
  1. 取得权限为public的属性:getField( 属性 );
  2. 取得所有权限的属性:getDeclaredField ( 属性 ) ;
  • 取得类中所有属性
  1. 取得权限为public的属性:getFileds();
  2. 取得所有权限的属性:getDeclaredFiled();
  • 设置/取得属性值
  1. 设置属性值:set(对象,  值);
  2. 取得对象值:get(对象);

三、Java类加载器

3.1 Java类加载器定义

首先,什么是java类加载器:java类加载器是Java运行环境的一部分,它负责将Java类动态的加载到Java细虚拟机的内存空间中。

把 “通过一个类的全限定名来描述此类的二进制流” 这个动作放在Java虚拟机的外部去实现,以便让程序自己去决定如何获取所需的类,实现这个类的代码模块就叫做类加载器。

3.2 JDK中内置的3大类加载器

  • BooiStrap(启动类加载器)
  1. 由C++实现
  2. 负责将存放于JAVA_HOME\lib目录下的能被JVM识别的类库加载到JVM中
  3. 启动类加载器不能被Java程序直接引用
  • ExtClassLoader(扩展类加载器)
  1. Java语言实现
  2. 负责加载JAVA_HOME\lib\ext目录下的能被JVM识别的类库
  • AppClassLoader(应用程序类加载器)
  1. 负责加载用户路径(classpath)上指定的类库
  2. 如果应用程序中没有自定义类加载器,则此加载器就是Java中默认的加载器

3.3 双亲委派模型

1、双亲委派模型的定义

  • JDK中内置的三种类加载器和用户自定义的类加载器之间的层次关系称为双亲委派模型
  • 在双亲委派模型中,除了最顶层的类加载器之外,其余的类加载器都应该有自己的父类加载器
双亲委派模型
双亲委派模型

2、执行流程

如果一个类加载器收到了一个类加载的请求,它首先不会自己尝试去加载这个类,而是将类加载请求托付给父类加载器去完成,每一个层次的类加载器均是如此。只有当父类加载器无法完成请求时(在自己的搜索范围类没有找到此类),子类才会尝试去自己加载。

3、意义:

双亲委派模型保证了Java程序运行的稳定性。Java基础类库一定由顶层Bootstrap类加载器加载,因此诸如Object等核心类在各种加载环境下都是同一个类

4、如果我们自己写一个java.lang.Object类会怎么样呢???

这样的话,如果你此时手动创建一个java.lang.Object类,Java虚拟机会区分开这两个类,因为Java中原生的java.lang.Object会由Bootstrap ClassLoader加载,而我们自己写的这个类由于前两个类加载器都没有它的路径,就会由Application ClassLoader类加载器去加载,但是如果此时Bootstrap ClassLoader已经加载了java原生的Object类,虚拟机就会发现有两个不同的Object类,就会报错。

同时,如果要比较两个类是否相等,也必须要在同一个类加载器下比较才有意义。

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值