Java反射理解
序言
一般而言,动态语言是指程序运行时,允许改变程序结构或变量类型的语言。
从这个观点来看,Perl、Python、Ruby是动态语言,C++、Java、C#不是动态语言。
但是Java有动态相关机制:Reflection,反射,是指可以运行时加载、探知、使用编译期间完全未知的Classes。
一、什么是反射?
Java程序可以加载一个运行时才得知名称的Class,获取其完整构造,并生成其对象实体,设置属性,调用方法。
这种动态获取类信息以及动态调用对象方法的功能就是Java语言的反射机制。
二、反射的作用?
1、在运行时判断任意一个对象所属的类
2、在运行时构造任意一个类的对象
3、在运行时判断任意一个类所具有的成员变量和方法
4、在运行时调用任意一个对象的方法
三、反射的一些概念
1、反射相关的类和接口,都放在软件包java.lang.reflect
软件包java.lang.reflect提供类和接口,以获取关于类和对象的反射信息。
在安全限制内,反射允许编程访问关于加载类的字段、方法和构造方法的信息,并允许使用反射字段、方法和构造方法对对象上的基本对等项进行操作。
如果必需的 ReflectPermission 可用,则 AccessibleObject 允许抑制访问检查。Array 提供动态创建和访问数组的静态方法。
此包中的类以及 java.lang.Class 可以适应以下应用程序的需要:调试程序、解释程序、对象检查程序、类浏览程序等。
2、反射相关类摘要
| 类名 | 说明 |
| AccessibleObject | AccessibleObject 类是Field、Method 和 Constructor 对象的基类。 |
| Constructor<T> | Constructor提供关于类的单个构造方法的信息以及对它的访问权限。 |
| Field | Field提供有关类或接口的单个字段的信息,以及对它的动态访问权限。 |
| Method | Method提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。 |
| Modifier | Modifier类提供了static方法和常量,对类和成员访问修饰符进行解码。 |
| Proxy | Proxy提供用于创建动态代理类和实例的静态方法,它还是由这些方法创 建的所有动态代理类的超类。 |
| ReflectPermission | 反射操作的Permission类。 |
3、java.lang.Class说明
Class 类和一般类一样继承自 Object ,其实体用以表达 Java 程序运行时的类和接口,枚举,数组,基础类型(boolean, byte, char, short, int, long, float, double)以及关键词void。
Class 没有公共构造方法。当一个 Class 被加载,或当加载器(class loader)的 defineClass() 被 JVM 调用, JVM 便自动产生一个类对象 。
Java 有个 Object 类,是所有 Java 类的继承根源,其内声明了数个应该在所有 Java 类中被改写的方法: hashCode()、equals()、clone() 、toString() 、getClass() 等。
其中 getClass() 返回一个 Class 类的对象,因此对于任意一个 Java 对象,都可以通过此方法获得对象的类型。
===Class 类是 Reflection API 中的核心类,它有以下方法===
getName() :获得类的完整名字。
getFields() :获得类的 public 类型的属性。
getDeclaredFields() :获得类的所有属性。
getMethods() :获得类的 public 类型的方法。
getDeclaredMethods() :获得类的所有方法。
getMethod(String name, Class[] parameterTypes) :获得类的特定方法, name 参数指定方法的名字, parameterTypes 参数指定方法的参数类型。
getConstructors() :获得类的 public 类型的构造方法。
getConstructor(Class[] parameterTypes) :获得类的特定构造方法, parameterTypes 参数指定构造方法的参数类型。
newInstance() :通过类的不带参数的构造方法创建这个类的一个对象。
四、反射的具体实现
反射用到的测试类:含测试用的方法和属性
package code.lemon; import java.util.Map;
import java.util.Set;
import java.util.List; public class Pear{
Map<String, String> map;
public Set<String> set;
public Class<?> clazz;
String str;
Set set1;
public List<String> list; private static Pear pear;
static{
pear = new Pear();
} private Pear(){
} public Pear(String str){
this.str = str;
} public static void main(String [] args){
System.out.println(Pear.class.getPackage());
} public String getStr(){
return str;
} private void setStr(String str){
this.str = str;
}
}
1、获取类的构造方法
public static void printConstructor(String className) {
try {
Class<?> clazz = Class.forName(className);
//返回一个包含某些 Constructor 对象的数组,
//这些对象反映此 Class 对象所表示的类的所有公共构造方法。
Constructor<?>[] constructors = clazz.getConstructors();
for (int i = 0; i < constructors.length; i++) {
System.out.println(constructors[i]);
}
System.out.println("------------------");
//返回 Constructor 对象的一个数组,
//这些对象反映此 Class 对象表示的类声明的所有构造方法。
Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
for (int i = 0; i < declaredConstructors.length; i++) {
//返回此类或接口以整数编码的 Java 语言修饰符。
int modifiers = declaredConstructors[i].getModifiers();
System.out.println(declaredConstructors[i] + ":"
+ Modifier.toString(modifiers));
}
} catch (Exception e) {
}
}
2、获取类属性
public static void printField(String className) {
try {
Class<?> clazz = Class.forName(className);
//返回一个包含某些 Field 对象的数组,
//这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。
Field[] fields = clazz.getFields();
for (int i = 0; i < fields.length; i++) {
System.out.println(fields[i]);
}
System.out.println("------------------");
//返回 Field 对象的一个数组,
//这些对象反映此 Class 对象所表示的类或接口所声明的所有字段,
//包括公共、保护、默认(包)访问和私有字段,但不包括继承的字段。
Field[] declaredFields = clazz.getDeclaredFields();
for (int i = 0; i < declaredFields.length; i++) {
int modifiers = declaredFields[i].getModifiers();
System.out.println(declaredFields[i] + ":"
+ Modifier.toString(modifiers));
}
} catch (Exception e) {
}
}
3、获取类方法
public static void printMethod(String className) {
try {
Class<?> clazz = Class.forName(className);
//返回一个包含某些 Method 对象的数组,
//这些对象反映此 Class 对象所表示的类或接口
//包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口的公共方法。
Method[] methods = clazz.getMethods();
for (int i = 0; i < methods.length; i++) {
System.out.println(methods[i]);
}
System.out.println("------------------");
//返回 Method 对象的一个数组,
//这些对象反映此 Class 对象表示的类或接口声明的所有方法,
//包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
Method[] declaredMethods = clazz.getDeclaredMethods();
for (int i = 0; i < declaredMethods.length; i++) {
int modifiers = declaredMethods[i].getModifiers();
System.out.println(declaredMethods[i] + ":"
+ Modifier.toString(modifiers));
}
} catch (Exception e) {
}
}
4、私有方法的调用
public static void invokeMethod(String className) {
try {
Class<?> clazz = Class.forName(className);
//Pear pear = new Pear("hello");
Object pear = clazz.getConstructor(new Class[]{}).newInstance(new Object[]{});
//返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。
//name 参数是一个 String,它指定所需方法的简称,
//parameterTypes 参数是 Class 对象的一个数组,它按声明顺序标识该方法的形式参数类型。
Method declaredMethod = clazz.getDeclaredMethod("setStr", new Class[]{String.class});
//对所有属性设置访问权限 当类中的成员变量为private时 必须设置此项
declaredMethod.setAccessible(true);
//对带有指定参数的指定对象调用由此 Method 对象表示的基础方法。
declaredMethod.invoke(pear, new Object[]{"world"});
Method declaredMethod1 = clazz.getDeclaredMethod("getStr", new Class[]{});
Object result = declaredMethod1.invoke(pear, new Object[]{});
System.out.println((String)result);
} catch (Exception e) {
}
}
5、动态创建、访问数组
public static void printArray() {
try{
Class <?> classType = Class.forName("java.lang.String");
//newInstance创建此 Class 对象所表示的类的一个新实例。
Object array = Array.newInstance(classType, 10);
Array.set(array, 5, "hello");
for(int i =0;i < Array.getLength(array);i ++){
String str = (String)Array.get(array,i);
System.out.println(str);
}
}catch(Exception e){
}
}
本例的包名为code.lemon,参数className为"code.lemon.Pear"
五、具体代码如下
Java反射理解的更多相关文章
- Java反射理解(五)-- 方法反射的基本操作
Java反射理解(五)-- 方法反射的基本操作 方法的反射 1. 如何获取某个方法 方法的名称和方法的参数列表才能唯一决定某个方法 2. 方法反射的操作 method.invoke(对象,参数列表) ...
- Java反射理解(四)-- 获取成员变量构造函数信息
Java反射理解(四)-- 获取成员变量构造函数信息 步骤 获取成员变量信息: obj.getClass() 获取类类型对象 成员变量也是对象,java.lang.reflect.Field 类中封装 ...
- Java 反射理解(三)-- Java获取方法信息
Java 反射理解(三)-- Java获取方法信息 基本的数据类型.void关键字,都存在类类型. 举例如下: public class ClassDemo2 { public static void ...
- Java 反射理解(二)-- 动态加载类
Java 反射理解(二)-- 动态加载类 概念 在获得类类型中,有一种方法是 Class.forName("类的全称"),有以下要点: 不仅表示了类的类类型,还代表了动态加载类 编 ...
- Java 反射理解(一)-- Class 类的使用
Java 反射理解(一)-- Class 类的使用 概念 这里阐述几个基本概念: 在面向对象的世界里,万事万物皆对象.(在 Java 语言中,静态的成员.普通数据类型除外) 类也是对象,类是 java ...
- Java反射机制的学习
Java反射机制是Java语言被视为准动态语言的关键性质.Java反射机制的核心就是允许在运行时通过Java Reflection APIs来取得已知名字的class类的相关信息,动态地生成此类,并调 ...
- Java反射机制(转载)
原文链接:http://www.blogjava.net/zh-weir/archive/2011/03/26/347063.html Java反射机制是Java语言被视为准动态语言的关键性质.Jav ...
- (转载)Java反射机制
Java反射机制是Java语言被视为准动态语言的关键性质.Java反射机制的核心就是允许在运行时通过Java Reflection APIs来取得已知名字的class类的相关信息,动态地生成此类,并调 ...
- java反射机制 + Method.invoke解释 getMethod + 反射理解
功能: 通过读取另一个Dll去创建一个控件(Form,Button,TextBox,DataGridView),然后对当中一些属性进行检查. 创建控件的大致流程是,Assembly->Modul ...
随机推荐
- [PHP] PHP1 与 CGI
早期,一个web程序通过cgi方式提供数据处理,编写cgi程序可以用不同的语言. 这个过程是,我们生成一个服务端可执行程序,处理 web server 传过来的请求,(设置header头)然后返回数据 ...
- Redis之Sentinel高可用安装部署
背景: 之前通过Redis Sentinel 高可用实现说明和Redis 复制.Sentinel的搭建和原理说明大致已经介绍了sentinel的原理和实现,本文再次做个简单的回顾.具体的信息见前面的两 ...
- BZOJ ac100题存档
不知不觉AC100题了,放眼望去好像都是水题.在这里就做一个存档吧(特别感谢各位大神尤其是云神http://hi.baidu.com/greencloud和丽洁姐http://wjmzbmr.com/ ...
- Java重写equals()和hashCode()
1.何时需要重写equals() 当一个类有自己特有的 ”逻辑相等”概念(不同于对象身份的概念). 2.设计equals() [1]使用instanceof操作符检查 ”实参是否为正确的类型”. [2 ...
- C# 的四舍五入
c#的四舍五入有两种情况: 1.常规四舍五入 (decimal).ToString("f2") 2.四舍六入五取偶 除1里面的其他方式四舍五入都是四舍六入五取偶.
- [微信小程序-开发工具]快捷键
1.进入快捷键 > > 2.快捷键 1.元素面板 ↑↓:导航元素 →←:展开/折叠 Enter:编辑属性 H:隐藏元素 F2:切换编辑HTML 2.样式窗口 Tab/Shift + T ...
- CAAnimation动画--(旋转/缩放/移动/闪烁)
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #1d9421 } p.p2 { margin: 0.0px 0. ...
- Spring DelegatingFilterProxy
Spring 里面定义了许多 Filter. 比如 OncePerRequestFilter. 如果我们自定义OncePerRequestFilter, 则可以配置到web.xml中进行一些拦截或日志 ...
- yii中调整ActiveForm表单样式
Yii2中对于表单和字段的支持组件为ActiveForm和ActiveField, <?php $form = ActiveForm::begin([ 'id' => 'login-for ...
- 让CEF支持FLASH(非安装插件的形式)
测试环境: CEF3 + CefGlue 下载FLASH的NPAPI DLL文件 , 在CEF目录下新建文件夹plugins,然后把DLL文件放进去即可. 据说下面是PPAPI的方式,未测试 启动的时 ...