您的位置:首页 > 职场人生

黑马程序员——反射

2015-05-30 16:02 288 查看
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
< 今日心情 >放掉懒惰,再加上一份坚持

反射

映射就是将类中的各种成分映射成class类

类中的成分有:

Constructor 构造函数

Method 方法

Field 字段

import java.lang.*;
import java.lang.reflect.*;
import java.util.regex.*;
class ReflectDemo
{
/*
映射一个People类,已知这个类
类中有含有两个成员变量
name-->姓名
email-->电子邮箱
这个类是单例模式
这个类的对象被使用时将不能再次被获取,直到使用者释放该对象的使用(调用该类的方法释放)

要求:
1.即使这个类的对象被使用,也可以获取
2.改变name的值和email的用户名,不改变email的域名

分析:
1.通过反射获取该类的类类型实例
2.通过实例获得构造方法的Constructor实例
3.改变并使构造方法的访问权限失效
4.创建People对象
5.通过该实例获取类的成员变量name和email的值
6.改变并使成员变量的访问权限失效
7.改变成员变量的值并赋值给对象

*/
public static void main(String[] args) throws Exception
{
//对象已经被使用
People p=People.getPeople();
People p0=People.getPeople();

//三种方式获得people类的类实例
Class c1=p.getClass();
Class c2=People.class;
Class c3=Class.forName("People");

//反射出该类的构造函数并创建对象
Constructor cr1=c1.getDeclaredConstructor();
cr1.setAccessible(true);
People p1=cr1.newInstance();

//反射该类的成员变量,改变对象中成员变量的值
Field fName=c2.getDeclaredField("name");
fName.setAccessible(true);
Field fEmail=c2.getDeclaredField("email");
fEmail.setAccessible(true);

String newEmail=((String)fEmail.get(p1)).replaceAll(".+(@)","你猜$1");
//正则:String newEmail=Pattern.compile(".+(@)").matcher((String)fEmail.get(p1)).replaceFirst("你猜$1");
fEmail.set(p1,newEmail);
fName.set(p1,"你猜");

//反射封装的show方法并调用
Method mShow=c1.getDeclaredMethod("show");
mShow.setAccessible(true);
System.out.println("第一次使用,p:"+p);
mShow.invoke(p);
System.out.println("第二次使用,p0:"+p0);
System.out.println("反射后使用,p1:"+p1);
mShow.invoke(p1);
/*
补充说明:
get成分(成分名字,可变形参类型列表)
get后加Declared可以获得被访问权限限制的成分,使用时要将其accessible设置为true
invoke(对象名,可变实参列表)
前面的方法在类中属于静态成员时,对象名为null
*/
}
}

class People
{
private String email="bace@qq.com";
private String name="zhangsan";
//单例设计模式,私有一个本类对象
private static final People people=new People();
//标记该对象是否被使用或被释放
private static boolean flag=false;

//私有构造方法,单例设计模式
private People()
{

}
//获取该类的对象,在这个对象被使用并被释放以前不能再次获取
public static People getPeople()
{
if(flag)
{
System.out.println("该工作人员已经派出,请等待!");
return null;
}
else
{
flag=true;
people.show();
return people;
}
}

//封装的功能代码
private void show()
{
System.out.println("name:"+name+"---Email:"+email);
System.out.println("为您服务!");
}
public void release()
{
flag=true;
}
}
method.invoke(Object obj,Object...args)
可以使用该方法调用反射获得类中的方法,obj为该类的一个实例

反射获得类中的方法是用数组做形参时,不能直接使用数组做参数传递。
原因:
在jdk1.4中,对invoke方法的定义为:invoke(Object obj,Object[] objs)
由向下兼容的原则,当把数组引用直接传递进来时,javajdk1.4的语法进行处理
即,把数组拆分成若干个参数来处理
解决办法:
invoke(obj,new Object(){new XX[]{XX,XX..}})
invoke(obj,(Object)new XX[]{XX,XX..})

数组的反射
数组也是一个类对象,通过class类的isArray方法判断反射的类是否是数组类,
借用Array工具类的get方法获取数组中的元素

如:

public static void print(Object obj)
{
Class array=obj.getClass();
if(array.isArray())
for(int i=0;i
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息