Day14 注解和反射的学习
Day14
注解和反射
注解
注释是给人看的,注解不仅给人看还给程序来看
Annotation 可以被其他程序读取
重写的注解 Override
格式就是@ +注释名 在代码中很常见
注解能在很多地方使用 ,比如包 类 方法 通过反射机制来对元数据进行访问
内置注解
@Override 定义在java.lang.Override 方法声明表示打算重写父类的方法。
@SuppressWarnings 用来抑制编译的警告问题 这个需要添加一个参数才能进行。
元注解
作用就是负责注解其他注解,java定义了四个标准的meta-annotation类,用来提供对其他annotation类的解释说明。
@Target @Retention @Documented @Inherited
Target 用来描述注解的使用范围
Retention 表示用什么级别保存该注释信息,用于描述注解的生命周期 (SOURCE<ClASS<RUNTIME)
Documented 表示该注解会被包含在Javadoc里面
Inherited 说明子类可以继承父类的该注解。
正常是选择运行是有效,所以就是RetentionPolicy.RUNTIME
自定义注解
使用@interface来定义
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface myannotation{
//注解的参数,由参数类型+参数名字+() 在使用该注解时就需要加参数 也可以用default来设置默认值
String name() default " ";
int age() default -1;//如果默认值为-1就代表不存在
}
如果注解只有一个参数,可以使用value命名,在使用时不写参数名用value直接写值
思考一下,写注解有什么用,前面了解到注解是给人喝程序看的修饰性语句 这些注解携带参数,会不会起到传递参数的作用
要学习反射机制才能了解,看看是如何访问的
反射概述
有了反射让java变成动态语言
Reflection
反射机制允许在运行期间借用reflection api 取得任何类的内部信息
优点 可以动态创建对象和编译,体现出很大的灵活性
缺点 对性能有影响 使用反射基本上是一种解释操作 告诉jvm要怎么做 ,这样会慢与直接执行的操作
一个类在内存中只有一个class对象
一个类被加载后,整个类的结构都会被封装进一个class对象
通过对象得到类
class类的创建方式
通过对象 getclasss获得
通过Class.forname("包路径")获得
通过类名.class获得
基本内置类型都有一个Type方法
Integer.Type()也可以得到一个class
获得父类类型 class.getSuperclass
class有很多方法来使用
所以类型的class对象
几乎所有的类都有
class 外部类,成员,局部内部类,匿名内部类
interface 接口
数组
枚举enum
annotation 注解@interface
基本数据类型
void
只要类型一样就会只有一个class
类加载内存分析
先static静态再执行构造函数
先在方法区设置类的属性,静态方法,常量池,然后生成class文件在堆里面,当一切都完成后开始执行代码。
核心就是 加载 链接 初始化
分析类的初始化
类的主动引用(一定会发生类的初始化)
父类没被加载会先加载父类,再加载子类
反射也会加载主动引用
引用常量不会触发初始化,引用父类不会引起子类的初始化,数组定义类不会引起子类的初始化
类加载器
ext 扩展类加载器
//获取系统类的加载器
ClassLoader systemClassLoader=ClassLoader.getSystemClassLoader();
获取运行时的结构
再得到对象的类后可以用方法得到类的结构
得到类的名称getName
得到类的属性getFields 这个只能得到类的public属性
getDeclaredFields 能找到全部属性
通过反射来获得类的构造器,方法名称属性。
动态创建对象执行方法
有了class对象能做什么
通过反射调用 可以创造类的对象
创造类的对象,使用的是无参构造,需要在类里有无参构造
User user=(User) c1.newInstance()
若想要使用有参构造器创造对象
Constructor constructor=c1.getDeclaredConstructor(String.class,int.class,int.class);//原类代码必须要有参构造
User user2=(User) constructor.newInstance("gg",2,3);
System.out.println(user2.getName());
就是首先设置一个构造器再用newinstance方法。
使用反射调用方法的操作
Method setname=c1.getDeclaredMethod("setName", String.class);
setname.invoke(user3,"guo");
invoke激活,这样就可以使用方法调用
使用反射调用属性
Field name = c1.getDeclaredField("name");//不能直接操作私有属性
name.setAccessible(true);//取消java的安全检验,使反射可以使用私有属性 默认false
name.set(user4,"gagag");
性能对比分析
setAccessible () 启用访问安全检查的开关。
关闭后能提高使用反射的效率
正常方式的性能最好,使用反射会影响效率,在使用反射后关闭安全检查能比不关闭要提高不少效率
获取泛型信息
通过反射去操作泛型
首先什么是泛型
就是指在类定义时不会设置类中的属性或方法参数的具体类型,而是在类使用时(创建对象)再进行类型的定义。
就是类型参数化,参数化类型
获取注解信息
ORM 对象关系映射
都是通过反射来进行的,首先创建一个class类对象,运用方法开始对注解进行分析
首先用getAnnotations可以得到该类的所有注解
Annotation[] annotations=c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
得到注解的值
Tablekuang annotation = (Tablekuang)c1.getAnnotation(Tablekuang.class);
System.out.println(annotation.value());
对属性的注解也是一样,先得到属性的class,然后还是getAnnotation,然后输出值
要多加练习。
思考
前面几天个人原因没更新日志,今天又空闲,开始继续学习,把注解和反射学习了,注解就是对程序和人看的注释,起表明的作用,前面有疑问,注解带参数那到底有没有值的传递,现在看确实有的,通过反射学习到,能够通过反射得到注解的值,程序也根据注解的值来判断和匹配相应的位置,反射就是通过程序编译的class文件,然后进行操作,期间学到了内存的问题,说实话还是有点模糊,要多看看计组和操作系统了,学习情况就要算法题,操作系统,计算机组成原理,然后就是框架的学习。