Java(Android)注解

相机SDK开发C++篇-常用开发函数封装讲解(迈德威视相机) / 软触发失败,返回false } return true;= (nRet = CameraSetSysOption("NumBuffers", QString("%1").arg(getImageBufferNodeNum()).toLocal8Bit().data()))) { setLastErrorMsg("相机#%1设置缓存区数量错误,错误码:%2").arg(getCameraIndex()).arg(nRet); 阅读详情

概述

注解(Annotation)在JDK1.5之后增加的一个新特性,注解的引入意义很大,有很多非常有名的框架,比如Hibernate、Spring,Android新推出的AAC/Room等框架中都大量使用注解。注解作为程序的元数据嵌入到程序。注解可以被解析工具或编译工具解析,此处注意注解不同于注释(comment)。

当一个接口直接继承java.lang.annotation.Annotation接口时,仍是接口,而并非注解。要想自定义注解类型,只能通过@interface关键字的方式,其实通过该方式会隐含地继承.Annotation接口。

API 摘要

所有与Annotation相关的API摘要如下:

注解类型(Annotation Types) API
注解类型含义
Documented表示含有该注解类型的元素(带有注释的)会通过javadoc或类似工具进行文档化
Inherited表示注解类型能被自动继承
Retention表示注解类型的存活时长
Target表示注解类型所适用的程序元素的种类

1. Documented

源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}

表示拥有该注解的元素可通过javadoc此类的工具进行文档化。该类型应用于注解那些影响客户使用带注释(comment)的元素声明的类型。如果类型声明是用Documented来注解的,这种类型的注解被作为被标注的程序成员的公共API。

例如,上面源码@Retention的定义中有一行@Documented,意思是指当前注解的元素会被javadoc工具进行文档化,那么在查看Java API文档时可查看当该注解元素。

2. Inherited

源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}

@Inherited:表示该注解类型被自动继承,如果用户在当前类中查询这个元注解类型并且当前类的声明中不包含这个元注解类型,那么也将自动查询当前类的父类是否存在Inherited元注解,这个动作将被重复执行知道这个标注类型被找到,或者是查询到顶层的父类。@Inherited对字段,子类对于继承的方法才能通过反射获取注解,但是对于子类重写父类的方法是无法获取父类的注解的。,如果要查看子类中父类的字段,需要从子类中通过Clazz.getSuper()获取到父类,在获取对应的字段及其注解

3. Retention

源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    RetentionPolicy value();
}

@Retention:表示该注解类型的注解保留的时长。当注解类型声明中没有@Retention元注解,则默认保留策略为RetentionPolicy.CLASS。关于保留策略(RetentionPolicy)是枚举类型,共定义3种保留策略,如下表:

RetentionPolicy含义
SOURCE仅存在Java源文件,经过编译器后便丢弃相应的注解
CLASS存在Java源文件,以及经编译器后生成的Class字节码文件,但在运行时VM不再保留注释
RUNTIME存在源文件、编译生成的Class字节码文件,以及保留在运行时VM中,可通过反射性地读取注解

例如,上面源码@Retention的定义中有一行@Retention(RetentionPolicy.RUNTIME),意思是指当前注解的保留策略为RUNTIME,即存在Java源文件,也存在经过编译器编译后的生成的Class字节码文件,同时在运行时虚拟机(VM)中也保留该注解,可通过反射机制获取当前注解内容。

4. Target

源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    ElementType[] value();
}

@Target:表示该注解类型的所使用的程序元素类型。当注解类型声明中没有@Target元注解,则默认为可适用所有的程序元素。如果存在指定的@Target元注解,则编译器强制实施相应的使用限制。关于程序元素(ElementType)是枚举类型,共定义8种程序元素,如下表:

ElementType含义
ANNOTATION_TYPE注解类型声明
CONSTRUCTOR构造方法声明
FIELD字段声明(包括枚举常量)
LOCAL_VARIABLE局部变量声明
METHOD方法声明
PACKAGE包声明
PARAMETER参数声明
TYPE类、接口(包括注解类型)或枚举声明

例如,上面源码@Target的定义中有一行@Target(ElementType.ANNOTATION_TYPE),意思是指当前注解的元素类型是注解类型。

