抑郁症健康,内容丰富有趣,生活中的好帮手!
抑郁症健康 > Java基础——注解和反射——注解自定义与反射具体使用实例

Java基础——注解和反射——注解自定义与反射具体使用实例

时间:2023-06-04 20:30:29

相关推荐

文章目录

1.注解1.1、什么是注解?1.2、注解有哪些?1.3、什么是元注解?1.4、如何自定义注解?1.5、自定义注解实例(定义和使用)(1)Test01.java2.反射2.1、什么是反射?2.2、如何获取class对象?2.3、如何使用反射?反射实例:Person类和注解类(准备):reflect用法一(获取类的基本信息):获得类的名字获得类的属性获得指定属性的值获得类的方法获得指定方法获取构造器获得指定的构造器reflect用法二(创建并操作对象):反射方式创建对象调用无参构造器创建对象通过有参构造器通过私有的构造器通过反射设置公有属性通过反射设置私有属性通过反射调用方法通过反射调用私有方法reflect用法三(获取泛型信息):ParameterizedType:表示一种参数化类型比如 Collection< String>GenericArrayType:表示种元素类型是参数化类型或者类型变量的数组类型TypeVariable:是各种类型变量的公共父接口WildcardType:代表种通配符类型表达式reflect用法四(获取注解信息):获取类上的注解获取属性上的注解获取方法上的注解

1.注解

1.1、什么是注解?

注解就是源代码的元数据,通熟的讲就是代码中的标签。注解就有如下的特点:

注解是一个附属品,依赖于其他元素(包、类、方法、属性等等)存在。注解本身没有作用,在恰当的时候由外部程序进行解析才会发生作用。

1.2、注解有哪些?

按来源分 JDK 自带注解,例如:@Override, @Deprecated, @SuppressWornings 。第三方注解。自定义注解。 按生命周期划分 SOURCE:只存在于源代码中,编译成 class 文件就不存在了。Class:存在于源代码中和 class 文件中。RUNTIME:注解保留到运行时。

1.3、什么是元注解?

元注解指的是用于构成注解的注解,包括如下几个:

@Retention:指明 Annotation 的生命周期,传入的值是一个枚举类型,可选值为:RetentionPolicy.SOURCERetentionPolicy.CLASSRetentionPolicy.RUNTIME@Target:指明 Annotation 可以修饰程序哪些元素,传入的值为ElemetType[] 类型,值可为:ElementType.CONSTRUCTOR:构造器ElementType.FIELD:属性ElementType.LOCAL_VARIABLE:局部变量ElementType.METHOD:方法ElementType.PACKAGE:包ElementType.PARAMETER:参数ElementType.TYPE:类、接口(包括注解类型和 enum 声明) @Documented:使用此修饰的注解将会被 javadoc 工具提取成文档,使用此注解,其 @Retention 必须被设置为RetentionPolicy.RUNTIME。@Inherited:具有继承性。

1.4、如何自定义注解?

自定义注解需要注意的问题:

使用 @interface 关键字定义。

自动继承java.lang.annotation.Annotation接口。

配置参数的类型只能是八大基本类型、String、Class、enum、Annotation 和对应的数组类型。

配置参数声明的语法格式如下([] 表示可省略):

类型 变量名() [default 默认值];

如果只有一个配置参数,其参数名必须为 value。

如果定义的注解含有配置参数,那在使用注解时,必须指定参数值,指定形式为:“参数名=参数值”。如果只有一个参数,直接写参数值即可,定义中指定了默认值的参数可以不指定值,但没有的一定要指定值

没有成员的注解为标记,包含成员的称为元数据

1.5、自定义注解实例(定义和使用)

参考代码:

(1)Test01.java

import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;public class Test01 {@Info(name = "张三",address="北京")public void test01(){}@One("value")public void test02(){}@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.TYPE,ElementType.METHOD})@interface Info {String name();String address();int age()default 18;}@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.TYPE, ElementType.METHOD})@interface One{String value();}}

2.反射

2.1、什么是反射?

反射指的是程序在运行期间借助反射 API 取得任何类的内部信息,并通过这些内部信息去操作对应对象的内部属性和方法。

任何一个类,在第一次使用时,就会被 JVM 加载到堆内存的方法区中。JVM 加载类成功后,就会在方法区中产生一个对应的 Class 对象(一个类只要一个 Class 对象),这个 Class 对象包含被加载类的全部结构信息。

2.2、如何获取class对象?

