Java反射机制探秘
如何获得Class对象
1.针对每一个对象.getCalss(),可以得到对应的Class.
2.Class.forName(String),String的写法:包名.类名.就会创建包名.类名对应的那个对象
注:1.2只适用于引用类型
3.对于基本类型:封装类.TYPE代表了对应的基本类型的Class对象.Integer.TYPE对应的是int的Class对象
注:3只适用于基本类型
4.类型,Class。<第4种是通用的.>
上面的4种方法,只有方法2是动态的,只要换一个包就可以了.它具有动态潜质.所以真正意义的想体现动态编程只能使用方法2.
每种类型的Class对象只有一个,即他们的地址只有一个,但是不同类型是不同的.
所以下面的打印结果都为true.
//对与引用类型
Class c1 = "".getClass();
Class c2 = Class.forName("java.lang.String");
Class c3 = String.class;
System.out.println(c1 ==c2);//true
//对于基本类型
Class num1 = Integer.TYPE;
Class num2 = int.class;
System.out.println(num1 == num2);//true
反射获取类中的成员的相关方法
[获取构造<根据参数类型>](使用时一般用不带declared的)
Constructor<T> getConstructor(Class<?>... parameterTypes)
返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
Constructor<?>[] getConstructors()
返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。
Constructor<?>[] getDeclaredConstructors()
返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。
[获取属性<根据属性名>](使用时一般用是带declared的,因为属性一般都是私有的)
Field getField(String name)
返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
Field[] getFields()
返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。
Field getDeclaredField(String name)
返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。
Field[] getDeclaredFields()
返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。
[获取方法<方法名加上参数类型>](使用时一般用不带declared的)
Method getMethod(String name, Class<?>... parameterTypes)
返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
Method[] getMethods()
返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。
Method getDeclaredMethod(String name, Class<?>... parameterTypes)
返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。
Method[] getDeclaredMethods()
返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
T newInstance()
创建此 Class 对象所表示的类的一个新实例。 <new Instance()可以动态的创建对象>
String toString()
将对象转换为字符串。
注意:
new Instance()调用的是无参构造,如果该类没有无参构造方法,则newInstance()会产生异常.
有declared的方法是支持私有,但是不支持继承,无declared的方法支持继承,不支持私有,且只能取出public的东西.
因此取属性的时候一般来说是带declared的,因为属性一般都是私有的,取方法时一般是不带declared的,取构造时一般也是不带declared的.
实例模拟反射获取类中的相关属性和方法
利用反射对属性赋值
Field中的方法
Object get(Object obj)
返回指定对象上此 Field 表示的字段的值。
Field f = c.getXXField(属性名);
值 = f.get(对象);
void set(Object obj, Object value)
将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
f.set(对象,值);
Class<?> getType()
返回一个 Class 对象,它标识了此 Field 对象所表示字段的声明类型。
用于获取属性的类型(返回Class对象).
Class c = Student.class;
Object obj = c.newInstance(); //创建Student类的对象
Field f = c.getDeclaredField("name"); //获取name属性
f.setAccessible(true); //设置私有可以访问.
f.set(obj, "zhangsan");
System.out.println(f.get(obj)); //获取obj的name属性的值.
利用反射调用构造
对于构造真正调用是在调用newInstance()方法时.
Class c = Class.forName("com.clazz.reflect.Student");
Constructor con = c.getConstructor(); //没有执行构造,
Object cObj = c.getConstructor().newInstance();//调用无参的构造方法
Constructor conAll = c.getConstructor(int.class,String.class,int.class);
Object caobj = conAll.newInstance(1001,"zjamgs",234235);//调用含参的构造方法.
System.out.println(caobj); //打印输出
利用反射调用方法
对象.方法名(值1,2,3);
Method m = c.getMethoed(方法名,参数类型...);
m.invoke(对象,方法调用的参数 )如果底层方法所需的形参数为 0,则所提供的 args 数组长度可以为 0 或 null。
Class c = Class.forName("com.clazz.reflect.Student");
Object obj = c.newInstance(); //创建Sutdent对象.
Method msetName = c.getMethod("setName", String.class);//obj无须转换类型
msetName.invoke(obj, "zhangsan");//调用方法setName, 并传参.
Method msetId = c.getMethod("setId", int.class);
msetId.invoke(obj, 409090202);
System.out.println(obj);
反射应用实例
实体类
package org.dennisit.reflect.entity;
import java.io.Serializable;
/**
*
* User.java
*
* @version : 1.1
*
* @author : 苏若年 <a href="mailto:DennisIT@163.com">发送邮件</a>
*
* @since : 1.0 创建时间: 2013-2-26 下午01:43:56
*
* TODO : class User.java is used for ...
*
*/
public class User implements Serializable{ private String test; public void execute(String name,int age){
System.out.println("name=" + name + ",age=" + age);
}
}
反射测试类
package org.dennisit.reflect.main;
import java.lang.reflect.Field;
/**
*
* ReflectEx.java
*
* @version : 1.1
*
* @author : 苏若年 <a href="mailto:DennisIT@163.com">发送邮件</a>
*
* @since : 1.0 创建时间: 2013-2-26 下午01:46:00
*
* TODO : class ReflectEx.java is used for ...
*
*/
public class ReflectEx { public static void main(String[] args)throws Exception {
Class cls = Class.forName("org.dennisit.reflect.entity.User");
Object obj = cls.newInstance(); //创建User的对象
Field f = cls.getDeclaredField("test"); //获取test属性
f.setAccessible(true); //打开私有属性test的访问权限
f.set(obj, "zhangsan"); //为test重新复制
System.out.println(f.get(obj)); //获取obj的test属性值
//根据方法名execute获取方法
java.lang.reflect.Method m = cls.getMethod("execute", String.class, int.class);
m.invoke(obj, "dennisit",23); //调用execute方法
}
}
运行效果
zhangsan
name=dennisit,age=23
编写一个反射动态实例化类的例子
package org.dennisit.reflect.main;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;
/**
*
* DynamicReflect.java
*
* @version : 1.1
*
* @author : 苏若年 <a href="mailto:DennisIT@163.com">发送邮件</a>
*
* @since : 1.0 创建时间: 2013-2-26 下午01:58:12
*
* TODO : 利用反射动态实例化的例子
*
*/
public class DynamicReflect { public static Object getInstance(String className,Map<String,Object> map)throws Exception{
Class c = Class.forName(className);
Object obj = c.newInstance(); //对象对象
Set<String> keys = map.keySet(); //获取对应的所有属性
Field[] fAll = c.getDeclaredFields(); //获取类中所有属性
for(int i=0;i<fAll.length;i++){
for(String key:keys){ //循环匹配
if(fAll[i].getName().equals(key)){ //如果用户传入的属性跟获取到的类中的属性名匹配
Field f = c.getDeclaredField(key);//获取该属性
//构建setXxx()方法名
String methodName = "set" + key.substring(0,1).toUpperCase()+key.substring(1);
Method method = c.getMethod(methodName, f.getType());//根据构建的用户名获取对应的方法
method.invoke(obj, map.get(key));//方法调用
}else{
continue;
}
}
}
return obj;
}
}
接下来我们测试我们编写的动态反射实例化例子
实体类
package org.dennisit.reflect.entity;
import java.io.Serializable;
/**
*
* User.java
*
* @version : 1.1
*
* @author : 苏若年 <a href="mailto:DennisIT@163.com">发送邮件</a>
*
* @since : 1.0 创建时间: 2013-2-26 下午01:43:56
*
* TODO : 实体类
*
*/
public class User implements Serializable{ private String name;
private int age;
private String email; public User() { //必须有无参构造 } //getter() and setter() }
主测试类
package org.dennisit.reflect.main;
import java.util.HashMap;
import java.util.Map;
import org.dennisit.reflect.entity.User;
/**
*
* ReflectEx.java
*
* @version : 1.1
*
* @author : 苏若年 <a href="mailto:DennisIT@163.com">发送邮件</a>
*
* @since : 1.0 创建时间: 2013-2-26 下午01:46:00
*
* TODO : class ReflectEx.java is used for ...
*
*/
public class ReflectEx { public static void main(String[] args)throws Exception {
Class cls = Class.forName("org.dennisit.reflect.entity.User");
String className = "org.dennisit.reflect.entity.User";
Map<String,Object> map = new HashMap<String, Object>();
map.put("name", "dennisit");
map.put("age", 22);
map.put("email", "dennisit@163.com"); User user = (User)DynamicReflect.getInstance(className, map);
System.out.println(user.getName() + "," + user.getAge() + "," + user.getEmail());
}
}
程序运行结果
dennisit,22,dennisit@163.com
Java反射机制探秘的更多相关文章
- 第28章 java反射机制
java反射机制 1.类加载机制 1.1.jvm和类 运行Java程序:java 带有main方法的类名 之后java会启动jvm,并加载字节码(字节码就是一个类在内存空间的状态) 当调用java命令 ...
- Java反射机制
Java反射机制 一:什么事反射机制 简单地说,就是程序运行时能够通过反射的到类的所有信息,只需要获得类名,方法名,属性名. 二:为什么要用反射: 静态编译:在编译时确定类型,绑定对象,即通过 ...
- java基础知识(十一)java反射机制(上)
java.lang.Class类详解 java Class类详解 一.class类 Class类是java语言定义的特定类的实现,在java中每个类都有一个相应的Class对象,以便java程序运行时 ...
- java基础知识(十一)java反射机制(下)
1.什么是反射机制? java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象都能够调用他的属性和方法,这种动态获取属性和方法的功能称为java的反射机制. ...
- Java反射机制专题
·Java Reflection Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方 ...
- java反射机制深入详解
java反射机制深入详解 转自:http://www.cnblogs.com/hxsyl/archive/2013/03/23/2977593.html 一.概念 反射就是把Java的各种成分映射成 ...
- Java反射机制DOME
Java反射机制 public class TestHibernate { @Test public void TestHb(){ try { Class cs = Class.forName(&qu ...
- 反射——Java反射机制
反射概述 什么是反射? ① 反射的概念是由Smith在1982年首次提出的,主要指程序可以访问.检测和修改它本身状态或行为的一种能力. ② JAVA反射机制是在运行状态中,对应任意一个类,都能 ...
- Java反射机制可以动态修改实例中final修饰的成员变量吗?
问题:Java反射机制可以动态修改实例中final修饰的成员变量吗? 回答是分两种情况的. 1. 当final修饰的成员变量在定义的时候就初始化了值,那么java反射机制就已经不能动态修改它的值了. ...
随机推荐
- CentOS 6 下RPM方式安装MySQL5.6
CentOS 6 下RPM方式安装MySQL5.6 1. 下载Linux对应的RPM包,如:CentOS6.7_64对应的RPM包,如下:[root@mysql ~]# ll总用量 113808-rw ...
- rac 11g_生产库日志组损坏处理
原创作品,出自 "深蓝的blog" 博客,转载时请务必注明出处,否则有权追究版权法律责任. 深蓝的blog:http://blog.csdn.net/huangyanlong/ar ...
- ThreadContext
//#define UseThreadContext using System; using System.Collections.Generic; using System.Linq; using ...
- ASP.Net:Table类的使用
在做Asp.Net的时候,很多情况下数据的绑定都是使用GridView或者我之前提到的ListView,但是这两个适合用于数据的绑定,而有些时候,数据需要在后台进行处理,例如数据据内地某一条数据的特殊 ...
- TKinter布局之grid 网格布局
1.由于我们的程序大多数都是矩形,因此特别适合于网格 布局,也就是 grid 布局. 2.使用 grid 布局的时候,我们使用 grid 函数,在里面指 定两个参数,用 row 表示行,用 colum ...
- 【性能诊断】四、单功能场景的性能分析(RedGate,找到同一个客户端的并发请求被串行化问题)
问题描述: 客户端js连续发起两个异步http请求,请求地址相同,但参数不同:POST http://*.*.*.*/*****/webservice/RESTFulWebService/RESTFu ...
- 简单了解ddos攻击
1.一种为流量攻击,主要是针对网络带宽的攻击,即大量攻击包导致网络带宽被阻塞,合法网络包被虚假的攻击包淹没而无法到达主机: 2.另一种为资源耗尽攻击,主要是针对服务器主机的攻击,即通过大量攻击包导致主 ...
- 初试体验java多线程
现在个人电脑以及服务器都是多核cpu,如何提高多核cpu的利用率,就要用到多线程技术了. public class TestThread1 { ; static class PThread exten ...
- 每日学习心得:未定义的命名空间前缀"xsd"问题和<%%>、<%=%>、<%$%>、<%@%>的区别
2013-6-29 1. 未定义的命名空间前缀“xsd” 上周在项目开发中遇到这样的一个问题,在一个页面用到了自定义的Picker控件,在IE6.7.8.9以及IE10兼容模式下都没有任何问题,但是一 ...
- linux下的chmod,chown和chgrp
对于linux的权限掌握以下几个命令就可以非常熟练的操作系统中的各种权限了. 使用权限 : 所有使用者 使用方式 : chmod [-cfvR] [--help] [--version] mode f ...