Java注解和反射学习笔记(有想法随时添加)

    技术2022-07-11  94

    注解

    @SuppressWarnings(“all”) //镇压警告注解 给强迫症用的0.0

    元注解:

    @Target,描述注解可以用在什么地方 @Retention,描述注解的生命周期 source-> class-> runtime(默认) @Documented,说明该注解被包含在Javadoc中 @Inherited,说明子类可以继承父类中的该注解

    使用元注解自定义一个注解

    例如:

    //自定义注解 public class AnnoByMe { @MyAnno(name = "我的自定义注解",schools = {"无心大学","龙哥大学"}) public void test(){} @MyAnno2("只有一个value可以省略,只有value可以省略,这是规范") public void test2(){} } @Target({ElementType.TYPE,ElementType.METHOD}) //作用域,类上和方法上 @Retention(RetentionPolicy.RUNTIME) //生命周期,一般在Runtime @interface MyAnno{ //注解的参数: 参数类型+参数名(); String name() default ""; //默认为空 int age() default 0; int id() default -1; //如果默认值为-1 就代表不存在 String[] schools() default {"哈哈哈哈","呵呵呵呵"}; } @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnno2{ String value(); }

    反射

    反射机制运行程序在执行期间借助Reflection API取得任何类的内部信息,并且能直接操作任意对象的内部属性以及方法。

    正常方式:引入需要的包名->new实例化->取得实例化对象

    反射方式:实例化对象->getClass方法->得到类完整包名

    初识反射:

    package ReflectionClass; public class WhatIsReflection { public static void main(String[] args) throws ClassNotFoundException { //通过反射去获取类的Class对象 Class c1 = Class.forName("ReflectionClass.User"); System.out.println(c1); Class c2 = Class.forName("ReflectionClass.User"); Class c3 = Class.forName("ReflectionClass.User"); Class c4 = Class.forName("ReflectionClass.User"); //一个类在内存中只有一个Class对象 //一个类被加载后,类的整个结构都会被封装在Class对象中 System.out.println(c2.hashCode()); System.out.println(c3.hashCode()); System.out.println(c4.hashCode()); } } //实体类 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 void setName(String name) { 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; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", id=" + id + ", age=" + age + '}'; } }

    获取Class的几种方式

    package ReflectionClass; //测试Class类的创建方式有哪些 public class findClass { 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("ReflectionClass.Student"); System.out.println("第二种方式:" + c2.hashCode()); //方式3:通过类名获得 Class<Student> c3 = Student.class; System.out.println("第三种方式:" + c3.hashCode()); //方式4:基本内置类型的包装类都有一个Type属性 Class<Integer> type = Integer.TYPE; System.out.println(type); //获得父类的Class Class superclass = c1.getSuperclass(); System.out.println(superclass); } } 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:注解@interfaceprimitive type:基本数据类型void

    Java内存

    堆:存放new的对象和数组,可以被所有线程共享,不会存放别的对象引用。栈:存放基本数据类型,会包含这个基本数据类型的具体数值;还存放引用对象的变量,会存放这个引用在堆里面的具体地址。方法区:可以被所有线程共享,包含了所有的class和static变量。

    类加载过程

    类的加载:将类的class文件字节码读入内存,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的java.lang.Class对象。类的链接:将类的二进制数据合并到JRE中。 验证:确保加载的类的信息符合JVM规范,无安全问题。准备:正式为类(static)变量分配内存并设置类变量初始值的阶段,这些内存都将在方法区中进行分配。解析:虚拟机常量池内的符号引用(常量名)替换成直接引用(地址)的过程。 类的初始化:JVM负责 执行类构造器,()方法的过程。类构造器()方法是由编译期自动收集类中所有类变量的赋值动作,和静态代码块中的语句合并产生的。当初始化一个类的时候,如果发现父类还没有初始化,就先会触发父类的初始化。虚拟机会保证一个类的,()方法在多线程环境中被正确的加锁和同步。
    加载和链接小例子
    package ReflectionClass; public class ClassHowToLoad { public static void main(String[] args) { A a = new A(); System.out.println(A.m); /* 1.加载到内存开辟空间,会产生一个类对应得Class对象 2.链接,由于是int,m会被赋初始值为0 3.初始化 <clinit>(){ } 然后静态代码块和静态变量赋值按顺序执行 */ } } class A{ static { System.out.println("A类的静态代码块初始化******"); m=300; } static int m = 100; public A(){ System.out.println("A类的无参构造初始化------"); } }

    类加载示例(例如rt.jar)

    package ReflectionClass; public class TestClassLoader { 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++) 一般为null无法打印 ClassLoader parent1 = parent.getParent(); System.out.println(parent1); //测试当前类是哪个类加载器加载的 ClassLoader classLoader = Class.forName("ReflectionClass.TestClassLoader").getClassLoader(); System.out.println(classLoader); //测试JDK内置的类是谁加载的 ClassLoader classLoader1 = Class.forName("java.lang.Object").getClassLoader(); System.out.println(classLoader1); //如何获取系统类加载器可以加载的路径 String property = System.getProperty("java.class.path"); System.out.println(property); /* sun.misc.Launcher$AppClassLoader@18b4aac2 sun.misc.Launcher$ExtClassLoader@1540e19d null sun.misc.Launcher$AppClassLoader@18b4aac2 null C:\Program Files\Java\jdk1.8.0_162\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_162\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_162\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_162\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_162\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_162\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_162\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_162\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_162\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_162\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_162\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_162\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_162\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_162\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_162\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_162\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_162\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_162\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_162\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_162\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_162\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_162\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_162\jre\lib\rt.jar;F:\SpringStudy\SpringBootStudySecond\mianshi\out\production\mianshi;F:\Program Files\JetBrains\IntelliJ IDEA 2019.3.2\lib\idea_rt.jar */ /* 补充: 双亲委派机制 例如自己写了一个java.lang.String 类 那么类加载器会从 用户类加载器->系统类(应用程序)加载器->扩展类加载器->根加载器 逐级检查,如果发现了改类,那么自己写的String类就没有用了。 */ } }

    有了Class对象我们能干嘛?

    动态创建对象

    package ReflectionClass; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; //通过反射动态创建对象 public class DynamicCreate { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException { //获得Class对象 Class<?> c1 = Class.forName("ReflectionClass.User"); //构造一个对象 User user = (User) c1.newInstance(); //本质上构造了无参构造器,如果类里面没有,就会报错 System.out.println(user); //通过构造器创建对象,没有无参构造器也没关系 Constructor<?> constructor = c1.getDeclaredConstructor(String.class, int.class, int.class); User user2 = (User) constructor.newInstance("神仙姐姐", 10, 10); System.out.println(user2); //通过反射调用方法 User user3 = (User) c1.newInstance(); //通过反射来获取方法 Method setName = c1.getDeclaredMethod("setName", String.class); setName.invoke(user3,"八八八八八"); //invoke:调用;激活 (对象,值) System.out.println(user3.getName()); //通过反射操作属性 User user4 = (User)c1.newInstance(); Field name = c1.getDeclaredField("name"); name.setAccessible(true); //关闭程序的属性安全检测,可以去操作private私有属性,没有这句话会报错 name.set(user4,"四号"); System.out.println(user4.getName()); } }

    反射操作泛型

    package ReflectionClass; 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 FanXing { public void test111(Map<String,User> map, List<User> list){ System.out.println("test111"); } public Map<String,User> test222(){ System.out.println("test222"); return null; } public static void main(String[] args) throws NoSuchMethodException { //通过反射获取泛型 Method test111 = FanXing.class.getMethod("test111", Map.class, List.class); Type[] genericParameterTypes = test111.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); } } } Method test222 = FanXing.class.getMethod("test222", null); Type[] genericParameterTypes1 = test111.getGenericParameterTypes();//获得泛型的类型 for (Type genericParameterType : genericParameterTypes1) { System.out.println("##" + genericParameterType); if (genericParameterType instanceof ParameterizedType) {//判断这个类型是不是结构化的参数类型 Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); } } } } }

    反射操作注解

    package ReflectionClass; import java.lang.annotation.*; import java.lang.reflect.Field; //反射操作注解 public class ORM { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { Class<?> c1 = Class.forName("ReflectionClass.Student2"); //通过反射获得注解 Annotation[] annotations = c1.getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation); } //获取注解的value值 TableKusch tableKusch = c1.getAnnotation(TableKusch.class); String value = tableKusch.value(); System.out.println(value); //获取类指定的注解 Field f = c1.getDeclaredField("id"); FieldKusch annotation = f.getAnnotation(FieldKusch.class); System.out.println(annotation.columnName()); System.out.println(annotation.length()); System.out.println(annotation.type()); } } //简单实体类 @TableKusch("db_student") class Student2{ @FieldKusch(columnName = "db_id",type = "int",length = 10) private int id; @FieldKusch(columnName = "db_age",type = "int",length = 10) private int age; @FieldKusch(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 TableKusch{ String value(); } //属性注解 @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface FieldKusch{ String columnName(); String type(); int length(); }
    Processed: 0.010, SQL: 9