Java 注解与反射 基础
注解与反射 基础什么是注解 Annotation 注解
Annotation 的作用:不是程序本身,可以对程序做出解释。可以被其他程序(比如 编译器等)读取
annotation 的格式: 注解是以 ”@注释名“ 再代码中存在的,还可以添加一写参数值,例如 @SupperWarnings(value = "unchecked")
Annotation 在哪可以使用? 可以在 package,class,method,field 等上面,相当于给他们添加额外的辅助信息,我们可以通过反射机制编程实现对这些元数据的访问
内置注解 @Override 重写
@Deprecated 不鼓励使用,但是可以使用
@SuppreWarning 警告
元注解元注解的作用是负责注解其他注解
@Target
@Retention
@Documented
@ Inherited
package opp2;
import java.lang.annotation.*;
public class demo01 {public void test(){
}
//定义一个注解//Target 表示我们的注解可以用在上面地方 @Target(value = {ElementType.METHOD, ElementType.TYPE})
//Retention 表示我们的注解在上面地方有效//RUNTIME >CLASS >SOURCES@Retention(value = RetentionPolicy.RUNTIME)
//Documented 表示释放将我们的注解生成在 JavaDoc 中 @Documented
//Inherited 子类可以继承父类的注解 @Inherited@interface MyAnnotation{
}自定义注解使用 @interface 自定义注解时,自动继承 import java.lang.annotation.Annotation 接口
@interface 用来声明一个注解,格式: public @interface 注解名{定义内容}其中的每一个方法实际上声明的是一个配置函数方法的名称就是参数的名称返回值类型就是参数的类型(返回值只能是基本类型,class,string,enum)可以通过 default 来声明参数默认值如果只有一个参数成员,一般参数名为 value 注解元素必须要有值,我们定义注解元素时,经常使用空字符串,0 作为默认值 package opp2;
import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;
public class demo02 {
}
@Target(value = {ElementType.METHOD, ElementType.TYPE})@Retention(value = RetentionPolicy.RUNTIME)@interface MyAnnotation2{//直接的参数:参数类型 +参数名()String name();String color() default "";int age() default 0;int id() default -1;
}
@Target(value = {ElementType.METHOD, ElementType.TYPE})@Retention(value = RetentionPolicy.RUNTIME)@interface MyAnnotation3{String value();}反射 java.Reflection
时 Java 被视为动态语言的关键,反射机制允许程序在执行期借助 Reflection api 获得任何类的信息,并能直接操作任意对象的内部属性及方法。
获得反射对象 getClass()
package opp2;
/**
什么是反射*/public class demo03 {public static void main(String[] args) throws ClassNotFoundException {Class<?> c1 = Class.forName("opp2.User");Class<?> c2 = Class.forName("opp2.User");Class<?> c3 = Class.forName("opp2.User");System.out.println(c1);
}}
//实体类 class User{private String name;private int id;private int age;
}得到 class 类的几种方式 Java 注解与反射 基础插图
package opp2;
public class demo04 {public static void main(String[] args) throws ClassNotFoundException {Person person = new student();System.out.println(person.name);
}
class Person{String name;public Person(){}
}class student extends Person{public student(){this.name = "学生";}}
class teacher extends Person{public teacher(String name) {this.name = "老师";}}所有类型的 Class 对象 class:外部类、成员(内部成员、外部成员),局部内部类,匿名内部类
interface:接口
[] :数组
enum:枚举
annotation:注解 @interface
primitive type:基本数据类型
void
package opp2;
import javax.xml.bind.Element;
public class demo {public static void main(String[] args) {Class c1 = Object.class; //类 Class c2 = Comparable.class; //接口 Class c3 = String[].class; //一维数组 Class c4 = int[][].class; //二维数组 Class c5 = Override.class; //注解 Class c6 = Element.class; //枚举 Class c7 = Integer.class; //基本数据类型 Class c8 = void.class; //voidClass c9 = Class.class; //Class
}类加载内存分析加载------>链接---->初始化
package opp2;
public class demo06 {public static void main(String[] args) {A a = new A();System.out.println(a.m);/*** 1.【加载】到内存,会产生一个类对应的 Class 对象* 2.【链接】,链接后, m = 0* 3.【初始化】:* <clint>(){* system.out.println("A 类的静态代码块初始化");* m = 300;* m = 100;* }*/}}
class A{static {System.out.println("A 类的静态代码块");m = 300;}
}分析类初始化类的主动引用(一定会发生初始化)类的被动引用(不会发生类的初始化)package opp2;
public class demo07 {
}
class F{static int b = 2;static {System.out.println("父类被加载");}}
class S extends F{static {System.out.println("子类被加载");m = 300;}static int m = 100;static final int M = 1; //常量}类加载器 Java 注解与反射 基础插图 1
package opp2;
public class demo08 {public static void main(String[] args) throws ClassNotFoundException {//获取系统类的加载器 ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();System.out.println(systemClassLoader);//获取系统类加载器的父类加载器->扩展加载器 ClassLoader parent = systemClassLoader.getParent();System.out.println(parent);
}获取类的运行时结构通过反射获取运行时类的完整结构
Field、Method、Constructor、Superclass、Interface、Annotation
package opp2;
import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;
public class demo09 {public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {Class<?> c1 = Class.forName("opp2.User");
// for (Field field1 : field){// System.out.println(field1);// }//field = c1.getDeclaredFields();for (Field fields : field){ //找到全部属性 System.out.println(fields);}
}动态创建对象执行方法能做啥?
步骤:
通过 Class 类的 getDeclaredConstructor(Class ... parameterType)获取本类的指定形参类型的构造器向构造器的行参中传递一个对象素组进去,里面包含了构造器中所需的各个参数通过 Constructor 实例化对象 package opp2;
import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;
public class demo10 {public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
}性能对比分析 setAccessible:启动和禁用访问安全检查的开关。参数值为 true 则指反射的对象在使用时应该取消 java 语言访问检查
提高反射效率。如果代码中必须使用反射,而该句代码需要频发的被调用,那么请设置为 true 使得原本无法访问的私有成员也可以访问参数值为 false 则指反射的对象在使用时对 java 语言进行访问检查
package opp2;
import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;
public class demo11 {public static void test1(){User user = new User();long startTime = System.currentTimeMillis();for (int i = 0; i < 1000000000; i++) {user.getName();}long endTime = System.currentTimeMillis();System.out.println("普通方法执行 10 亿次 " + (endTime-startTime)+"ms");}
}获取泛型信息 Java 采用泛型擦除的机制来引入泛型,Java 中的泛型仅仅是给编辑器 javac 使用的,确保数据的安全性和免去强制类型转换问题,但是,一旦编译完成,所有和泛型有关的类型全部擦除
为了通过反射操作这些类型,Java 新增了 ParameterizedType,GenericArrayType,TypeVariable 和 WindcardType 几种类型来代表不能被归一到 Class 类中的类型但是又和原始类型齐名的类型
ParameterizedType:表示一种参数化类型,不如 CollectionGenericArrayType:表示一种元素类型是参数化类型或者类型变量的数组类型 TypeVariable:是各种类型变量的公共父接口 WindcardType:代表一种通配符类型的公示 package opp2;
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 demo12 {public void test(Map<String,User> map, List<User>list){System.out.println("test01");}public Map<String,User> test02(){System.out.println("test02");return null;}
public static void main(String[] args) throws NoSuchMethodException {Method method = demo12.class.getMethod("test", Map.class, List.class);Type[] genericParameterTypes = method.getGenericParameterTypes();for (Type ge : genericParameterTypes){System.out.println("#" + ge);if (ge instanceof ParameterizedType){Type[] actualTypeArguments = ((ParameterizedType) ge).getActualTypeArguments();for (Type act : actualTypeArguments){System.out.println(act);}}}method = demo12.class.getMethod("test02", null);Type genericParameterType = method.getGenericReturnType();if (genericParameterType instanceof ParameterizedType){Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();for (Type act : actualTypeArguments){System.out.println(act);}}}}获取注解信息 ORM 对象关系映射
package opp2;
import java.lang.annotation.*;import java.lang.reflect.Field;
/**
练习反射操作注解*/public class demo13 {public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {Class<?> c1 = Class.forName("opp2.Student2");Annotation[] annotation = c1.getAnnotations();
// Field name = c1.getDeclaredField("name");Field name = c1.getDeclaredField("id");Fk annotation1 = name.getAnnotation(Fk.class);System.out.println(annotation1.columnName());System.out.println(annotation1.Type());System.out.println(annotation1.length());
}
@TableM("db_student")class Student2{@Fk(columnName = "db_id",Type = "int", length = 10)private int id;@Fk(columnName = "db_age",Type = "int", length = 10)private int age;@Fk(columnName = "db_name", Type = "varchar", length = 3)private String name;public Student2(){
}
//类名的注解 @Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@interface TableM{String value();}
//属性的注解 @Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@interface Fk{String columnName();String Type();int length();}
版权声明: 本文为 InfoQ 作者【卢衍飞】的原创文章。
原文链接:【http://xie.infoq.cn/article/f334e388338af0bf8151b6152】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论