一、反射Class 基本分析
反射的基石: Class 字节码
//得到这个类的字节码的实例对象3种
类名.class 如,System.class;
对象.class 如p1.getClass();
Class.for("java.lang.String"); //返回字节码
有9个预定义的Class实例对象
8个基本类型对应的,加1个void
基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象
。 Class cls1 = void.class;
public class TestReflect {
public static void main(String[] args) throws Exception {
String str1 = "abc";
Class cls1 = str1.getClass();
Class cls2 = String.class;
Class cls3 = Class.forName("java.lang.String");
System.out.println(cls1 == cls2);
System.out.println(cls2 == cls3);
System.out.println(cls1.isPrimitive());//是否是一个基本类型的字节码 //flase
System.out.println(int.class.isPrimitive()); //true
System.out.println(int.class == Integer.class); //false
System.out.println(int.class == Integer.TYPE); //基本类型可以写成这样 true
System.out.println(int[].class.isPrimitive()); //false
System.out.println(int[].class.isArray()); //数组的Class实例对象 true
}
}
二、反射加强
反射就是把Java类中的各种成分映射成相应的java类。
---Class对象,类的组成部分: 成员变量,方法,构造方法,包等等信息。
---来获取其中的变量,方法,构造方法,修饰符,包等信息,用相应类的实例对象来表示,
它们是File、Method、Constructor、Package等等
class --->constructor --->new Object
Constructor类
---得到某个类所有的构造方法
Constructor[] constructor = Class.forName("java.lang.Sting").getConstructor();
----得到类中某一个构造方法 //获得方法时要用到类型
Constructor con1 = Class.forName("java.lang.String").getConstructor(StringBuffer.class);
---创造实例对象 //获得调用方法时候用到上面相同类型
1. 通常方式 String str = new String(new StringBuffer("abc"));
2.反射方式 String str = (String)constructor.newInstance(new StringBuffer("abc"));
----Class.newInstance()方法
Sting obj = (String)Class.forName("java.lang.String").newInstance();
//该方法内部得到构造方法,然后用该构造方法创造实例对象。 //用到了缓存机制来保存默认构造方法的实例对象
成员变量的反射---Field类
ReflectPoint.java
public class ReflectPoint {
private int x;
public int y;
public String str1 = "ball";
public String str2 = "basketball";
public String str3 = "itcast";
public ReflectPoint(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return str1+":"+str2+":"+str3;
}
}
//获得其值方法
Field fieldX = pt1.getClass().getDeclaredField("x");//x是private,该方法不管是否私有
fieldX.setAccessible(true); //获得其值X,需要设置可见
System.out.println(fieldX.get(pt1));
//把对象上所有的String成员变量中的"b"换成"a"
main方法中
替换方法
Method类 ---代表某个类上的一个成员方法
----得到类中的某一个方法
Method charAt = Class.forName("java.lang.String").getMethod(charAt,int.class);
---调用方法
1. 通常方式 System.out.println(str.charAt(1));
2.反射方式 System.out.println(charAt.invoke(str,1));
//如果传递给Method对象的invoke()方法的一个参数为null,,,说明该Method对象对应的是一个静态方法
=================用反射方式执行某个类中的main方法
在类中再增加一个类
调用代码如下:
======数组的反射
Array工具类用于完成对数组的反射操作
//不能得到数组中的整个元素类型 ,,只能得到某一个元素类型
对数组进行反射
Object aObj1 = a1;
Object aObj2 = a4;
//Object[] aObj3 = a1;
Object[] aObj4 = a3;
Object[] aObj5 = a4;
System.out.println(a1);
System.out.println(a4);
System.out.println(Arrays.asList(a1));//[[I@42719c]整数没有转,这里必须接收Object数组形式
System.out.println(Arrays.asList(a4)); //[a, b, c, d]字符串就转了
//Object obj = null;
pirintObject(a1);
}
//打印数组
private static void pirintObject(Object obj) {
Class clazz = obj.getClass();
if(clazz.isArray()){
int len = Array.getLength(obj);
for(int i=0;i<len;i++){
System.out.println(Array.get(obj, i));
}
}else{
System.out.println(obj);
}
}
内省 --IntroSpector -->JavaBean--->特殊的Java类
JDK中提供了对JavaBean进行操作的一些API,这套API就称为内省。
如果要在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象(Value Object,简称VO)
PropertyDescriptor //import java.beans.PropertyDescriptor; 属性描述
在ReflectPoint中增加set,get方法
IntroSpectorTest.java
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class IntroSpectorTest {
public static void main(String[] args) throws Exception {
ReflectPoint pt1 = new ReflectPoint(3,5);
String propertyName ="x";
//"x"--->"X"-->"getX"-->MethodGetX-->
Object retVal = getProperty(pt1, propertyName);
System.out.println(retVal);
Object value = 7;
setProperty(pt1, propertyName, value);
System.out.println(pt1.getX());
}
//Eclipse重构抽取方法
private static void setProperty(Object pt1, String propertyName,
Object value) throws IntrospectionException,
IllegalAccessException, InvocationTargetException {
PropertyDescriptor pd2 = new PropertyDescriptor(propertyName,pt1.getClass());
Method methodSetX = pd2.getWriteMethod();// 获得应该用于set属性值的方法。
methodSetX.invoke(pt1, value);
}
//Eclipse重构方法获得
private static Object getProperty(Object pt1, String propertyName)
throws IntrospectionException, IllegalAccessException,
InvocationTargetException {
PropertyDescriptor pd = new PropertyDescriptor(propertyName,pt1.getClass());
Method methodGetX = pd.getReadMethod();// 获得应该用于读取属性值的方法。
Object retVal = methodGetX.invoke(pt1);
return retVal;
}
}
----采用遍历BeanInfo的所有属性方式来查找和设置某个ReflectPoint对象的属性. 调用了IntroSpector.getBeanInfo()方法 .封装了JavaBean的信息的。
Apache公司提供了beanutils工具包操作JavaBean,
Beanutils.getProperty(pt1,"x").getClass().getName();//返回String类型
BeanUtils.setProperty(pt1,"x","9"); //因为设置进去是以String. //如传到服务器一个int7是以字符串形式。
假设ReflectPoint增加一个 Date 属性 birthday = new Date();
BeanUtils.setProperty(pt1,"birthday.time","222"); //支持级联操作
Beanutils.getProperty(pt1,"birthday.time");
可以转换成map
map{age:33,name:heima} //java 7..
BeanUtils.setProperty(map,"birthday.time","222"); //map对象
另,PropertyUtils.setProperty(pt1,"x",9); //以int类型存储
------------------------反射的基本操作实例-------------------------------------------------
Person.java
public class Person {
private String name;
private int age;
private static int total;
private Person() {
super();
total++;
}
private Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public static int getTotal() {
return total;
}
public static void setTotal(int total) {
Person.total = total;
}
@Override
public String toString() {
return "name:"+name+",age:"+age;
}
}
测试类
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Scanner;
@SuppressWarnings("unchecked")
public class TestReflection {
public static void main(String[] args) {
System.out.println("请输入类型名称:");
Scanner scan = new Scanner(System.in);
String className = scan.next();
System.out.println("当前类型:"+className);
try {
Class c = Class.forName(className);
//解析属性
Field[] fs = c.getDeclaredFields();
for(Field f : fs){
System.out.println("-----------------------");
System.out.println("属性:"+f.toString());
System.out.println("/t数据类型:"+f.getType());
System.out.println("/t属性名称:"+f.getName());
int mod = f.getModifiers(); //返回这个字段的修饰符
System.out.println("/t属性修饰符:"+ Modifier.toString(mod));
}
//解析方法
Method[] ms = c.getDeclaredMethods();
for(Method m :ms){
System.out.println("-----------------------");
System.out.println("方法:"+m.toString());
System.out.println("/t方法名:"+m.getName());
int mod = m.getModifiers(); //返回这个字段的修饰符
System.out.println("/t方法修饰符:"+ Modifier.toString(mod));
System.out.print("/t方法参数列表:");
Class pts[] = m.getParameterTypes(); //参数列表
for(int i=0;i<pts.length;i++){
Class class1 = pts[i];
if(i!=0)
System.out.print(","); //这里标逗号,值得借鉴
System.out.print(class1);
}
System.out.println();
System.out.println("/t返回值类型:"+m.getReturnType());// 方法的返回值类型
}
System.out.println("-构造方法信息-----------------------------------");
//解析构造方法
Constructor[] cs = c.getConstructors();
for(Constructor con :cs){
System.out.println("-----------------------");
System.out.println("构造方法:"+con.toString());
System.out.println("/t构造方法名:"+con.getName());
int mod = con.getModifiers();
System.out.println("/t方法修饰符:"+ Modifier.toString(mod));
System.out.println("/t方法参数列表:");
Class pts[] = con.getParameterTypes(); //参数列表
for(int i=0;i<pts.length;i++){
Class class1 = pts[i];
if(i!=0)
System.out.print(","); //这里标逗号,值得借鉴
System.out.print(class1);
}
System.out.println();
}
System.out.println("------------------------------------");
//解析当前类型的父类
Class getSuper = c.getSuperclass();
System.out.println("当前父类:"+getSuper.toString());
System.out.println("----------------");
//当前实现的接口
Class[] interfaces = c.getInterfaces();
System.out.println("当前实现的所有接口:");
for(Class class1 : interfaces){
System.out.println(class1.toString()+"/t");
}
System.out.println("/n------------------------------------");
//当前所在包信息
Package p =c.getPackage();
System.out.println("当前所在包:"+c.toString());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
=====
User.java
public class User {
public String name;
public int age;
public static int total=10;
/* public User() {
super();
total++;
}*/
public User(String name, int age) {
super();
this.name = name;
this.age = age;
total++;
}
public void setAll(String name,int age){
this.name = name;
this.age = age;
}
public static void showTotal(){
System.out.println("int total showTotal,total="+total);
}
public String toString(){
return "用户名:"+name+",年龄:"+age;
}
}
测试
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class TestRefUer {
public static void main(String[] args) throws Exception {
User u1 = new User("dd", 33);
TestRefUer tf = new TestRefUer();
System.out.println("-------------------------------");
tf.mdf(u1, "name", "刷个");
tf.mdf(u1, "age", 13);
System.out.println(u1);
System.out.println("-------------------------------");
tf.mdf1("Reflect.User", "total", 44);
System.out.println("-------------------------------");
// Class[] argtype = new Class[]{String.class,int.class};
Class[] argtype = {String.class,int.class}; //同上...
Object[] argss = new Object[]{"王武",88};
tf.mdf2(u1, "setAll", argtype, argss);
System.out.println(u1);
System.out.println("-------------------------------");
tf.mdf4("Reflect.User", "showTotal", new Class[0], new Object[0]);
}
//直接操作对象属性
public void mdf(Object o,String fieldName,Object newValue) throws Exception{
Class c = o.getClass();
Field f = c.getField(fieldName);
Object field = f.get(o);
System.out.println("修改前:"+fieldName+"="+field);
f.set(o, newValue);
System.out.println("修改后:"+fieldName+"="+f.get(o));
}
//直接操作类属性
public void mdf1(String o,String fieldName,Object newValue) throws Exception{
Class c = Class.forName(o);
Field f = c.getField(fieldName);
Object field = f.get(o);
System.out.println("修改前:"+fieldName+"="+field);
f.set(c, newValue); //这里操作的是class对象
System.out.println("修改后:"+fieldName+"="+f.get(c));
}
//调用对象成员,赋值
public void mdf2(Object obj,String methodName,Class[] argType,Object[] args) throws Exception{
Class c = obj.getClass();
Method m = c.getMethod(methodName, argType);
Object result = m.invoke(obj, args);
//System.out.println(result);
}
//调用类成员方法
public void mdf4(String obj,String methodName,Class[] argType,Object[] args) throws Exception{
Class c = Class.forName(obj);
Method m = c.getMethod(methodName, argType);
Object result = m.invoke(null, args);
//System.out.println(result);
}
}
=========调用构造方法
import java.lang.reflect.Constructor;
public class TestRefUser2 {
public static void main(String[] args) {
Class c ;
try {
//调用有参构造方法
c = Class.forName("Reflect.User");
Class[] argTypes = {String.class,int.class}; //此处为User类的有参构造方法参数类型
Constructor cons = c.getConstructor(argTypes);
Object obj = cons.newInstance("中国",5333);
System.out.println(obj);
//调用无参
cons =c.getConstructor();
//等同cons = c.getConstructor(new Class[0]);
//cons = c.getConstructor(null);
obj = cons.newInstance();
System.out.println(obj);
//调用参构造方法2
obj = c.newInstance();
System.out.println(obj+"dd");
} catch (Exception e) {
}
}
}
=========一个例子,用Hashtable存储对象======
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;
//通过读取到文件中的值存储到Hashtable的KEY对象中去
public class TestRefHash {
private static Hashtable mySession;
static {
mySession = new Hashtable();
mySession.put("stu", new User());
mySession.put("role", "monitor");
}
public static void main(String[] args) throws Exception {
Properties ps = new Properties();
FileInputStream fis = new FileInputStream("props.txt");
ps.load(fis);
fis.close();
Enumeration pnames = ps.propertyNames();
while(pnames.hasMoreElements()){
String name = (String)pnames.nextElement();
String pvalue = ps.getProperty(name); //通过KEY获得值
TestRefHash.receiveParams("stu", name, pvalue);
}
System.out.println(TestRefHash.mySession.get("stu")); //打印键值
}
public static void receiveParams(String beanName,String propertyName,String pValue)throws Exception{
Object o = mySession.get(beanName); //取得key返回的 User对象
Class c = o.getClass();
String methodName = "set"+propertyName.substring(0,1).toUpperCase()+propertyName.substring(1);
if(methodName.equals("setAge")){
Method method = c.getMethod(methodName, new Class[]{int.class});
//int a =Integer.valueOf(pValue).intValue();
//System.out.println(pValue); pValue是int类型, 不能接收
//method.invoke(o, a); //设定对象方法上的set值
}else{
Method method = c.getMethod(methodName, new Class[]{java.lang.String.class});
method.invoke(o, pValue); //设定对象方法上的set值
}
}
}
====转换字符串INTEGER arraylist
final ArrayList<String> target = new ArrayList<String>();
target.add("sss");
target.add("bbb");
target.add("ccc");
Collection proxy = (Collection) Proxy.newProxyInstance(ArrayList.class.getClassLoader(),
new Class[]{Collection.class},
new InvocationHandler(){
public Object invoke(Object proxy, Method method,
Object[] values) throws Throwable {
if("add".equals(method.getName())){
return method.invoke(target, values);
}
return method.invoke(target, values);
}
});
proxy.add(12);
proxy.add(33);
for(Object o : proxy){
System.out.println(o.toString());
}
System.out.println(proxy.size());
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class ClassMethod { public static void main(String[] args) { Person p = new Person(); try { Method m = p.getClass().getMethod("println",null); m.invoke(p, null); m = p.getClass().getMethod("returns", null); String s = (String) m.invoke(p, null); System.out.println(s); m = p.getClass().getMethod("returns", String.class); s = (String) m.invoke(p, "hello"); System.out.println(s); } catch (Exception e) { e.printStackTrace(); } } } class Person { private String s = "s"; public void println(){ System.out.println("laiba"); } public String returns(){ return "hh"; } public String returns(String s){ return "sss"+s; } }