Java注释@interface的用法

本文深入讲解Java注解的定义与使用,包括@Override、@Deprecated、@SuppressWarnings等常见注解的作用,以及如何自定义注解并利用反射技术读取注解信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java用 @interface Annotation{ }定义一个注解 @Annotation,一个注解是一个类。

@Override,@Deprecated,@SuppressWarnings为常见的3个注解

注解相当于一种标记,在程序中加上了注解就等于为程序加上了某种标记,以后,

JAVAC编译器,开发工具和其他程序可以用反射来了解你的以及各种元素上有无任何标记,看你有什么标记,就去干相应的事。

1.注解@Override用在方法上,当我们想重写一个方法时,在方法上加@Override,当我们方法的名字出错时,编译器就会报错,如图:


2.注解@Deprecated,用来表示某个类的属性或方法已经过时,不想别人再用时,在属性和方法上用@Deprecated修饰,如图:


注解@SuppressWarnings用来压制程序中出来的警告,比如在没有用泛型或是方法已经过时的时候,如图:


4.注解@Retention可以用来修饰注解,是注解的注解,称为元注解。

Retention注解有一个属性value,是RetentionPolicy类型的,Enum RetentionPolicy是一个枚举类型,
这个枚举决定了Retention注解应该如何去保持,也可理解为Rentention 搭配 RententionPolicy使用。RetentionPolicy有3个值:CLASS  RUNTIME   SOURCE


用@Retention(RetentionPolicy.CLASS)修饰的注解,表示注解的信息被保留在class文件(字节码文件)中当程序编译时,但不会被虚拟机读取在运行的时候;
用@Retention(RetentionPolicy.SOURCE )修饰的注解,表示注解的信息会被编译器抛弃,不会留在class文件中,注解的信息只会留在源文件中;
用@Retention(RetentionPolicy.RUNTIME )修饰的注解,表示注解的信息被保留在class文件(字节码文件)中当程序编译时,会被虚拟机保留在运行时,
所以他们可以用反射的方式读取。RetentionPolicy.RUNTIME 可以让你从JVM中读取Annotation注解的信息,以便在分析程序的时候使用.

下面试测试注解示例一:

package cn.mayongfa;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)  
public @interface MyTarget  
{ }  

package cn.mayongfa;

import java.lang.reflect.Method;

public class MyTargetTest {
	@MyTarget
	public void doSomething() {
		System.out.println("hello world");
	}

	public static void main(String[] args) throws Exception {
		Method method = MyTargetTest.class.getMethod("doSomething", null);
		if (method.isAnnotationPresent(MyTarget.class))// 如果doSomething方法上存在注解@MyTarget,则为true
		{
			System.out.println(method.getAnnotation(MyTarget.class));
		}
	}
}

上面程序打印:@com.self.MyTarget(),如果RetentionPolicy值不为RUNTIME,则不打印。

@Retention(RetentionPolicy.SOURCE )  
public @interface Override  
  
@Retention(RetentionPolicy.SOURCE )  
public @interface SuppressWarnings  
  
@Retention(RetentionPolicy.RUNTIME )  
public @interface Deprecated  

由上可以看出,只有注解 @Deprecated在运行时可以被JVM读取到 

此外:注解中可以定义属性,看例子: 

package cn.mayongfa;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * 注解中可以定义属性 
 * 上面程序中,定义一个注解@MyAnnotation,定义了6个属性,他们的名字为:
 * hello,world,array,lamp,lannotation,style. 
 * 属性hello类型为String,默认值为gege
 * 属性world类型为String,没有默认值 
 * 属性array类型为数组,默认值为2,4,5,6 
 * 属性lamp类型为一个枚举,没有默认值
 * 属性lannotation类型为注解,默认值为@TestAnnotation,注解里的属性是注解
 * 属性style类型为Class,默认值为String类型的Class类型
 */
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
	String hello() default "gege";
	
	String world();

	int[] array() default { 2, 4, 5, 6 };
	
	EnumTest.TrafficLamp lamp();

	TestAnnotation lannotation() default @TestAnnotation(value = "ddd");

	Class style() default String.class;
}

