Java注解和反射学习笔记
1.什么是注解
Annotation是从JDK5.0开始引入的新技术
作用:可以被其他程序(比如编译器等)读取
格式:@注释名,还可以添加一些参数值
内置注解: @Override 重写
@Deprecated 不推荐使用,但是可以使用,或者存在更好的方式
@SuppressWarning 镇压警告 @SuppressWarning(“all”)镇压所有警告
元注解: 作用就是负责注解其他注解
@Target:表示注解的使用范围,可以用在哪些地方
1 2 3 4 5 6 7 8 9 10 11 12 @MyAnnotation public class Test01 { @MyAnnotation public void test () { } }@Target(value ={ElementType.METHOD,ElementType.TYPE})
@Retention(保留的意思):表示注解的生命周期,在什么地方还有效, runtime>class>source
1 2 @Retention(value = RetentionPolicy.RUNTIME)
@Documentted:表示是否将我们注解生成在javadoc中
@Inherited:表示子类可继续父类的注解
自定义注解: 使用@interface自定义注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class Test02 { @MyAnnotation1() public void test1 () {} @MyAnnotation3("侬好") public void test2 () {} }@Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation1{ String name () default "" ; int age () default 18 ; int id () default -1 ; String[] shcool() default {"清华大学" }; }@Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation3{ String value () ; }
2.什么是反射
动态语言:运行时可以改变其结构的语言 ,比如JavaScript,php,python
静态语言:运行时结构不可改变,比如java,c,c++
概念:
优点: 实现动态创建对象和编译,灵活性
缺点: 对性能有影响,使用反射基本上是一种解释操作 ,我们告诉JVM,我们希望做什么并且它满足我们的需求,比直接执行相同的操作慢。
反射相关的主要API: java.lang.Class:代表一个类
java.lang.reflect.Method:代表类的方法
java.lang.reflect.Field:代表类的成员变量
java.lang.reflect.Constructor:代表类的构造器
Class类: Class类是Reflection的根源,针对任何你想动态加载、运行的类,要先获得相应的Class对象。
获取Class类的实例:
通过对象获取(getClass)
通过类名获取
通过类名.class获取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 package test;public class Test04 { 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()); Class c2=Class.forName("test.Student" ); System.out.println(c2.hashCode()); Class c3=Student.class; Class c4= c1.getSuperclass(); System.out.println(c4); } }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 Teacher extends Person { public Teacher () { this .name="老师" ; } }
哪些类型可以有Class对象? class:外部类,成员,局部内部类,匿名内部类
interface:接口
[]:数组
enum:枚举
annotation:注解
基本数据类型
void
java内存分析 java内存:
堆内存:
存放new的对象和数组
可以被所有的线程共享,不会存放别的对象引用
栈内存
存放基本变量类型(会包括这个基本类型的具体数值)
引用对象的变量(会存放这个引用在堆里面的具体地址)
方法区
可以被所有的线程共享
包含了所有的class和static变量
类的加载与ClassLoader的理解 加载:
链接:
初始化:
什么时候会发生类初始化? 类的主动引用:一定会发生类的初始化
虚拟机启动,先初始化main方法所在的类
new一个类的对象
调用类的静态成员和静态方法
使用java.lang.reflect包的方法对类进行反射调用
当初始化一个类时,其父类没有被初始化,则会先初始化它的父类
类的被动引用:不会发生类的初始化
当访问静态域时,只有真正声明这个域的类才会被初始化,例如:当子类引用父类的静态变量,不会导致子类初始化
通过数组定义类引用,不会触发此类的初始化
引用常量不会触发此类的初始化(常量和静态变量在连接阶段就存入调用类的常量池中了)
类加载器 概念:类加载器作用是用来把类(class)装载进内存的,有引导类加载器,扩展类加载器,系统类加载器
获取运行时类的完整结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 package test;import java.lang.reflect.Field;import java.lang.reflect.Method;public class Test06 { public static void main (String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException { Class c1 = Class.forName("test.User" ); System.out.println(c1.getName()); System.out.println(c1.getSimpleName()); Field[] fields = c1.getFields(); fields = c1.getDeclaredFields(); for (Field field : fields) { System.out.println(field); } Field age = c1.getDeclaredField("age" ); System.out.println(age); c1.getMethods(); c1.getDeclaredMethods(); Method getName = c1.getMethod("getName" , null ); Method setName = c1.getMethod("setName" , String.class); c1.getConstructors(); c1.getDeclaredConstructors(); c1.getConstructor(String.class,int .class,int .class); } }
有了Class对象,能做什么?
通过反射创建对象
newInstance //本质是调用了类的无参构造器
通过构造器创建对象 //调用了有参构造方法
通过反射调用普通方法 //getDeclaredMethod //invoke(对象,”方法的值”)
通过反射操作属性 //getDeclaredField
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 package test;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;public class Test07 { public static void main (String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException { Class c1 = Class.forName("test.User" ); User user = (User) c1.newInstance(); Constructor constructor = c1.getDeclaredConstructor(String.class, int .class, int .class); User user1 = (User) constructor.newInstance("大白" , 18 , 001 ); System.out.println(user1); User user2 = (User) c1.newInstance(); Method setName= c1.getDeclaredMethod("setName" , String.class); setName.invoke(user2,"反射" ); System.out.println(user2.getName()); User user3 = (User) c1.newInstance(); Field name = c1.getDeclaredField("name" ); name.setAccessible(true ); name.set(user3,"反射操作属性" ); System.out.println(user3.getName()); } }
性能检测: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 package test;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;public class Test08 { public static void test01 () { User user=new User(); long start=System.currentTimeMillis(); for (int i = 0 ; i < 1000 ; i++) { user.getName(); } long end=System.currentTimeMillis(); System.out.println("普通方式执行时间:" +(end-start)); } public static void test02 () throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { Class c1= Class.forName("test.User" ); User user= (User) c1.newInstance(); long start=System.currentTimeMillis(); Method getName= c1.getDeclaredMethod("getName" ); for (int i = 0 ; i < 1000 ; i++) { getName.invoke(user,null ); } long end=System.currentTimeMillis(); System.out.println("反射执行时间:" +(end-start)); } public static void test03 () throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { Class c1= Class.forName("test.User" ); User user= (User) c1.newInstance(); long start=System.currentTimeMillis(); Method getName= c1.getDeclaredMethod("getName" ); getName.setAccessible(true ); for (int i = 0 ; i < 100000000 ; i++) { getName.invoke(user,null ); } long end=System.currentTimeMillis(); System.out.println("反射执行(关闭检测)时间:" +(end-start)); } public static void main (String[] args) throws ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException { test01(); test02(); test03(); } }
反射读取注解 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 package test;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;public class Test10 { public static void main (String[] args) throws ClassNotFoundException, NoSuchFieldException { Class c1=Class.forName("test.Student1" ); c1.getAnnotations(); Table table= (Table) c1.getAnnotation(Table.class); String value= table.value(); System.out.println(value); java.lang.reflect.Field f= c1.getDeclaredField("name" ); Field annotation = f.getAnnotation(Field.class); annotation.columnName(); annotation.type(); annotation.length(); } }@Table("db_stydent") class Student1 { @Field(columnName = "db_id",type = "int",length = 10) private int id; @Field(columnName = "db_age",type = "int",length = 10) private int age; @Field(columnName = "db_name",type = "varchar",length = 10) private String name; public Student1 () { } public Student1 (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; } }@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface Table{ String value () ; }@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface Field{ String columnName () ; String type () ; int length () ; }