java_反射
来源:互联网 发布:环保75标准数据 编辑:程序博客网 时间:2024/06/11 02:43
Java 反射
一 认识反射
l “程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。
l 尽管在这样的定义与分类下Java不是动态语言,它却有着一个非常突出的动态相关机制:Reflection。
l 什么是反射
a) 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。
b) JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
l 应用场景
Ø Spring框架:IOC(控制反转)
Ø Hibernate框架:关联映射等
Ø 白盒测试
二 反射讲解
l 什么是反射:
可以通过类名动态的创建对象,可以根据对象获取类中所有的属性和方法。
l 获取Class
根据字符串得到类名Class cls=Class.forName(String className);
根据对象获取类:Class =obj.getClass();
根据类获取类:Class cls =Person.class;
根据全路径来获取:Class cls=Class.forName(报名.类名);
l 获取属性
获取所有属性Filed[] filed =cls.getDeclaredFields();
获取所有公共属性: Filed[] fields=cls.getFileds();
获取指定属性:Field fields=cls.getDeclaredFiled(Stringname)
取得指定公共属性Field fields=cls.getField(String name)
l 取得方法
获得所有方法: Methodmethods=cls.getDeclaredMethods();
获取所有公共方法:Method[] methods=cls.getMethods();
取得指定的方法:Method method=cls.getDeclaredMethod(Stringname,Class[] paramsType);
获取指定公共的方法: Method method =cls.getMethod(Stringname,Class[] paramsType);
l 获取构造方法
获得使用特殊的参数类型的公共构: Constructor constructor=cls.getConstructor(Class[]params)
获得类的所有公共构造函数:Constructor[] constructor=cls. getConstructors()
获得使用特定参数类型的构:Constructor constructor=cls.getDeclaredConstructor(Class[]params)
获得类的所有构造函数:Constructor[] constructor=cls.getDeclaredConstructors()
l 执行某个方法
Method.invoke(Object target,Object[] params);
List获取类:
获取方式
说明
示例
object.getClass()
每个对象都有此方法
获取指定实例对象的Class
List list = new ArrayList();
Class listClass = list.getClass();
class. getSuperclass()
获取当前Class的继承类Class
List list = new ArrayList();
Class listClass = list.getClass();
Class superClass = listClass. getSuperclass();
Object.class
.class直接获取
Class listClass = ArrayList.class;
Class.forName(类名)
用Class的静态方法,传入类的全称即可
try {
Class c = Class.forName("java.util.ArrayList");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Primitive.TYPE
基本数据类型的封装类获取Class的方式
Class longClass = Long.TYPE;
Class integerClass = Integer.TYPE;
Class voidClass = Void.TYPE;
平常情况我们通过new Object来生成一个类的实例,但有时候我们没法直接new,只能通过反射动态生成。
实例化无参构造函数的对象,两种方式:
①Class. newInstance();
②Class. getConstructor (new Class[]{}).newInstance(new Object[]{})
实例化带参构造函数的对象:
clazz.getConstructor(Class<?>... parameterTypes) .newInstance(Object... initargs)
程序实例:
public class BaseUser {
private StringId;
private Stringname;
public BaseUser(){
}
public BaseUser(String name, String id) {
super();
this.name = name;
Id = id;
}
public String getId() {
returnId;
}
public String getName() {
returnname;
}
public voidsetId(String id) {
Id = id;
}
public voidsetName(String name) {
this.name = name;
}
public String toString() {
return"BaseUser[name=" +name + ", Id="+Id + "]";
}
}
public class User extendsBaseUser {
private Stringsex;
public User(){
}
public User(String sex) {
super();
this.sex = sex;
}
public User (String id,String name,String sex){
super(name, id);
this.sex=sex;
}
public String getSex() {
returnsex;
}
public voidsetSex(String sex) {
this.sex = sex;
}
public String toString() {
return"User[sex=" +sex +", name="+this.name+", id="+this.Id+"]";
}
}
测试类:
public classReflaceTest {
/**
* @param args
* @throws SecurityException
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public static void main(String[] args)throwsIllegalArgumentException, InvocationTargetException, NoSuchMethodException,SecurityException, InstantiationException, IllegalAccessException {
// TODO Auto-generated method stub
Class cls= User.class;
User user=(User) cls.newInstance();
System.out.println(user);
User user2=(User) cls.getConstructor(new Class[]{}).newInstance(new Object[]{});
System.out.println(user2);
User user3=(User)cls.getConstructor(new Class[]{String.class,String.class,String.class}).newInstance(new Object[]{"肖正文","xwx354128","男"});
System.out.println(user3);
User user4=newUser("男");
System.out.println(user4);
Class clss=Class.forName("xiao.it.base.User");
User u=(User) clss.newInstance();
System.out.println(u);
}
}
User [sex=null,name=null, id=null]
User [sex=null,name=null, id=null]
User [sex=男, name=xwx354128, id=肖正文]
User [sex=男, name=null, id=null]
User [sex=null,name=null, id=null]
Ø 获得当前类以及超类的public Method:
– Method[] arrMethods = classType. getMethods();
Ø 获得当前类申明的所有Method:
– Method[] arrMethods = classType. getDeclaredMethods();
Ø 获得当前类以及超类指定的public Method:
– Method method = classType. getMethod(String name,Class<?>... parameterTypes);
Ø 获得当前类申明的指定的Method:
– Method method = classType. getDeclaredMethod(String name,Class<?>... parameterTypes)
Ø 通过反射动态运行指定Method:
– Object obj = method.invoke(Object obj, Object... args)
反射的方式进行方法的调用
public class Methodss {
/**
* @param args
* @throwsSecurityException
* @throwsNoSuchMethodException
* @throwsInvocationTargetException
* @throwsIllegalArgumentException
* @throwsIllegalAccessException
* @throwsInstantiationException
*/
public static void main(String[] args)throws NoSuchMethodException,SecurityException, IllegalAccessException, IllegalArgumentException,InvocationTargetException, InstantiationException {
// TODO Auto-generatedmethod stub
Class<?> cls=User.class;
User u=(User) cls.newInstance();
Method[] me=cls.getMethods();
for(Method m:me){
System.out.println("本类与超类的公共方法"+m);
}
Method setId=cls.getMethod("setId",new Class[]{String.class});
System.out.println("当前类或是父类的setId方法"+setId); System.out.println("===========================");
Method[] me1=cls.getDeclaredMethods();
for(Method m:me1){
System.out.println("本类的方法"+m);
}
System.out.println("===========================");
Method setSex=cls.getDeclaredMethod("setSex",new Class[]{String.class});
System.out.println("本类的方法的setSex方法"+setSex);
//不做java访问语言检查,类外访问私有字段
setId.setAccessible(true);
setId.invoke(u, new Object[]{"xwx354128"});
System.out.println("反射的方式调用父类或本类的方法"+cls.getMethod("getId",new Class[]{}).invoke(u, new Object[]{}));
System.out.println("==========================");
setSex.setAccessible(true);
setSex.invoke(u, new Object[]{"男"});
System.out.println("反射的方式调用本类的方法"+cls.getMethod("getSex",new Class[]{}).invoke(u, new Object[]{}));
System.out.println("========================");
}
}
测试结果:
本类与超类的公共方法public java.lang.String xiao.it.base.User.toString()
本类与超类的公共方法public void xiao.it.base.BaseUser.setId(java.lang.String)
本类与超类的公共方法public java.lang.String xiao.it.base.BaseUser.getName()
本类与超类的公共方法public java.lang.String xiao.it.base.BaseUser.getId()
本类与超类的公共方法public voidxiao.it.base.BaseUser.setName(java.lang.String)
本类与超类的公共方法public final void java.lang.Object.wait() throws java.lang.InterruptedException
本类与超类的公共方法public final void java.lang.Object.wait(long,int) throwsjava.lang.InterruptedException
本类与超类的公共方法public final native void java.lang.Object.wait(long)throwsjava.lang.InterruptedException
本类与超类的公共方法public boolean java.lang.Object.equals(java.lang.Object)
本类与超类的公共方法public native int java.lang.Object.hashCode()
本类与超类的公共方法public final native java.lang.Classjava.lang.Object.getClass()
本类与超类的公共方法public final native void java.lang.Object.notify()
本类与超类的公共方法public final native void java.lang.Object.notifyAll()
当前类或是父类的setId方法public void xiao.it.base.BaseUser.setId(java.lang.String)
===========================================
本类的方法public void xiao.it.base.User.setSex(java.lang.String)
本类的方法public java.lang.String xiao.it.base.User.getSex()
本类的方法public java.lang.String xiao.it.base.User.toString()
===========================================
本类的方法的setSex方法public void xiao.it.base.User.setSex(java.lang.String)
反射的方式调用父类或本类的方法xwx354128
===========================================
反射的方式调用本类的方法男
===========================================
Ø 获得当前类以及超类的publicField:
– Field[] arrFields = classType. getFields();
Ø 获得当前类申明的所有Field:
– Field[] arrFields = classType. getDeclaredFields();
Ø 获得当前类以及超类指定的publicField:
– Field field = classType. getField(String name);
Ø 获得当前类申明的指定的Field:
– Field field = classType. getDeclaredField(String name);
Ø 通过反射动态设定Field的值:
– fieldType.set(Object obj, Object value);
Ø 通过反射动态获取Field的值:
– Object obj = fieldType. get(Object obj) ;
public class Filedsds {
/**
* @param args
*/
public static void main(String[] args)throws Exception {
// TODO Auto-generatedmethod stub
User u=new User();
Class cls=User.class;
Field [] field=cls.getFields();
for(Field f:field){
System.out.println("子类或者父类的字段属性public型"+f);
}
System.out.println("=======================");
Field [] fileds=cls.getDeclaredFields();
for(Field ff:fileds){
System.out.println("本类字段"+ff);
}
System.out.println("=======================");
Field name=cls.getField("name");
name.setAccessible(true);
name.set(u, "肖正文");
System.out.println("公共类与子类的字段子类或者父类的字段属性public型:"+name.get(u));
System.out.println("=======================");
Field sex=cls.getDeclaredField("sex");
sex.setAccessible(true);
sex.set(u, "女");
System.out.println("本类中声明的方法"+sex.get(u));
System.out.println("=======================");
}
}
运行结果:
子类或者父类的字段属性public型public java.lang.String xiao.it.base.BaseUser.Id
子类或者父类的字段属性public型public java.lang.String xiao.it.base.BaseUser.name
=======================
本类字段private java.lang.String xiao.it.base.User.sex
=======================
公共类与子类的字段子类或者父类的字段属性public型:肖正文
=======================
本类中声明的方法女
=======================
1.检测类:
1.1 reflection的工作机制
import java.lang.reflect.*;
public class DumpMethods {
public static voidmain(String args[]) {
try {
Class c =Class.forName(args[0]);
Method m[] =c.getDeclaredMethods();
for (int i = 0; i< m.length; i++)
System.out.println(m[i].toString());
} catch (Throwable e){
System.err.println(e);
}
}
}
按如下语句执行:
java DumpMethods java.util.Stack
它的结果输出为:
public java.lang.Object java.util.Stack.push(java.lang.Object)
public synchronized java.lang.Objectjava.util.Stack.pop()
public synchronized java.lang.Objectjava.util.Stack.peek()
public boolean java.util.Stack.empty()
public synchronized intjava.util.Stack.search(java.lang.Object)
这样就列出了java.util.Stack 类的各方法名以及它们的限制符和返回类型。
这个程序使用 Class.forName 载入指定的类,然后调用getDeclaredMethods 来获取这个类
中定义了的方法列表。java.lang.reflect.Methods 是用来描述某个类中单个方法的一个类。
框架应用案例:hibernate
已知有一个user实体(属性id,name,phone)需要被update
我们的解决方式其实很简单:
首先User loadUser = session.load(user.getId); 此时loadUser是持久化的
然后使用loadUser.setXXX(user.getXXX)方法把需要更新的字段set一下
至于怎么判断哪些属性需要更新,我们可以通过反射先获得所有的getXXX方法,然后逐个invoke获得它们的值,判断一下如果值需要更新才执行loadUser.setXX(user.getXXX)
框架应用案例之spring IOC
只要用到反射,先获得Class Object
没有方法能获得当前类的超类的private方法和属性,你必须通过getSuperclass()找到超类以后再去尝试获得
通常情况即使是当前类,private属性或方法也是不能访问的,你需要 设置压制权限setAccessible(true)来取得private的访问权。但说实话,这已经破坏了面向对象的规则,所以除非万不得已,请尽量少用。
- Java_反射
- JAVA_反射
- java_反射
- java_反射
- JAVA_反射
- Java_反射
- Java_反射
- java_反射
- java_什么是反射?
- Java_反射机制
- java_反射日记
- Java_反射机制
- Java_反射(reflect)
- Java_反射_内省JavaBean
- Java_反射的基本应用
- Java_反射技术_简述
- 第十三章:Java_反射机制
- java_反射个人理解简记
- Windows:服务主机:本地系统(网络受限) CPU利用率高,磁盘利用率高
- codeblock 配置 opencv
- 乘法器仿真问题
- S5PV210(TQ210)学习笔记——内存配置(DDR2)
- 轻松学习自定义控件实现表钟效果-进阶篇新手必看,分分钟搞定自定义View
- java_反射
- 【android文件存放路径】
- linux kernel poll & 等待队列
- c程序插入背景音乐(复制到他人电脑也能使用)
- yii邀请好友,分页
- IT 照亮未来
- swift笔记-提醒控件
- Posted和Non-Posted传送方式
- 版本更新(自开服务器版)