java源码解析第二天

1.事件委托模式,jdk中并没有对其进行封装。

事件委托的原理:分为两个对象,A对象、B对象。A对象中有事件需要执行,但是A对象不会主动执行,需要B对象来通知后才会执行。

public class Mytest1{
    public static void main(String[] args) {
         AddLister al=new AddLister(); //对象本身
         Event1 e=new Event1(al, "stop");//封装事件,并实现method方法的代理
         TestNotifier tn=new TestNotifier();//具体的实现类代理类,代理执行添加事件,执行事件
         tn.addEvent(e);//添加事件
         try {
           Thread.sleep(5000);
        } catch (Exception e2) {
            // TODO: handle exception
        } 
         tn.invoke();//执行事件
    }
}

AddLister 对象本身:

public class AddLister {
    public  AddLister(){//一开始实例化就执行
        System.out.println("开始");
    } 
    public void stop(){//此方法注册到 代理类中,有代理类
        System.out.println("结束");
    } 
}

 

Event1 封装事件,提供方法名,对象,参数的出入口,实现代理方法

public class Event1 { 
    private Object object;//事件对象本身
    private Object[] params;//参数数组
    private  Class[] paramType;//参数类型
    private String mothodName;//需要代理处理的事件名 
    /**
     * 传值赋值
     * @param obj   
     * @param methodN
     * @param args
     */
    Event1(Object obj,String methodN,Object...args){
        this.object=obj;
        System.out.println("对象:"+this.object);
        this.mothodName=methodN;
        System.out.println("方法名:"+this.mothodName);
        for (int i=0;i<args.length;i++) {
            this.params[i]=args[i];
            System.out.println("参数:"+this.params[i]);
        }
        if(null!=this.params){
            createParamType(this.params);
        } 
    } 
    /**
     * 从参数中获取参数的类型
     */
    private void createParamType(Object[] obj){
        for (int i=0;i<obj.length;i++) {
            paramType[i]=object.getClass();
            System.out.println("参数类型:"+this.paramType[i]);
        }
    } 
    public void invoke(){
        try {
            System.out.println("开始执行代理方法");
            Method method=object.getClass().getMethod(mothodName, paramType);
            if(null==method){
                return;
            }
          method.invoke(object, params);
        } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
    } 
    public Object getObject() {
        return object;
    }
    public void setObject(Object object) {
        this.object = object;
    }
    public Object[] getParams() {
        return params;
    }
    public void setParams(Object[] params) {
        this.params = params;
    }
    public Class[] getParamType() {
        return paramType;
    }
    public void setParamType(Class[] paramType) {
        this.paramType = paramType;
    }
    public String getMothodName() {
        return mothodName;
    }
    public void setMothodName(String mothodName) {
        this.mothodName = mothodName;
    } 
}

 

Notifier1  抽象代理类,公共的类,有具体的代理类实现

public abstract class Notifier1 { 
    public EventHander eh=new EventHander(); 
    public EventHander getEh() {
        return eh;
    } 
    public void setEh(EventHander eh) {
        this.eh = eh;
    }  
    public void addEvent(Event1 e){
        this.eh.addEventListenter(e);
    } 
    public void invoke(){
        this.eh.notifyx();
    } 
}

 

EventHander  事件处理器

public class EventHander { 
    List<Event1> list=null; 
    EventHander(){
        list=new ArrayList<Event1>();
    } 
    public void addEventListenter(Event1 e){
        list.add(e);
    } 
    /**
     * 遍历事件数组执行事件
     */
    public void notifyx(){
        for (Event1 event1 : list) {
            event1.invoke();
        }
    } 
}

总结:将对象本身的方法代理给其他封装好的类,让这个类代理对象的方法。

特点1:   这个代理类本身具有通用性、特别性(提供公共抽象类,抽象类规范好方法让子类去实现,子类也可以扩展其他自己独有的方法);

特点2: 事件封装与事件代理,封装好事件类,只需要传入具体的参数,让事件类本身自动化完成事件代理的一些列操作,再将封装好的事件类注入到公共代理类中即可,EventHander这个类可以不要,直接放在event中即可。

 