枚举(Enum) API
枚举含义
ElementType程序元素类型,用于Target注解类型
RetentionPolicy注解保留策略,用于Retention注解类型
异常和错误 API
异常/错误含义
AnnotationTypeMismatchException当注解经过编译(或序列化)后,注解类型改变的情况下,程序视图访问该注解所对应的元素,则抛出此异常
IncompleteAnnotationException当注解经过编译(或序列化)后,将其添加到注解类型定义的情况下,程序视图访问该注解所对应的元素,则抛出此异常。
AnnotationFormatError当注解解析器试图从类文件中读取注解并确定注解出现异常时,抛出该错误

内建注解

Java提供了多种内建的注解,下面接下几个比较常用的注解:@Override、@Deprecated、@SuppressWarnings这3个注解。

  • @Override(覆写)

源码:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

用途:用于告知编译器,我们需要覆写超类的当前方法。如果某个方法带有该注解但并没有覆写超类相应的方法,则编译器会生成一条错误信息。

注解类型分析:@Override可适用元素为方法,仅仅保留在java源文件中。

  • @Deprecated(不赞成使用)

源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}

用途:用于告知编译器,某一程序元素(比如方法,成员变量)不建议使用时,应该使用这个注解。Java在javadoc中推荐使用该注解,一般应该提供为什么该方法不推荐使用以及相应替代方法。

注解类型分析: @Deprecated可适合用于除注解类型声明之外的所有元素,保留时长为运行时VM。

  • @SuppressWarnings(压制警告)

源码:

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
    String[] value();
}

用于:用于告知编译器忽略特定的警告信息,例在泛型中使用原生数据类型。

注解类型分析: @SuppressWarnings可适合用于除注解类型声明和包名之外的所有元素,仅仅保留在java源文件中。

该注解有方法value(),可支持多个字符串参数,例如:

@SupressWarning(value={"uncheck","deprecation"})

前面讲的@Override,@Deprecated都是无需参数的,而压制警告是需要带有参数的,可用参数如下:

参数含义
deprecation使用了过时的类或方法时的警告
unchecked执行了未检查的转换时的警告
fallthrough当Switch程序块进入进入下一个case而没有Break时的警告
path在类路径、源文件路径等有不存在路径时的警告
serial当可序列化的类缺少serialVersionUID定义时的警告
finally任意finally子句不能正常完成时的警告
all以上所有情况的警告

3.4 对比
3种内建注解的对比:

内建注解TargetRetention
OverrideMETHODSOURCE
SuppressWarnings除ANNOTATION_TYPE和PACKAGE外的所有SOURCE
Deprecated除ANNOTATION_TYPE外的所有RUNTIME

注解解析

接下来,通过反射技术来解析自定义注解@AuthorAnno,关于反射类位于包java.lang.reflect,其中有一个接口AnnotatedElement,该接口定义了注释相关的几个核心方法,如下:

返回值方法解释
TgetAnnotation(Class annotationClass)当存在该元素的指定类型注解,则返回相应注释,否则返回null
Annotation[]getAnnotations()返回此元素上存在的所有注解
Annotation[]getDeclaredAnnotations()返回直接存在于此元素上的所有注解。
booleanisAnnotationPresent(Class annotationClass)当存在该元素的指定类型注解,则返回true,否则返回false

注解实战

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Age {
    int value() default 0;//如果不添加默认值的话,在使用的时候就必须要设置默认值
}

