注释就这么简单-Betway官网登录_betway体育app_必威体育app

出自:Java3y htt家电论坛ps://mp.weixin.qq.com/s/n-P8W8OzcKIg3UiFC-JycA

前语

今日要讲的是注解,关于本章节,最好是有Servlet根底的人查阅~由于单纯是Java根底的话,或许用不上注解这个东西。但假如开发过Ser舜世金服vlet,就对@WebServlet不会生疏。

现在的开发都推重运用注解来进行开发,这样就能够免除写XML装备了,十分便利的一项技能~

学习注解能够更好地了解注解是怎样作业的,看见注解了就能够想到它的运转原理了~。

假如有错的当地请咱们多多包容并欢迎在谈论区纠正~

一、什么是注解?

注解:Annotation….

注解其实便是代码中的特别符号,这些符号能够在编译、类加载、运转时被读取,并履行相对应的处理

二、为什么咱们需求用到注解?

传统的办法,咱们是经过装备文件(xml文件)来通知类是怎样运转的

有了注解技能今后,咱们就能够经过注解通知类怎样运转

例如:咱们曾经编写Servlet的时分,需求在web.xml文件装备详细的信息

这儿写图片描绘

咱们运用了注解今后,能够直接在S注释就这么简略-Betway官网登录_betway体育app_必威体育app ervlet源代码上,添加注解…Servlet就被装备到Tomcat上了。也便是说,注解能够给类、办法上注入信息。

这儿写图片描绘

明显地能够看出,这样是十分直观的,而且Servlet标准是推重这种装备办法的

三、根本Annotation

在java.lang包下存在着5个根本的Annotation,其中有3个Annotation咱们是十分常见的了。

3.1@Override

重写注解

假如咱们运用IDE重写父类的办法,咱们就能够看见它了。那它有什么用呢??

@Overried是通知编译器要查看该办法是完成父类的…能够帮咱们防止一些初级的过错…

比方,咱们在完成equals()办法的时分,把euqals()打错了,那么编译器就会发现该办法并不是完成父类的,与注解@Overr注释就这么简略-Betway官网登录_betway体育app_必威体育app ide抵触,所以就会给予过错

这儿写图片描绘



3.2@Deprecated

过期注解

该注解也十分常见,Java在规划的时分,或许觉得某些办法规划得欠好,为了兼容曾经的程序,是不能直接把它扔掉的,所以就设置它为过期

Date目标中的toLocalString()就被设置成全家过期了

 @Deprecated
public String toLocaleString() {
DateFormat formatter = DateFormat.getDateTimeInsta宝骏轿车nce();
return formatter.format(this);
}

当咱们在程序中调用它的时分,在IDE上会呈现一条横杠,阐明该办法是过期的。

这儿写图片描绘


3.3@SuppressWarnings

按捺编译器正告注解

该注解在咱们写程序的时分并不是很常见,咱们能够注释就这么简略-Betway官网登录_betway体育app_必威体育app 用它来让编译器不给予咱们正告

当咱们在运用调集的时分,假如没有指定泛型,那么会提示安全查看的正告

这儿写图片描绘

假如咱们在类上添加了@SuppressWarnings这个注解,那么编译器就不会给予咱们正告了

这儿写图片描绘

3.4@SafeVarargs

Java 7“堆污染”正告

什么是堆污染呢??当把一个不是泛型的调集赋值给一个带泛型的调集的时分,这种状况就很容易发生堆污染….

这个注解也是用来按捺编译器正告的注解…用的当地并不多,我也不详细阐明晰……有用到的时分再回来填坑吧。

3.5@FunctionalInterface

@FunctionalInterface用来指定该接口是函数式接口

用该注解显现指定该接口是一个函数式接口。


四、自界说注解根底

上面解说的是java.lang包下的5个注解,咱们是能够自己来写注解,给办法或类注入信息

4.1符号Annotation

没有任何成员变量的注解称作为符号注解,@Overried便是一个符号注解

//有点像界说一个接口相同,只不过它多了一个@
public @int九妹erface MyAnnotation {
}

4.2元数据Annotation

咱们自界说的注解是能够带成员变量的,界说带成员变量的注解叫做元数据Annotation

在注解中界说成员变量,语法类似于声明办法相同….

public @interface MyAnnotation {
//界说了两个成员变量
String username();
int age();
}

留意:在注解上界说的成员变量只能是String、数组、Class、枚举类、注解

有的人或许会古怪,为什么注解上还要界说注解成员变量??听起来就很杂乱小天才了….

上边现已说了,注解的效果便是给类、办法注入信息。那么咱们常常运用XML文件,通知程序怎样运转。XML常常会有嵌套的状况

<书>
<作者>zhongfucheng
<价钱>22222

那么,当咱们在运用注解的时分,也或许需求有嵌套的时分,所以就答应了注解上能够界说成员变量为注解。

4.3运用自界说注解

上面咱们现已界说了一个注解了,下面咱们来运用它吧

4.3.1惯例运用

下面我有一个add的办法,需求username和age参数,咱们经过注解来让该办法具有这两个变量

 //注解具有什么特点,在润饰的时分就要给出相对应的值
