我是靠谱客的博主 粗心钢铁侠,最近开发中收集的这篇文章主要介绍java核心技术——反射一、什么是反射?二、什么是类信息三、反射机制能做什么 四、通过反射查看类信息五、使用反射并操作对象,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

目录

一、什么是反射?

二、什么是类信息

三、反射机制能做什么

四、通过反射查看类信息

1、获得Class对象

2、从 Class 中获取信息

2.1 获取 Class 对应类的成员变量

2.2 获取 Class 对应类的方法

2.3 获取 Class 对应类的构造函数

2.4 获取 Class 对应类的 Annotation(注释)

2.5 获取 Class 对应类的内部类

2.6 获取 Class 对应类的外部类

2.7 获取 Class 对应类所实现的接口

2.8 获取 Class 对应类所继承的父类

2.9 获取 Class 对应类的修饰符、所在包、类名等基本信息

2.10 判断该类是否为接口、枚举、注解类型等

五、使用反射并操作对象

1.Class类

2. 调用方法

2.1 暴力反射相关

3. 访问成员变量值


一、什么是反射?

 1. Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法,不受访问修饰符的限制。本质是JVM得到类对象之后,再通过类对象进行反编译,从而获取对象的各种信息。
 2. Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁
能够分析类能力的程序称为反射(reflective )  ——《java核心技术卷》

二、什么是类信息

简单的来说比如 属性、方法、构造器等等

三、反射机制能做什么

 1. 在运行时判断一个对象所属的类
 2. 在运行时可以构造任意一个类的对象
 3. 在运行时可以任意判断一个类所包含的成员变量和方法
 4. 在运行时可以任意调用一个对象的方法
 5. 生成动态代理


四、通过反射查看类信息

1、获得Class对象

每个类被加载之后,系统就会为该类生成一个对应的Class对象。通过该Class对象就可以访问到JVM中的这个类。

在Java程序中获得Class对象通常有如下三种方式:

  1. 使用 Class 类的forName(String clazzName)静态方法。该方法需要传入字符串参数,该字符串参数的值是某个类的全限定名(必须添加完整包名)
  2. 调用某个类的class属性来获取该类对应的 Class 对象。
  3. 调用某个对象的getClass()方法。该方法是java.lang.Object类中的一个方法。
//第一种方式 通过Class类的静态方法——forName()来实现
class1 = Class.forName("com.lvr.reflection.Person");
//第二种方式 通过类的class属性
class1 = Person.class;
//第三种方式 通过对象getClass方法
Person person = new Person();
Class<?> class1 = person.getClass();

对于方式一和方式二都是直接根据类来取得该类的 Class 对象,相比之下,方式二有如下的两种优势:

  • 代码跟安全。程序在编译阶段就能够检查需要访问的 Class 对象是否存在。
  • 线程性能更好。因为这种方式无须调用方法,所以性能更好。

可以通过类的类类型创建该类的对象实例。

Class.newInstance();
//Class下的newInstance()的使用有局限,因为它生成对象只能调用无参的构造函数
Foot foot = (Foot) c1.newInstance();

2、从 Class 中获取信息

一旦获得了某个类所对应的Class 对象之后,就可以调用 Class 对象的方法来获得该对象的和该类的真实信息了。

2.1 获取 Class 对应类的成员变量

Field[] getDeclaredFields(); // 获取 Class 对象对应类的所有属性即所有字段,与成员变量的访问权限无关。
Field[] getFields(); // 获取 Class 对象对应类的所有 public 属性。
Field getDeclaredField(String name); // 获取 Class 对象对应类的指定名称的属性,与成员变量的访问权限无关。
Field getField(String name); // 获取 Class 对象对应类的指定名称的 public 属性。

2.2 获取 Class 对应类的方法

Method[] getDeclaredMethods(); // 获取 Class 对象对应类的所有声明方法,于方法的访问权限无关。
Method[] getMethods(); // 获取 Class 对象对应类的所有 public 方法,包括父类的方法。
Method getMethod(String name, Class<?>...parameterTypes); // 返回此 Class 对象对应类的、带指定形参列表的 public 方法。
Method getDeclaredMethod(String name, Class<?>...parameterTypes); // 返回此 Class 对象对应类的、带指定形参列表的方法,与方法的访问权限无关。

