1.java反射
1.个人理解:java反射是指能够在程序运行时动态的操作一个类,包括这个类的构造方法,属性,方法。对这个类进行剖析,相当于让程序自己去调用这个类。java反射和RTTI的区别就是:对于反射来说.class文件在编译的时候是不可获取的,所以是在运行时打开和检查.class文件。
2.应用:
1.工厂模式。
在工厂模式下使用反射,可以通过读取一个xml的配置文件进行调用,通过传入classname,调用Class.forname(“classname”)这种方法,可以获得class。这样,调用起来更灵活。如果增加一种业务类型也更方便。程序整体更规则,更美观,利于维护和增量开发。
2.测试场景。
在测试场景下进行进行测试某个类的时候,可以通过反射看到这个类的方法,属性,类型,泛型等各种信息。
3.动态加载。
2.例子
1.获取class类对象(共三种方法)
public class ReflectTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Class<?> class1 = null;
Class<?> class2 = null;
Class<?> class3 = null;
class1 = Class.forName("gwb.TestReflect");/* 用的最多 */
class2 = new ReflectTest().getClass(); /* 几乎没什么用处 我既然new了一个,为什么还要用反射呢? */
class3 = ReflectTest.class;
}
}
2.获取父类和实现的所有接口
public class ReflectTest {
private static final long serialVersionUID = -123125704934876293L;
public static void main(String[] args) {
// TODO Auto-generated method stub
Class<?> clazz = Class.forName("");
/* 获得父类 */
Class<?> parentClass = clazz.getSuperclass();
System.out.println("clazz的父类为: " + parentClass.getName());
/* 获得所有的接口 */
Class<?> intes[] = clazz.getInterfaces();
System.out.println("clazz 实现的接口有:");
for(int i = 0; i < intes.length;i++){
System.out.println((i+1) + ": " + intes[i].getName());
}
}
}
2.获取构造函数
package ReflectTest.src;
import java.lang.reflect.Constructor;
class User{
private int age;
private String name;
public User(){
super();
}
public User(String name){
super();
this.name = name;
}
public User(int age,String name){
super();
this.age = age;
this.name = name;
}
public int getAge(){
return age;
}
public void setAge(int age){
this.age = age;
}
public void setName(String name){
this.name = name;
}
@Override
public String toString(){
return "User [age=" + age + ",name = " + name + "]";
}
}
public class ReflectTest {
public static void main(String[] args) throws Exception{
Class<?> class1 = null;
class1 = Class.forName("ReflectTest.src.User");
/* 第一种方法:实例化默认构造方法,调用set赋值 */
User user = (User)class1.newInstance();
user.setAge(20);
user.setName("guowenbang");
System.out.println(user);
/* 第二种方法:获取全部的构造函数,使用构造函数赋值 */
/* 获得构造函数的顺序不确定 */
Constructor<?> cons[] = class1.getConstructors();
for(int i = 0; i< cons.length;i++){
Class<?> clazzs[] = cons[i].getParameterTypes();
System.out.println("cons[" + i + "] (");
for(int j = 0;j < clazzs.length;j++){
if(j == clazzs.length - 1)
System.out.println(clazzs[j].getName());
else
System.out.println(clazzs[j].getName() + ",");
}
System.out.println(")");
}
user = (User) cons[2].newInstance("guowen");
System.out.println(user);
user = (User) cons[1].newInstance(20,"guowen");
System.out.println(user);
}
}
结果
User [age=20,name = guowenbang]
cons[0] (
)
cons[1] (
int,
java.lang.String
)
cons[2] (
java.lang.String
)
User [age=0,name = guowen]
User [age=20,name = guowen]
3.获取一个类的全部属性
package RefectTest.src;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class TestReflect implements Serializable{
private static final long serialVersionUID = -1324354324355243242L;
public static void main(String[]args) throws Exception{
Class<?> clazz = Class.forName("RefectTest.src.TestReflect");
Class<?> clazzsuper = clazz.getSuperclass(); /* 由于此类是通过实现接口,所以不能通过getSuperClass的方法来获得Serializable 本身就不是父类嘛。。。 */
System.out.println("the super class is " + clazzsuper);/* the super class is class java.lang.Object */
System.out.println("===========本类属性========");
Field[] fields = clazz.getDeclaredFields(); /* 获取本类的所有属性 包括private public protected */
for(int i = 0; i < fields.length;i++){
/* 权限修饰符 */
int mo = fields[i].getModifiers();
String priv = Modifier.toString(mo);
/* 属性类型 */
Class<?> type = fields[i].getType();
System.out.println(priv + " " + type.getName() + " " + fields[i].getName() + ";");
}
System.out.println("==========实现的接口或者父类的属性========");
Field[] field1 = clazzsuper.getDeclaredFields();
System.out.println("size " + field1.length);/* */
for(int j = 0; j < field1.length;j++){
int mo = field1[j].getModifiers();
String priv = Modifier.toString(mo);
Class<?> type = field1[j].getType();
System.out.println(priv + " " + type.getName() + " " + field1[j].getName() + ";");
}
}
}
4.调用类方法
package gwb2;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class TestReflect {
private static final long serialVersionUID = -23498779765678654L;
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
Class<?> clazz = Class.forName("gwb2.TestReflect");
Method[] method = clazz.getMethods();
for(int i = 0; i < method.length;i++){
Class<?> returnType = method[i].getReturnType();
Class<?> para[] = method[i].getParameterTypes();
int temp = method[i].getModifiers();
System.out.println(Modifier.toString(temp) + " ");
System.out.println(returnType.getTypeName() + " ");
System.out.println(method[i].getName() + " ");
System.out.println("(");
for(int j = 0;j < para.length;j++){
System.out.println(para[j].getName() + " " + "arg" + j);
if(j < para.length-1){
System.out.println(",");
}
}
Class<?> exce[] = method[i].getExceptionTypes();
if(exce.length>0){
System.out.println(") throws");
for(int k = 0;k < exce.length;k++){
System.out.println(exce[k].getName() + " ");
if( k < exce.length - 1){
System.out.println(",");
}
}
}
else{
System.out.println(")");
}
System.out.println();
}
}
}
5.获取某个类的全部方法
package ReflectTest.src.gwb2;
import java.lang.reflect.Method;
public class TestReflect {
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
Class<?> clazz = Class.forName("ReflectTest.src.gwb2.TestReflect");
Method method = clazz.getMethod("reflect1");
method.invoke(clazz.newInstance());
method = clazz.getMethod("reflect2", int.class,String.class);
method.invoke(clazz.newInstance(),20,"张三");
}
public void reflect1(){
System.out.println("java 反射机制 - 调用某一个类的方法1");
}
public void reflect2(int age,String name){
System.out.println("java 反射机制 - 调用某个类的方法2");
System.out.println("age -> " + age + ".name ->" + name);
}
}
输出结果:
java 反射机制 - 调用某一个类的方法1
java 反射机制 - 调用某个类的方法2
age -> 20.name ->张三
6.修改类属性
package ReflectTest.src.gwb3;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class TestReflect {
private String proprety = null;
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
Class<?> clazz = Class.forName("ReflectTest.src.gwb3.TestReflect");
Object obj = clazz.newInstance();
Field field = clazz.getDeclaredField("proprety");
field.setAccessible(true);
field.set(obj, "java 反射机制的demno");
Method method = clazz.getMethod("getproprety");
System.out.println("the Proprety:" + field.get(obj));
System.out.println("the proprety : " + field);
/* invoke 这里面最开始传入的是clazz.newinstance() 因为这样相当于传入的是一个新的实例,调用的自然也就是新势力的getproprety所以此时是返回null的*/
String a = (String)method.invoke(obj);
System.out.println("the proprety a : " + a);
}
public String getproprety(){
return proprety;
}
}
7.动态代理
先来一个demo
package gwb3;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface Subject{
public String say(String name,int age);
}
class RealSubject implements Subject{
public String say(String name,int age){
return name + " " + age;
}
}
class MyInvocationHandler implements InvocationHandler{
private Object obj = null;
public Object bind(Object obj){
this.obj = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
Object temp = method.invoke(this.obj, args);
return temp;
}
}
public class TestReflect {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyInvocationHandler demo = new MyInvocationHandler();
Subject sub = (Subject)demo.bind(new RealSubject());
String info = sub.say("Rollen",20);
System.out.println(info);
}
}
1.那么什么是动态代理呢?
2.那什么是代理呢?
代理是设计模式之一。代理通常充当着中间人的角色。
再来个代理的demo摘自java变成思想。
interface Interface{
void doSomething();
void somethingElse(String arg);
}
class RealObject implements Interface{
public void doSomething(){System.out.println("do Somethis");}
public void somethingElse(String arg){
System.out.println("somethingElse " + arg);
}
}
class SimpleProxy implements Interface{
private Interface proxied;
public SimpleProxy(Interface proxied){
this.proxied = proxied;
}
public void doSomething(){
/* 这个输出就代表额外操作了 */
System.out.println("SimpleProxy doSomething");
proxied.doSomething();
}
public void somethingElse(String arg){
/* 这个输出就代表额外操作了 */
System.out.println("SimpleProxy somethingElse " + arg);
proxied.somethingElse(arg);
}
}
public class SimpleProxyDemo {
public static void consumer(Interface iface){
iface.doSomething();
iface.somethingElse("bonobo");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
/* 传入了两个实现了interface的类 */
consumer(new RealObject());
/* 相当于在上面new RealObject的基础上封装了一个类 可以新增一些额外的操作,比如查看代码开销等 */
consumer(new SimpleProxy(new RealObject()));
}
}
嗯。从上面来看,这就叫代理。简单归纳一下,当你希望跟踪一个类中的方法的调用。比如查看代码的调用开销,这个时候,你必然不能修改原有的接口啊。不仅容易引入问题而且验证完事之后还不好删除,这时这个代理模式就用上了。其实不只是调用开销,其他的测试也会有用到的。(感觉这个和python中的装饰器原理很像,有什么区别呢,先留一个坑_)
ok,现在对于代理基本的意识已经有了,那么什么是动态代理呢?
顾名思义。那就是动态的创建代理,和动态的调用代理。。。。。。。。。。
那现在重写一下上面的普通代理的例子
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface Interface{
void doSomething();
void somethingElse(String arg);
}
class RealObject implements Interface{
public void doSomething(){System.out.println("do Somethis");}
public void somethingElse(String arg){
System.out.println("somethingElse " + arg);
}
}
class DynamicProxyHandler implements InvocationHandler{
private Object proxied;
public DynamicProxyHandler(Object proxied){
this.proxied = proxied;
}
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
System.out.println("**** proxy: " + proxy.getClass() + " . method: " + method + ",args " + args);
if(args != null){
for(Object arg : args){
System.out.println(" " + arg);
}
}
return method.invoke(proxied, args);
/*
* 此处可以有优化,比如进行函数的过滤,因为走的是代理流程的化 这个是函数调用的入口,所以可以这样
* if(method.getName().equals("MethodName"))
* {
* dosomethind...
* }*/
}
}
class SimpleDynamicProxy{
public static void consumer(Interface iface){
iface.doSomething();
iface.somethingElse("bonobo");
}
public static void main(String[] args){
RealObject real = new RealObject();
consumer(real);
/* 通过调用newProxyInstance可以创建动态代理 */
/* 1.需要一个类加载器 2.一个用户希望代理能够实现的接口列表 3.一个实现了InvocationHandler的类 */
/* 这个动态代理可以将所有调用重定向到调用到处理器,所以在调用处理器中要传入一个 对象的引用,这样这个调用就转换了 */
Interface proxy =
(Interface)Proxy.newProxyInstance
(Interface.class.getClassLoader(),
new Class[]{Interface.class},
new DynamicProxyHandler(real));
//
consumer(proxy);
}
}