反射入门2(使用反射生成和操作对象)
来源:互联网 发布:mac双系统开机切换 编辑:程序博客网 时间:2024/06/10 02:43
/*<<java学习笔记>>读后思
反射入门2(使用反射生成和操作对象)
author: shine
*/
1 生成对象
1) 若一个类有无参数的构造函数,则可以使用Class的newInstance()方法,按照无参的构造函数实例化一个对象,实例化对象以Object类型返回。
Class c = Class.forName(className);
Object obj = c.newInstance();
exp1:
package flectUser;
import java.util.List;
public class NewInstanceDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
Class c = Class.forName("java.util.ArrayList");
List list = (List)c.newInstance();
for (int i = 0; i < 5; i++) {
list.add("element "+i);
}
for (Object o : list.toArray()) {
System.out.println(o);
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
输出结果:
element 0
element 1
element 2
element 3
element 4
2)若要使用反射按照一个有参的构造函数生成实例。就要给newInstance传入参数:
exp2:
//Student.java
package flectUser;
public class Student {
private String name;
private int score;
public Student() {
name = "N/A";
}
public Student(String name,int score) {
this.name = name;
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public String toString() {
return name + ":" + score;
}
}
//NewInstanceDeom2
package flectUser;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class NewInstanceDeom2 {
public static void main(String[] args) {
try {
Class c = Class.forName("flectUser.Student");
//指定参数类型
Class[] params = new Class[2];
//第一参数是String
params[0] = String.class;
//第二个参数是int
params[1] = Integer.TYPE;
//取得对应参数列的构造函数
Constructor constructor = c.getConstructor(params);
//指定变量内容
Object[] argObjs = new Object[2];
argObjs[0] = "shine";
argObjs[1] = 100;
//指定变量并实例化(带参数)
Object obj = constructor.newInstance(argObjs);
System.out.println(obj);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
输出结果:
shine:100
小结:
代码中
params[1] = Integer.TYPE; 获得Integer对应的原始数据类型int
params[1] = Integer.class; 获得Integer(封装类)
............................................................................................................................................................................................................
2 调用方法
1)可以使用反射取回类的方法的对象代表(java.lang.reflect.Method)的实例,通过invoke()方法来动态调用指定的方法。
exp3: (继续使用exp2中flectUser.Student)
package flectUser;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class InvokeMethodDemo {
public static void main(String[] args) {
try {
Class c = Class.forName("flectUser.Student");
Object targetObj = c.newInstance();
//设定setName方法参数类型
Class[] params = new Class[]{String.class};
//根据方法名和参数类型取回方法对象setName
Method setName = c.getMethod("setName", params);
//设定setName传入的参数值
Object[] argObjs1 = new Object[]{"shine"};
//调用setName方法
setName.invoke(targetObj, argObjs1);
//设定setScore方法的参数类型
Class[] params2= new Class[]{Integer.TYPE};
//取得方法对象setScore
Method setScore = c.getMethod("setScore", params2);
//设定setScore方法传入的参数值
Object[] argObjs2 = new Object[]{100};
//调用setScore方法
setScore.invoke(targetObj, argObjs2);
System.out.println(targetObj);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
输出结果:
shine:100
2)上例中是通过getMethod方法来获得方法对象,看到reflect api中除了getMethod以外,还有getDeclaredMethod方法,他们之间有什么区别和联
系呢?
getMethod只能获得public的方法,而如果要得到private或protect的方法,可以通过getDeclaredMethod方法获得。
Method privateMethod = c.getDeclaredMethod.("somePrivateMethod",new Class[] paramTypes);
privateMethod.setAccessible(true);
privateMethod.invoke(targetObj,argObjs);
............................................................................................................................................................................................................
3. 修改成员值
尽管直接存取类的域成员(Field)是不被鼓励的,但仍可以直接存取公开的域成员。甚至于私有域变量。
exp4:
//TestUser.java
package flectUser;
public class TestField {
public int testInt;
private String testStr;
public String toString() {
return testInt + " : " + testStr;
}
}
//AssignFieldDemo.java
package flectUser;
import java.lang.reflect.Field;
public class AssignFieldDemo {
public static void main(String[] args) {
try {
Class c = Class.forName("flectUser.TestField");
Object targetObj = c.newInstance();
//取得公有属性testInt
Field testInt = c.getField("testInt");
//取得私有属性testStr
Field testStr = c.getDeclaredField("testStr");
testStr.setAccessible(true);
//改变域变量的值
testInt.setInt(targetObj, 100);
testStr.set(targetObj, "shine");
System.out.println(targetObj);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
输出结果:
100 : shine
............................................................................................................................................................................................................
4.再来看看反射在数组中的应用。
1)静态数组
exp5:
package flectUser;
public class ArrayDemo {
public static void main(String[] args) {
short[] sArr = new short[5];
int[] iArr = new int[5];
long[] lArr = new long[5];
char[] cArr = new char[5];
String[] strArr = new String[5];
byte[] bArr = new byte[5];
boolean[] booArr = new boolean[5];
float[] fArr = new float[5];
double[] dArr = new double[5];
System.out.println("short 数组类:"+sArr.getClass());
System.out.println("int 数组类:"+iArr.getClass());
System.out.println("long 数组类:"+lArr.getClass());
System.out.println("char 数组类:"+cArr.getClass());
System.out.println("String 数组类:"+strArr.getClass());
System.out.println("byte 数组类:"+bArr.getClass());
System.out.println("boolean 数组类:"+booArr.getClass());
System.out.println("float 数组类:"+fArr.getClass());
System.out.println("double 数组类:"+dArr.getClass());
}
}
输出结果:
short 数组类:class [S
int 数组类:class [I
long 数组类:class [J
char 数组类:class [C
String 数组类:class [Ljava.lang.String;
byte 数组类:class [B
boolean 数组类:class [Z
float 数组类:class [F
double 数组类:class [D
小结:
使用toString()显示数组对象的类名称时,以class[开始,之后跟随一个类型表示字符。
2)动态数组,使用反射机制可以动态生成数组,使用java.lang.reflect.Array
exp6:
package flectUser;
import java.lang.reflect.Array;
public class NewArrayDemo {
public static void main(String[] args) {
Class c = String.class;
//定义数组的元素类型和数组大小
Object objArr = Array.newInstance(c, 5);
for(int i=0; i < 5; i++) {
Array.set(objArr, i, i+"");
}
for (int i = 0; i < 5; i++) {
System.out.println(Array.get(objArr, i));
}
System.out.println();
String[] strs = (String[])args;
for (String string : strs) {
System.out.println(string + " ");
}
}
}
输出结果:
0
1
2
3
4
3)可以通过Class实例的getComponetType()方法,取得集合类元素的Class实例:
int[] arr = new int[5]
system.out.println(iArr.getClass().getComponentType());
输出结果:
int
...........................................................................................................................................................................................................
5. Proxy类
java.lang.reflect.Proxy类,可协助实现动态代理功能。举个例子,打算开发一个HelloSpeaker类,其中有一个hello方法,想要在hello()调用前后加上
记录功能,但又不想将记录的功能写入到HelloSpeaker类中,这是可以使用Proxy类来实现动态代理。
exp7:
//IHello.java
package com.shine.proxy;
public interface IHello {
public void hello(String name);
}
//HelloSpeaker.java
package com.shine.proxy;
public class HelloSpeaker implements IHello{
public void hello(String name) {
System.out.println("Hello: " + name);
}
}
//LogHandler,java代理类
package com.shine.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.logging.Level;
import java.util.logging.Logger;
public class LogHandler implements InvocationHandler{
private Logger logger = Logger.getLogger(this.getClass().getName());
private Object delegate;
//绑定要代理的对象
public Object bind(Object delegate) {
this.delegate = delegate;
return Proxy.newProxyInstance(delegate.getClass().getClassLoader(), delegate.getClass().getInterfaces(), this);
}
//代理要调用的方法,并在前后增加行为
public Object invoke(Object proxy,Method method, Object[] args) throws Throwable {
Object result = null;
try {
logger.log(Level.INFO, "method starts..." + method.getName());
result = method.invoke(delegate, args);
logger.log(Level.INFO, "method ends..." + method.getName());
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
注:
要完成代理类必须实现InvocationHandler(调用代理)接口,这个接口只有一个必须实现的方法;
public Object invoke(Object proxy,Method method, Object[] args) throws Throwable 该方法有三个参数:
1) 代理类实例(在这里就是指LogHandler)。
2) 代理类调用的方法对象。
3) 传入该方法的参数数组。
实际上就是在调用方法还是靠" method.invoke(delegate, args); "
//Test.java 测试
package com.shine.proxy;
public class Test {
public static void main(String[] args) {
LogHandler handler = new LogHandler();
IHello speaker = new HelloSpeaker();
//代理speaker的对象
IHello speakerProxy = (IHello)handler.bind(speaker);
speakerProxy.hello("shine");
}
}
输出结果:
2008-4-4 21:42:00 com.shine.proxy.LogHandler invoke
信息: method starts...hello
Hello: shine
2008-4-4 21:42:00 com.shine.proxy.LogHandler invoke
信息: method ends...hello
...........................................................................................................................................................................................................
2008-4-4
- 反射入门2(使用反射生成和操作对象)
- 使用反射生成并操作对象
- 反射(概述,Class对象和信息,使用反射生产并操作对象,数组,反射与框架)
- [NET]Net中的反射使用入门(根据类名和函数名,生成和调用对象的成员函数)
- [NET]Net中的反射使用入门(根据类名和函数名,生成和调用对象的成员函数) .
- java基础-反射2(反射,反射操作对象,Class对象的使用,类型信息的获取)
- 黑马程序员-Java中使用反射生成并操作对象
- Java学习 之 获取Class对象、使用反射生成并操作对象
- java基础-反射3(反射,反射创建对象,操作对象属性,调用对象方法)
- 通过反射操作对象
- 反射使用入门
- C#反射使用入门
- 反射生成SQL语句入门
- scala 反射生成对象方法
- java反射机制生成对象
- 反射对象和方法
- 使用反射操作list
- JAVA-使用反射为任意对象生成XML
- 华为专区
- Java中的日期类
- security
- 项目人生,成长与感悟
- Java中的日历类
- 反射入门2(使用反射生成和操作对象)
- Java 中内置日期的格式
- Spring.Net IoC容器+Observer模式
- 将viewstate内容转移到文件
- 异常:NoClassDefFoundError org/apache/commons/collections/map/AbstractHashedMap
- Java中操作日期
- VMware 下无法换镜象的问题解决
- ASP.NET 仿MSN Messenger Alert的弹出窗口控件
- 使用日期