其中EnumTest.TrafficLamp 是定义在另一个class中的枚举类型


TestAnnotation是定义的一个注解


  • 上面程序中,定义一个注解@MyAnnotation,定义了6个属性,他们的名字为:  
  • hello,world,array,lamp,lannotation,style.  
  • 属性hello类型为String,默认值为gege  
  • 属性world类型为String,没有默认值  
  • 属性array类型为数组,默认值为2456  
  • 属性lamp类型为一个枚举,没有默认值  
  • 属性lannotation类型为注解,默认值为@TestAnnotation,注解里的属性是注解  
  • 属性style类型为Class,默认值为String类型的Class类型  


    看下面例子:定义了一个MyTest类,用注解@MyAnnotation修饰,注解@MyAnnotation定义的属性都赋了值 

    package cn.mayongfa;
    
    import cn.mayongfa.EnumTest.TrafficLamp;
    
    @MyAnnotation(hello = "beijing", world="shanghai",array={},lamp=TrafficLamp.RED,style=int.class)
    public class MyTest {
    
    	@MyAnnotation(lannotation = @TestAnnotation(value = "baby"), world = "shanghai", array = {
    			1, 2, 3 }, lamp = TrafficLamp.YELLOW)
    	@Deprecated
    	@SuppressWarnings("")
    	public void output() {
    		System.out.println("output something!");
    	}
    
    }
    
    接着通过反射读取注解的信息:

    package cn.mayongfa;
    
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Method;
    
    public class MyReflection {
    	public static void main(String[] args) throws Exception {
    		
    		MyTest myTest = new MyTest();
    		Class<MyTest> c = MyTest.class;
    		Method method = c.getMethod("output", new Class[] {});
    		
    		// 如果MyTest类名上有注解@MyAnnotation修饰,则为true
    		if (MyTest.class.isAnnotationPresent(MyAnnotation.class)) {
    			System.out.println("have annotation");
    		}
    		if (method.isAnnotationPresent(MyAnnotation.class)) {
    			method.invoke(myTest, null); // 调用output方法
    			// 获取方法上注解@MyAnnotation的信息
    			MyAnnotation myAnnotation = method
    					.getAnnotation(MyAnnotation.class);
    			String hello = myAnnotation.hello();
    			String world = myAnnotation.world();
    			System.out.println(hello + ", " + world);// 打印属性hello和world的值
    			System.out.println(myAnnotation.array().length);// 打印属性array数组的长度
    			System.out.println(myAnnotation.lannotation().value()); // 打印属性lannotation的值
    			System.out.println(myAnnotation.style());
    		}
    		// 得到output方法上的所有注解,当然是被RetentionPolicy.RUNTIME修饰的
    		Annotation[] annotations = method.getAnnotations();
    		for (Annotation annotation : annotations) {
    			System.out.println(annotation.annotationType().getName());
    		}
    	}
    
    }
    

    上面程序打印:



    如果注解中有一个属性名字叫value,则在应用时可以省略属性名字不写。

    可见,@Retention(RetentionPolicy.RUNTIME )注解中,RetentionPolicy.RUNTIME是注解属性值,属性名字是value,  

    属性的返回类型是RetentionPolicy,如下:

    public @interface MyTarget  
    {  
        String value();  
    }  
    可以这样用:

     @MyTarget("aaa")  
     public void doSomething()  
     {  
      System.out.println("hello world");  
     }  

     注解@Target也是用来修饰注解的元注解,它有一个属性ElementType也是枚举类型,值为:ANNOTATION_TYPE CONSTRUCTOR  FIELD LOCAL_VARIABLE METHOD PACKAGE PARAMETER TYPE

    @Target(ElementType.METHOD) 修饰的注解表示该注解只能用来修饰在方法上。

    @Target(ElementType.METHOD)  
    @Retention(RetentionPolicy.RUNTIME)  
    public @interface MyTarget  
    {  
     String value() default "hahaha";  
    }  

  • 如把@MyTarget修饰在类上,则程序报错,如:  
  • @MyTarget  
  • public class MyTargetTest  
  • 注解大都用在开发框架中吧,好了有关注解就学习那么多了,谢谢。
    转载至:http://blog.youkuaiyun.com/liuwenbo0920/article/details/7290586/