(1)类的 class 属性

每一个类,都有一个 class 静态属性,这个静态属性就是类对应的 Class 对象。

1 Class<Person> cl1 = Person.class;

(2)Object 对象 的 getClass() 方法

1 Person p1 = new Person();2 Class<Person> cl2 = (Class<Person>) p1.getClass();

(3)通过 Class 类的 forName() 方法(最常用)

1 try {2Class cl3 = Class.forName("com.llm.hkl.Person");3 } catch (ClassNotFoundException e) {4e.printStackTrace();5 }

(4)通过 ClassLoader 类(不常用)

1 ClassLoader cl = Person.class.getClassLoader();2 try {3Class cl4 = cl.loadClass("com.llm.hkl.Person");4 } catch (ClassNotFoundException e) {5e.printStackTrace();6 }

2.3、如何使用反射?

反射的基本使用包括创建对象,设置属性和调用方法。Class 对象中大多数 get 方法有 Declared 和无 Declared,他们的区别是:

无 Declared:只能获取到 public 修饰的,包括当前类和所有父类。有 Declared:获取到当前类所有的(含有 private),但不包括其父类。

反射实例:

Person类和注解类(准备):

import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Info(name = "张三", habbit = "编程")public class Person {@Filed("张三")private String name;public String habbit;private int age;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getHabbit() {return habbit;}public void setHabbit(String habbit) {this.habbit = habbit;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", habbit='" + habbit + '\'' +", age=" + age +'}';}private String say(String str) {String str1 = name + "说:" + str;System.out.println(str1);return str1;}public void eat(String food) {System.out.println(name + "吃" + food);}public Person() {}public Person(String name, String habbit, int age) {this.name = name;this.habbit = habbit;this.age = age;}private Person(String name, String habbit) {this.name = name;this.habbit = habbit;}@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD, ElementType.TYPE})@interface Info {String name();String habbit();int age() default 18;}@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)@interface Filed{String value();}}

reflect用法一(获取类的基本信息):

获得类的名字
获得类的属性
获得指定属性的值
获得类的方法
获得指定方法
获取构造器
获得指定的构造器

Class<?> person = Class.forName("Person");//获得类的名字System.out.println("<-----------------------------------获得类的名字-------------------------->");String name = person.getName();System.out.println(name);//获得类的属性System.out.println("<-------------------------------------获得类的属性--------------------->");//仅publicSystem.out.println("<-----------------getFields----------------->");Field[] fields = person.getFields();for (Field field : fields) {System.out.println(field);}System.out.println("<-----------------getDeclaredFields----------------->");Field[] declaredFields = person.getDeclaredFields();for (Field declaredField : declaredFields) {System.out.println(declaredField);}//获得指定属性的值System.out.println("<--------------------获得类的指定属性--------------------------------------->");Field name1 = person.getDeclaredField("name");System.out.println(name1);//获得类的方法System.out.println("<--------------------获得类的方法--------------------------------------->");//仅publicSystem.out.println("<-----------------getMethods----------------->");Method[] methods = person.getMethods();for (Method method : methods) {System.out.println(method);}System.out.println("<-----------------getDeclaredMethods----------------->");Method[] declaredMethods = person.getDeclaredMethods();for (Method declaredMethod : declaredMethods) {System.out.println(declaredMethod);}//获得指定方法System.out.println("<-------------------------获得类的指定方法--------------------------------------->");Method say = person.getDeclaredMethod("say",String.class);System.out.println(say);//获取构造器System.out.println("<--------------------------获得类的构造器--------------------------------->");System.out.println("<-----------------getConstructors----------------->");//仅publicConstructor<?>[] constructors = person.getConstructors();for (Constructor<?> constructor : constructors) {System.out.println(constructor);}System.out.println("<-----------------getDeclaredConstructors----------------->");Constructor<?>[] declaredConstructors = person.getDeclaredConstructors();for (Constructor<?> declaredConstructor : declaredConstructors) {System.out.println(declaredConstructor);}//获得指定的构造器System.out.println("<---------------------------获得类指定的构造器------------------------------>");Constructor<?> declaredConstructor = person.getDeclaredConstructor(String.class, String.class, int.class);System.out.println(declaredConstructor);

reflect用法二(创建并操作对象):

反射方式创建对象
调用无参构造器创建对象
通过有参构造器
通过私有的构造器
通过反射设置公有属性
通过反射设置私有属性
通过反射调用方法
通过反射调用私有方法