@MyAnnota祝精隆tion(username = "zhongfucheng", age = 20)
public void add(String username, int age) {
}

4.3.2默许值

当然啦,咱们能够在注解声明特点的时分,给出默许值。那么在润饰的时分,就能够不必详细指定了。

public @interface MyAnnotation {
//界说了两个成员变量
String username() default "zicheng";
int age() default 23;
}
  • 在润饰的时分就不需求给出详细的值了
 @MyAnnotation()
public void add(String username, int age) {
}



4.3.3注解特点为value

还有一种特别的状况,假如注解上只要一个特点,而且特点的名称为value,那么在运用的时分,咱们能够不写value,直接赋值给它就行

public @interface MyAnnotation2 {
String value();
}
  • 运用注解,能够不指定value,直接赋值机油
 @MyAnnotation2("zhongfucheng")
public void find(String id) {
}



4.4把自界说注解的根本信息注入到办法上

上面咱们现已运用到了注解,可是现在为止注解上的信息和办法上的信息是没有任何相关的

咱们运用Servlet注解的时分,只是调用注解,那么注解的就收效了。这是Web容器把内部完成了。咱们自己写的自界说注解是需求咱们自己来处理的

那现在问题来了,咱们怎样把注解上的信息注入到办法上呢???咱们运用的是反射技能

过程可分为三部:

  • 反射出该类的办法
  • 经过办法得到注解上详细的信息
  • 将注解上的信息注入到办法上
 //反射出该类的办法
Class aClass = Demo2.class;
Method method = aClass.getMethod("add", Stri注释就这么简略-Betway官网登录_betway体育app_必威体育app ng.class, int.class);
//经过该办法得到注解上的详细信息
MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
String username = annotation.username();
int age = annotation.age();
//将注解上的信息注入到办法上
Object o = aClass.newInstance();
metho注释就这么简略-Betway官网登录_betway体育app_必威体育app d.invoke(o, username, age);

当咱们履行的时分,咱们发现会呈现异常…

这儿写图片描绘

此刻,咱们需求在自界说注解上参加这样一句代码(下面就会讲到,为什么要参加这句代码)

 @Retention(RetentionPolicy.RUNTIME)


再次履行的时分,咱们就会发现,能够经过注解来把信息注入到办法中了。


五、JDK的元Annotation

前面咱们现已介绍了java.lang包下的几个根本Annotation了。在JDK中除了java.lang包下有Annotation,在java.lang.annotation下也有几个常用的元Annotation。

在annotation包下的好几个元Annotation都是用于润饰其他的Annotation界说


5.1@Retention

上面在将注解信息注入到办法中的时分,咱们最终加上了@Retention虾米音乐网的注解….否则就会报错了..那它是干什么用的呢?

@Retention只能用于润饰其他的Annotation,用于指定被润饰的Annotation被保存多长时间。

@Retention 包含了一个RetentionPolicy类型的value变量,所以在运用它的时分,有必要要为value成员变量赋值

value变量的值只要三个:

public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}

java文件有三个时期:编译,class,运转。@Retention默许是class

前面咱们是运用反射来得到注解上的信息的,由于@Retention默许是class,而反射是在运转时期来获取信息的。因而就获取不到Annotation的信息了。所以,就得在自界说注解上修正它的Retent眼ionPolicy值


5.2@Target

@Target也是只能用于润饰别的的Annotation它用于指定被润饰的Annotation用于润饰哪些程序单元

@Target是只要一个value成员变量的,该成员变量的值是以下的:

public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE
}

假如@Target指定的是ElementType.ANNOTATION_TYPE,那么该被润饰的Annotation只能润饰Annotaion


5.3@Documented

@Documented用于指定被该Annotation润饰的Annotation类将被javadoc东西提取成文档

该元Annotation用得挺少的….


5.4@Inherited

@Inherite注释就这么简略-Betway官网登录_betway体育app_必威体育app d也是用来润饰其他的Annotation的,被润饰过的Annotation将具有承继性。。。

比如:

  1. @xxx是我自界说的注解,我现在运用@xxx注解在Base类上运用….
  2. 运用@Inherited润饰@xxx注解
  3. 当有类承继了Base类的时分,该完成类主动具有@xxx注解



六、注入目标到办法或成员变量上

6.1把目标注入到办法上

前面咱们现已能够运用注解将根本的信息注入到办法上了,现在咱们要运用的是将目标注入到办法上…..

上边现已说过了,注解上只能界说String、枚举类、Double之类的成员变量,那怎样把目标注入到办法上呢?

6.1.2模仿场景:

  • Person类,界说username和age特点,具有uername和age的getter和setter办法
public class Person {
private String username;
private int age;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
  • PersonDao类,PersonDao类界说了Person目标,具有person的setter和getter办法
public class PersonDao {
private Perstoryson person;
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person东方时髦驾校;
}
}
  • 现在我要做的便是:运用注解将Person目标注入到setPerson()办法中,然后设置了PersonDao类的person特点
