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 注解和反射的主要内容,如果未能解决你的问题,请参考以下文章