分享知识-快乐自己:反射机制Demo解析
Java-Reflect专题
基本反射简介:
1):JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
2):JAVA反射(放射)机制:"程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言"。从这个观看,Perl,PythonRuby是动态语言,C++,Java,C#不是动态语言。
3):但是JAVA有着一个非常突出的动态相关机制:Reflection用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。
4):换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。
Java反射机制提供的功能:
1):在运行时判断任意一个对象所属的类在运行时构造任意一个类的对象
2):在运行时判断任意一个类所具有的成员变量和方法
3):在运行时调用任意一个对象的方法
4):生成动态代理
Class类介绍:
Class 类描述Java程序运行时的所有 Classes 和 interfaces,同时也用来描述enum、array、Java基本数据类型。
生成Class:当一个class文件被加载或者类加载器的defineClass()被JVM调用时,JVM便自动产生一个Class 对象。
常用API:
生成Class对象的方法:
1):根据完整类名获取类,调用 Class 的静态方法 forName():
Class<?> classType = Class.forName(“java.lang.String”);
2):通过类名获取,使用class语法,这里ReflectionTest为一个类名:
Class<?> classType = ReflectionTest.class;
3):通过对象的getClass()方法获取:
User user = new User();
Class<?> classType = user.getClass();
//获取user的父类的Class对象
Class superClass = classType.getSuperclass();
4):对于包装类的Class的获取,使用包装类的TYPE语法:
Class classType = Integer.Type;
Class c = Integer.class;
创建反射获取的类的实例的方法:
1):调用Class的newInstance()方法:
Class c = Class.forName("mlq.Student");
Student student = (Student) c.newInstance();
2):通过Class获取构造方法再实例化:
Class c = Class.forName("mlq.Student");
Student student=(Student)c.getConstructor(new Class[]{}).newInstance(new Object[]{});
提示:当Class数组为空时,本质上等价于①,即调用无参构造函数
获取方法信息函数:
1):获取所有公共方法:
Method getMethod(String name, Class[] params) -- 使用特定的参数类型,获得命名的公共方法 Method[] getMethods() -- 获得类的所有公共方法
2):获取所有方法:(不问访问权限)
Method getDeclaredMethod(String name, Class[] params) -使用特写的参数类型,获得类声明的命名的方法 Method[] getDeclaredMethods() -- 获取的是所有该类自己声明的方法,不问访问权限
获取成员变量:
1):获取所有的 public 的成员变量的信息
Field getField(String name) -- 获得指定命名的公共字段 Field[] getFields()--方法获取的是所有的public的成员变量的信息
2):获取所有成员变量:(不问访问权限)
Field getDeclaredField(String name) -- 获取指定的域,返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段:
Field[] getDeclaredFields()--获取所有的域,包括公共、保护、默认(包)访问和私有域,但不包括继承的域:
field.setAccessible(true);--设置压制访问控制检查,这样就可以获取和设置私有域的值了:
Field field = classType.getDeclaredField("fieldName");--获取某个对象的域的对应值:
field.get(object);
Field field = classType.getDeclaredField("fieldName");--设置某个对象的域的对应值:
field.set(obj, "arthinking");
获取构造函数信息:
1):获取所有public的函数:
Constructor getConstructor(Class[] params) -- 获得使用特殊的参数类型的公共构造函数,
Constructor[] getConstructors()--获取所有的public的构造函数
2):获取构造函数:(不问访问权限)
Constructor getDeclaredConstructor(Class[] params) -- 获得使用特定参数类型的构造函数(与接入级别无关)
Constructor[] getDeclaredConstructors()--得到自己声明的构造函数,推荐使用(与接入级别无关)
案例Demo:点我下载源码
1):获取Student类的完整限定名==》全类名
/**
* 获取Student类的完整限定名==》全类名
* 01、Class.forName(类的完整限定名) 来加载类 (常用)
* 02、Student.class 任何类名.class都是获取了Class类
* 03、new Student().getClass() 任何对象.getClass()都是获取了Class类
*/
@Test
public void test01() {
try { System.out.println("打印类的完整限定名、会走静态代码块:" + Class.forName("mlq.Student"));
System.out.println("====================================");
System.out.println("只打印类的全名称:" + Student.class);
System.out.println("====================================");
System.out.println("无参、静态与非静态块、类完整名称;都会执行" + new Student().getClass().getName());
} catch (Exception e) {
e.printStackTrace();
}
}
2):获取包名、类名、访问修饰符值 和 name
/**
* 获取包名、类名、访问修饰符值 和 name
*/
@Test
public void test02() {
try {
//加载Student 类
Class c = Class.forName("mlq.Student");
System.out.println("Student所在包名称:" + c.getPackage().getName());
System.out.println("Student全类名:" + c.getName());
System.out.println("Student类名:" + c.getSimpleName());
//获取类的访问修饰符
int num = c.getModifiers();
System.out.println("public访问修饰符对应的数值:" + num);
//访问修饰符对相应的名称
System.out.println(Modifier.toString(num));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
3): 获取类中所有的属性相关信息
/**
* 获取类中所有的属性相关信息
*/
@Test
public void test03() {
try {
Class c = Class.forName("mlq.Student");
//获取所有字段
Field[] fields = c.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
System.out.println(fields[i]);
}
//获取所有字段的访问修饰符
for (int i = 0; i < fields.length; i++) {
//修饰符值对象的修饰符名称
System.out.print(Modifier.toString(fields[i].getModifiers()));
//访问修饰符对应的数值
System.out.println(":" + fields[i].getModifiers());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
4):获取类中所有的方法相关信息 不包含构造方法
/**
* 获取类中所有的方法相关信息 不包含构造方法
* 01、c.getMethod(方法名称,参数类型)只能是public修饰的
* 02、c.getMethods()只能是public修饰的
* 03、c.getDeclaredMethods() 所有
*/
@Test
public void test04() {
try {
Class c = Class.forName("mlq.Student");
//获取所有方法,包含private私有的
Method[] declaredMethods = c.getDeclaredMethods();
for (int i = 0; i < declaredMethods.length; i++) {
System.out.println("方法的名称是:" + declaredMethods[i].getName());
System.out.println("方法的修饰符数值时:" + declaredMethods[i].getModifiers());
System.out.println("方法的修饰符名称是:" + Modifier.toString(declaredMethods[i].getModifiers()));
System.out.println("方法的返回值类型是:" + declaredMethods[i].getReturnType());
System.out.println("=============================================");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
5):获取类中的所有构造方法相关信息
/**
* 获取类中的所有构造方法相关信息
*/
@Test
public void test05() {
try {
Class c = Class.forName("mlq.Student");
//获取所有构造,包含private私有的
Constructor[] declaredConstructors = c.getDeclaredConstructors();
for (int i = 0; i < declaredConstructors.length; i++) {
System.out.println("构造方法的名称是:" + declaredConstructors[i].getName());
System.out.println("构造方法的修饰符数值是:" + declaredConstructors[i].getModifiers());
System.out.print("构造的访问修饰符及参数列表:" + Modifier.toString(declaredConstructors[i].getModifiers()) + "(");
//获取构造中的参数
Class[] parameterTypes = declaredConstructors[i].getParameterTypes();
for (int j = 0; j < parameterTypes.length; j++) {
System.out.print(parameterTypes[j].getName() + ",");
}
System.out.println(")");
System.out.println("=======================================");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
6):访问类中私有的属性和方法并且让它执行
/**
* 访问类中私有的属性和方法并且让它执行
*/
@Test
public void test06() {
try {
Class c = Class.forName("mlq.Student");
//Student student=(Student)c.getConstructor(new Class[]{}).newInstance(new Object[]{});
//实例化
Student student = (Student) c.newInstance();
//获取私有字段
Field userName = c.getDeclaredField("userName"); //输出字段名称
System.out.println("输出字段名称:"+userName.getName());
//打开字段开关
userName.setAccessible(true);
//userName.set(student,"abc");
//输出字段信息
System.out.println("输出字段信息:"+userName.get(student));
//获取私有的方法
Method getSum = c.getDeclaredMethod("getSum", double.class);
//开启方法开关
getSum.setAccessible(true);
//调用执行方法
double invoke = (Double) getSum.invoke(student, 50.5);
//输出返回值
System.out.println(invoke);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
Face your past without regret. Handle your present with confidence.Prepare for future without fear. keep the faith and drop the fear.
面对过去无怨无悔,把握现在充满信心,备战未来无所畏惧。保持信念,克服恐惧!一点一滴的积累,一点一滴的沉淀,学技术需要不断的积淀!
分享知识-快乐自己:反射机制Demo解析的更多相关文章
- ReflectUitls类的编写和对反射机制的解析
ReflectUitls类的编写和对反射机制的解析 反射相关的类 反射相关的类,最基本的当然是Class类. 获取了Class对象之后,就可以接着生成对象实例.调用方法.查看字段等等. 字段(Fiel ...
- Java反射机制demo(七)—反射机制与工厂模式
Java反射机制demo(七)—反射机制与工厂模式 工厂模式 简介 工厂模式是最常用的实例化对象模式. 工厂模式的主要作用就是使用工厂方法代替new操作. 为什么要使用工厂模式?直接new不好吗? 直 ...
- Java反射机制demo(六)—获得并操作一个类的属性
Java反射机制demo(六)—获得并操作一个类的属性 获得并操作一个类的属性?! 不可思议啊,一个类的属性一般都是私有成员变量啊,private修饰符啊! 但是毫无疑问,这些东西在Java的反射机制 ...
- Java反射机制demo(五)—获得并调用一个类中的方法
Java反射机制demo(五)—获得并调用一个类中的方法 这个demo在使用反射机制操作属性之前,主要原因是因为在.class文件字节码中,方法排在属性的前面. 1,获得一个类中的方法 先看一下方法和 ...
- Java反射机制demo(四)—获取一个类的父类和实现的接口
Java反射机制demo(四)—获取一个类的父类和实现的接口 1,Java反射机制得到一个类的父类 使用Class类中的getSuperClass()方法能够得到一个类的父类 如果此 Class 表示 ...
- Java反射机制demo(三)—获取类中的构造函数
Java反射机制demo(三)—获取类中的构造函数 1,获取类中所有的构造函数 如下面的代码中所示,这个类中显式的构造函数有五个. 空构造: public UserInfo() 带参构造有四个: pu ...
- Java反射机制demo(二)—通过Class实例化任意类的对象
Java反射机制demo(二)—通过Class实例化任意类的对象 上一章节中,实例化了Class类对象的实例,这个部分的demo展示了如何使用Class对象的实例去获得其他类的对象的实例. 任意一个类 ...
- Java反射机制demo(一)—实例化Class对象,并获得其他类包名和类型
Java反射机制demo(一)——实例化Class对象,通过对象获得包名和类型 使用Java中的 本地类作为实验对象,避免自定义的类带来的一些不便. public static void main(S ...
- Java反射机制(Reflect)解析-----https://www.cnblogs.com/fzz9/p/7738381.html
Java反射机制(Reflect)解析-----https://www.cnblogs.com/fzz9/p/7738381.html
随机推荐
- centos6下手工编译vitess
vitess是youtub开源的一款mysql代理,在ubuntu下编译非常方便.可是在centos下且不能訪问google的情况下坑比較多.近期依据其bootstrap.sh脚本手工编译成功.把过程 ...
- FMM和BMM的python代码实现
FMM和BMM的python代码实现 FMM和BMM的编程实现,其实两个算法思路都挺简单,一个是从前取最大词长度的小分句,查找字典是否有该词,若无则分句去掉最后面一个字,再次查找,直至分句变成单词或者 ...
- jquery get ($.get) 事件用法与分析
jquery get ($.get) 事件用法与分析 get() 方法通过远程 HTTP GET 请求载入信息.这是一个简单的 GET 请求功能以取代复杂 $.ajax .请求成功时可调用回调函数.如 ...
- Spring Cloud 微服务六:调用链跟踪Spring cloud sleuth +zipkin
前言:随着微服务系统的增加,服务之间的调用关系变得会非常复杂,这给运维以及排查问题带来了很大的麻烦,这时服务调用监控就显得非常重要了.spring cloud sleuth实现了对分布式服务的监控解决 ...
- 解决from lxml import etree 导入的时候,显示etree不存在
问题: 当安装完lxml之后,发现使用 from lxml import etree 时,etree不可用 原因 :是lxml中没有etree包 解决: 去官网下载对应包:官网地址:http://l ...
- Entity Framework(1)——Connections and Models
原文:https://msdn.microsoft.com/en-us/data/jj592674 应该选择CodeFirst.ModelFirst还是databaseFirst网上已经很多资料了,这 ...
- wordpress 获取分类ID,分类标题,分类描述,分类链接url函数
get_cat_ID() 根据分类名称获取分类ID ///// get_cat_name() 根据分类ID获取分类名称 用法:<?phpget_cat_ID( $cat_name ...
- VS2010 fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
VS2010在经历一些更新后,建立Win32 Console Project时会出“error LNK1123” 错误,解决方案为将 项目|项目属性|配置属性|清单工具|输入和输出|嵌入清单 “是”改 ...
- Python菜鸟之路:Python基础-逼格提升利器:装饰器Decorator
一.装饰器 装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等. 装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身 ...
- Android开发之深入理解泛型extends和super的区别
摘要: 什么是泛型?什么是擦除边界?什么是上界限定或下界限定(子类型限定或超类型限定)?什么是类型安全?泛型extends关和super关键字结合通配符?使用的区别,两种泛型在实际Android开发中 ...