public class PersonDao {
private Person person;
public Person getPerson() {
return person;
}
//将username为zhongfucheng,age为20的Person目标注入到setPerson办法中
@InjectPerson(username = "zhongfucheng",age = 20)
public void setPerson(Person person) {
this.person = person;
}
}

过程:

①: 自界说一个注解,特点是和JavaBean类共同的

//注入东西是经过反射来得到注解的信息的,所以保存域有必要运用RunTime
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectPerson {
String username();
int age();
}

②:编写注入东西

 //1.运用内省【后边需求得到特点的写办法】,得到想要注入的特点
PropertyDescriptor descriptor = new PropertyDescriptor("person", PersonDao.class);
//2.得到要想注入特点的详细目标
Person person = (Person) descriptor.getPropertyType().newInstance();
//3.得到该特点的写办法【setPerson()】
Method method = descriptor.getWriteMethod();
//4.得到写办法的注解
Annotation annotation = method.getAnnotation(InjectPerson.class);
//5.得到注解上的信息【注解的成员变量便是用办法来界说的】
Method[] methods = annotation.getClass().getMethods();
//6.将注解上的信息填充到person目标上
for (Method m : methods) {
//得到注解上特点的姓名【age或name】
String name = m.getName();
//看看P社会实践陈述范文erson目标有没有与之对应的办法【setAge(),setName()】
try {
//6.1这儿假定:有与之对应的写办法,得到写办法
PropertyDescriptor descriptor1 = new PropertyDescriptor(name, Person.class);
Method method1 = descriptor1.getWriteMethod();//setAge(), setName()
//得到注解中的值
Object o = m.invoke(annotation, null);
//调用Person目标的setter办法,将注解上的值设置进去
method1.invoke(person, o);
} catch (Exception e) {
//6.2 Person目标没有与之对应的办法,会跳到catch来。咱们要让注释就这么简略-Betway官网登录_betway体育app_必威体育app 它持续遍历注解就好了
continue;
}
}
//当程序遍历完之后,person目标现已填充完数据了
//7.将person目标赋给PersonDao【经过写办法】
PersonDao personDao = new PersonDao();
method.invoke(personDao, person);
System.out.println(personDao.getPerson().getUsername());
System.out.println(personDao.getPerson().getAge());

③:总结一下过程

其实咱们是这样把目标注入到办法中的:

  • 得到想要类中注入的特点
  • 得到该特点的目标
  • 得到特点对应的写办法
  • 经过写办法得到注解
  • 获取注解详细的信息
  • 将注解的信息注入到目标上
  • 调用特点写办法,将已填充数据的目标注入到办法中

6.2把目标注入到成员变量

上面现已说了怎样将目标注入到办法上了,那么注入到成员变量上也是十分简略的。

过程陵水气候:

①:在成员变量上运用注解

public class PersonDao {
@InjectPerson(username = "zhongfucheng",age = 20) private Person person;
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = perzara我国官网son;
}
}

②:编写注入东西

 //1.得到想要注入的特点
Field field = PersonDao.class.getDeclaredField("person");
//2.得到特点的详细目标
Person person = (Person) field.getType().newInstance();
//3.得到特点上的注解
Annotation annotation = field.getAnnotation(InjectPerson.class);
//4.得到注解的特点【注解上的特点运用办法来表明的】
Method[] methods = annotation.getClass().getMethods();
//5.将注入的特点填充到person目标上
for (Meth铝合金门窗od method : methods) {
//5.1得到注解特点的姓名
String name = method.getName();
//查看一下Person目标上有没有与之对应的写办法
try {
//假如有
PropertyDescriptor descriptor = new PropertyDescriptor(name, Person.class);
//得到Person目标上的写办法
Method method1 = descriptor.getWriteMethod();
//得到注解上的值
Object o = method.invoke(annotation, null);
//填充person目标
method1.invoke(person, o);
} catch (IntrospectionException e) {
//假如没有想对应的特点,持续循环
continue;大人荟
}
}
//循环完之后,person就现已填充好数据了
//6.把person目标设置到PersonDao中
PersonDao personDao = new PersonDao();
field.setAcc彭安东essible(true);
field.set(personDao, person);
System.out.println(personDao.getPerson().getUsername());

七、总结

①:注入目标的过程:得到想要注入的目标特点,经过特点得到注解的信息,经过特点的写办法将注解的信息注入到目标上,最终将目标赋给类

②:注解其实便是两个效果:

  • 让编译器查看代码
  • 将数据注入到办法、成员变量、类上


③:在JDK中注解分为了

  • 根本Annotation
  • 在lang包下,用于常用于符号该办法,按捺编译器正告等
  • 元Annotaion
  • 在annotaion包下,常用于润饰其他的Annotation界说

微信大众号【程序员乔戈里】 作者乔戈里,斜杠青年,哈工大本硕985 硕士,百度Java 研制工程师,现在致米思米力于共享求职必备学习经历、求职心得和生长感悟/技能文章。(重视大众号送9000G 考研/python/C++/java/前端/小程序/微信大众号/机器学习/人工智能资源)

评论(0)