@IntDef({1,5,10})//建议值
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})//可以作用于变量,方法,参数列表
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Level {
    int value();//没有设置默认值,所以使用的时候需要设置值
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Gender {
    Type value() default Type.Male;

     enum Type {

        Male("男"),
        Female("女"),
        Other("中性");

        private String genderStr;

         Type(String arg0) {
            this.genderStr = arg0;
        }

        @Override
        public String toString() {
            return genderStr;
        }

    }
}

@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Job {
    String name();
    boolean isManager();
}

@Documented
@Inherited
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Name {
    String value() default "none";
}

使用注解:

public abstract class Person {
    @Name()
    protected String mName;
    @Age(value = 10)
    protected int mAge;
    @Gender(Gender.Type.Female)
    protected String mGender;
    @Job (name = "Android程序员", isManager = false)
    protected String mJob;

    @Level(1)
    protected int mLevel;

    public String getName() {
        return mName;
    }

    public void setName(@NonNull String name) {
        mName = name;
    }

    public @Level(1) int getLevel() {
        return mLevel;
    }

    public void setLevel(@Level(1) int level, @Age int age) {
        mLevel = level;
    }

    public @Age int getAge() {
        return mAge;
    }

    public void setAge(@Age int age) {
        mAge = age;
    }

    @Age
    public @Gender @Name String getGender(@Age(2) int age) {
        return mGender;
    }

    public @Gender @Name @Job(name = "abcd", isManager = true) abstract String getAllInfo(@Level(10) @Age(30)int level);

    public void setGender(String gender) {
        mGender = gender;
    }

    public void setJob(String job) {
        mJob = job;
    }

    public @Job(name = "anndroid", isManager = false) String getJob(@Level(10) int level) {
        return mJob;
    }

    @Override
    public String toString() {
        return "name=" + mName + " age=" + mAge + " gender=" + mGender;
    }
}

public class ChinesePersion extends Person {
    @Override
    public String getGender(int age) {
        return super.getGender(age);
    }

    @Override
    public String getAllInfo(int level) {
        return null;
    }

}

测试注解:

public class TestAnnotation {
    public static void main(String[] args){
        analyzeClass(Person.class);
        System.out.println("\n");
        analyzeClass(ChinesePersion.class);
    }

    public static void analyzeClass(Class  cla){
        System.out.println("##################AnalyzeClass " + cla.getName() + " ######################");
        displayFileds(cla);
        displayMedthods(cla);
    }

    private static void displayMedthods(Class cla) {
        Method[] methods = cla.getMethods();
        for(Method method : methods){
            Annotation[] methodAnnotations = method.getAnnotations();
            Annotation[][] paramAnotations = method.getParameterAnnotations();
            if(methodAnnotations.length == 0 && paramAnotations.length == 0){
                continue;
            }
            System.out.println( "============================Analyze methodName=" + method.getName() + "================");
            displayMethodAnotations(method);
            displayParamAnotations(method);
        }
    }

    //打印字段注解
    private static void displayFileds(Class cla) {
        System.out.println( "====================DisplayFields========================");
        //只能获取当前类定义的字段,父类的不能获取,如果要获取父类字段的需要Clazz.getSuper()获取到父类,在获取其对应字段
        Field fields[] = cla.getDeclaredFields();
        for(Field field : fields){
            if(field.isAnnotationPresent(Name.class)){
                Name name = field.getAnnotation(Name.class);
                System.out.println("name=" + name.value());
            }
            if(field.isAnnotationPresent(Age.class)){
                Age age = field.getAnnotation(Age.class);
                System.out.println("age=" + age.value());
            }
            if(field.isAnnotationPresent(Gender.class)){
                Gender gender = field.getAnnotation(Gender.class);
                System.out.println("gender=" + gender.value().toString());
            }
            if(field.isAnnotationPresent(Level.class)){
                Level level = field.getAnnotation(Level.class);
                System.out.println("level=" + level);
            }
            if(field.isAnnotationPresent(Job.class)){
                Job job = field.getAnnotation(Job.class);
                System.out.println("job name=" + job.name() + " isManager=" + job.isManager());
            }
        }
    }

    //打印参数注解
    private static void displayParamAnotations(Method method) {
        Annotation[][] paramAnotations = method.getParameterAnnotations();
        if(paramAnotations != null && paramAnotations.length > 0){
            for(Annotation[] annotations : paramAnotations){
                if(annotations == null || annotations.length == 0){
                    continue;
                }
                for(Annotation  annotation : annotations){
                    System.out.println("*****Param Annotation=" + annotation);
                }
            }
        }
    }

    //打印方法注解,只能获取到继承父类的方法的注解,不能获取到重写父类的方法的注解
    private static void displayMethodAnotations(Method method) {
        Annotation[] anotations = method.getAnnotations();
        if(anotations != null && anotations.length > 0){
            for(Annotation annotation: anotations){
                if(annotation instanceof Job){
                    Job job = (Job) annotation;
                    System.out.println("-----Method Annotation:job name=" + job.name() + " isManager=" + job.isManager());
                }
                if(annotation instanceof Name){
                    Name name = (Name) annotation;
                    System.out.println("-----Method Annotation:name=" + name.value());
                }
                if(annotation instanceof Age){
                    Age age = (Age) annotation;
                    System.out.println("-----Method Annotation:age=" + age.value());
                }
                if(annotation instanceof Gender){
                    Gender gender = (Gender) annotation;
                    System.out.println("-----Method Annotation:gender=" + gender.value().toString());
                }
                if(annotation instanceof Level){
                    Level level = (Level) annotation;
                    System.out.println("-----Method Annotation:level=" + level);
                }
            }
        }
    }

}

输出:

##################AnalyzeClass com.example.administrator.mannotation.Person ######################
====================DisplayFields========================
name=none
age=10
gender=女
job name=Android程序员 isManager=false
level=@com.example.administrator.mannotation.Level(value=1)
============================Analyze methodName=setName================
============================Analyze methodName=getLevel================
-----Method Annotation:level=@com.example.administrator.mannotation.Level(value=1)
============================Analyze methodName=setLevel================
*****Param Annotation=@com.example.administrator.mannotation.Level(value=1)
*****Param Annotation=@com.example.administrator.mannotation.Age(value=0)
============================Analyze methodName=getAge================
-----Method Annotation:age=0
============================Analyze methodName=setAge================
*****Param Annotation=@com.example.administrator.mannotation.Age(value=0)
============================Analyze methodName=getGender================
-----Method Annotation:age=0
-----Method Annotation:gender=男
-----Method Annotation:name=none
*****Param Annotation=@com.example.administrator.mannotation.Age(value=2)
============================Analyze methodName=getAllInfo================
-----Method Annotation:gender=男
-----Method Annotation:name=none
-----Method Annotation:job name=abcd isManager=true
*****Param Annotation=@com.example.administrator.mannotation.Level(value=10)
*****Param Annotation=@com.example.administrator.mannotation.Age(value=30)
============================Analyze methodName=setGender================
============================Analyze methodName=setJob================
============================Analyze methodName=getJob================
-----Method Annotation:job name=anndroid isManager=false
*****Param Annotation=@com.example.administrator.mannotation.Level(value=10)
============================Analyze methodName=wait================
============================Analyze methodName=wait================
============================Analyze methodName=equals================


##################AnalyzeClass com.example.administrator.mannotation.ChinesePersion ######################
====================DisplayFields========================
============================Analyze methodName=getGender================
============================Analyze methodName=getAllInfo================
============================Analyze methodName=setName================
============================Analyze methodName=getLevel================
-----Method Annotation:level=@com.example.administrator.mannotation.Level(value=1)
============================Analyze methodName=setLevel================
*****Param Annotation=@com.example.administrator.mannotation.Level(value=1)
*****Param Annotation=@com.example.administrator.mannotation.Age(value=0)
============================Analyze methodName=getAge================
-----Method Annotation:age=0
============================Analyze methodName=setAge================
*****Param Annotation=@com.example.administrator.mannotation.Age(value=0)
============================Analyze methodName=setGender================
============================Analyze methodName=setJob================
============================Analyze methodName=getJob================
-----Method Annotation:job name=anndroid isManager=false
*****Param Annotation=@com.example.administrator.mannotation.Level(value=10)
============================Analyze methodName=wait================
============================Analyze methodName=wait================
============================Analyze methodName=equals================
查看类的注解
@Documented
@Inherited
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Name {
    String value() default "none";
}

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Name
public @interface Age {
    int value() default 0;//如果不添加默认值的话,在使用的时候就必须要设置默认值
}

@Name
public abstract class Person {
    @Name()
    protected String mName;
    @Age(value = 10)
    protected int mAge;
    @Gender(Gender.Type.Female)
    protected String mGender;
    @Job (name = "Android程序员", isManager = false)
    protected String mJob;

    @Level(1)
    protected int mLevel;

    public String getName() {
        return mName;
    }

    public void setName(@NonNull String name) {
        mName = name;
    }

    public @Level(1) int getLevel() {
        return mLevel;
    }

    public void setLevel(@Level(1) int level, @Age int age) {
        mLevel = level;
    }

    public @Age int getAge() {
        return mAge;
    }

    public void setAge(@Age int age) {
        mAge = age;
    }

    @Age
    public @Gender @Name String getGender(@Age(2) int age) {
        return mGender;
    }

    public @Gender @Name @Job(name = "abcd", isManager = true) abstract String getAllInfo(@Level(10) @Age(30)int level);

    public void setGender(String gender) {
        mGender = gender;
    }

    public void setJob(String job) {
        mJob = job;
    }

    public @Job(name = "anndroid", isManager = false) String getJob(@Level(10) int level) {
        return mJob;
    }

    @Override
    public String toString() {
        return "name=" + mName + " age=" + mAge + " gender=" + mGender;
    }
}

@Age
public class ChinesePersion extends Person {
    @Override
    public String getGender(int age) {
        return super.getGender(age);
    }

    @Override
    public String getAllInfo(int level) {
        return null;
    }

}

public class TestAnnotation {
    public static void main(String[] args){
        displayClassAnnotation(Name.class);
        System.out.println("\n");
        displayClassAnnotation(Age.class);
        System.out.println("\n");
        displayClassAnnotation(Person.class);
        System.out.println("\n");
        displayClassAnnotation(ChinesePersion.class);
    }

    private static void displayClassAnnotation(Class cla) {
    //getAnnotations能拿到所有的注解包括父类,getDeclaredAnnotations只能拿到当前直接类的注解
        Annotation annotations[] = cla.getAnnotations();
        for(Annotation annotation : annotations){
            System.out.println(annotation);
        }
    }
}

输出

@java.lang.annotation.Documented()
@java.lang.annotation.Inherited()
@java.lang.annotation.Target(value=[FIELD, METHOD, ANNOTATION_TYPE, TYPE])
@java.lang.annotation.Retention(value=RUNTIME)


@java.lang.annotation.Target(value=[FIELD, METHOD, PARAMETER, ANNOTATION_TYPE, TYPE])
@java.lang.annotation.Retention(value=RUNTIME)
@java.lang.annotation.Inherited()
@com.example.administrator.mannotation.Name(value=none)


@com.example.administrator.mannotation.Name(value=none)


@com.example.administrator.mannotation.Name(value=none)
@com.example.administrator.mannotation.Age(value=0)

用注解(IntDef/StringDef)替代枚举

public class TestAnnotation1 {
    public static final int ONE = 1;
    public static final int TWO = 2;
    public static final int THREE = 3;

    public static final String STR1 = "s1";
    public static final String STR2 = "s2";
    public static final String STR3 = "s3";

    @IntDef({ONE, TWO, THREE})
    @interface IntDataType{
    }

    @StringDef({STR1, STR2, STR3})
    @interface StrDataType{
    }
    static class Data {
        private int mDataI;

        public String mDataS;

        public void setDataI(@IntDataType int dataI) {
            mDataI = dataI;
        }

        public void setDataS(@StrDataType String dataS) {
            mDataS = dataS;
        }
    }

    static void main(String[] args){
        Data data = new Data();
        data.setDataI(TestAnnotation1.ONE);//编译正确
        data.setDataS(TestAnnotation1.STR3);//编译正确

        data.setDataI(2);//编译报错
        data.setDataS("s1");//编译报错
    }

}

注解限制输入

在Java自带注解中,可以通过@IntRange,@FloatRange限制输入参数,

    private int mAge;
    public void setAge(@IntRange(from = 0, to = 100) int age){
        mAge = age;
    }

    private double mPrice;
    public void setAge(@FloatRange(from = 10.0f, to = 100.0f) double price){
        mPrice = price;
    }

    private void test(){
        setAge(-1);//编译报错
        setAge(10);//编译通过

        setPrice(101);//编译报错
        setPrice(100.0);//编译通过
    }

但是,如果代码如下,则编译正常:因为注解的归根结底只是起注释作用,无法去动态判定变量的值

    private int mAge;
    public void setAge(@IntRange(from = 0, to = 100) int age){
        mAge = age;
    }

    private void test(){
        setAge(calAge());//编译通过
    }


    private int calAge() {
        return -100;
    }

所以正确的使用姿势是:在方法体内也要做参数判断

    private int mAge;
    public void setAge(@IntRange(from = 0, to = 100) int age){
        if(age < 0 || age > 100){
            return;
        }
        mAge = age;
    }

    private void test(){
        setAge(calAge());//编译通过
    }

    private int calAge() {
        return -100;
    }

Android 注解替代findViewById

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IdInject {
    int value();
}
public class MainActivity extends AppCompatActivity {

    private LinearLayout mRootLy;
    @IdInject(R.id.annotation_btn)
    private Button mAnnotationBtn;

    @IdInject(R.id.rootly)
    private LinearLayout mLinearLayout;

    @IdInject(R.id.dyn_view)
    private Button mDynAnnotationBtn;

    ...
    ...

     @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        testAnnotation();
    }

    private void testAnnotation() {
        IdInjectHelper.inject(this);//通过注解获取view
        mAnnotationBtn.setText("这是个注解的button");
        Button button = new Button(this);
        button.setId(R.id.dyn_view);//需要使用自定义viewID
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        button.setLayoutParams(params);
        mLinearLayout.addView(button);
        IdInjectHelper.inject(this, button.getId());//通过注解获取动态view
        mDynAnnotationBtn.setText("这是个动态的注解button");
    }
}

