我发现了几个与此相关(不重复)的问题,但它们并没有让我满意。
我无法理解在哪里以及为什么使用
custom annotations
?
在书上看过一个自定义标注的例子,但是解释的不够透彻。
@interface MyAnno
{
String str();
int val();
}
class MyClass
{
@MyAnno(str = "Annotation example", val = 100)
public static void myMeth()
{
System.out.println("Inside myMeth()");
}
}
class CustomAnno
{
public static void main(String args[])
{
MyClass.myMeth();
}
}
输出符合预期
Inside myMeth()
。
我对这个例子有几个疑问。
1- 如何在此程序中使用
和String str()
?或int val()
的任何抽象方法有什么用?custom annotation
2-为什么
。我的意思是它们对任何代码有什么影响。custom annotations
3-如何创建一个具有像 @override 那样的效果的注释?(我的意思是任何可以注意到的效果)
如果这个例子对你来说没用,那么请给我一个合适的小例子,其中使用了
custom annotation
。
使用自定义注释的三个主要原因是:
在每种情况下,与其他非注释方法相比,使用注释可以降低代码中出现错误的可能性。
这是一个最小的例子。以下代码演示了自定义注释的使用。
这是关于员工和福利的。如果我们有这样的要求,即 BasicBenefits 必须应用于所有类型的员工,那么我们可以提出自定义注释,例如 BasicBenefits,并使用以下注释注释所有类型的 Employee 实现(例如 CorporateEmployee、ContractEmployee、ManagerEmployee 等)基本福利。
自定义注解类(接口)
import java.lang.annotation.*;
@Inherited
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface BasicBenefits {
String bId() default "B-101";
String bName() default "General Class A Employee";
}
使用自定义注释的类(不需要任何导入):
@BasicBenefits(bId="B-400", bName="General Plus Class A Employee")
public class Employee {
String eId;
String eName;
public Employee(String eId, String eName){
this.eId = eId;
this.eName = eName;
}
public void getEmployeeDetails(){
System.out.println("Employee ID: "+eId);
System.out.println("Employee Name: "+eName);
}
}
驱动程序类来测试上述内容。
import java.lang.annotation.Annotation;
public class TestCustomAnnotationBasicBenefits {
public static void main(String[] args) throws Exception{
Employee emp = new Employee("E-100", "user3320018");
emp.getEmployeeDetails();
Class reflectedClass = emp.getClass();
Annotation hopeBenefitAnn = reflectedClass.getAnnotation(BasicBenefits.class);
BasicBenefits bBenefits = (BasicBenefits)hopeBenefitAnn;
System.out.println("Benefit ID: "+bBenefits.bId());
System.out.println("Benefit Name: "+bBenefits.bName());
}
}
您的代码看起来差不多了,只需在 main 方法中包含两件事。
1.) 需要引用 MyClass 2.) 需要使用 MyClass 的反射来获取注释。
这里是对您所拥有的代码进行了一些修改:
@Inherited
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnno
{
String str();
int val();
}
//using above custom annotation on class level
//can also use method level
//just need to change t @Target(ElementType.METHOD)
@MyAnno(str = "Annotation example", val = 100)
class MyClass
{
public static void myMeth()
{
System.out.println("Inside myMeth()");
}
}
import java.lang.annotation.Annotation;
class CustomAnno
{
public static void main(String args[])
{
//1. getting reference to the class where the custom annotation is applied.
//2. then getting the annotation to get the values
MyClass myClass = new MyClass();
Class cls = myClass.getClass();
Annotation getMyAnno = cls.getAnnotation(MyAnno.class);
MyAnno myAnno = (MyAnno)getMyAnno;
MyClass.myMeth(); //left this as is.
System.out.println("myAnno.str(): "+ myAnno.str());
System.out.println("myAnno.str(): "+ myAnno.val());
}
}
注释的抽象方法定义了您可以传递给它的值(在您的情况下
str = "Annotation example", val = 100
)。您可以使用反射来访问它们 (Method.<T>getAnnotation(Class<T>)
)。自定义注释没有直接影响。仅当您评估它们时它们才有用。
@Retention(value=RUNTIME)
来注释自定义注释,才能通过反射读取它。
要发挥任何作用,必须首先解析注释。内置注释(例如
@Override
或 @FunctionalInterface
,仅列出最明显的注释)由编译器本身进行解析。至于自定义注释,这些家伙通常由第三方框架解析,尽管我们也可以使用反射机制在独立代码中演示这种技术。
举例来说,下面的代码会根据名为
@SwitchingAnnotation
的自定义注释中声明的字段的值在运行时更改其行为:
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface SwitchingAnnotation{
boolean flag();
}
public class Worker{
void doThis(){ System.out.println("Doing this"); }
void doThat(){ System.out.println("Doing that"); }
@SwitchingAnnotation(
flag = false
)
public void work(boolean flag) {
if (flag) doThis();
else doThat();
}
}
class Test{
public static void main(String[] args) {
try{
SwitchingAnnotation sw = Worker.class.getMethod("work", boolean.class)
.getAnnotation(SwitchingAnnotation.class);
new Worker().work(sw.flag()); // prints Doing that
}
catch(NoSuchMethodException nsme){
System.out.println(nsme);
}
}
}
In my case I tried with METHOD level annotaions and below is the parsing the annotaion code given.
`public static void main(String[] args) throws Exception {
Framework myFramework = new Framework();
System.out.println("==WithOut-Annotation Parsing==");
myFramework.serviceCall();
System.out.println("==Annotation Parsing==");
myFramework.serviceCallx();
}
@Inherited
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomOne {
String valueOne() default "valueOne";
String valueTwo() default "valueTwo";
}
@Inherited
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomTwo {
String valueThree() default "valueThree";
String valueFour() default "valueFour";
}
public class Service {
@CustomOne(valueOne = "One", valueTwo = "Two")
@CustomTwo(valueThree = "Three", valueFour = "Four")
public void test() {
System.out.println("I am inside Service :: test() method");
}
@CustomOne
@CustomTwo
public void testx() {
System.out.println("I am inside Service :: testx() method");
}
}
public class Framework {
// normal
public void serviceCall() {
Service service = new Service();
service.test();
service.testx();
}
// annotation parsing
public void serviceCallx() throws Exception {
Service service = new Service();
Method method = service.getClass().getMethod("testx"); // give specific method in string format
if (method.isAnnotationPresent(CustomOne.class)) {
CustomOne customOne = method.getAnnotation(CustomOne.class);
System.out.println("Custom One Annotation Parsing : " + customOne.valueOne() + " " + customOne.valueTwo());
}
if (method.isAnnotationPresent(CustomTwo.class)) {
CustomTwo customTwo = method.getAnnotation(CustomTwo.class);
System.out.println("Custom Two Annotation Parsing : " + customTwo.valueThree() + " " + customTwo.valueFour());
}
}
}
`