《面試1v1》Java注解

我是 javapub,一名 Markdown
程序員從?????,八股文種子選手。
《面試1v1》更新中...?
面試官: 接下來(lái),聊聊Java的注解,它們到底有什么用?
候選人: 注解的用處主要三個(gè): 第一個(gè),編譯期使用。比如@Override確保你正確重寫(xiě)了方法,@Deprecated表示這個(gè)方法以后可能會(huì)刪掉。 第二個(gè),運(yùn)行期使用。很多框架通過(guò)反射來(lái)讀注解,根據(jù)注解改變程序的行為。像Spring的@Autowired就是運(yùn)行期讀取的。 第三個(gè), build tool用。很多構(gòu)建工具會(huì)在構(gòu)建代碼時(shí)掃描和讀取注解,根據(jù)注解做相應(yīng)的操作。JUnit的@Test就是告訴測(cè)試運(yùn)行器哪些是測(cè)試方法。
面試官:注解和注釋有什么區(qū)別吧?
候選人: 注釋是寫(xiě)給人看的,注解是寫(xiě)給機(jī)器看的。注釋不會(huì)對(duì)程序產(chǎn)生任何影響,注解會(huì)影響程序的編譯、運(yùn)行。注釋是// 或者/* */,注解是@打頭的。
面試官:舉個(gè)自定義注解的例子?
候選人: 這里有個(gè)自定義注解的示例:
//自定義注解
(ElementType.METHOD)
(RetentionPolicy.RUNTIME)??
public? ?MyAnno?{
????String?name()?default?"Hello";?
}
//使用注解
public?class?MyClass?{
?? (name?=?"World")
??public?void?sayHello()?{
????System.out.println("Hello?World");?
??}
}?
//讀取注解
MyAnno?anno?=?MyClass.class.getMethod("sayHello").getAnnotation(MyAnno.class);??
String?name?=?anno.name();?//?name?=?"World"
面試官:說(shuō)說(shuō)Spring中常見(jiàn)的注解?
候選人: Spring中超級(jí)常用的注解有: @Component:把類標(biāo)記為Spring的組件,用于組件掃描。 @Autowired:自動(dòng)裝配成員變量、構(gòu)造方法和方法參數(shù)。 @Service:標(biāo)記業(yè)務(wù)層組件。@Controller:標(biāo)記控制層組件。 @Repository:標(biāo)記數(shù)據(jù)訪問(wèn)組件。 @RequestMapping:映射請(qǐng)求URL到控制器處理方法。 @Configuration:標(biāo)記配置類。 @Enable*:開(kāi)啟某個(gè)功能,比如@EnableTransactionManagement 開(kāi)啟事務(wù)功能。 這些注解大大簡(jiǎn)化了Spring的配置,真的很常用!
面試官:SpringBoot中常見(jiàn)的注解也說(shuō)一下?
候選人: SpringBoot中常用的注解有: @SpringBootApplication:標(biāo)記這個(gè)類是SpringBoot的主配置類。 @Configuration:標(biāo)記這個(gè)類是配置類。 @EnableAutoConfiguration:開(kāi)啟SpringBoot的自動(dòng)配置。 @ComponentScan:開(kāi)啟組件掃描,找出應(yīng)用相關(guān)的bean。 @RestController:標(biāo)記這個(gè)控制器直接返回JSON或XML數(shù)據(jù)。 @RequestMapping:映射請(qǐng)求URL。 @Autowired:自動(dòng)裝配bean。 @Repository、@Service、@Controller:標(biāo)記DAO、Service、Controller層的bean。 這些注解的作用和Spring差不多,只是在SpringBoot中簡(jiǎn)單了很多,幾乎都可以不寫(xiě)XML配置了。
面試官:最后,AOP中的注解呢?
候選人: AOP中最重要的注解有:
@Aspect:標(biāo)記一個(gè)切面。
@Pointcut:定義一個(gè)切點(diǎn),可以是一個(gè)規(guī)則表達(dá)式,和@Before等注解搭配使用。
@Before:前置通知,在目標(biāo)方法調(diào)用前執(zhí)行。
@AfterReturning:后置通知,在目標(biāo)方法正常返回后執(zhí)行。
@AfterThrowing:異常通知,在目標(biāo)方法拋出異常后執(zhí)行。
@After:最終通知,無(wú)論目標(biāo)方法是否正常完成都會(huì)執(zhí)行。
@Around:環(huán)繞通知,手動(dòng)控制目標(biāo)方法調(diào)用時(shí)機(jī)。
這些AOP注解通過(guò)在方法上標(biāo)記,就可以實(shí)現(xiàn)方法的切入、替換等,真正做到面向切面編程。
面試官:自定義注解需要什么?
候選人: 自定義注解需要兩個(gè)注解:@Target定義可以用于什么地方(方法、類等),@Retention定義注解的生命周期(編譯期、運(yùn)行期、源碼)。然后使用@interface自定義注解,可以添加屬性,默認(rèn)值等。
面試官:注解的生命周期有幾種?
候選人: 注解生命周期有3種: 源碼階段:@Retention(RetentionPolicy.SOURCE),編譯后失效。 編譯階段:@Retention(RetentionPolicy.CLASS),編譯后存在于字節(jié)碼文件中,運(yùn)行時(shí)無(wú)法獲得。 運(yùn)行階段:@Retention(RetentionPolicy.RUNTIME),編譯后存在于字節(jié)碼文件中,運(yùn)行時(shí)可以通過(guò)反射獲取。 大部分自定義注解都使用RUNTIME,以方便通過(guò)反射來(lái)讀取和使用注解信息。
面試官:Enum中的注解呢?
候選人: @Retention(RetentionPolicy.SOURCE)只存在于源碼,編譯后失效。 @Retention(RetentionPolicy.RUNTIME)會(huì)保留至運(yùn)行時(shí),可以通過(guò)反射讀取。所以Enum中的注解一般使用RUNTIME。 枚舉例子:
(RetentionPolicy.RUNTIME)
?Color?{
????ColorType?value();
}
public?enum?ColorType?{
???? (ColorType.RED)?RED,?
???? (ColorType.GREEN)?GREEN,?
???? (ColorType.BLUE)?BLUE
}
面試官:注解在哪些地方可以使用?
候選人: 注解可以放在: 類、接口、枚舉上 字段、方法上 方法的參數(shù)上 局部變量上 構(gòu)造器上 包上 所以注解的@Target有: ElementType.TYPE:接口、類、枚舉、注解 ElementType.FIELD:字段、枚舉的常量 ElementType.METHOD:方法 ElementType.PARAMETER:方法參數(shù) ElementType.CONSTRUCTOR:構(gòu)造器 ElementType.LOCAL_VARIABLE:局部變量 ElementType.PACKAGE:包 等等。
面試官:運(yùn)行時(shí)注解的使用場(chǎng)景?
候選人: 運(yùn)行時(shí)注解主要有兩大使用場(chǎng)景:
框架使用:很多框架使用運(yùn)行時(shí)注解讀取注解信息,調(diào)用相應(yīng)的處理邏輯。如Spring使用@Autowired、@PostConstruct等實(shí)現(xiàn)依賴注入和初始化方法調(diào)用。
自定義注解:我們可以自定義運(yùn)行時(shí)注解,在程序運(yùn)行時(shí)通過(guò)反射讀取注解,執(zhí)行相應(yīng)邏輯。比如:
(ElementType.METHOD)
(RetentionPolicy.RUNTIME)
public? ?MyAnnotation?{
}
public?class?Main?{
???? ?
????public?void?doSomething()?{
????????//?...
????}
}
然后通過(guò)反射調(diào)用:
Method?m?=?Main.class.getMethod("doSomething");?
MyAnnotation?anno?=?m.getAnnotation(MyAnnotation.class);
//執(zhí)行相關(guān)邏輯
面試官:最后一個(gè)問(wèn)題,注解有哪些限制?
候選人: 注解有以下幾個(gè)限制:
注解不能繼承其他注解或接口。
注解只有成員變量,沒(méi)有方法。
注解中的成員變量只能是基本類型、String、Enum、Annotation等,不能是對(duì)象。
如果注解有默認(rèn)值,在使用注解時(shí)可以忽略該值。
同一個(gè)地方不能同時(shí)存在兩個(gè)同名注解。
注解不能作用于變量、類的私有成員上。
注解不會(huì)繼承,子類或者實(shí)現(xiàn)類無(wú)法繼承父類或者接口的注解。
最近我在更新《面試1v1》系列文章,主要以場(chǎng)景化的方式,講解我們?cè)诿嬖囍杏龅降膯?wèn)題,致力于讓每一位工程師拿到自己心儀的offer,感興趣可以關(guān)注JavaPub追更!
《面試1v1》更新中...?

??目錄合集:
Gitee:https://gitee.com/rodert/JavaPub
GitHub:https://github.com/Rodert/JavaPub
http://javapub.net.cn