2.3 获取 Class 对应类的构造函数

Constructor<?>[] getDeclaredConstructors(); // 获取 Class 对象对应类的所有声明构造函数,于构造函数的访问权限无关。
Constructor<?>[] getConstructors(); // 获取 Class 对象对应类的所有 public 构造函数。
Constructor<T> getDeclaredConstructor(Class<?>...parameterTypes); // 返回此 Class 对象对应类的、带指定形参列表的构造函数,与构造函数的访问权限无关。
Constructor<T> getConstructor(Class<?>...parameterTypes); // 返回此 Class 对象对应类的、带指定形参列表的 public 构造函数。

2.4 获取 Class 对应类的 Annotation(注释)

<A extends Annotation>A getAnnotation(Class<A> annotationClass); // 尝试获取该 Class 对对象对应类存在的、指定类型的 Annotation;如果该类型的注解不存在,则返回 null。
<A extends Annotation>A getDeclaredAnnotation(Class<A> annotationClass); // 这是Java8新增的方法,该方法尝试获取直接修饰该 Class 对象对应类、指定类型的Annotation;如果该类型的注解不存在,则返回 null。
Annotation[] getAnnotations(); // 返回修饰该 Class 对象对应类存在的所有Annotation。
Annotation[] getDeclaredAnnotations(); // 返回直接修饰该 Class 对应类的所有Annotation。
<A extends Annotation>A[] getAnnotationsByType(Class<A> annotationClass); // 获取修饰该类的、指定类型的多个Annotation。
<A extends Annotation>A[] getDeclaredAnnotationsByType(Class<A> annotationClass); // 获取直接修饰该类的、指定类型的多个Annotation。

2.5 获取 Class 对应类的内部类

Class<?>[] getDeclaredClasses(); // 返回该 Class 对象对应类包含的全部内部类。

2.6 获取 Class 对应类的外部类

Class<?> getDeclaringClass(); // 返回该 Class 对象对应类所在的外部类。

2.7 获取 Class 对应类所实现的接口

Class<?>[] getInterfaces();

2.8 获取 Class 对应类所继承的父类

Class<? super T> getSuperClass();

2.9 获取 Class 对应类的修饰符、所在包、类名等基本信息

int getModifiers(); // 返回此类或接口的所有修饰符。修饰符由 public、protected、private、final、static、abstract 等对应的常量组成,返回的整数应使用 Modifier 工具类的方法来解码,才可以获取真实的修饰符。
Package getPackage() // 获取该类的包。
String getName() // 以字符串的形式返回此 Class 对象所表示的类的名称。
String getSimpleName() // 以字符串的形式返回此 Class 对象所表示的类的简称。

2.10 判断该类是否为接口、枚举、注解类型等

boolean isAnnotation() // 返此 Class 对象是否是一个注解类型(由@interface定义)。
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) // 判断此 Class 对象是否使用了Annotation修饰。
boolean isAnonymousClass() // 此 Class 对象是否是一个匿名类。
boolean isArray() //此 Class 对象是否是一个数组。
boolean isEnum() // 此 Class 对象是否是一个枚举(由 enum 关键字定义)。
boolean isInterface() // 此 Class 对象是否是一个接口(由 interface 关键字定义)。
boolean isInstance(Object obj) // 判断 obj 是否是此 Class 对象的实例。该方法完全可以替代 instanceof 操作符。

五、使用反射并操作对象

Class 对象可以获得该类里的方法(由 Method 对象表示)、构造器(由 Constructor 对象表示)、成员变量(由 Field 对象表示),这三个类都位于 java.lang.reflect 包下。

程序可以通过 Method 对象来执行对应的方法,
通过 Constructor 对象来调用对应的构造器创建实例,
通过 Field 对象直接访问并修改对象的成员变量值。

1.Class类

