Annotation
是从 JDK5.0 开始引入的新技术Annotation
的作用:
Annotation
的格式:
@SuppressWarnings(value="unchecked")
Annotation
在哪里使用?
package,class,method,field
等上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制编程实现对这些元数据的访问package ink.annotation; import java.util.ArrayList; import java.util.List; public class Test01 extends Object { //@Override 重写的注解 @Override public String toString() { return super.toString(); } //@Deprecated 不推荐程序员使用,但可以使用,或者存在更好的方式 @Deprecated public static void test() { System.out.println("Deprecated"); } //@SuppressWarnings 用来抑制编译时的警告信息 //参数有:all unchecked value={"unchecked","deprecation"} 等 @SuppressWarnings("all") public static void test02() { List list = new ArrayList(); } public static void main(String[] args) { test(); test02(); } }
@Target
:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)@Retrntion
:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(runtime > class > source)@Document
:说明该注解将被包含在javadoc中@Inherited
:说明子类可以继承父类中的该注解package ink.annotation; import java.lang.annotation.*; public class Test02 { @MyAnnotation public void test() { } } //定义一个注解 //Tatget 表示我们的注解可以用在哪些地方 @Target(value = {ElementType.METHOD,ElementType.TYPE}) //Retention 表示我们的注解在什么地方还有效 //runtime > class > source @Retention(value = RetentionPolicy.RUNTIME) //@Documented 表示是否将我们的注解生成在JavaDoc中 @Documented //@interface 子类可以继承父类的注解 @interface MyAnnotation { }
使用@interface
自定义注解时,自动继承了java.lang.annotation.Annotation
接口
分析:
@interface
用来声明一个注解,格式:public @ interface 注解名 { 定义内容 }
default
来声明参数的默认值package ink.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; //自定义注解 public class Test03 { //注解可以显示赋值,如果没有默认值,我们就必须给注解赋值 @MyAnnotation2(age = 18,name = "熊大") public void test() { } @MyAnnotation3("hello") public void test2() { } } @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation2 { //注解的参数:参数类型 + 参数名(); String name() default ""; int age(); int id() default -1; //如果默认值为 -1,代表不存在 String[] schools() default {"西部开源","惠州学院"}; } @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation3 { String value(); }
Class c = Class.forName("java.lang.String")
引入需要的"包类"名称 --> 通过new实例化 --> 取得实例化对象
实例化对象 --> getClass()方法 --> 得到完整的"包类"名称
功能:
优点:
缺点:
相关的主要API:
java.lang.Class
:代表一个类java.lang.reflect.Method
:代表类的方法java.lang.reflect.Field
:代表类的成员变量java.lang.reflect.Constructor
:代表类的构造器Class类:在Object类中定义了以下方法,此方法将被所有子类继承
public final Class getClass()
package ink.reflection; //什么叫反射 public class Test02 extends Object{ public static void main(String[] args) throws ClassNotFoundException { //通过反射获取类的Class对象 Class c1 = Class.forName("ink.reflection.User"); System.out.println(c1); Class c2 = Class.forName("ink.reflection.User"); Class c3 = Class.forName("ink.reflection.User"); Class c4 = Class.forName("ink.reflection.User"); //一个类在内存中只有一个Class对象 //一个类被加载后,类的整个结构都会被封装在Class对象中 System.out.println(c2.hashCode()); System.out.println(c3.hashCode()); System.out.println(c4.hashCode()); /* class ink.reflection.User 21685669 21685669 21685669 */ } } //实体类:pojo、entity class User { private String name; private int id; private int age; public User() { } public User(String name, int id, int age) { this.name = name; this.id = id; this.age = age; } public String getName() { return name; } public int getId() { return id; } public int getAge() { return age; } public void setName(String name) { this.name = name; } public void setId(int id) { this.id = id; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", id=" + id + ", age=" + age + '}'; } }
对于每个类而言,JRE都为其保留一个不变的Class类型对象。一个Class对象包含了特定某个结构(class / interface / enum / annotation / primitive type / void / [])的有关信息
特点:
.class
文件常用方法
static ClassforName(String name)
:返回指定类名name的Class对象Object newInstance()
:调用缺省构造函数,返回Class对象的一个实例getName()
:返回此Class对象所表示的实体(类,接口,数组类 或 void)的名称Class getSuperClass()
:返回当前Class对象的父类的Class对象Class[] getinterfaces()
:获取当前对象的接口ClassLoader getClassLoader()
:返回该类的类加载器Constructor[] getConstructors()
:返回一个包含某些Constructor对象的数组Method getMothed(String name,Class.. T)
:返回一个Method对象,此对象的形参类型为paramType
Field[] getDecIaredFields()
:返回Field对象的一个数组package ink.reflection; //测试class类的创建方式有哪些 public class Test03 { public static void main(String[] args) throws ClassNotFoundException { Person person = new Student(); System.out.println("这个人是;" + person.name); //方式一:通过对象获得 Class c1 = person.getClass(); System.out.println(c1.hashCode()); //方式二;forname获得 Class c2 = Class.forName("ink.reflection.Student"); System.out.println(c2.hashCode()); //方式三:通过类名 .class 获得 //最为安全可靠,程序性能最高 Class c3 = Student.class; System.out.println(c3.hashCode()); //方式四:基本内置类型的包装类都有一个Type属性 Class c4 = Integer.TYPE; System.out.println(c4); //获得父类类型 Class c5 =c1.getSuperclass(); System.out.println(c5); /* 这个人是;学生 21685669 21685669 21685669 int class ink.reflection.Person */ } } class Person { public String name; public Person() { } public Person(String name) { this.name = name; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + '}'; } } class Student extends Person { public Student() { this.name = "学生"; } } class Tescher extends Person { public Tescher() { this.name = "老师"; } }
package ink.reflection; import java.lang.annotation.ElementType; public class Test04 { 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 = ElementType.class; //枚举 Class c7 = Integer.class; //基本数据类型 Class c8 = void.class; //void Class c9 = Class.class; //Class System.out.println(c1); System.out.println(c2); System.out.println(c3); System.out.println(c4); System.out.println(c5); System.out.println(c6); System.out.println(c7); System.out.println(c8); System.out.println(c9); //只要元素类型与维度一样,就是同一个Class int[] a = new int[10]; int[] b = new int[100]; System.out.println(a.getClass().hashCode()); System.out.println(b.getClass().hashCode()); /* class java.lang.Object interface java.lang.Comparable class [Ljava.lang.String; class [[I interface java.lang.Override class java.lang.annotation.ElementType class java.lang.Integer void class java.lang.Class 21685669 21685669 */ } }
java.lang.Class
对象<clinit>()
方法的过程。类构造器<clinit>()
方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。(类构造器是构造类信息的,不是构造该类对象的构造器)<clinit>()
方法在多线程环境中被正确加锁同步package ink.reflection; public class Test05 { public static void main(String[] args) { A a = new A(); System.out.println(A.m); /* A类静态代码块初始化 A类的无参构造初始化 300 */ /* 总结: 1.加载到内存,会产生一个类对应Class对象 2.链接,链接结束后 m = 0 3.初始化 <clinit>() { System.out.println("A类静态代码块初始化"); m = 300; m = 100; } */ } } class A { static int m = 100; static { System.out.println("A类静态代码块初始化"); m = 300; } public A() { System.out.println("A类的无参构造初始化"); } }
java.lang.reflect
包的方法对类进行反射调用package ink.reflection; //测试类什么时候会初始化 public class Test06 { static { System.out.println("Main类被加载"); } public static void main(String[] args) throws ClassNotFoundException { //1.主动引用 //Son son = new Son(); //2.反射也会产生主动引用 //Class.forName("ink.reflection.Son"); //不会产生类的引用的方法 //System.out.println(Son.b); //Son[] array = new Son[5]; //System.out.println(Son.M); } } class Father { static int b = 2; static { System.out.println("父类被加载"); } } class Son extends Father { static { System.out.println("子类被加载"); m = 300; } static int m = 100; static final int M = 1; }
类加载的作用:
java.lang.Class
对象,作为方法区中数据的访问入口类缓存:
代码加载流程:
源文件 *.java
--> Java编译器 --> 字节码 *.class
--> 类加载器 --> 字节码校验器 --> 解释器 --> 操作系统平台类加载器作用是用来把类(class)装载进内存的。JVM 规范定义了如下类型的加载器
jre/lib/ext
目录下的jar
包或-D java.ext.dirs
指定目录下的jar
包装入工作库java-classpath
或-D java.class.path
所指的目录下的类与jar
包装入工作,是最常用的加载器package ink.reflection; public class Test07 { public static void main(String[] args) throws ClassNotFoundException { //获取系统类的加载器 ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); System.out.println(systemClassLoader); //获取系统类加载器的父亲加载器 --> 扩展类加载器 ClassLoader parent = systemClassLoader.getParent(); System.out.println(parent); //获取扩展类加载器的父类加载器 --> 根加载器(C/C++) ClassLoader parent1 = parent.getParent(); System.out.println(parent1); //测试当前类是那个加载器加载的 ClassLoader classLoader = Class.forName("ink.reflection.Test07").getClassLoader(); System.out.println(classLoader); //测试JDK内置的类是谁加载的? --> 根加载器(C/C++) classLoader = Class.forName("java.lang.Object").getClassLoader(); System.out.println(classLoader); /* sun.misc.Launcher$AppClassLoader@18b4aac2 sun.misc.Launcher$ExtClassLoader@14ae5a5 null sun.misc.Launcher$AppClassLoader@18b4aac2 null */ } }
Field、Method、Constructor、Superclass、Interface、Annotation
package ink.reflection; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; //获得类的信息 //User类代码,见上边 “Java反射机制研究及应用” public class Test08 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException { //Class c1 = Class.forName("ink.reflection.User"); User user = new User(); Class c1 = user.getClass(); //获得类的名字 System.out.println(c1.getName()); //获得包名 + 类名 System.out.println(c1.getSimpleName()); //获得类名 //获得类的属性 System.out.println("===================="); Field[] fields = c1.getFields(); //只能找到public属性 fields = c1.getDeclaredFields(); //找到全部属性 for (Field field : fields) { System.out.println(field); } //获得指定属性的值 System.out.println(); Field name = c1.getDeclaredField("name"); System.out.println(name); //获得类的方法 System.out.println("===================="); Method[] methods = c1.getMethods(); //获得本类及其父类的全部public方法 for (Method method : methods) { System.out.println("正常的:" + method); } System.out.println(); methods = c1.getDeclaredMethods(); //获得本类全部方法 for (Method method : methods) { System.out.println("getDeclaredMethods:" + method); } //获得指定方法 //存在重载,所以需要参数 System.out.println(); Method getName = c1.getMethod("getName", null); Method setName = c1.getMethod("setName", String.class); System.out.println(getName); System.out.println(setName); //获得指定的构造器 System.out.println("===================="); Constructor[] constructors = c1.getConstructors(); //获得public的 for (Constructor constructor : constructors) { System.out.println(constructor); } System.out.println(); constructors = c1.getDeclaredConstructors(); //获取全部的 for (Constructor constructor : constructors) { System.out.println("#:" + constructor); } //获得指定构造器 System.out.println(); Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class); System.out.println("指定:" + declaredConstructor); /* ink.reflection.User User ==================== private java.lang.String ink.reflection.User.name private int ink.reflection.User.id private int ink.reflection.User.age private java.lang.String ink.reflection.User.name ==================== 正常的:public java.lang.String ink.reflection.User.toString() 正常的:public java.lang.String ink.reflection.User.getName() 正常的:public int ink.reflection.User.getId() 正常的:public void ink.reflection.User.setName(java.lang.String) 正常的:public void ink.reflection.User.setAge(int) 正常的:public void ink.reflection.User.setId(int) 正常的:public int ink.reflection.User.getAge() 正常的:public final void java.lang.Object.wait() throws java.lang.InterruptedException 正常的:public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException 正常的:public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException 正常的:public boolean java.lang.Object.equals(java.lang.Object) 正常的: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() getDeclaredMethods:public java.lang.String ink.reflection.User.toString() getDeclaredMethods:public java.lang.String ink.reflection.User.getName() getDeclaredMethods:public int ink.reflection.User.getId() getDeclaredMethods:public void ink.reflection.User.setName(java.lang.String) getDeclaredMethods:private void ink.reflection.User.test() getDeclaredMethods:public void ink.reflection.User.setAge(int) getDeclaredMethods:public void ink.reflection.User.setId(int) getDeclaredMethods:public int ink.reflection.User.getAge() public java.lang.String ink.reflection.User.getName() public void ink.reflection.User.setName(java.lang.String) ==================== public ink.reflection.User() public ink.reflection.User(java.lang.String,int,int) #:public ink.reflection.User() #:public ink.reflection.User(java.lang.String,int,int) 指定:public ink.reflection.User(java.lang.String,int,int) */ } }
创建类的对象:调用Class对象的 newInstance()
方法
**思考?**难道没有无参构造器就不能创建对象了吗?
getDeclaredConstructor(Class ... parameterTypes)
取得本类的指定形参类型的构造器Constructor
实例化对象调用指定方法:
getMethod(String name,Class...parameterTypes)
方法取得一个Method对象,并设置此方法操作时所需要的参数类型Object invoke(Object obj,Object ... args)
进行调用,并向方法中传递要设置的obj对象的参数信息
invoke()
方法前,显示调用方法对象的setAccessible(true)
方法,将可访问private
的方法setAccessible
setAccessible()
方法setAccessible
作用时启动和禁用访问安全检查的开关package ink.reflection; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; //动态的创建对象,通过反射 public class Test09 { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException { //获得Class对象 Class c1 = Class.forName("ink.reflection.User"); //构造一个对象 User user = (User) c1.newInstance(); //本质是调用了类的无参构造器 System.out.println(user); // User{name='null', id=0, age=0} //通过构造器创建对象 Constructor constructor = c1.getDeclaredConstructor(String.class,int.class,int.class); User user2 = (User)constructor.newInstance("熊大",001,18); System.out.println(user2); // User{name='熊大', id=1, age=18} //通过反射调用普通方法 User user3 = (User)c1.newInstance(); //通过反射获取一个方法 Method setName = c1.getDeclaredMethod("setName", String.class); //invoke : 激活的意思 // (对象 , "方法的值") setName.invoke(user3,"狂神"); System.out.println(user3.getName()); // 狂神 //通过反射操作属性 User user4 = (User)c1.newInstance(); Field name = c1.getDeclaredField("name"); //不能直接操作私有属性,我们需要关闭程序的安全检测,属性或者方法的setAccessible(true) name.setAccessible(true); name.set(user4,"狂神2"); System.out.println(user4.getName()); // 狂神2 } }
package ink.reflection; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; //分析性能问题 public class Test10 { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { test1(); test2(); test3(); /* 普通方式执行10亿次: 3ms 反射方式执行10亿次: 3721ms 反射方式调用 关闭检测,执行10亿次: 1551ms */ } //普通方式调用 public static void test1() { User user = new User(); long startTime = System.currentTimeMillis(); for (int i = 0; i < 10_0000_0000; i++) { user.getName(); } long endTime = System.currentTimeMillis(); System.out.println("普通方式执行10亿次: " + (endTime - startTime) + "ms"); } //反射方式调用 public static void test2() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { User user = new User(); Class c1 = user.getClass(); Method getName = c1.getDeclaredMethod("getName",null); long startTime = System.currentTimeMillis(); for (int i = 0; i < 10_0000_0000; i++) { getName.invoke(user,null); } long endTime = System.currentTimeMillis(); System.out.println("反射方式执行10亿次: " + (endTime - startTime) + "ms"); } //反射方式调用 关闭检测 public static void test3() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { User user = new User(); Class c1 = user.getClass(); Method getName = c1.getDeclaredMethod("getName",null); getName.setAccessible(true); long startTime = System.currentTimeMillis(); for (int i = 0; i < 10_0000_0000; i++) { getName.invoke(user,null); } long endTime = System.currentTimeMillis(); System.out.println("反射方式调用 关闭检测,执行10亿次: " + (endTime - startTime) + "ms"); } }
ParameterizedType
:表示一种参数化类型,比如Collection<String>
GenericArrayType
:表示一种元素类型是参数化类型或者类型变量的数组类型TypeVariable
:是各种类型变量的公共父接口WildcardType
:代表一种通配符类型表达式package ink.reflection; 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 Test11 { public void method1(Map<String,User> map, List<User> list) { System.out.println("test1"); } public Map<String,User> method2() { System.out.println("test2"); return null; } public static void main(String[] args) throws NoSuchMethodException { Method method1 = Test11.class.getMethod("method1", Map.class, List.class); Type[] genericParameterTypes = method1.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("===================="); Method method2 = Test11.class.getMethod("method2",null); Type genericReturnType = method2.getGenericReturnType(); if (genericReturnType instanceof ParameterizedType) { Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); } } /* class java.lang.String class ink.reflection.User #: java.util.List<ink.reflection.User> class ink.reflection.User ==================== class java.lang.String class ink.reflection.User */ } }
package ink.reflection; import java.lang.annotation.*; import java.lang.reflect.Field; //练习反射操作注解 public class Test12 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { Class c1 = Class.forName("ink.reflection.Student2"); //通过反射获得注解 Annotation[] annotations = c1.getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation); } //获得注解的value的值 System.out.println(); Tablekuang tablekuang = (Tablekuang)c1.getAnnotation(Tablekuang.class); String value = tablekuang.value(); System.out.println(value); //获得类指定的注解 System.out.println(); Field f = c1.getDeclaredField("name"); Fieldkuang annotation = f.getAnnotation(Fieldkuang.class); System.out.println(annotation.columnName()); System.out.println(annotation.type()); System.out.println(annotation.length()); /* @ink.reflection.Tablekuang(value=db_student) db_student db_name varchar 3 */ } } @Tablekuang("db_student") class Student2 { @Fieldkuang(columnName = "db_id",type = "int",length = 10) private int id; @Fieldkuang(columnName = "db_age",type = "int",length = 10) private int age; @Fieldkuang(columnName = "db_name",type = "varchar",length = 3) private String name; public Student2() { } public Student2(int id, int age, String name) { this.id = id; this.age = age; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } 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; } @Override public String toString() { return "Student2{" + "id=" + id + ", age=" + age + ", name='" + name + '\'' + '}'; } } //类名的注解 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface Tablekuang { String value(); } //属性的注解 @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface Fieldkuang { String columnName(); String type(); int length(); }