2. transient 反序列化

一般来说,在实体类中都会实现Serializable接口来自动化序列化,但是这却是将所有成员变量都序列化了,那么这些数据将会在数据磁盘中持久化,为了不让数据持久化,这时就可以加上这个关键字,在流传输的过程中,数据只会存在于内存中,不会在磁盘中持久化,这也保证了数据的安全性,如密码等,不会泄露密码。

代码实现:

class Rectangle implements Serializable{ 
    private static final long serialVersionUID = 1710022455003682613L;
    private Integer width;
    private Integer height;
    private transient Integer area;
 
    public Rectangle (Integer width, Integer height){
        this.width = width;
        this.height = height;
        this.area = width * height;
    } 
    public void setArea(){
        this.area = this.width * this.height;
    } 
    @Override
    public String toString(){
        StringBuffer sb = new StringBuffer(40);
        sb.append("width : ");
        sb.append(this.width);
        sb.append("\nheight : ");
        sb.append(this.height);
        sb.append("\narea : ");
        sb.append(this.area);
        return sb.toString();
    }

 

main方法:

public static void main(String args[]) throws Exception {
            Rectangle rectangle = new Rectangle(7,28);
            System.out.println("1.原始对象\n"+rectangle);
            ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("rectangle"));
            // 往流写入对象
            o.writeObject(rectangle);
            o.close(); 
            // 从流读取对象
            ObjectInputStream in = new ObjectInputStream(new FileInputStream("rectangle"));
            Rectangle rectangle1 = (Rectangle)in.readObject();
            System.out.println("2.反序列化后的对象\n"+rectangle1);
            rectangle1.setArea();
            System.out.println("3.恢复成原始对象\n"+rectangle1);
            in.close();
        }

1.原始对象
width : 7
height : 28
area : 196
2.反序列化后的对象
width : 7
height : 28
area : null
3.恢复成原始对象
width : 7
height : 28
area : 196 

总结:好处是安全性提高,节省内存,释放内存块。(常用于不需要序列化的字段)。

 

3.关于对xml的操作,存在读写

将对象实例化,并设置数据,利用xmlEncoder类写入xml中,利用xmlDecoder读取数据到对象中

代码:

    public static void main(String[] args) throws FileNotFoundException {
         da d=new da();
         d.setId(1);
         d.setNaem("42das");
         d.setSex("你放假斯卡迪");
        InputStream is =new FileInputStream("C:/newJava/111/src/dahyu/file.xml");
        OutputStream po=new FileOutputStream("C:/newJava/111/src/dahyu/file.xml");
        XMLEncoder xe=new XMLEncoder(po);
        XMLDecoder xd=new XMLDecoder(is); 
        xe.writeObject(d);
        xe.close(); 
        d=(da)xd.readObject();
        System.out.println(d.getId()+","+d.getNaem());  
    }

 

4.注解,元注解

判断指定类是否有注解,有返回true,类的getAnnotation拿到注解

if(dskla.class.isAnnotationPresent(mydas.class)){
            mydas d=dskla.class.getAnnotation(mydas.class);
            System.out.println(d.getClass());
        }else{
            System.out.println("15235");
        }

java中的元注解有四个:@Target,@Retention ,@Document, @Inherited

@Retention 又有三个,

@Retention(Retention.SOURCE)  //注解只会存在源码中,在class字节码文件中不包含

@Retention(Retention.CLASS)  //注解在class文件中会存在,但是无法获取到注解

@Rentention(Retention.RUNTIME) //注解在class文件存在,也可以通过注解获取到

 

@Target  又有八个

 @Target (ElementType.Type)//接口、类、注解、枚举

@Target(ElementType.METHOD) //方法

@Target (ElementType.paramter)//参数

@Target (Element.filed) //字段

@Target (ElementType.PACKAGE) //包

@Target (ElementType.CONSTRUCTOR)// 构造函数

@Target (ElementType.LOCAL_VARIABLE)//局部变量

@Target (ElementType.ANNOTATION_TYPE)//注解

 

@Document 该注解会在javadoc

@inherited 子类会继承父类的注解

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值