------------android培训 java培训 期待与您的交流!--------------
/*
* 反射的基础------->Class类:描述各个Java类的一个类
* 字节码 一个类的标识,使用时,从硬盘上加载进来
*/
//得到字节码对应的实例对象的三种方式
Date date=new Date();
Class c1=Date.class //--> 通过类名:c1指向内存中已加载的类的字节码
date.getClass(); //--> 通过类创建的实例对象:调用getClass方法返回自己所属于的字节码
Class.forName("java.lang.String"); //--> 通过Class类的静态方法 比较常用 可以由String临时送进来
//如果已经加载,则直接返回类的字节码,没有加载过,则调用类加载器去加载到缓存区,再返回
//八个基本类型 boolean byte char short int long float double和一个void都有Class objects
//反射实例代码1 Class基本分析
public class ReflecTest1
{
public static void main(String [] args ) throws Exception
{
}
public static void test1() throws Exception
{
String str1="hello";
Class c1=str1.getClass();
Class c2=String.class;
Class c3=Class.forName("java.lang.String");
//验证他们在内存中是否是同一个字节码
System.out.println(c1==c2); //true
System.out.println(c1==c3); //true
System.out.println(c1.isPrimitive()); //是否是基本类型 否
System.out.println(int.class==Integer.class); //false
System.out.println(int.class==Integer.TYPE); //常量标示被包装的基本类型
System.out.println(int [].class.isPrimitive()); //数组不是基本类型 数组类型的Class实例对象用Class.isArray()
//总之,只要是在源程序中出现的类型,都有各自的Class实例对象
}
}
//反射实例代码2 反射知识
/*
*反射就是把Java类中的各种成分 映射成相应的所属的Java类
*Class表示Java类
*以下类都是对不同java类的不同成分的统一管理
*Method类 代表某个类的一个成员方法
*Constructor类 代表某个类中的构造方法
*Field类 代表某个类的一个成员变量
*/
//Constructor类分析
//通过参数来区别所要获取的构造方法 jdk.1.5之后的可变参数
Constructor const1=String.class.getCostructor(StringBuffer.class); //const1反射String类的一个构造方法
//实现const1反射的构造方法 要用到相同的参数类型,否则会报错
String str2=(String)const1.newInstance(new StringBuffer("hello"));
//Class.newInstance()------>对应无参数的构造方法
String str21=(String)Class.forName("java.lang.String").newInstance();
//Field类分析与案例
public class ReflectPoint
{
private int x;
public int y;
public ReflectPoint(int x,int y)
{
super();
this.x=x;
this.y=y;
}
}
import java.lang.reflect.Field;
public class ReflectPointTest
{
public static void main(String [] args ) throws Exception
{
ReflectPoint pt1=new ReflectPoint(5,20);
Field fY=pt1.getClass().getField("y");//将类的y字段转为Field对象
//--->fY不代表一个某个对象的具体值,只代表类上一个变量
System.out.println(fY.get(pt1)); //取出对象pt1的y变量的值
Field fX=pt1.getClass().getDeclaredField("x");//只要定义了就能让你反射到。(不管这个变量是否私有)
//暴力反射
fX.setAccessible(true); //私有变量可以通过get获取到
System.out.println(fX.get(pt1));
}
}
//关于Field的一个反射小案例:将任意的一个对象中的所有String类型的成员变量所对应的字符串内容的'b'改写成'a'
import java.lang.reflect.Field;
class ReflectPoint1
{
public String str1="abcde";
public String str2="borball";
public String str3="niubi";
@Override
public String toString()
{
return str1+"\t"+str2+"\t"+str3;
}
}
class ReflectPoint1Test
{
public static void main(String [] args)throws Exception
{
ReflectPoint1 rp1=new ReflectPoint1();
changeStringValue(rp1);
System.out.println(rp1);
}
public static void changeStringValue(Object obj) throws Exception //将案例单独做成一个函数
{
Field [] fields=obj.getClass().getFields();
for (Field field:fields) //加强版的for循环
{
if(field.getType()==String.class) //字段都有类型,两个字节码的比较用==,而不用equals,字节码就一份
{
String oldValue=(String)field.get(obj); //取得字段的值
String newValue=oldValue.replace('b','a'); //替换字符
field.set(obj,newValue); //新的字段写入对象
}
}
}
}
//Method类分析与案例
import java.lang.reflect.Method;
//Method的用法
class MethodTest
{
public static void main(String [] args) throws Exception{
Method funCharAt=String.class.getMethod("charAt",int.class); //funCharAt就是String的成员方法CharAt();这里也一样通过参数区分重载问题
String str1="abcde";
//如果第一个参数是null;说明是静态方法 下面等价于str1.CharAt(1);
System.out.println(funCharAt.invoke(str1,1)); //调用Method的invoke来实现被其反射到的方法
}
}
//小案例要求: 写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法
class MethodTest1
{
public static void main(String []args ) throws Exception
{
MethodTest.main(new String [] {});//普通方式调用
//反射方式,在不知道类名,类名由args[0]传入
String className=args[0];
Method funMain=Class.forName(className).getMethod("main",String [].class); //反射到你传入的那个类的main方法
funMain.invoke(null,new Object[]{new String[]{"dawd","daw"}}); //必须将数组在封装成一个对象,数组才不会拆包
//(null,(Object)new String[]{"dawd",dwad}) 这两种方式在调用这个数组时都不会将数组拆包
}
}