自定义viewID,为给view.setID()时候用:


<resources>
    <item name="dyn_btn" type="id"></item>
    <item name="dyn_view" type="id"></item>
</resources>
public class IdInjectHelper {

    //获取所有注解字段对应view
    public static void inject(Activity activity){
        Class cla = activity.getClass();
        Field fields[] = cla.getDeclaredFields();//获取到所有的字段
        for(Field field : fields){
            if(field.isAnnotationPresent(IdInject.class)){//获取指定注解的字段
                try {
                    IdInject inject = field.getAnnotation(IdInject.class);
                    View view = activity.findViewById(inject.value());
                    field.setAccessible(true);
                    field.set(activity, view);//给对应view赋值
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //动态获取某个id的字段
    public static void inject(MainActivity activity, int id) {
        Class cla = activity.getClass();
        Field fields[] = cla.getDeclaredFields();
        for(Field field : fields){
            if(field.isAnnotationPresent(IdInject.class)){
                try {
                    IdInject inject = field.getAnnotation(IdInject.class);
                    if(id == inject.value()){
                        View view = activity.findViewById(inject.value());
                        field.setAccessible(true);
                        field.set(activity, view);
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
超级详细!!!新手使用AutoDL跑深度学习(MixVPR项目)的学习记录 新手第一次在AutoDL上跑深度学习的实验,遇到一些问题,简单记录一下。如果大家发现问题,欢迎和我讨论。 阅读详情

相关推荐

中国1990-2021连续30年土地利用CLCD数据分享

CLCD(China Land Cover Dataset)数据集是由武汉大学黄昕老师基于Google Earth Engine上的335,709景Landsat数据制作的中国年度土地覆盖数据集。为了提高CLCD的时空一致性,还提出了一种包含时空滤波和逻辑推理的后处理方法。该数据集最大的优势在于每年30米的土地利用分类结果,且连续覆盖了30年时间。相比其他产品如GLC_FCS30、Global30、AGLC2000_2015、FROM-GLC10、ESA10、ESRI10等,CLCD在时间分辨率上更高。

qq_48539301的博客 1万+

自定义注解

自定义一个注解: @Inherited @Documented @Target({ElementType.CONSTRUCTOR,ElementType.TYPE,ElementType.FIELD,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { long id

Benson的专栏 1753

银河麒麟高级服务器操作系统V10SP2(X86)PXE无人值守批量部署实战指南

本文详细介绍了银河麒麟高级服务器操作系统V10SP2(X86)PXE无人值守批量部署的实战指南。通过PXE网络引导技术,实现全自动化、高效率的系统部署,特别适用于企业级数据中心和国产化替代项目。文章涵盖基础环境准备、关键服务配置、Kickstart高级定制及部署测试等核心内容,帮助用户快速掌握批量部署技巧。

weixin_42525637的博客 382

Java注解解析(二)

上一篇博客介绍到注解的分类以及每一种注解的特点。这次来说说自定义注解。 在说注解之前先说说元注解。 元注解 元注解简单来说就是注解的注解。 在上一篇博客说到注解根据运行机制可以分为三种。那么我们自定义的注解是属于哪一种呢?其实可以属于任何一种。因为我们可以用元注解给我们自定义的注解标记到底是编译时注解还是运行时注解。 元注解主要有以下几种: @Target   用来标

javy_codercoder的博客 711

ADS交叉耦合振荡器VCO仿真

本文主要参考视频中如何使用进行ADS交叉耦合振荡器仿真和分析,由于视频中有诸多错误和视频清晰度较低,虽然视频博主及时改正,为了节省学习时间,可以直接参考本文。

qq_32589131的博客 5424

QTest 单元测试框架及单元测试思考

qt 单元测试框架 QTEST 及思考

一个老菜鸟的学习分享 1万+

androidannotation 3.0 注解不生效 求解

在3.0上配置 androidannotation 按照配置 只需要添加插件应用和jar依赖     //androidannotation 注解     annotationProcessor "org.androidannotations:androidannotations:4.5.+" implementation "org.androidannotations:androidan...

NextDoorOldYu的博客 1245

CRMEB商城系统任意文件下载漏洞(CVE-2024-52726)分析与修复

在Web应用安全领域,API接口安全是保障系统边界安全的核心环节。其原理在于通过签名验证、参数校验等机制,确保请求的合法性与完整性。这项技术的价值在于为系统间数据交互提供安全通道,防止未授权访问和数据泄露。典型的应用场景包括电商系统的对外数据接口、第三方服务集成等。然而,当签名验证逻辑存在缺陷或文件路径处理不当,便会引发严重的安全风险。本文以CRMEB开源商城系统为例,深入剖析其对外API模块中因签名验证绕过和路径遍历导致的任意文件下载漏洞。该漏洞允许攻击者下载服务器敏感文件,如数据库配置文件、日志和源码,

weixin_27722377的博客 376

Android 修改代码后不生效问题的终极方案

但是最终遇到一个咋配置都不生效的项目,这里主要就是当你咋配studio都不生效,gradle咋改都不好使的时候,提供一些节约时间的方法。最后,到底为啥改了代码重新run会不生效,我没找到根本原因,怀疑是gradle配置的问题,会不会与多module的sourcesets有关系,尝试去配置了sourcesets,但是没生效,希望找到原因的同学一起交流。前言: 最近遇到几个项目,都出现了代码修改后,直接点studio上的run,跑起来后代码没生效,如果重新clean。这个方案比较麻烦,要操作步骤比较多。

u011835956的专栏 4932

HP SPP download

是一个全面的系统软件和固件更新解决方案,以单个ISO映像的形式提供。该解决方案使用智能更新管理器(SUM)作为部署工具。

极致,细节 9858

大模型部署指南:SGLang 框架

本文介绍使用 SGLang 框架部署大模型

举世誉之而不加劝,举世非之而不加沮,定乎内外之分,辩乎荣辱之境,斯已矣。 1611

Java、Kotlin、Android中的注解(Annotation)

注解机制: JDK1.5后,Java引入了一种新的注释机制(Annotation),其一般作为说明信息,与程序的业务逻辑无关。 注解仅仅是一种说明信息,它广泛的应用于一些工具或框架中。 (官方定义)注解Annotation就是Java提供了一种元程序中的元素关联任何信息和任何元数据(metadata)的途径和方法。 什么是注解? “元数据”可以描述它,即一种描述数据的数据。所以,可以说注解就...

手写我对你的温柔 5665

分享一个我自用的 Python 消息发送模块,支持邮件、钉钉、企业微信

🔥 分享一个我自用的 Python 消息发送模块,支持邮件、钉钉、企业微信

XiaoqiangClub的博客 477

深入理解Java注解(注解在Android中的应用)

在许多程序设计语言里,比如 Java、C#,依赖注入是一种较流行的设计模式,在 Android开发中也有很多实用的依赖注入框架,可以帮助我们少写一些样板代码,达到各个类之间解耦的目的,因此掌握并深入理解注解对于一个Java工程师是来说是很有必要的事。本篇我们将通过以下几个角度来分析注解的相关知识点。 一 注解 从JDK 5开始,Java增加了注解,注解是代码里的特殊标记,这些标记可以在编译、类加载、运行时被读取,并执行相应的处理。通过使用注解,开发人员可以在不改变原有逻辑的情...

lixiong0713的博客 2万+

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Java注解在Android中必须学习的细节知识

前言对于注解,相信大家都不陌生了,但是这种熟悉对于Android开发者来说,也就是仅仅是它认识你,你不认识它吧,因为,我们几乎都停留在用上了。像dagger2,像retrofit,像greenDao,他们都是满满的使用了注解,而我们只是停留在知其然缺不知其所以然的层面,那么我本次分享讲分成几批博客共享给大家一个体系的又不失针对Android平台需要的恰到好处的给大家整理真正需要掌握的知识体系。注解...

weixin_34406061的博客 161

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Android java注解整理

注解   1.     注解作用   (1) 代码分析与检查。通过IDE 工具可以在编译期间发现数据配置语法错误。 (2) 代码自动生成。开发者可以更关注于实际应用的业务逻辑,避免写那些重复的代码,从而提高效率。例如测试,日志,事务类文件自动生成等 (3) 代码更简洁,便于代码的阅读和理解。 2.     Java 注解 1.1             元注解   元注解的作用就

wanwanwanwang7881041的专栏 1025

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Java 进阶 _ 注解及其在 Android 中的应用

Javapoet 是一个用来生成.java文件的 Java API,由 Square 开发,你可以在它的 Github 主页中了解它的基本使用方法。它的好处就是对方法、类文件和代码等的拼接进行了封装,有了它,我们就不用再按照字符串的方式去拼接出一段代码了。相比于直接使用字符串的方式,它还可以生成代码的同时直接import对应的引用,可以说是非常方便、快捷的一个库了。这里的是用来生成类文件的核心类,它是一个抽象类,一般使用的时候我们只要覆写它的方法中的4个就可以了。init。

2401_84132544的博客 430

Android 开发也要掌握的Java知识 - Java注解

文章目录1.注解的定义2.注解是什么样的3.注解的分类以及作用4.注解写法5.注解使用5.1 过时标记5.2 语法检查5.3 findViewById5.4 View的Onclick6.结尾 Android开发中大量的使用了注解,开源框架也大量使用,我们自己虽然自定义的注解不多,但也要了解基本的知识。 1.注解的定义 Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。 注解是元数据的一种形式,提供有关 于程序但不属于程序本身的数据。注解对它们注解的代码的

Good包籽的Android专栏 273

@column注解_Java 注解及其在 Android 中的应用

Linux编程点击右侧关注,免费入门到精通!作者丨WngShhnghttps://juejin.im/post/5b824b8751882542f105447d一般的,注解在 Android 中有两种应用方式,一种方式是基于反射的,即在程序的运行期间获取类信息进行反射调用;另一种是使用注解处理,在编译期间生成许多代码,然后在运行期间通过调用这些代码来实现目标功能。在本篇文章中,我们会先重...

weixin_39719472的博客 560

Java_注解 (元注解 / Java内置注解 / Android内置注解)

注解: 给程序看的提示. (注释: 给程序员看的提示) Java1.5开始引入注解功能. 元数据: 描述数据的数据, 可以说注解便是这元数据. (除注解外, XML也被用于描述元数据) 注解仅仅是元数据, 与业务逻辑无关, 注解的 添加 / 删除 不能影响程序的执行

Luzhuo 的博客 1109

Android Java 注解

1.简介 Java注解是一系列元数据,它提供数据用来解释程序代码,但是注解并非是所解释的代码本身的一部分。 注解对于代码的运行效果没有直接影响。 个人理解:注解就是给代码加上标记,这个标记可以在编译时、运行时获取到,从而可以让我们对 打标记的代码在编译或者运行时进行处理。 注解本身没有任何意义,单独的注解就是一种注释,它需要结合其它如反射、插桩等技术才有意义 2.定义注解 注解和接口的定义一样,使用interface关键词,不过需要在关键词前加上@ public @interface Chxip {

chxip的博客 363

java 注解应用场景_Java 注解及其在 Android 中的应用

原标题:Java 注解及其在 Android 中的应用来源:WngShhnghttps://juejin.im/post/5b824b8751882542f105447d一般的,注解在 Android 中有两种应用方式,一种方式是基于反射的,即在程序的运行期间获取类信息进行反射调用;另一种是使用注解处理,在编译期间生成许多代码,然后在运行期间通过调用这些代码来实现目标功能。在本篇文章中,我们会先重...

weixin_33376046的博客 207

Java注解在Android中使用

注解(Annotation)也被称为元数据(Metadata),是在Java SE 5中提供的一个新特性。Annotation可以用来修饰类,属性,方法。在Java中,除了使用系统内置的Annotation以外,用户还能够通过自定义Annotation来实现所需要的功能。下面就来看一下如何使用自定义的Annotation。

李江东 6097

理解Java和Android原生注解

声明:本博客转载自C . Shawn,优秀博客值得多次转播。 地址 http://blog.youkuaiyun.com/CShawnX/article/details/51605919 原文1.引言从JDK1.5开始,引入了注解类Annotation,Annotation其实是一种接口,可以作用于类、方法、属性等等 ,它可以通过反射机制来访问annotation信息,获取所加上注解信息,做相应的操作。相

星光小站 800

Android 中Java注解的使用

参考 Java注解在Android中使用 Android 打造编译时注解解析框架 这只是一个开始 android注解入门 并来自己写一个框架

zuochunsheng的博客 512

Java 注解及其在 Android 中的应用

一般的,注解在 Android 中有两种应用方式,一种方式是基于反射的,即在程序的运行期间获取类信息进行反射调用;另一种是使用注解处理,在编译期间生成许多代码,然后在运行期间通过调用这些代码来实现目标功能。 在本篇文章中,我们会先重温一下 Java 的注解相关的知识,然后分别介绍一下上面两种方式的实际应用。 1、Java 注解回顾 1. Java 注解的基础知识 Java 中的注解分成标准注解和元...

weixin_34319374的博客 204
上一篇: 初探RxJava2Android
下一篇: 精致自绘渐变进度条-Path/Paint.setXfermode
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值