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 子类会继承父类的注解