博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
类反射,代理
阅读量:6333 次
发布时间:2019-06-22

本文共 6993 字,大约阅读时间需要 23 分钟。

Class文件加载流程

类的加载条件:

当创建一个类的实例时,如 通过new创建对象,或者通过反射、克隆、反序列化

调用类方法时,即使用了字节码的invokestatic指令

当使用类或接口的类字段(除final常量外),比如使用了getstatic或pushstatic指令

当使用了java.lang.reflect包中的方法反射类的方法时

当初始化子类时,要求先初始化父类

作为启动虚拟机,含有main方法的哪个类

类加载器

类加载器(CLassLoader)用于加载类,在Java中主要有以下四种类加载器:

Bootstrap ClassLoader:此加载器采用C++编写,一般开发中是看不到的,加载系统核心类,如String类;

Extension ClassLoader:用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类;

AppClassLoader:加载classpath指定的类,即加载用户类,也就是应用程序的类。

自定义类加载器

Class类型获取

public class Class_test {    public static void main(String[] args) throws ClassNotFoundException {        1      Class
class_testClass = Class_test.class; System.out.println(class_testClass); //class com.zym.com.zym.Class_test     2 Class_test class_test = new Class_test(); Class aClass = class_test.getClass(); System.out.println(aClass); //class com.zym.com.zym.Class_test     3 Class aClass1 = Class.forName("com.zym.com.zym.Class_test"); System.out.println(aClass1); //class com.zym.com.zym.Class_test }}

