Java反射机制小结

1 Java反射机制概述

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

1.1 Java反射机制提供的功能

Ø运行时判断任意一个对象所属的

Ø运行时构造任意一个类的对象

Ø运行时判断任意一个类所具有的成员变量和方法

Ø运行时调用任意一个对象的成员变量和方法

Ø生成动态代理

2.1 反射相关的主要API

Øjava.lang.Class:代表一个类

Øjava.lang.reflect.Method:代表类的方法

Øjava.lang.reflect.Field:代表类的成员变量

Øjava.lang.reflect.Constructor:代表类的构造方法

 

2 理解Class类并获取Class类的实例

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

●  public final Class getClass()

以上的方法返回值的类型是一个Class类,此类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称。

2.1 Class类

对象照镜子后可以得到的信息:某个的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE 为其保留一个不变Class 类型的对象。一Class 对象包含了特定某个类的有关信息

Class本身也是一个类

Class 对象只能由系统建立对象

一个类JVM 只会有一个Class实例

一个Class对象对应的是一个加载到JVM中的一个.class文件

每个类的实例都会记得自己是由哪个 Class 实例所生成

通过Class可以完整地得到一个类中的完整结构

2.2 常用方法

方法名

功能说明

static Class  forName(String name)

返回指定类名 name Class 对象

Object newInstance()

调用缺省构造函数,返回该Class对象的一个实例

getName()

返回此Class对象所表示的实体(类、接口、数组类、基本类型或void)名称

Class getSuperClass()

返回当前Class对象的父类的Class对象

Class [] getInterfaces()

获取当前Class对象的接口

ClassLoader getClassLoader()

返回该类的类加载器

Class getSuperclass()

返回表示此Class所表示的实体的超类的Class

Constructor[] getConstructors()

返回一个包含某些Constructor对象的数组

Field[] getDeclaredFields()

返回Field对象的一个数组

Method getMethod(String name,Class  …  paramTypes)

返回一个Method对象,此对象的形参类型为paramType

2.3 实例化Class类对象(四种方法)

1前提:若已知具体的类,通过类的class属性获取,该方法

                    最为安全可靠,程序性能最高

       实例Class clazz = String.class;

2前提:已知某个类的实例,调用该实例的getClass()方法

                    Class对象

       实例:Class clazz = “www.yizhihanduxiu.com”.getClass();

3前提:已知一个类的全类名,且该类在类路径下,可通过

       Class类的静态方法forName()获取,可能抛出ClassNotFoundException

       实例:Class clazz = Class.forName(“java.lang.String”);

4)其他方式(不做要求)

ClassLoader cl = this.getClass().getClassLoader();

Class clazz4 = cl.loadClass(“类的全类名”);

3 类的加载与ClassLoader的理解

3.1 类的加载过程

当程序主动使用某个类时,如果该类还未被加载到内存中,则系统会通过如下三个步骤来对该类进行初始化。

3.2 ClassLoader

类加载器是用来把类(class)装载进内存的JVM 规范定义了两种类型的类加载器:启动类加载(bootstrap)和用户自定义加载(user-defined class loader)JVM在运行时会产生3个类加载器组成的初始化加载器层次结构 ,如下图所示:

//1.获取一个系统类加载器
ClassLoader classloader = ClassLoader.getSystemClassLoader();
System.out.println(classloader);
//2.获取系统类加载器的父类加载器,即扩展类加载器
classloader = classloader.getParent();
System.out.println(classloader);
//3.获取扩展类加载器的父类加载器,即引导类加载器
classloader = classloader.getParent();
System.out.println(classloader);
//4.测试当前类由哪个类加载器进行加载
classloader = Class.forName("exer2.ClassloaderDemo").getClassLoader();
System.out.println(classloader);
//5.测试JDK提供的Object类由哪个类加载器加载
classloader = Class.forName("java.lang.Object").getClassLoader();
System.out.println(classloader);
//*6.关于类加载器的一个主要方法:getResourceAsStream(String str):获取类路径下的指定文件的输入流
InputStream in = null;
in = this.getClass().getClassLoader().getResourceAsStream("exer2\\test.properties");
System.out.println(in);

4 通过反射创建运行时类的对象

创建类的对象:调用Class对象的newInstance()方法

要  求:  1)类必须有一个无参数的构造器。

  2)类的构造器的访问权限需要足够。

难道没有无参的构造器就不能创建对象了吗?