可以通过专门的 Java 类访问这些信息 保存这些信息的类被称为 Class , 这 个 名 字很容易让人混淆。 Object 类中的 getClass ( ) 方法将会返回一个 Class 类型的实例
Employee e;
Class cl = e.getClassO;
如同用一个 Employee 对象表示一个特定的雇员属性一样,一个 Class 对象将表示一个特定类的属性。 最常用的 Class 方法是 getName 这个方法将返回类的名字
如果类名保存在字符串中 并可在运行中改变 就可以使用这个方法 当然 这个方法只有在 className 是类名或接口名时才能够执行 否则 forName 方法将抛出一个 checked exception ( 已检查异常 无论何时使用这个方法 都应该提供一个异常处理器( exception handler) .
获得 Class 类对象的第三种方法非常简单 如果 T 是任意的 Java 类型 void 关键字 )
T . class 将代表匹配的类对象 例如
Class dl = Random,cl ass; // if you import java.util
Gass cl 2 = int.class;
Class cl 3 = Doublet],cl ass;
还有一个很有用的方法 newlnstance ( ) 可以用来动态地创建一个类的实例例如,
e.getClass0.newlnstance();
创建了一个与 e 具有相同类类型的实例 newlnstance 方法调用默认的构造器 没有参数的构 器) 初始化新创建的对象 如果这个类没有默认的构造器 就会抛出一个异常

将 forName newlnstance 配合起来使用可以根据存储在字符串中的类名创建一个对象

String s = "java.util .Random";
Object m = Cl ass.forName (s) .newlnstance();

2. 调用方法

当获得某个类对应的 Class 对象后,就可以通过该 Class 对象的方法:
getMethods() // 获取全部方法。
getMethod() // 获取指定方法。
这两个方法的返回值是 Method 数组,或者 Method 对象。

每个 Method 对象对应一个方法,获得 Method 对象后,程序就可通过该 Method 来调用它对应的方法。在 Method 里包含一个 invoke() 方法:
Object invoke(Object obj, Object... args) // 该方法中的 obj 是执行该方法的主调,后面的 args 是执行该方法时传入该方法的实参。

// 生成新的对象:用newInstance()方法
Object obj = class1.newInstance();
// 首先需要获得与该方法对应的Method对象
Method method = class1.getMethod("setAge", int.class);
// 调用指定的函数并传递参数
method.invoke(obj, 28);

当通过Method的invoke()方法来调用对应的方法时,Java会要求程序必须有调用该方法的权限。如果程序确实需要调用某个对象的 private 方法,则可以先调用以下方法:
setAccessible(true)

值为true,指示该 Method 在使用时应该取消Java语言的访问权限检查;值为false,则知识该Method在使用时要实施Java语言的访问权限检查。

Method 、 Constructor 、Field 都可以调用该方法,从而实现通过反射来调用 private 方法、private 构造器、private 成员变量。

2.1 暴力反射相关

1,概述
专门用来 反射 类中的 公开数据 和 私有数据
2,新的API
--普通反射 -- 只能获取public的
getMethod()
getMethods()
getField()
getFields()
getConstructor()
getConstructors()
--暴力反射 --除了public的甚至连private都可以获取
getDeclaredMethod()
getDeclaredMethods()
getDeclaredField()
getDeclaredFields()
getDeclaredConstructor()
getDeclaredConstructors()
反射和暴力反射的区别
总结:
1, 普通反射 和 暴力反射 的区别 ?
  暴力反射是可以获取public的甚至private
  普通反射只能获取public的

2, 怎么使用暴力反射?
  用对API ( getDeclaredXxx() )
  设置访问权限( setAccessible(true) )

3, getDeclaredXxx() 和 getXxx() 的区别??
  getXxx() 获取public资源 -- 获取自己的方法和父类的方法
  getDeclaredXxx() 获取所有资源 --只获取自己的方法

3. 访问成员变量值

通过Class对象的:
getFields() // 获取全部成员变量,返回 Field数组或对象。
getField() // 获得指定成员变量,返回 Field数组或对象。

Field 提供了两组方法来读取或设置成员变量的值:
getXXX(Object obj) // 获取obj对象的该成员变量的值。
setXXX(Object obj, XXX val) // 将 obj 对象的该成员变量设置成val值。



 

最后

以上就是粗心钢铁侠为你收集整理的java核心技术——反射一、什么是反射?二、什么是类信息三、反射机制能做什么 四、通过反射查看类信息五、使用反射并操作对象的全部内容,希望文章能够帮你解决java核心技术——反射一、什么是反射?二、什么是类信息三、反射机制能做什么 四、通过反射查看类信息五、使用反射并操作对象所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部