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自带的反射机制可以很方便的达到这种目的,同 ...
随机推荐
-
2016huasacm暑假集训训练五 C-Common Subsequence
题目链接:http://acm.hust.edu.cn/vjudge/contest/126708#problem/C 题意:这是一道求字符串的公共子串的最大长度的题目,用dp动态方程即可 if(a[ ...
-
JavaScript作用域闭包简述
JavaScript作用域闭包简述 作用域 技术一般水平有限,有什么错的地方,望大家指正. 作用域就是变量起作用的范围.作用域包括全局作用域,函数作用域以块级作用域,ES6中的let和const可以形 ...
-
Excel 2007中的新文件格式
*.xlsx:基于XML文件格式的Excel 2007工作簿缺省格式 *.xlsm:基于XML且启用宏的Excel 2007工作簿 *.xltx:Excel2007模板格式 *.xltm:Excel ...
-
C# windows ce编程-----我的第一次
最近公司要求开发抄表软件,软件分为PC端和手持终端(简称HHU),HHU是基于英文版的windows ce6.0操作系统,开发环境要求VS2005+SQLite数据库,开发语言为C#,因为是第一次基本 ...
-
WPF TreeView 选择事件执行两次,获取TreeView的父节点的解决方法
1.TreeView选择事件执行两次 Very often, we need to execute some code in SelectedItemChanged depending on the ...
-
node 图片上传功能
node 代码: var http = require("http"); var express = require('express') app = express(), for ...
-
【转】解决IDEA新建项目名称为红色
idea如果当前project用了版本控制器,其下面新建的所有的项目默认都是加入到版本控制里面,所以项目名称和文件都是红色的,如图: File-->Settings-->version c ...
-
http://www.xuexi111.com/
http://www.xuexi111.com/ http://www.minxue.net/ 拼吾爱
-
C# Session操作
Session.Abandon();//清除全部Session//清除某个SessionSession["UserName"] = null;Session.Remove(&quo ...
-
Hie with the Pie(POJ3311+floyd+状压dp+TSP问题dp解法)
题目链接:http://poj.org/problem?id=3311 题目: 题意:n个城市,每两个城市间都存在距离,问你恰好经过所有城市一遍,最后回到起点(0)的最短距离. 思路:我们首先用flo ...