 反射

public class fanshe {    public static void main(String[] args) {        //获得一个类        Class
cls = Student1.class; //获取类所在的包 Package apackage = cls.getPackage(); System.out.println(apackage); //获得属性(公开) System.out.println("获得属性(公开)"); Field[] attr_Student1 = cls.getFields(); for (Field s : attr_Student1 ) { System.out.println(s); } //获得属性(所有) System.out.println("------------------"); System.out.println("获得属性(所有)"); Field[] fileds_all_stu1 = cls.getDeclaredFields(); for (Field f : fileds_all_stu1 ) { System.out.println(f); } //获得构造方法(公开的),一般加Declared的都是所有 System.out.println("-----------"); Constructor
[] constructors = cls.getConstructors(); for (Constructor con:constructors ) { System.out.println(con); } //获得普通的犯法,公开的方法,包括继承的方法 System.out.println("-----------"); Method[] methods = cls.getMethods(); for (Method m:methods ) {// System.out.println(m); } //获得普通方法,所有本类的所有方法,不包括继承方法 System.out.println("-----------"); Method[] declaredMethods = cls.getDeclaredMethods(); for (Method s : declaredMethods ) { System.out.println(s); } }}

执行类中的方法,普通方法,构造方法

public class TestPropertyDescriptor {     public static void main(String[] args) {          Person person = new Person();          person.setName("zhangsan");          person.setAge(18);          getFiled(person, "name");//结果输出 zhangsan     }          // 通过反射得到name      // 通过得到属性的get方法(pd.getReadMethod())再调用invole方法取出对应的属性值     // 调用set方法()     private static void getField(Object object, String field) {          Class
clazz = object.getClass(); PropertyDescriptor pd = null; Method getMethod = null; Method setMethod = null; try { pd = new PropertyDescriptor(field, clazz); if (null != pd) { // 获取field属性的get方法 getMethod = pd.getReadMethod(); Object getInvoke = getMethod.invoke(object); // 获取field属性的set方法 setMethod= pd.getWriteMethod(); Object setInvoke = setMethod.invoke(object,"123"); System.out.println(setInvoke+ getInvoke); } } catch (Exception e) { e.printStackTrace(); } }}
public static void main(String[] args) throws Exception {        //给对象赋值        /*Person p = new Person();        p.setAge(20);        p.setAddress("北京");        p.setName("张三");*/        //获得Person的Class类型         Class
cls = Person.class; //实例化Person /*Person p = cls.newInstance();//通过Person无参构造方法实例化 p.setAge(20); p.setAddress("北京"); p.setName("张三"); System.out.println(p);*/ Constructor
con = cls.getConstructor(String.class,int.class,String.class); Person p=con.newInstance("张三",23,"昌平"); //获得set方法 Field field = cls.getDeclaredField("age");// System.out.println(field.getName()); String mname="set"+field.getName().substring(0, 1).toUpperCase()+field.getName().substring(1); System.out.println(mname); Method m = cls.getMethod(mname, int.class); //执行方法 m.invoke(p,21); System.out.println(p); //调用show Method show = cls.getMethod("show", String.class); // obj 实例对象,args 参数 show.invoke(p, "测试"); }

反射缺点

破坏了类的封装;

平时开发不会使用反射机制!!!

设计模式

静态代理

一个接口一个功能,也可以在代理类中写功能

对其他对象提供一种代理以控制对这个对象的访问。

对已经存在的类,添加功能,不能修改原有类的任何功能!!!

 

public class compute implements PublicObject {    @Override    public void Info(String name, double price) {        System.out.println("电脑名称:"+name+"价格:"+price);    }}
compute
public class proxy implements PublicObject{    public PublicObject po;    public proxy(PublicObject po) {        this.po = po;    }    @Override    public void Info(String name, double price) {        po.Info(name,price);    }    public void gift(){        System.out.println("反现金");    }}
代理类
public interface PublicObject{    public void Info(String name,double price);}
继承的接口
public class proxy_test {    public static void main(String[] args) {        compute c = new compute();        proxy p = new proxy(c);        p.Info("zzzz", 123);        p.gift();    }}
测试类

 动态代理

之前曾为读者讲解过代理机制的操作,但是之前所讲解的代理设计,属于静态代理,因为每一个代理类只能为一个接口服务,这样一来程序开发中必然会产生过多的代理了,最好的做法是可以通过一个代理类完成全部的代理功能,那么此时就必须使用动态代理完成。

在Java中要想实现动态代理机制,则需要java.lang.reflect.InvocationHandler接口和java.lang.reflect.Proxy类的支持。

 

public class MyProxy implements InvocationHandler{
//动态代理 private Object obj; //绑定的对象 public Object bind(Object o){ this.obj=o;// ClassLoader loader:类加载器 // Class
[] interfaces:得到全部的接口 // InvocationHandler h:得到InvocationHandler接口的子类实例 return Proxy.newProxyInstance(o.getClass().getClassLoader(), o.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// System.out.println("参数:"+Arrays.toString(args));// System.out.println(method.getName()); return method.invoke(obj, args); //执行目标对象的方法 } }
代理类
//目标对象public class Computer implements PublicObj {    @Override    public void Info(String name, double price) {        System.out.println(name+"系列电脑!"+price);    }}
compute
//抽象对象public interface PublicObj {    //电脑系列    public void Info(String name,double price);}
抽象接口
public class Test {    public static void main(String[] args) {        MyProxy handler = new MyProxy();        PublicObj po =new Computer();//真实目标对象        PublicObj o = (PublicObj) handler.bind(po);         o.Info("IBM", 9999.99);    }}
测试类

 

转载于:https://www.cnblogs.com/taozizainali/p/10883317.html

你可能感兴趣的文章
log4j Test
查看>>
HDU 1255 覆盖的面积(矩形面积交)
查看>>
Combinations
查看>>
SQL数据库无法附加,提示 MDF" 已压缩,但未驻留在只读数据库或文件组中。必须将此文件解压缩。...
查看>>
第二十一章流 3用cin输入
查看>>
在workflow中,无法为实例 ID“...”传递接口类型“...”上的事件“...” 问题的解决方法。...
查看>>
获取SQL数据库中的数据库名、所有表名、所有字段名、列描述
查看>>
Orchard 视频资料
查看>>
简述:预处理、编译、汇编、链接
查看>>
调试网页PAIP HTML的调试与分析工具
查看>>
路径工程OpenCV依赖文件路径自动添加方法
查看>>
玩转SSRS第七篇---报表订阅
查看>>
WinCE API
查看>>
SQL语言基础
查看>>
对事件处理的错误使用
查看>>
最大熵模型(二)朗格朗日函数
查看>>
深入了解setInterval方法
查看>>
html img Src base64 图片显示
查看>>
[Spring学习笔记 7 ] Spring中的数据库支持 RowMapper,JdbcDaoSupport 和 事务处理Transaction...
查看>>
FFMPEG中关于ts流的时长估计的实现(转)
查看>>