Class<?> person = Class.forName("Person");// 反射方式创建对象System.out.println("<-----反射方式创建对象----->");Person instance01 = (Person) person.newInstance();System.out.println(instance01);// 调用无参构造器创建对象System.out.println("<-----调用无参构造器创建对象----->");Constructor<?> noneConstructor = person.getDeclaredConstructor();Person instance02 = (Person) noneConstructor.newInstance();System.out.println(instance02);// 调用有参构造器创建对象System.out.println("<-----调用有参构造器创建对象----->");Constructor<?> constructor = person.getDeclaredConstructor(String.class, String.class, int.class);Person instance03 = (Person) constructor.newInstance("张三", "编程", 18);System.out.println(instance03);// 调用私有的构造器创建对象System.out.println("<-----调用私有的构造器创建对象----->");java.lang.reflect.Constructor<?> privateConstructor = person.getDeclaredConstructor(String.class, String.class);privateConstructor.setAccessible(true);Object instance04 = privateConstructor.newInstance("张三", "编程");System.out.println(instance04);// 通过反射设置公有属性System.out.println("<-----通过反射设置公有属性----->");Field habbit = person.getDeclaredField("habbit");habbit.set(instance01, "编程");System.out.println(instance01);// 通过反射设置私有属性System.out.println("<-----通过反射设置私有属性----->");Field name = person.getDeclaredField("name");name.setAccessible(true);name.set(instance01, "张三");System.out.println(instance01);// 通过反射调用公有方法System.out.println("<-----通过反射调公用方法----->");Method eat = person.getDeclaredMethod("eat", String.class);eat.invoke(instance01,"饭");// 通过反射调用私有方法System.out.println("<-----通过反射调用私有方法----->");Method say = person.getDeclaredMethod("say", String.class);say.setAccessible(true);say.invoke(instance01,"呵呵");

reflect用法三(获取泛型信息):

Java采用泛型擦除的机制来引入泛型,Java中的泛型仅仅是给编译器 Javac使用的,确保数据的安全性和免去强制类型转换问题,但是,一旦编译完成,所有和泛型有关的类型全部擦除。

为了通过反射操作这些类型,Java新增了 ParameterizedType, GenericArrayTypeType Variable和 WildcardType几种类型来代表不能被归一到class类中的类型但是又和原始类型齐名的类型。

ParameterizedType:表示一种参数化类型比如 Collection< String>
GenericArrayType:表示种元素类型是参数化类型或者类型变量的数组类型
TypeVariable:是各种类型变量的公共父接口
WildcardType:代表种通配符类型表达式

import java.lang.reflect.Method;import java.lang.reflect.ParameterizedType;import java.lang.reflect.Type;import java.util.List;import java.util.Map;public class Test03 {public void test01(Map<String, Person> map, List<Person> list) {System.out.println("test01");}public Map<String, Person> test02(){System.out.println("test02");return null;}public static void main(String[] args) throws Exception {Class<Test03> test03 = Test03.class;System.out.println("<--------test01---------->");Method test01 = test03.getDeclaredMethod("test01", Map.class, List.class);Type[] genericParameterTypes = test01.getGenericParameterTypes();for (Type genericParameterType : genericParameterTypes) {System.out.println(genericParameterType);if (genericParameterType instanceof ParameterizedType) {Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();for (Type actualTypeArgument : actualTypeArguments) {System.out.println(actualTypeArgument);}}}System.out.println("<--------test02---------->");Method test02 = test03.getDeclaredMethod("test02");Type genericReturnType = test02.getGenericReturnType();System.out.println(genericReturnType);if (genericReturnType instanceof ParameterizedType) {Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();for (Type actualTypeArgument : actualTypeArguments) {System.out.println(actualTypeArgument);}}}}

运行结果:

reflect用法四(获取注解信息):

获取类上的注解
获取属性上的注解
获取方法上的注解

Class<?> person = Class.forName("Person");System.out.println("<----------获取类上的注解------------->");//获取类上的注解Info annotation = person.getAnnotation(Info.class);System.out.println(annotation.name());System.out.println(annotation.habbit());System.out.println(annotation.age());System.out.println("<----------获取属性上的注解------------->");//获取属性上的注解Field name = person.getDeclaredField("name");Person.Filed file = name.getAnnotation(Person.Filed.class);String value = file.value();System.out.println(value);//获取方法上的注解 略。。。

运行结果:

如果觉得《Java基础——注解和反射——注解自定义与反射具体使用实例》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。