<think>好的,我现在需要帮助用户了解Java中@FunctionAction注解用法和含义。首先,我应该检查用户提供的引用内容,看看是否有相关的信息。用户提到了引用[2],其中有一个FunctionAction类,看起来像是一个SpringMVC的控制器,使用了@Controller和@Autowired注解。不过用户提到的@FunctionAction注解在引用中并没有直接出现,可能是一个自定义的注解,或者是用户打错了名字。接下来,用户提供的引用[1]提到了自定义的@OperateLog注解,用于记录操作日志。引用[3]讨论了@Deprecated注解,而引用[4]和[5]涉及Shiro和SSH2的权限管理。这些可能与@FunctionAction没有直接关联,但需要确认是否有间接的联系。考虑到用户可能混淆了类名和注解名,比如FunctionAction是一个类而不是注解,我需要验证这一点。在引用[2]中,FunctionAction确实是一个控制器类,继承自BaseAction,并使用了@Controller和@Scope注解,但没有提到@FunctionAction注解的存在。因此,可能用户误解了类名作为注解,或者项目中有自定义的注解未被引用直接说明。 另外,用户可能参考了其他资料,将某个框架中的注解名称记错。例如,Spring或Struts中有类似的注解,但名字可能不同。例如,@Action或者@Controller等,但@FunctionAction并不是标准注解。需要检查常见的Java框架文档,确认是否存在这样的注解。 假设用户项目中确实存在自定义的@FunctionAction注解,可能类似于引用[1]中的@OperateLog,用于标记特定功能的方法。这种情况下,注解的定义可能在项目的其他部分,但未被用户提供出来。需要建议用户检查项目源码或文档,查看该注解的定义和使用场景。 此外,用户的问题可能源于拼写错误,例如将@FunctionAction误写为其他注解,如@Action或@Function。需要指出可能的拼写错误,并提供常见相关注解的信息,帮助用户找到正确的答案。 最后,确保回答结构清晰,分点说明可能的情况,并提供相关问题引导用户进一步澄清需求。同时,引用提供的参考资料,特别是引用[2]中的FunctionAction类,指出可能存在的混淆点,并建议用户核实注解的实际定义。</think>根据提供的引用内容分析,**Java标准库和常见框架中并没有原生提供@FunctionAction注解**。不过从引用[2]中可以看到`FunctionAction`是一个自定义的Spring MVC控制器类,结合上下文推测可能是项目中用于权限管理的自定义注解。以下是两种可能性分析: --- ### 一、可能情况分析 1. **类名与注解混淆** 引用[2]中的`FunctionAction`是一个控制器类,而非注解。它继承`BaseAction`并用于处理权限功能请求,示例代码中使用了`@Controller`和`@Autowired`注解[^2]。 2. **自定义注解的误记** 如果存在`@FunctionAction`注解,可能是项目中自定义的注解(类似引用[1]中的`@OperateLog`),用于标记权限功能相关的方法。此时需通过源码查看其定义,例如: ```java @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface FunctionAction { String value() default ""; //可定义功能名称等属性 } ``` --- ### 二、常见权限管理注解参考 若需实现功能绑定,可参考以下方案: 1. **Shiro权限控制** 如引用[4]所示,通过`@RequiresPermissions`注解控制方法访问权限: ```java @RequiresPermissions("user:delete") public void deleteUser() { ... } ``` 需在Spring配置中启用Shiro注解支持[^4]。 2. **Spring Security注解** 使用`@PreAuthorize`实现细粒度控制: ```java @PreAuthorize("hasRole('ADMIN')") public void adminOperation() { ... } ``` 3. **自定义日志注解** 类似引用[1]的`@OperateLog`,可记录功能操作日志[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值