Java 注解和反射

Posted 钟文涛

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 注解和反射相关的知识,希望对你有一定的参考价值。

注解(Annotation)

注解是JDK5.0开始引入的新技术

注解的作用:

  • 不是程序本身,但可以对程序做出解释。(这一点和注释(comment)没什么区别,但注释是给我们人看的)
  • 可以被其它程序读取(比如:编译器等)

注解的格式:

  • 注解是以@注释名在代码中存在的,还可以添加一些参数值,列。

    如:@SuppressWarnings(value="unchecked")

注解可以附加在package,calss,method,field等上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制编程实现对这些元数据的访问。

内置注解

@override:定义在java.lang.Override中,此注释只适用于修辞方法,表示一个方法声明打算重写超类中的另一个方法声明。

@Deprecated:定义在java.lang.Deprecated中,此注释可以用于修辞方法,属性,类,表示不鼓励程序员使用这样的元素,通常是因为它很危险,或者有更好的选择。

@SuppressWarnings:定义在java.lang.SuppressWarnings中,用来抑制编译时的警告信息,与前两个注释有所不同,你需要添加一个正确的参数才能正确使用,这些参数都是已经定义好的,我们选择性使用就好。例如:

​ @SuppressWarnings("all")

​ @SuppressWarnings("unchecked")

​ @SuppressWarnings("value={"unchecked","depreacation"}")

​ 等等......

元注解

元注解的作用就是负责注解其它注解的注解,java定义了四个标准的meta-annotation类型,他们被用来提供对其它annotation类型作说明。

这些类型和它们所支持的类在java.lang.annotation包中可以找到,(@Target,@Retention,@Documented,@Inherited)

@Target:用于描述注解的使用范围(即:被描述的注解,可以用在什么地方)

@Retention:用于描述注解的生命周期(SOURCE<CLASS<RUNTIME)

@Documented:说明该注解将被包含在javadoc中

@Inherited:说明子类可以继承父类的该注解

自定义注解

使用@interface自定义注解,自动继承了java.lang.annotation.Annotation接口

格式是:public @interface 注解名{定义内容}

其中每一个方法实际上是声明了一个配置参数

方法的名称就是参数的名称

返回值类型就是参数的类型(返回值只能是基本类型,Class,String,enum)

可以通过default来声明默认值

如果只有一个参数成员,一般参数名为value

// 无参注解 案例一
public class ZhuJie {
    @Myzj()//此处就会报错,因为注解的使用范围是方法上,而这里是字段上。
    private int a;
    @Myzj()
    public void text(){

    }

}
@Target(ElementType.METHOD)//表示我们自定义的这个注解只能用在方法上
@Retention(RetentionPolicy.SOURCE)//表示注解只在源码上有效,编程之后这个注解就失效。
@interface myzj{
    
}
//有参 没有默认值 案例二
@myzj2(value="123")//只有一个参数时且参数名为value时,可以直接这样写 @myzj2("123")
public class ZhuJie2 {
    private int a;
    public void text(){

    }

}
@Target(ElementType.TYPE)//表示我们自定义的这个注解只能用在类上
@Retention(RetentionPolicy.CLASS)//表示注解在CLASS文件上还有效,运行的时候就失效。
@interface myzj2{
    String value();
}
//有参 有默认值 案例三
public class ZhuJie3 {
    //可以看出以下除了height属性,其余的我都给了默认值。所以我用的注解的时候,只需要给height传值,其余的可传可不传。
   	@myzj3(int=185)
    private int a;
    public void text(){

    }
}
@Target(ElementType.FIELD)//表示我们自定义的这个注解只能用在属性上
@Retention(RetentionPolicy.RUNTIME)//表示运行的时候还有效。
@interface myzj3{
    String value() default "钟文涛";
    int age() default 18;
    String[] girlfriend() default {"迅猛龙","小耳朵"};
    int height();
}

反射(Reflection)

反射是java被视为动态语言的关键,反射机制运行程序在执行期借助于reflection api取得任何类的内部信息,并能直接操纵任意对象的内部属性及方法。

加载完类之后,在堆内存的方法区中就产生一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看类的结构,所以我们形象的称为:反射。

优点:可以实现动态创建对象和编译,体现出很大的灵活性。

缺点:对性能有影响。使用反射基本是一种解释操纵,我们可以直接告诉JVM,我们需要做什么并且它满足我们的需求。这类操纵总是慢于直接执行相同的操纵。

Class类的常用方法:

方法名 功能说明
static ClassforName(String name) 返回指定类名name的Class对象
Object newInstance() 调用缺省构造函数,返回Class对象的一个实例
getName() 返回此Class对象的所表示的类实体(类,接口,数组类胡void)的名称
Class getSuperClass() 返回当前Class对象的父类的Class对象
Class[] getinterface() 获取当前Class对象的接口
ClassLoader getClassLoader() 返回该类的加载器
Constructor[] getConstrutor() 返回一个包含某些Constructor对象的数组
Method getMethod(String name,Class..T) 返回一个Method对象,对此对象的形参类型为param Type
Field[] getDeclaredFields() 返回Field对象的一个数组

获取Class类的实例:

public class FanShe {
    public static void main(String[] args) throws ClassNotFoundException {
        //若已知具体的类,通过类的Class属性获取,该方法最为安全可靠,程序性能最高。
        Class c1=user.class;
        //已知某个类的实例,调用该实例的getClass()方法获取Class对象
        Class c2=new user().getClass();
        //已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,
        //可能会抛出ClassNotFoundException
        Class c3=Class.forName("tao.user");
    }
}
class user extends  user{

}

以上是关于Java 注解和反射的主要内容,如果未能解决你的问题,请参考以下文章

注解与反射

Java 注解和反射

java注解和反射

java 反射代码片段

java 通过反射和注解创建对象

Java注解和反射