1.23.了解注解以及深浅拷贝

注解

元注解:注解上的注解;

@Target(ElementType.TYPE)
//target就是元注解,无target时,note_1注解可以放到任何地方,类,方法,成员属性均可以
//target可以规定注解可以放在什么地方,可以反正Type(类),Field(字段),Method(方法),Constructor(构造方法)等等,可以多个叠加,如@Target(ElementType.TYPE,ElementType.Field)
@Retention(RetentionPolicy.SOURCE)// 标记的注解仅保留在源级别,并被编译器忽略
public @interface note_1 {
    String value() default "note_1";
}

要注意若注解只有value,使用的时候,无需加上value=" ";其他的(包括多个属性)均需要列出完整的赋值代码;

@Node_1(id="OnCreate")

@target(如上)

@Retention(保留注解到什么时候) 保留级别

A)SOURCE:保留到源码阶段,经过javac编译就会被抹除掉;

B)CLASS:保留到class文件;但在JVM加载的时候会忽略掉;

C)RUNTIME:标记的注解由JVM保留,在运行环境中可以使用,获取;(通过反射技术获取)

SOURCE<CLASS<RUNTIME

不同级别注解的使用场景:

**SOURCE级别:**即源码级别,运用于APT(Annotation Processor Tools)技术(注解处理器);在编译期获取注解于注解声明的类包括类中的所有成员的信息,一般用于生成额外的辅助类;

注解处理器的运行:

​ 运行在编译阶段;注解处理程序是由javac调用的

javac将.java文件转换成.class文件时会采集到所有的注解信息,再将其包装成Element节点,交给注解处理程序

		.java -> javac ->.class
通过@Intdef元注解进行语法检查
@Retention(SOURCE)
@Target({ANNOTATION_TYPE})
public @interface IntDef {
    /** Defines the allowed constants for this element */
    int[] value() default {};

    /** Defines whether the constants can be used as a flag, or just as an enum (the default) */
    boolean flag() default false;

    /**
     * Whether any other values are allowed. Normally this is
     * not the case, but this allows you to specify a set of
     * expected constants, which helps code completion in the IDE
     * and documentation generation and so on, but without
     * flagging compilation warnings if other values are specified.
     */
    boolean open() default false;
}

CLASS:即字节码级别,运用于字节码增强技术(如;热修复技术)【可以通过ASM生成】

字节码增强:也就是在字节码中写代码,即在.class文件中写。(要了解.class的格式 数据按照特定的方式记录与排列)

将注解保留到class文件,便于进行选择性进行代码注入,比如对于加了注解的那些方法进行代码注入;

javap:用于反编译;

RUNTIME:即运行级别;运用于反射技术;通过在运行时,只知道某个类的信息,不需要有这个类的引用;反射是基于class的

@Target({ElementType.TYPE,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Node_1 {

//    @IdRes int value() default 10;
    @IdRes int value() default 10;//加@idres注解的原因在于明白value对应的是资源的id
    int size() default 20;
}
public  class InjectUtils {
    public  static  void injectView(Activity activity){
        Class<? extends Activity> cls = activity.getClass();//获取字节码码文件
//        try {
//            cls.getMethod("showDrawingToolsMenu");//获取指定方法
//            cls.getField("drawingView");//可以获取自己+父类的成员(不包括private,只能是public)
            Field[] drawingViewFields = cls.getDeclaredFields();//只能获取自己的成员(不包括父类,但可以获取全部作用域的)
            for(Field field:drawingViewFields){
                if(field.isAnnotationPresent(Node_1.class)) {//判断该属性是否加了注解
                    Node_1 injectview=field.getAnnotation(Node_1.class);//获取注解
                    int size =injectview.size();
//                    获取注解中设置的id
                    int id =injectview.value();
                    View view =activity.findViewById(id);
//反射设置属性的值:
                    field.setAccessible(true);//设置访问权限,使得可以操作private属性
                    try {
                        field.set(activity,view);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
//        } catch (NoSuchMethodException e) {
//            e.printStackTrace();
//        } catch (NoSuchFieldException e) {
//            e.printStackTrace();
//        }

//        Method[] clsMethods = cls.getMethods();//获取所有方法;


    }
}

json是一种数据类型,gson是操作json的一种数据框架;

Java序列化与反序列化的含义

序列化指的是:将Java对象转为字节流

反序列指的是:将字节流转换为java 对象

序列化和反序列化不仅可以用于网络传输和本地保存,还可以用于Java对象的深度复制。通过将对象序列化为字节流,然后再将字节流反序列化为一个新的对象,就可以实现对象的深度复制,从而避免了手动复制对象的繁琐过程。

浅拷贝与深拷贝

浅拷贝:【拷贝方法;重写clone()方法;】

a)对于基本数据类型的成员变量(存放在栈里),浅拷贝会直接进行值传递;即将属性值复制一份给新的对象;简单来说,这是两份数据,对某一对象的属性值进行修改,不会影响另一个对象拷贝的值;

b)对于引用数据类型的成员变量(如:类,接口,数组等,存放在堆里),浅拷贝会进行引用传递,也就是将成员变量的引用地址复制给新的对象,那么对于一份数据的修改,另一份拷贝的数据也会被修改;

clone方法:

在类内重写clone方法

class Fruit implements Cloneable{
public Object clone() {       
Object obj=null;        //调用Object类的clone方法,返回一个Object实例       
try {            
obj= super.clone();        
} catch (CloneNotSupportedException e) {
e.printStackTrace();        
}       
return obj;   
}
}
Fruit apple_2=(Fruit)apple1.clone();

深拷贝:

无论是基本数据类型还是引用数据类型都是重新创建,因此修改原来那份的内容,都不会影响到拷贝后的那份;

缺点很明显:较于浅拷贝速度较慢并且花销较大。

通常通过对象序列化实现深拷贝;

对于要进行深拷贝的类及其中设计的其他类的对象均继承Serializable接口,

class Fruit implements Serializable{
//...
}
//使用
Fruit apple1=new Fruit(...);
//通过序列化方法实现深拷贝
bos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bos);
oos.writeObject(apple1);
oos.flush();
ObjectInputStream ois=new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
Fruit apple2=(Fruit)ois.readObject();
  • 12
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值