手机网站建设林肖单页面网站做百度推广效果

当前位置: 首页 > news >正文

手机网站建设林肖,单页面网站做百度推广效果,google 网站 提交,互联网企业网站模板前言 Java 中的反射大家都不陌生#xff0c;有很多很好的文章都进行了讲解#xff0c;但是很难找到一篇文章能完全解释反射的所有用法#xff0c;特别是反射获取这个对象的注解的信息和泛型信息#xff0c;往往都停留在了获取类的函数、方法#xff0c;构造上。所以这篇文…前言 Java 中的反射大家都不陌生有很多很好的文章都进行了讲解但是很难找到一篇文章能完全解释反射的所有用法特别是反射获取这个对象的注解的信息和泛型信息往往都停留在了获取类的函数、方法构造上。所以这篇文章将全面讲解 Java 反射中的所有用法特别是对于类中的注解的获取上。另外本文章不会对反射的原理进行讲解看完本文你应该只能学会怎么用反射至于其原理本文不会涉及。 首先我们自定义两个类和一个注解用于后续我们来演示反射的用法。简单来说就是 Student 类继承自 Person 类并在 Student 类上使用了 Work 注解。Person 类比较简单我就不贴出来了另外两个 Java 文件如下我们后续将通过反射获取这个类对象的所有信息。 Work.java package lic.reflect;Retention(RetentionPolicy.RUNTIME) Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE}) Documented() Inherited() public interface Work {String value();int category() default 0;Class? workClass(); }Student.java package lic.reflect;Work(value college, workClass Person.class) public class Student extends Person implements Cloneable {private volatile int level;private Student(String name) {super(name);}public Student(String name, int age) {super(name, age);}Work(value math, workClass HashMap.class)public ListString study(MapString, Integer map) {System.out.println(this study:\n);ListString list new ArrayList();for (EntryString, Integer entry : map.entrySet()) {System.out.println(entry.getKey() : entry.getValue());list.add(entry.getKey());}return list;}Overridepublic void printOccupation() {System.out.println(occupation student.);} }获取 Class 对象的四种方式 java.lang.Class 类是反射机制的基础存放着对应类型对象的运行时信息。在 Java 程序运行时Java虚拟机为所有类型维护一个 java.lang.Class 对象即每种类型的 Class 对象只有一个。 在使用反射做任何事情之前我们必须获得 Class 对象可以说Class 对象是我们进行反射操作的入口。那么怎么获取这个 Class 对象呢主要有四种方式 //方式一Object.getClass() Class studentClass student.getClass();//方式二T.class Class studentClass Student.class;//方式三static Class? Class.forName try {Class studentClass_3 Class.forName(lic.reflect.Student);System.out.println(Class.forName studentClass); } catch (ClassNotFoundException exception) { //此方式会抛出 ClassNotFoundException 异常exception.printStackTrace(System.err); }//方式四通过 ClassLoader try { ClassLoader classLoader Thread.currentThread().getContextClassLoader(); Class? c classLoader.loadClass(java.lang.String); } catch (ClassNotFoundException e) {e.printStackTrace(); }无论通过哪种方式其获取的 Class 对象都是一样的。 在 Class 对象中我们一般会获取的有个三类信息构造方法 Constructor、成员方法 Method、成员变量 Field。而后续作用域对象的操作都必须先过去到其对应的上述三类信息下面我们一一道来。 构造方法 Constructor Class 类中用于获取构造方法的方法 Constructor?[] getConstructors() 返回所有公共构造方法对象的数组只能获取 public 的构造方法Constructor?[] getDeclaredConstructors() 返回所有构造方法对象的数组所有构造方法包含 privateConstructorT getConsturctor(Class?… parameterTypes) 返回单个指定的公共构造方法ConstructorT getDeclaredConstructor(Class?… parameterTypes) 返回单个指定的构造方法 注意这上面带 declared 的方法和不带 declared 的方法的区别 不带 Declared的方法支持取出包括继承、公有Public 但不包括有Private的构造函数带 Declared的方法是支持取出包括公共Public、保护Protected、默认包访问和私有Private的构造方法但不包括继承的构造函数 这个规则不仅适用于获取 Constructor、还适用于获取 Method 和 Field 对象。 获取到 Constructor 对象之后即可用其创建对象相关方法如下 T newInstance(Object… initargs) 根据指定的构造方法创建对象setAccessible(boolean flag) 设置是否取消访问检查设置为 true 表示取消访问检查可以提高反射效率 下面我们试一下上面的几个方式获取构造器 Constructor[] constructors studentClass.getConstructors(); for(Constructor constructor: constructors) {System.out.println(constructor); } //输出 //public lic.reflect.Student(java.lang.String,int)constructors studentClass.getDeclaredConstructors(); for(Constructor constructor: constructors) {System.out.println(constructor); } //输出 //private lic.reflect.Student(java.lang.String) //public lic.reflect.Student(java.lang.String,int)try {Constructor constructor studentClass.getDeclaredConstructor(String.class, Integer.TYPE);System.out.println(constructor); } catch (NoSuchMethodException|SecurityException e) {e.printStackTrace(); } //输出 //public lic.reflect.Student(java.lang.String,int)当获取了 Constructor 之后即可以使用这个对象来创建 Student 类对象 constructor.setAccessible(true); //取消访问检查 Student student (Student)constructor.newInstance(Alan, 30); //创建对象 System.out.println(student);成员变量 Field Class 类中用于获取成员变量的方法 Field[] getFields() 返回此类和父类中所有public的成员变量Field[] getDeclaredFields() 返回此类中所有的成员变量不包括父类FIeld getField(String name) 从此类和父类中查找对应的public成员变量并返回Field getDeclaredField(String name) 在此类中查找指定的成员变量并返回 Field 类中用于设置和获取成员变量的方法 void set(Object obj, Object value) 设置 obj 对象中的此成员变量设置为 valueObject get(Object obj) 获取 obj 对象中的此成员变量String getName() 获取此成员变量的名称Class? getType() 获取此成员变量的类型int getModifiers() 获取此成员变量的修饰符即 private volatile之类的通过 Modifier 类方便查询 下面是 Field 这个类的使用示例 Field[] fields studentClass.getFields(); for(Field field: fields) System.out.println(field); //输出父类的 public name 成员变量 //public java.lang.String lic.reflect.Person.nameField[] fields studentClass.getDeclaredFields(); for(Field field: fields) System.out.println(field); //输出本类的 private level 成员变量 //private int lic.reflect.Student.leveltry {Field field studentClass.getDeclaredField(level);String fieldName field.getName();System.out.println(fieldName); //输出 levelClass fieldType field.getType();System.out.println(fieldType); //输出 intint modifier field.getModifiers();System.out.println(Modifier.isPrivate(modifier)); //输出 trueSystem.out.println(Modifier.isVolatile(modifier)); //输出 true } catch (NoSuchFieldException | SecurityException exception) {exception.printStackTrace(); }成员方法 Method Class 类中用于获取成员变量的方法 Method[] getMethdos() 返回所有 public 成员方法的对象包括继承的Method[] getDeclaredMethods() 返回此类中所有成员方法对象的数组Method getMethod(String name, Class?… parameterTypes) 查找此类及父类中指定的 public 成员方法Method getDeclaredMethod(String name, Class?… parameterTypes) 查找并返回单个成员方法 Method 类中的常用方法 Object invoke(Object obj, Object… args) 调用 obj 对象上的这个方法Class getReturnType() 返回这个方法的返回值类型Type getGenericReturnType() 返回这个方法的泛型返回值类型Class[] getParameterTypes() 返回这个方法的参数类型Type[] getGenericParameterTypes() 返回这个方法的参数的泛型信息Annotation[] getAnnotations() 返回这个方法上的注解 下面是 Method 类的使用示例 Method[] methods studentClass.getMethods(); for(Method method: methods)System.out.println(method); //输出可见大部分都是从 Object 类继承而来的方法 //public void lic.reflect.Student.study(java.util.Map) //public void lic.reflect.Student.printOccupation() //public java.lang.String lic.reflect.Person.getName() //public void lic.reflect.Person.setName(java.lang.String) //public int lic.reflect.Person.getAge() //public void lic.reflect.Person.setAge(int) //public static void lic.reflect.Person.staticFunc() //public boolean java.lang.Object.equals(java.lang.Object) //public java.lang.String java.lang.Object.toString() //public native int java.lang.Object.hashCode() //public final native java.lang.Class java.lang.Object.getClass() //public final native void java.lang.Object.notify() //public final native void java.lang.Object.notifyAll() //public final void java.lang.Object.wait(long) throws java.lang.InterruptedException //public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException //public final void java.lang.Object.wait() throws java.lang.InterruptedExceptionMethod[] methods studentClass.getDeclaredMethods(); for(Method method: methods)System.out.println(method); //输出 //public void lic.reflect.Student.study(java.util.Map) //public void lic.reflect.Student.printOccupation()try {Method method studentClass.getMethod(study, Map.class);System.out.println(method);MapString, Integer methodArgs new HashMapString, Integer();methodArgs.put(math, 10);method.invoke(student, methodArgs); //study 方法被正常调用 } catch (NoSuchMethodException | SecurityException | IllegalAccessException | InvocationTargetException e) {e.printStackTrace(); }Class returnType method.getReturnType(); //interface java.util.List Type type method.getGenericReturnType(); //java.util.Listjava.lang.StringClass[] parameterClass method.getParameterTypes(); //interface java.util.Map Type[] types method.getGenericParameterTypes(); //java.util.Mapjava.lang.String, java.lang.Integer Annotation[] annotations method.getAnnotations(); //lic.reflect.Work(category0, valuemath, workClassjava.util.HashMap.class)对注解进行解析 上面的代码中我们通过 method.getAnnotations() 方法获取了 study 方法上的注解下面将讲解如何解析注解的一些信息。注解是由 Annotation 这个接口来表示为了获取注解上的信息我们首先就要获取这个注解的 Class 对象 Class? extends Annotation annotationType() 获取这个注解的 Class 对象 有了这个 Class 对象再来看注解的解析。实际上跟上述获取类的成员方法并调用是一样的 Method[] methods annoClass.getDeclaredMethods(); //输出 //public abstract java.lang.String lic.reflect.Work.value() //public abstract int lic.reflect.Work.category() //public abstract java.lang.Class lic.reflect.Work.workClass()如果我们要获取定义在 study() 方法上的定义的注解 Work(value math, workClass HashMap.class)只需要进行如下的调用即可 String value (String) methods[0].invoke(annotation); System.out.println(value); //math int category (int) methods[1].invoke(annotation); System.out.println(category); //0 Class workClass (Class) methods[2].invoke(annotation); System.out.println(workClass); //class java.util.HashMap与反射相关的三个类 通过上面的解读我们肯定对反射有了基本的认识和运用在使用反射中我们往往会碰到三个类或接口其中另一个就是上面说的 Class。而另外两个一个是 Type 接口一个是 AnnotatedType 接口。下面就对这两个接口简单解释一下。 Type 接口 Type 是一个顶层接口表示 Java 语言中的所有类型它的几个子接口和实现类如下 Class?表示类或接口类型ParameterizedType表示参数化类型例如ListStringGenericArrayType表示泛型数组类型例如T[]TypeVariableD extends GenericDeclaration表示类型变量例如TWildcardType表示通配符类型例如? extends Number Type 接口主要用来在反射中表示和处理各种类型。通过这个接口可以获取类型的详细信息并执行相应的操作。一般来说当我们获取泛型类型的参数、确定数组类型时会用到这个接口。例如 public class Example {private ListString list;public static void main(String[] args) throws NoSuchFieldException {Field field Example.class.getDeclaredField(list);Type type field.getGenericType();System.out.println(Type: type); // 输出Type: java.util.Listjava.lang.String} }AnnotatedType 接口 AnnotatedType 接口是 AnnotatedElement 的一个子接口表示带有注解的类型允许访问和操作类型上的注解。但我们需要获取注解信息时就必须获取使用这个接口。例如 Retention(RetentionPolicy.RUNTIME) interface ExampleAnnotation { }public class Example {private ExampleAnnotation ListString list;public static void main(String[] args) throws NoSuchFieldException {Field field Example.class.getDeclaredField(list); AnnotatedType annotatedType field.getAnnotatedType(); System.out.println(Annotations: annotatedType.getAnnotations().length); // 输出Annotations: 1 } }Class 类 Class 对象是 Java 反射机制中的核心概念之一。它是 Type 接口的一个实现类代表了运行时的类或接口。Class 对象不仅仅是类型信息的载体还提供了大量的方法来检查类的结构、创建实例、访问成员等。 这个类上面说了一大堆的内容这里就不赘述了。 总结 Java 反射机制是 Java 语言的重要特性之一如果你开发框架或库时掌握反射的使用是必须的。例如大名鼎鼎的 Retrofit、Gson、Room 等都大量使用了反射。所以作为 Android 开发者这个反射咱们还真是得好好掌握。