不是!只要在操作的时候明确的调用类中的构造,并将参数传递进去之后,才可以实例化操作。步骤如下:

1)通过Class类的getDeclaredConstructor(Class … parameterTypes)取得本类的指定形参类型的构造器

2)向构造器的形参中传递一个对象数组进去,里面包含了构造器中所需的各个参数。

3)  

//1.根据全类名获取对应的Class对象
String name = “atguigu.java.Person";
Class clazz = null;
clazz = Class.forName(name);
//2.调用指定参数结构的构造器,生成Constructor的实例
Constructor con = clazz.getConstructor(String.class,Integer.class);
//3.通过Constructor的实例创建对应类的对象,并初始化类属性
Person p2 = (Person) 	con.newInstance("Peter",20);
System.out.println(p2);

5 通过反射获取运行时类的完整结构

1.实现的全部接口

Øpublic Class<?>[] getInterfaces()  

确定此对象所表示的类或接口实现的接口

2.所继承的父类

Øpublic Class<? Super T> getSuperclass()

返回表示此 Class 所表示的实体(类、接口、基本类型)的父类Class

3.全部的构造

Øpublic Constructor<T>[] getConstructors()

返回Class 对象所表示的类的所有public构造方法

Øpublic Constructor<T>[] getDeclaredConstructors()

返回Class 对象表示的类声明的所有构造方法。

lConstructor类中

Ø取得修饰符: public int getModifiers();

Ø取得方法名称: public String getName();

Ø取得参数的类型:public Class<?>[] getParameterTypes();

4.全部的方法

Øpublic Method[] getDeclaredMethods()

返回Class对象所表示的类或接口的全部方法

Øpublic Method[] getMethods() 

返回Class对象所表示的类或接口的public方法

lMethod类中:

Øpublic Class<?> getReturnType()取得全部的返回值

Øpublic Class<?>[] getParameterTypes()取得全部的参数

Øpublic int getModifiers()取得修饰符

Øpublic Class<?>[] getExceptionTypes()取得异常信息

5.全部Field

Øpublic Field[] getFields()

返回Class对象所表示的类或接口的publicField

Øpublic Field[] getDeclaredFields()

返回Class对象所表示的类或接口的全部Field

lField方法中:

Øpublic int getModifiers()  以整数形式返回此Field的修饰符

Øpublic Class<?> getType()  得到Field的属性类型

Øpublic String getName()  返回Field的名称。

6. Annotation相关

Øget Annotation(Class<T> annotationClass)

ØgetDeclaredAnnotations()

7.泛型相关

获取父类泛型类型:Type getGenericSuperclass()

泛型类型:ParameterizedType

获取实际的泛型类型参数数组:getActualTypeArguments()

8.类所在的包    Package getPackage()

6 通过反射调用运行时类的指定属性、指定方法等

6.1 调用指定方法

通过反射,调用类中的方法,通过Method类完成。步骤:

1.通过Class类的getMethod(String name,Class…parameterTypes)方法取得一个Method对象,并设置此方法操作时所需要的参数类型。

2.之后使用Object invoke(Object obj, Object[] args)进行调用,并向方法中传递要设置的obj对象的参数信息。

Object invoke(Object obj, Object …  args)

说明:

    1.Object 对应原方法的返回值,若原方法无返回值,此时返回null

    2.若原方法若为静态方法,此时形参Object obj可为null

    3.若原方法形参列表为空,则Object[] argsnull

    4.若原方法声明为private,则需要在调用此invoke()方法前,显式调用方法对象的setAccessible(true)方法,将可访问private的方法。

6.2 调用指定属性

在反射机制中,可以直接通过Field类操作类中的属性,通过Field类提供的set()get()方法就可以完成设置和取得属性内容的操作。

Øpublic Field getField(String name) 返回此Class对象表示的类或接口的指定的publicField

Øpublic Field getDeclaredField(String name)返回此Class对象表示的类或接口的指定的Field

Field中:

Øpublic Object get(Object obj) 取得指定对象obj上此Field的属性内容

Øpublic void set(Object obj,Object value) 设置指定对象obj上此Field的属性内容

注:在类中属性都设置为private的前提下,在使用set()get()方法时,首先要使用Field类中的setAccessible(true)方法将需要操作的属性设置为可以被外部访问。

Øpublic void setAccessible(true)访问私有属性时,让这个属性可见。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值