Java中的反射该如何使用?
1. 什么是反射
反射是一种功能强大且复杂的机制。Java反射说的是在运行状态中,对于任何一个类,我们都能够知道这个类有哪些方法和属性。对于任何一个对象,我们都能够对它的方法和属性进行调用。我们把这种动态获取对象信息和调用对象方法的功能称之为反射机制。
2. 反射可以用来做什么
反射能够分析类的能力,反射的机制十分强大,主要可以用来:
在运行时分析类的能力
在运行时查看对象
实现通用的数组操作代码
利用Method对象,实现C++中函数指针的功能
3. Class类
所谓的反射其实是获取类的字节码文件,也就是.class文件,而获取Class这个对象主要有三种方式:
getClass()函数、.class、forName()方法,代码如下:
package core.java;
import java.util.ArrayList;
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
ArrayList<Integer> test = new ArrayList<>();
//第一种方法
Class a = test.getClass();
System.out.println(a);
//第二种方法
Class b = Test.class;
System.out.println(b);
//第三种方法
Class c = Class.forName("java.lang.Math");
System.out.println(c);
}
}
4. 利用反射分析类
在reflect包中有三个类:Field、Method和Constructor分别用于描述类的域、方法和构造器。这三个类都有一个叫做getName()的方法,用来返回项目的名称。Field类有一个getType方法,用来返回描述域所属类型的Class对象。这三个类共同有一个getModifiers的方法,他将返回一个整型数值,来描述修饰符的情况。可以使用Modifier类的静态方法分析其返回的整型数值,也可以使用其toString()方法将对应的修饰符打印出来。
Class类中的getFields、getMethods和getConstructors方法将分别返回类提供的public域、方法和构造器数组,其中包括超类的共有成员。
Class类中的getDeclareFields、getDeclareMethods和getDeclaredConstructors方法将分别返回类中声明的全部域、方法和构造器,其中包括私有和受保护的成员,但不包括超类的成员。
实例代码:
package core.java.reflect;
import java.util.*;
import java.lang.reflect.*;
public class ReflectionTest
{
public static void main(String[] args)
{
// 读取类名
String name;
if (args.length > 0) name = args[0];
else
{
Scanner in = new Scanner(System.in);
System.out.println("Enter class name (e.g. java.util.Date): ");
name = in.next();
}
try
{
Class cl = Class.forName(name);
Class supercl = cl.getSuperclass();
String modifiers = Modifier.toString(cl.getModifiers()); //打印修饰符
if (modifiers.length() > 0) System.out.print(modifiers + " ");
System.out.print("class " + name);
if (supercl != null && supercl != Object.class) System.out.print(" extends "
+ supercl.getName());//输出超类
System.out.print("\n{\n");
printConstructors(cl); //输出构造器数组
System.out.println();
printMethods(cl); //输出方法
System.out.println();
printFields(cl); //输出域
System.out.println("}");
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
System.exit(0);
}
public static void printConstructors(Class cl)
{
Constructor[] constructors = cl.getDeclaredConstructors(); //获取构造器数组
for (Constructor c : constructors)
{
String name = c.getName();
System.out.print(" ");
String modifiers = Modifier.toString(c.getModifiers()); //输出修饰符
if (modifiers.length() > 0) System.out.print(modifiers + " ");
System.out.print(name + "("); //构造器签名
// print parameter types
Class[] paramTypes = c.getParameterTypes(); //获取构造器参数数组
for (int j = 0; j < paramTypes.length; j++)
{
if (j > 0) System.out.print(", ");
System.out.print(paramTypes[j].getName());
}
System.out.println(");");
}
}
public static void printMethods(Class cl)
{
Method[] methods = cl.getDeclaredMethods();
for (Method m : methods)
{
Class retType = m.getReturnType(); //获取返回类型
String name = m.getName(); //方法名
System.out.print(" ");
String modifiers = Modifier.toString(m.getModifiers()); //输出修饰符
if (modifiers.length() > 0) System.out.print(modifiers + " ");
System.out.print(retType.getName() + " " + name + "(");
// print parameter types
Class[] paramTypes = m.getParameterTypes(); //获取参数数组
for (int j = 0; j < paramTypes.length; j++)
{
if (j > 0) System.out.print(", ");
System.out.print(paramTypes[j].getName());
}
System.out.println(");");
}
}
public static void printFields(Class cl)
{
Field[] fields = cl.getDeclaredFields(); //获取域数组
for (Field f : fields)
{
Class type = f.getType(); //获取参数类型
String name = f.getName(); //获取域名称
System.out.print(" ");
String modifiers = Modifier.toString(f.getModifiers()); //输出修饰符
if (modifiers.length() > 0) System.out.print(modifiers + " ");
System.out.println(type.getName() + " " + name + ";");
}
}
}
5、利用反射技术得到所有的构造函数
public class Test02 {
public static void main(String[] args) {
try {
Class clazz = Student.class;// 获取class对象
String name = clazz.getName();// 获得类的名称(全限定名)
Constructor<?>[] constructors = clazz.getDeclaredConstructors();// 返回指定参数类型的所有构造器
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
} catch (SecurityException e) {
e.printStackTrace();
}
}
}
输出结果:
public com.etime2.Student()
public com.etime2.Student(java.lang.String,java.lang.Integer,java.lang.String)
备注:
getDeclaredConstructor()与getConstructor的区别
getDeclaredConstructor(Class<?>… parameterTypes)
这个方法会返回指定参数类型的所有构造器,包括public的和非public的,其中当然也包括private私有的。
getDeclaredConstructors()的返回结果就没有参数类型的过滤了。
getConstructor(Class<?>… parameterTypes)
这个方法返回的是上面方法返回结果的子集,外汇返佣只返回指定参数类型访问权限是public的构造器。
getConstructors()的返回结果同样也没有参数类型的过滤。
6、利用反射技术得到类的所有方法
public class Test03 {
public static void main(String[] args) {
try {
Class clazz = Class.forName("com.etime2.Student");// 获取类的class对象(加载和解析类的字节码,返回相应的class对象)
Method[] Methods = clazz.getDeclaredMethods();// 获取所有的方法,包括私有方法
for (Method method : Methods) {
String name = method.getName();// 获得类的名称(全限定名)
System.out.println(name);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
输出结果:
getName
setName
sleep
getGender
getAge
setAge
setGender
7、利用反射技术得到类的所有字段
public class Test04 {
public static void main(String[] args) {
try {
Class clazz = Class.forName("com.etime2.Student");
Field[] fields = clazz.getDeclaredFields();// 获取所有的字段
for (Field field : fields) {
System.out.println("字段:" + field);
String name = field.getName();// 获得类的名称(全限定名)
System.out.println("名称:" + name);
Class<?> type = field.getType();// 获取变量的类型
System.out.println("类型:" + type);
int modifiers = field.getModifiers();// 获得类的修饰符
boolean public1 = Modifier.isPublic(modifiers);
boolean static1 = Modifier.isStatic(modifiers);
boolean final1 = Modifier.isFinal(modifiers);
System.out.println("public1=" + public1 + " static1=" + static1 + " final1=" + final1);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
输出结果:
字段:private java.lang.String com.etime2.Student.name
名称:name
类型:class java.lang.String
public1=false static1=false final1=false
字段:private java.lang.Integer com.etime2.Student.age
名称:age
类型:class java.lang.Integer
public1=false static1=false final1=false
字段:private java.lang.String com.etime2.Student.gender
名称:gender
类型:class java.lang.String
public1=false static1=false final1=false
利用反射调用对象的私有方法(不完整)
public class Test05 {
public static void main(String[] args) {
try {
Class<?> clazz = Class.forName("com.etime2.Student");
Method method = clazz.getDeclaredMethod("sleep");
method.setAccessible(true);// 允许访问私有
Object newInstance = clazz.newInstance();// 调用无参构造函数创建对象
Student student = (Student) newInstance;
Object invoke = method.invoke(student);
System.out.println(invoke);
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
上课时间打盹!
null
Java中的反射该如何使用?的更多相关文章
- Java中的反射和注解
前言 在Java中,反射机制和注解机制一直是一个很重要的概念,那么他们其中的原理是怎么样呢,我们不仅仅需要会使用,更要知其然而之所以然. 目录 反射机制 反射如何使用 注解定义 注解机制原理 注解如何 ...
- java中的反射机制在Android开发中的用处
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反 ...
- 浅说Java中的反射机制(二)
写过一篇Java中的反射机制,不算是写,应该是抄了,因为那是别人写的,这一篇也是别人写的,摘抄如下: 引自于Java基础--反射机制的知识点梳理,作者醉眼识朦胧.(()为我手记) 什么是反射? 正常编 ...
- 浅说Java中的反射机制(一)
在学习传智播客李勇老师的JDBC系列时,会出现反射的概念,由于又是第一次见,不免感到陌生.所以再次在博客园找到一篇文章,先记录如下: 引用自java中的反射机制,作者bingoideas.(()为我手 ...
- java中动态反射
java中动态反射能达到的效果和python的语法糖很像,能够截获方法的实现,在真实方法调用之前和之后进行修改,甚至能够用自己的实现进行特别的替代,也可以用其实现面向切片的部分功能.动态代理可以方便实 ...
- 第89节:Java中的反射技术
第89节:Java中的反射技术 反射技术是动态的获取指定的类,和动态的调用类中的内容(没有类前就可以创建对象,将对象的动作完成,这就是动态的获取指定的类). 配置文件把具体实现的类名称定义到配置文件中 ...
- java笔记十:java中的反射
Java中,反射是一种强大的工具.它使您能够创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代表链接.反射允许我们在编写与执行时,使我们的程序代码能够接入装载到JVM中的类的内部信息,而 ...
- 【Java基础】java中的反射机制与动态代理
一.java中的反射机制 java反射的官方定义:在运行状态下,可以获取任意一个类的所有属性和方法,并且可通过某类任意一对象实例调用该类的所有方法.这种动态获取类的信息及动态调用类中方法的功能称为ja ...
- java中使用反射获取pojo(实体)类的全部字段值
说起反射.不得不说它实在是太强大了,通过反射就能够轻轻松松拿到各种东东,假设你想在项目中解除对某个类的依赖,能够考虑用反射. 今天跟大家分享的是通过java中的反射,获取pojo类的全部字段值. 为什 ...
- java 中利用反射机制获取和设置实体类的属性值
摘要: 在java编程中,我们经常不知道传入自己方法中的实体类中到底有哪些方法,或者,我们需要根据用户传入的不同的属性来给对象设置不同的属性值,那么,java自带的反射机制可以很方便的达到这种目的,同 ...
随机推荐
- MHA-Atlas-MySQL高可用(上)
MHA-Atlas-MySQL高可用(上) 链接:https://pan.baidu.com/s/17Av92KQnJ81Gc0EmxSO7gA 提取码:a8mq 复制这段内容后打开百度网盘手机App ...
- String的static方法
//String concat(String str) 拼接字符串 String concat_str0 = "abc"; String concat_str1 = "b ...
- div框,左右拖动
<script type="text/javascript"> function bindResize(el){ //初始化参数 var els = document. ...
- word文档操作
1.如何把word文档修改的地方标记出来 : https://zhidao.baidu.com/question/73648149.html 2.word 的几种 视图:https://zhid ...
- css3 动画+动画库
css3 动画 实现原理 1.transition 过渡:https://www.runoob.com/cssref/css3-pr-transition.html 语法:( transition的 ...
- nginx,php-fpm性能优化
When you running a highload website with PHP-FPM via FastCGI, the following tips may be useful to yo ...
- 计算1到N中包含数字1的个数
转自:http://pandonix.iteye.com/blog/204840 Mark N为正整数,计算从1到N的所有整数中包含数字1的个数.比如,N=10,从1,2...10,包含有2个数字1. ...
- HTTP与HTTPS的区别与联系
HTTP与HTTPS的区别与联系 HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure ...
- db2,用户名密码不对导致无法连接数据库: Reason: User ID or Password invalid. ERRORCODE=-4214, SQLSTATE=28000
文章目录 背景 解决 背景 qa需要db2的demo,运维给安装完db2,启动报错 com.ibm.db2.jcc.am.io: [jcc][t4][2013][11249][4.7.112] Con ...
- 校验文件是否是同一个文件,以及mac中使用MD5命令
背景 sz了war包,因为查看不到里面的内容,并不确定是否是同一个文件. 解决 通过MD5校验 md5sum xxxx 但是在mac中是没有这个命令的下载半天没下载下来,下面是快捷操作. 1.打开终端 ...