黑马程序员基础加强-内省-注解
内省:InstroSpector
概述:
InstroSpector:内省对应的英文单词,视察检查,通常用于内部;是对程序内部的检查。
内省主要针对JavaBean进行操作。
什么是JavaBean?
简单的说JavaBean是一种特殊的java类,主要用于传递数据信息,另外在这种java类中的方法主要用于访问私有的字段,而且方法名符合某种命名规则。
普通Java类和JavaBean类可以相同处理吗:
首先普通Java类不一定可以当做JavaBean类来处理;如果该类中的方法是含有某个私有属性的get和set方法,就可以当做JavaBean来处理,否则不行。
然而JavaBean是可以当做普通java类来处理的,可以照常使用传统的new对象,也可以使用反射技术;
JavaBean的属性
JavaBean的属性是根据其中的set和get方法前缀来确定的,不是依据其中的变量。在java类中方法名为set或get前缀的可以说是JavaBean,当把set和get前缀去掉后的部分就是JavaBean的属性名称。
注意:当剩余的部分第二个字母时小写那么首字母小写,后面是大写那么首字母大写。
如:getAge/setAge-->属性age;gettime-->属性time;setTime-->time;getCPU-->属性CPU
总之,一个类被当作javaBean使用时,JavaBean的属性是根据方法名推断出来的,它根本看不到java类内部的成员变量。
JavaBean简单内省操作
Javabean应用场景和值对象
如果要在两个模板之间传递多个信息,可将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象(Value Object,简称VO),这些信息在类中用私有字段来储存,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问。
好处:
一个符合JavaBean特点的类可以当做普通类进行使用,但是为什么一定要有JavaBean呢?因为它能给我们带来一些好处的:
1, 在Java EE开发中,经常要使用到JavaBean。很多环境就要求按JavaBean方式进行操作,别人都这么用和要求这么做,那你就没什么挑选的余地!
2, JDK中提供了对JavaBean进行操作的API,这套API称为内省,若要自己通过getX的方式来访问私有x,可用内省这套API,操作JavaBean要比使用普通的方式更方便。
下面将演示一个示例,对JavaBean类属性简单那的内省操作,但之前我们还得认识下对属性操作的PropertyDescriptor类的了解,看下面:
PropertyDescriptor类
该类是java.beans包中的类。指描述事物,属性描述;
PropertyDesciptor类描述了一个JavaBean类通过一对访问符方法对外暴露的属性;它是对JavaBean类中属性的抽象化。
构造方法:
PropertyDescriptor(String propertyName,Class<?> beanClass)// 通过调用 getFoo 和 setFoo 存取方法,为符合标准 Java 约定的属性构造一个 PropertyDescriptor。
参数一propertyName:指String类型的属性名;
参数二Class<?> beanClass:指该参数属性名所属的类;
其他常用方法:
对于不是final修饰的JavaBean类属性,我们只需要做的是对其属性的值进行设置或者获取;
Method getReadMethod();//获取应该用于读取JavaBean类属性的方法
Method getWriteMethod();//获取应该用于读取JavaBean类属性的方法
技巧:
因为它们的返回值类型都是Method,标志着获取到相应的方法之后,可用反射的方式的来操作这个方法
实例代码:对JavaBean的简单内省操作
JavaBean类
package cn.heima.Day2;
public class Bean {
private int age;
private String name;
public Bean(int age, String name) {
super();
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package cn.heima.Day2;
测试类,就是对JavaBean的简单操作
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectPoint {
public static void main(String[] args)throws Exception {
Bean bean = new Bean(22,"小米");
String propertyName = "age";
//打印出类中age属性的值
//x-->X-->getX-->MethodgetX
Object retValue = getProperty(bean, propertyName);//获取并调用getAge方法
System.out.println(retValue);
Object value = 5;
Object retValue2 = getProperty2(bean, propertyName, value);//获取并设置getAge方法
System.out.println(bean.getAge());//使用该类对象调用其方法打印设置后的值
}
//获取并设置getAge方法
private static Object getProperty2(Object bean, String propertyName,
Object value) throws IntrospectionException,
IllegalAccessException, InvocationTargetException {
//创建关联对象,来获取JavaBean的属性,
PropertyDescriptor pd = new PropertyDescriptor(propertyName, bean.getClass());
//已经知道其属性,那么就可以通过getWriteMethod()方法获取其JavaBean类中的setAge方法
Method methodSetAge = pd.getWriteMethod();
//调用setAge方法设置值
Object retValue2 = methodSetAge.invoke(bean,value);
return retValue2;
}
//获取并调用getAge方法
private static Object getProperty(Object bean, String propertyName)
throws IntrospectionException, IllegalAccessException,
InvocationTargetException {
//创建关联对象,来获取JavaBean的属性
PropertyDescriptor pd = new PropertyDescriptor(propertyName, bean.getClass());
//已经知道其属性,那么就可以通过getReadMethod()方法获取其JavaBean类中的getAge方法
Method methodGetAge = pd.getReadMethod();
//获取方法名
Object retValue = methodGetAge.invoke(bean);
return retValue;
}
}
练习:根据上面示例,通过JavaBean和反射技术,编写对person类的属性设置和获取
package cn.it.heima01;
public class JavaBeanPerson {
//设定一个javaBean类
private String name;
private int age;
public JavaBeanPerson(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "JavaBeanPerson [age=" + age + ", name=" + name + "]";
}
}
package cn.it.heima01;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectJavaBean {
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
//获取与设置指定类的属性,对JavaBean的简单内省操作。
JavaBeanPerson jbp = new JavaBeanPerson("lisi",22);
//对于下面的练习我们还可以将之抽取出来,统一设置属性或获取属性
String propertyName1 = "age";
Object name = getProperty(jbp, propertyName1);//接收参数对象和需要获取的属性;
System.out.println(name);
Object value = 44;
setProperty(jbp, propertyName1, value);//对指定参数对象的某属性进行设置;
System.out.println(jbp.getAge());
/*
String propertyName1 = "name";
String value1 = "zhangsan";
PropertyDescriptor ppd1 = new PropertyDescriptor(propertyName1,jbp.getClass());
Method personGetName = ppd1.getReadMethod();
Method personSetName = ppd1.getWriteMethod();
Object name = personGetName.invoke(jbp);//获取指定对象的name;
Object setName = personSetName.invoke(jbp, value1);//设置name;
System.out.println(jbp.toString());
String propertyName2 = "age";
int value2 = 33;
PropertyDescriptor ppd2 = new PropertyDescriptor(propertyName2,jbp.getClass());
Method personGetAge = ppd2.getReadMethod();
Method personSetAge = ppd2.getWriteMethod();
Object age = personGetAge.invoke(jbp);
Object setAge = personSetAge.invoke(jbp, value2);
System.out.println(jbp.toString());
*/
}
private static void setProperty(Object jbp, String propertyName1,
Object value) throws IntrospectionException,
IllegalAccessException, InvocationTargetException {
PropertyDescriptor ppd1 = new PropertyDescriptor(propertyName1,jbp.getClass());
Method personSetName = ppd1.getWriteMethod();
personSetName.invoke(jbp,value);
}
private static Object getProperty(Object jbp, String propertyName1)
throws IntrospectionException, IllegalAccessException,
InvocationTargetException {
PropertyDescriptor ppd1 = new PropertyDescriptor(propertyName1,jbp.getClass());
Method personGetName = ppd1.getReadMethod();
Object name = personGetName.invoke(jbp);
return name;
}
}
对JavaBean的复杂内省操作
因为要涉及相关类,让我们先来认识一下:
1,Introspector类:java.beans.Intspector;
该类是为通过工具学习有关受目标 Java Bean 支持的属性、事件和方法的知识提供了一个标准方法。
该类中有一个常用方法即:
getBeanInfo(Class<?>beanClass);其返回值类型是BeanInfo接口类型,传入的参数是相应对象的字节码文件,即Class文件;
2,BeanInfo接口类:java.beans.BeanInfo
该类实现此 BeanInfo 接口并提供有关其 bean 的方法、属性、事件等显式信息
该类中有一个常用方法即:
getPropertyDescriptors();获取的是javaBean类中所有的属性,其返回值类型就是PropertyDescriptor[]数组;
现在可以对内省进行复杂的操作演示了:
分析步骤:
1, 调用Introspector类中的getBeanInfo(Class cls)d 方法,通过该方法获取BeanInfo示例对象。
2, 再通过BeanInfo类中有getPropertyDescriptors()方法,获取所有的JavaBean类中的属性信息。
3, 通过遍历的形式,获取想要的那个属性信息。
接上面示例:
private static Object getProperty(Object jbp, String propertyName1)
throws IntrospectionException, IllegalAccessException,
InvocationTargetException {
/*PropertyDescriptor ppd1 = new PropertyDescriptor(propertyName1,jbp.getClass());
Method personGetName = ppd1.getReadMethod();
Object name = personGetName.invoke(jbp);*/
/*对JavaBean的复杂内省操作
分析步骤:
调用Introspector类中的getBeanInfo(Class cls)d 方法,通过该方法获取BeanInfo示例对象。
再通过BeanInfo类中有getPropertyDescriptors()方法,获取所有的JavaBean类中的属性信息。
通过遍历的形式,获取想要的那个属性信息。*/
PropertyDescriptor[] pds = Introspector.getBeanInfo(jbp.getClass()).getPropertyDescriptors();
Object name = null;
for(PropertyDescriptor pd : pds){
//如果属性跟参数的属性相等,就获取它的getAge方法
if(pd.getName().equals(propertyName1.getClass())){
Method personGetName = pd.getReadMethod();
name = personGetName.invoke(jbp);
}
break;
}
return name;
}
BeanUtils工具包的作用,导入操作,及操作方法
BeanUtils工具包简介:
该工具包是由阿帕奇公司提供的。
主要功能:
专门用于操作JavaBean的专业工具包,方法便于开发;
好处:
1, 提供的set或get方法中,传入的是字符串,返回的还是字符串,因为在浏览器中,用户输入到文本框的都是以字符串的形式发送至服务器上的,所以操作的都是字符串。也就是说这个工具包的内部有自动将整数转换为字符串的操作。
2, 支持属性的级联操作,即支持属性链。如可以设置:人的脑袋上的眼睛的眼珠的颜色。这种级联属性的属性连如果自己用反射,那就很困难了,通过这个工具包就可以轻松调用。
BeanUtils可以将8种基本数据类型进行自动的转换,因此对于非基本数据类型,就需要注册转换器Converter,这就需要ConverUtils包。
导入工具包操作方法:
下载引入依赖包:日志包即commons-logginng.jar
解压之后引入:commons-beanutils-x.x.x.jar即可;
导入有两种方法:
第一种方法:右键项目--选择Properties---Java Build Path--选择Liberiers标签。AddExternal Jars--选择要导入的jar包。即可。
这样做有个问题就是如果jar路径发生变化。项目就不能使用到这个jar包。
第二种方法:在项目中建立一个lib目录,专门用于存放项目所使用到的jar工具包。将要使用到jar包复制粘贴进来,并在jar上点右键--选择Builder Path---Add to BiuldPath,即可。这时jar包中的对象,就可以使用了。
这样做的好处:项目移动,jar随项目移动。
BeanUtils类及其常用方法:
注意:
因为这个类专用于JavaEE Web开发。由于Web开发中页面传值全部是String类型的,所以BeanUtils这个类的方法就帮你做了各种类型到String的类型转换。所以getProperty方法返回String而不是Object.。
常用静态方法方法:
设置指定对象指定属性的值:
Void setProperty(Object bean,String name,Object value);
获取指定对象指定属性的值:
String getProperty(Object bean,String name);
示例:
//使用BeanUtils工具包的方法来设置和获取值
BeanUtils.setProperty(bean, propertyName, "12");//参数类对象,参数方法名对象,要设置的值
System.out.println(BeanUtils.getProperty(bean,propertyName));//获取设置后的值
System.out.println(BeanUtils.getProperty(bean,propertyName).getClass().getName());//获取获取该值所属类型
示例:
//对JavaBean中birthDay属性进行设置
//实际上birthDay是JavaBean的属性,这个属性现在代表Date类型,
//而在Date类上有一个setTime方法,相当于birthday有一个time属性,
//这里可以理解为,在bean对象身上的brithDay属性的time属性赋值了。
//再简单的说就是可以连级设置,如,可以设置人的眼睛的眼珠的颜色;这里就是设置bean的brithDay的time。
BeanUtils.setProperty(bean, "birthDay.time","77");
System.out.println(BeanUtils.getProperty(bean,"birthDay.time"));//获取设置后的time值
示例:构建连级属性,在NewBean中引入变量DemoBean实例
package cn.heima.Day2;
public class DemoBean{
private String name;
public DemoBean(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package cn.heima.Day2;
public class NewBean {
private DemoBean db = new DemoBean();
public DemoBean getDb() {
return db;
}
public void setDb(DemoBean db) {
this.db = db;
}
}
测试类:
package cn.heima.Day2;
import java.lang.reflect.InvocationTargetException;
import org.apache.commons.beanutils.BeanUtils;
public class ReflectBean {
public static void main(String[] args)
throws IllegalAccessException,
InvocationTargetException, NoSuchMethodException {
NewBean nb = new NewBean();
BeanUtils.setProperty(nb, "db.name", "练习");
System.out.println(BeanUtils.getProperty(nb, "db.name"));
}
}
在BeanUtils工具包中还有一个工具类PeopertyUtils,用法跟BeanUtils一样
区别:
1, BeanUtils会对JavaBean的属性的类型进行转换,如属性本身是integer,会转成String。
2, PropertyUtils是以属性本身的类型进行操作的。
JDK1.5新特性——注解
概述:
如今注解的前景非常好,未来的开发模式的一种趋势就是基于注解注解的开发模式;
注解实际上就是JAVA代码中的特殊标记。在程序源代码中加上注解相当于在程序上打上了标记。另外,在以后的java编译器,开发工具或者其他程序就可以用反射来了解类和类中的各种元素有何标记,可以根据标记来做事,来完成一些普通java语句(没加注解的类)无法表达的的信息。
作用于哪里?
标记可以加在包,类,成员变量,方法,方法参数及局部变量上。
格式:
@注解类名
在java.lang包中,可以看到JDK中提供的最基本的annottaion。
注解的分类:基本注解,元注解,自定义注解
Java提供的几个基本注解:在java.lang包
通过System.runFinalizersOnExit(true);的编译警告引出;
1,@SuppessWannings(“deprecation”);表示告诉编译器或jvm不要警告过时提示了。
2,@Deprecated:表示告知调用者,该成员函数,成员变量等已经过时,不再推荐使用。
源代码标记@Deprecated是在JDK1.5中作为内置的annotation引入的,用于表明类 (class)、方法(method)、字段(field)已经不再推荐使用,并且在以后的JDK版本中可能 将其删除,编译器在默认情况下检测到有此标记的时候会提示警告信息。
3,@Override:表示下面的方法是在覆盖父类的方法,若不存在覆盖就会报错。
例子:某类中方法需要覆盖equals(Object obj)方法,因为参数类型必须是Object,这时加上注解@Override,就可以判断该方法是否覆盖,如果没有覆盖,注解就会提示警告。
元主注解:在java.lang.annotation子包下
元注解即注解的注解,在定义注解类的时候加注解,
作用于修饰其他注解,描述了被作用的注解的其作用范围,生命周期,是否被javadoc识别等。
元注解有四个:(常用两个是@Retention和@Target)
@Retention:(保留)用于说明注解保留在哪个阶段(即注解的生命周期)。
@Target:(目标)用于说明注解类的使用范围。如在方法上还是类上,默认值是任何地方。
@Documented:(备有证明文件)
@Inherited:(继承权的)
自定义注解:
需要用到@interface来定义
注解应用结构图
注解就相当于一个你的源程序中要调用的一个类,要在源程序中应用某个注解,得先准备好了这个注解类。就像你要调用某个类,得先有开发好这个类。
MyEcelipes编写注解类小提示:构建注解类快捷方法
方法一:打开File-->NewFile-->Other...-->Java-->Annotation(注解);
方法二:打开Java透视图-->在指定包名上右键-->New-->找到Annotation
自定义注解及其应用
定义格式:
@interface 名称{
statement
}
如:定义一个最简单的注解类:
Public @interface MyAnnotation{}
把他加在某个类上:
@MyAnnotation public class AnnotationTest{}
用反射测试AnnotationTest的定义上是否有@Myannotation
元注解:java.lang.annotation子包里面
根据反射测试的问题,引出@Retention元注解的讲解,
前面我们了解到,@Retention是用于说明注解保留在哪个阶段即就是注解的生命周期。
注解的生命周期包含哪些呢?
Java源程序__(编译时期)__class文件__(类加载器)__内存中的字节码;
生命周期对应的三个值:
RetentionPolicy.SOURCE: Java源文件时期(如@Override,@SuppressWarning)
RetentionPolicy.CLASS: class文件时期(默认阶段)
RetentionPolicy.RUNTIME: 运行时期(如@Deprecated)
如:在我们在注解类加上@Retention(RetentionPolicy.RUNTIME)//表示此注解保留到runtime阶段,即在运行阶段都还有。
总结的说就是:当我们在源程序上加注解,javac编译时,会对这上面的注解进行解读,来判断其生命周期,进而在编译时对注解进行相应的操作。
枚举类Taeget:用于说明注解类的使用范围
里面的成分:
PACKAGE(包声明)
FIELD(字段声明)
ANNOTATION_TYPE(注释类型声明)
CONSIRUCTOR(构造器声明)
METHOD(方法声明)
PARAMETER(参数声明)
TYPE(类、接口(包含注释类型)或枚举声明)
LOCAL_VARIABLE(局部变量声明)
知识点:
Type
因为class、enum、interface和@interface等都是平级的,所以需要代表类的值TYPE而不是CLASS
代码示例:
package cn.heima.Day02;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)//元注解
public @interface MyAnnotation {//注解类
}
package cn.heima.Day02;
import java.lang.annotation.RetentionPolicy;
@MyAnnotation
public class AnnotationTest {//应用类
@SuppressWarnings("deprecation")//表示压制过时信息警告
public static void main(String[] args) {
//该方法已过时,通过压制过时信息,就不会报错
System.runFinalizersOnExit(true);
//通过反射的原理来判断此类中是否有MyAnnoyation注释,若有就提供反射的方法来获取注解类
if(AnnotationTest.class.isAnnotationPresent(MyAnnotation.class)){
MyAnnotation annotation = AnnotationTest.class.getAnnotation(MyAnnotation.class);
System.out.println(annotation);
}
}
}打印结果:@cn.heima.Day02.MyAnnotation()
为注解增加各种属性
什么是注解的属性?
一个注解相当于一个胸牌,如果你胸前贴了胸牌,就是传智播客的学生,否则就不是。如果还想区分出事传智播客哪个班的学生,这时可以为胸牌再加上一个属性来区分,加了属性的标记效果为:@MyAnnotation(color=”red”);
定义格式:
String color();//同接口方法一样;
@MyAnnotation(color=”red”);
定义缺省格式:
String value()default”yellow”;
用反射获得注解对应的实例对象后,可以通过该对象来调用属性对应的方法获取其属性值。
如:MyAnnotation a = (MyAnnotation )AnnotationTest.class.getAnnotation(MyAnnotation.class);
System.out.println(a.color());
可以认为上面这个@MyAnnotation 是MyAnnotation类的一个实例对象。
Value属性:
1,如果注解最后有一个名称为value的属性,且你只想设置value属性(其他属性都采用默认值或者只有一个value属性),那么可以省略“value=”这个部分,@SuppressWarning(“deprecation”)。
2,可以为属性值指定缺省值(default),应用时同样可以重新设置属性。
为注解增加高级属性
数组类型的属性
如:int[] arrayAtter() default{1,2,3};不可定义默认值
@MayAnnotation(arrayAttr={2,3,4})可从新赋值
如果数组属性中只有一个元素(不管是否重新赋值的元素),这时候属性值部分可以省略大括号;
枚举类型的属性
如:假设定义了一个枚举类TrafficLamp,它是EnumTest的内部类,其值是交通灯的三色。
EnumTest.TrafficLamp.lamp();
@MyAnnotation(lamp=EnumTest.TrafficLamp.GREEN);
注解类型的属性
如:假定有个注解类:MetaAnnotation,其中定义了一个属性:String value()
MetaAnnotation annotationAttr() default @MetaAnnotation(“xxx”);
@MyAnnotation(annotationAttr=@MetaAnnotation(“yyy”);重新赋值
可以认为上面这个@MyAnnotation是MyAnnotation类的一个实例对象,同样道理,我 们也可以认为上面的这个@MetaAnnotation是MetaAnnotation的实例对象。
代码如下:
MetaAnnotationma =MyAnnotation.annotation();
System.out.println(ma.value());
Class类型的属性
如:Class clazz
@MyAnnotation(class=AnnotationDemo.class);
查询文档发现为注解增加的高级属性的返回值类型有:
1,八种基本数据类型;
2,String类型;
3,Class类型;
4,枚举类型;
5,注解类型;
6,前面五种类型的数组
示例:
package cn.heima.Day02;---------------------- ASP.Net+Android+IOS开发、 .Net培训、期待与您交流! ----------------------详细请查看: http://edu.csdn.net
//此注解类是用于注解类的
public @interface MyAnnotation2 {
String value();//定义一个属性,但是不定义值,让调用者来赋值
}
package cn.heima.Day02;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)//元注解:指定该注解保留在哪个阶段(RetentionPolicy:保存策略)
@Target({ElementType.METHOD,ElementType.TYPE})//元注解:指定元素的使用类型范围(ElementType:元素类型)
public @interface MyAnnotation {//注解类,下面是注解类添加各类型属性
//给注解类添加具体指定属性
String color() default "red";//指定该注解类默认的缺省值(default:缺省)
String value();//现在 先不指定,但是在应用的时候必须指定属性值
//数组类型的属性
int[] arr() default {1,2,3,4};//指定数组类型的默认缺省值;
//注:如果数组中只有一个元素,这时候属性值部分可以省略大括号
//枚举类型的属性
TrafficLamp lamp() default TrafficLamp.GREEN;
//注解类
MyAnnotation2 annotation2() default @MyAnnotation2("heima");
}
package cn.heima.Day02;
import java.lang.annotation.Annotation;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
//该注解是对此类的应用,然后注解自身进行属性赋值或从新定义值
//如:将默认值颜色从新赋值yellow,value赋值黑马,arr数组从新赋值一个元素(就不要大括号了),lamp从新赋值RED。
@MyAnnotation(color="yellow",value="黑马",arr=1,lamp=TrafficLamp.RED)
public class AnnotationTest {//应用类
@SuppressWarnings("deprecation")//表示压制过时信息警告
@MyAnnotation("Method")//将自定义注解应用到方法上
public static void main(String[] args) throws NoSuchMethodException{
//该方法已过时,通过压制过时信息,就不会报错
System.runFinalizersOnExit(true);
//通过反射的原理来判断此类中是否有MyAnnoyation注释,若有就提供反射的方法来获取注解类
if(AnnotationTest.class.isAnnotationPresent(MyAnnotation.class)){
MyAnnotation annotation = AnnotationTest.class.getAnnotation(MyAnnotation.class);
//获取注解信息
System.out.println(annotation);//获取注解名
System.out.println(annotation.color());//获取注解的颜色属性
System.out.println(annotation.value());//获取注解的值
System.out.println(annotation.lamp());//获取注解的灯属性
System.out.println(annotation.arr().length);//获取注解的数组长度属性
System.out.println(annotation.annotation2());//获取注解的元注解的值属性
}
//获取方法上的注解
//先取得Method对象即:返回值类型 Method+自定义名 = Class.getMethod("方法名",方法类型.class)
Method mainMethod = AnnotationTest.class.getMethod("main",String[].class);
//再通过反射的方法来获取方法上的注解对象
MyAnnotation methodAnnotation = (MyAnnotation)mainMethod.getAnnotation(MyAnnotation.class);
//获取压制过时信息的注解
SuppressWarnings sw = mainMethod.getAnnotation(SuppressWarnings.class);
//打印结果
System.out.println(methodAnnotation);
System.out.println(sw);
}
}