zoukankan      html  css  js  c++  java
  • 面试官问我注解怎么使用?我这样告诉他

    上次面试官问我注解,怎么自定义注解?我告诉他我不会

    就这样等我再去查校招进度的时候
    在这里插入图片描述

    俺发奋图强,通过一天的学习,终于明白注解。

    1. 自定义注解的使用!
    2. 通过注解我们能干什么?
    3. 注解究竟有什么好处?

    话不多说,直奔主题!

    自定义注解的创建

    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    public @interface AutoWired {
        //自动注入注解
        Class className();//获取class对象
        String name();
        int age();
    }
    

    乍一看您可能就有三个问题
    1.@Retention@Target是啥呀?
    答:这两个也是注解,是为了注解自定义注解的注解(中文八级hahahaha)
    在这里插入图片描述
    我们称注解自定义注解的注解为元注解,你可以理解为注解是一个标签,而元注解是给这些标签打标签的。

    2.元注解有什么用呀?
    答:只有两个比较重要和常用的元注解,就是上面两个,分别介绍一下他们的作用

    @Target:指明我们的自定义注解可以修饰的范围,如类,方法,变量
    @Retention:指明自定义注解存在的范围,可以指定为SOURCE,CLASS,RUNTIME;
    SOURCE表明注解只在.java文件中存在,CLASS表明注解在.class文件中存在,而RUNTIME表示在运行时,会把自定义注解加载到虚拟机中。

    3.className(),name(),age()是啥呀
    答:可以理解为属性,并且可以定义默认值。有了这些属性,我们在使用注解时可以赋值。

    @AutoWired(className = Person.class,name = "Yang",age=20)
        public static Person person1;
        @AutoWired(className = Person.class,name = "Zhang",age=20)
        public static Person person2;
    

    相比大家已经明白了基本使用了(估计有人想打死我)
    在这里插入图片描述

    通过注解我们能干什么?

    1.通过注解我们能够减少重复性的代码,让代码的可读性更好。
    2.现在很多框架中都有自定义的注解,比如在Spring中有自动注入,也是通过注解实现的,在Android中,为了避免重复的findviewById可以使用自定义注解,那么下面我们来演示如何在Java中通过注解实现自动注入,通过注解实现findviewById的自动完成。

    在这里插入图片描述

    实现自动注入

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    //自定义注解,三个属性,class对象
    public @interface AutoWired {
        //自动注入注解
        Class className();//获取class对象
        String name();//姓名
        int age();//年龄
    }
    
    
    import java.lang.reflect.Field;
    //我们知道静态代码块属于类,所以他会被先执行,我们在静态代码块中通过反射获取了Student类中定义的所有的成员变量(两个Person),然后分别给他们赋值,值也是从注解中获取的age和name.
    public class Student{
        static{
           Field[] fields = Student.class.getDeclaredFields();
           for (int i=0;i<fields.length;i++){
               AutoWired  auto = fields[i].getAnnotation(AutoWired.class);
               Class cl = auto.className();//获取class对象,根据class对象给Person初始化
               String name = auto.name();
               int age = auto.age();
               try {
                   Field field = fields[i];
                   field.setAccessible(true);//暴力访问,取消age的私有权限。让对象可以访问
                   Object obj = cl.newInstance();
                   Person p = new Person(name,age);
                   field.set(obj, p);//设置对象中,私有变道量的值
               } catch (InstantiationException e) {
                   e.printStackTrace();
               } catch (IllegalAccessException e) {
                   e.printStackTrace();
               }
    
           }
        }
    
        @AutoWired(className = Person.class,name = "Yang",age=20)
        public static Person person1;
        @AutoWired(className = Person.class,name = "Zhang",age=20)
        public static Person person2;
    
        public static void main(String[] args) {
        //从main方法中看,我们没有任何new,就能够获取到对象的属性,这和自动注入类似, 
            System.out.println(person1.getName()+"------"+person1.getAge()+"
    ");
            System.out.println(person2.getName()+"------"+person2.getAge()+"
    ");
    
            //自动注入
        }
    
    
    }
    
    

    实现不实用findviewById就指定绑定ID的功能

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface FindView {
        int resId();//我们只要输入id,就能帮我们自动的绑定
    }
    
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.TextView;
    
    import com.example.annimation.FindView;
    
    import java.lang.reflect.Field;
    
    public class FIndViewActivity extends AppCompatActivity {
    
        @FindView(resId = R.id.tv_name1)
        TextView tv_name1;
        @FindView(resId = R.id.tv_name2)
        TextView tv_name2;
        @FindView(resId = R.id.tv_name3)
        TextView tv_name3;
        @FindView(resId = R.id.tv_name4)
        TextView tv_name4;
        @FindView(resId = R.id.tv_name5)
        TextView tv_name5;
        @FindView(resId = R.id.tv_name6)
        TextView tv_name6;
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_find_view);
            //onCreate中我们通过一个函数解决findviewbyId的问题
            bindView(this);
        }
    
        public static void bindView(Activity activity) {
            Class classObj = activity.getClass();
            Field [] fields = classObj.getDeclaredFields();
    
            for (int i = 0; i < fields.length; i++) {
                Field field = fields[i];
                if (field.isAnnotationPresent(FindView.class)) {
                    FindView findView = field.getAnnotation(FindView.class);
                    int resId = findView.resId();
                    View view = activity.findViewById(resId);
                    field.setAccessible(true);//私有类型必须要设置
                    Class<?> targetType = field.getType();//成员变量的类型,如TextView
                    Class<?> viewType = view.getClass();//获取包名
                    if (!targetType.isAssignableFrom(viewType)) {
                        continue;
                    }
                    try {
                        field.set(activity, view);//通过set设置
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
    }
    
    

    大功告成,现在你对注解是不是又多了一点了解呢?如果大家还像了解注解的细节,请查阅其他资料。
    在这里插入图片描述

  • 相关阅读:
    数据库主从配置
    数据库导出导入
    MySQL命令行导出数据库
    [待完善]mycat使用(一)
    行转列group_concat()函数妙用
    sas和ssd盘写入数据效率对比
    MySQL库中表名忽略大小写设置的影响
    create table b1 as select * from b建表锁表测试
    SQL优化实战之加索引
    分区表主键不包含分区键报错ERROR 1105 (HY000)
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13309320.html
Copyright © 2011-2022 走看看