动态语言:
- 程序执行时,可以改变程序结构或者变量的类型,典型的语言:Python、ruby、javascript等。
- 弱类型的语言都是动态语言,在程序执行的时候能够动态改变程序的结构和类型
- C 、C++、java不是动态语言,但java是准动态的语言,具有一定的动态性,可以利用反射来操作字节码对象或者类似动态语言的特性
字节码是什么?
- 字节码是计算机的底层的二进制的表示形式,组成是由0和1进行组成
- 字节码本身就是一系列的字节数组,字节码数组的组成又是由0和1进行组成的
- 字节码的来源:可以文字,图像,视频等,计算机的底层都是使用采二进制进行运算过程,每次进行操作的时候都要将输入计算机的媒体转变成字节码被计算机进行识别,才能进行使用,通过计算机进行二进制的转码然后进行输出的
- java程序再运行的过程中采用的进行二进制的转码操作
- 底层输入进计算机的内存中读取的表示形式是二进制的补码形式
反射机制:
- 指的是可以在运行时加载,探知,使用编译期间完全不知道的类
- 程序在运行状态中,可以动态的加载一个只有名称的类,对于任意一个已经加载的类,都能够知道这个类的所有属性所有属性和方法,对于任意一个对象,都能调用它的任意一个方法和属性
- Class c = Class. forName ("com.beij.test.User");--->动态加载类,加载完成后产生一个对象
- 加载完类之后,在堆内存中,就产生一个Class类型的对象(一个类只有一个Class对象),这个都西昂就包含了完整的类的结构信息,我们通过这个对象看到类的结构,这个对象就像是一面镜子,可以折射出类的所有信息,所以称之为反射
Class类和对象:
- java.lang.Class类十分特殊,用来表示java中类型
- java中的类型包括:calss ,interface,enum,annotation,primitive type(元数据类型),void---->java中的对象
- Class类的对象包含了某个被加载类的结构,一个被加载的类对应一个Class对象
- 当一个class被加载,或者当加载器(class loader)的defineClass()被JVM调用,JVM便自动产生一个Class对象
- Class类是Reflection的根源。
- 针对任何您想动态加载、运行的类,唯有先获得相应的Class 对象
-
Class类的对象如何获取?
- 运用getClass() 运行时进行加载获得类的字节码对象
- 运用.class 语法 类名.class进行获取类的字节码对象 称之为编译期进行加载获取 Class对象
- 运用Class.forName(类的全路径类名)(最常被使用):称之为类的字节码建立期,还没进入编译期之前进行加载该类
反射机制能干什么?
- 动态加载类,动态获取类的信息(属性,构造器,方法)
- 动态构造对象
- 动态调用类和对象的任意方法,构造器
- 动态调用和处理属性
- 获取泛型信息
- 处理注解
反射中的泛型擦除机制:
- java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换的复杂操作,但是一旦进行编译完成,所有和泛型有关的类型将会被全部擦除
- 所以反射跳过了泛型的检查,没有泛型的约束
- 为了通过反射能够操作这些类型,并且开发的需要,Java就新增了ParameterizedType(参数类型),
- GenericArrayType(泛型数组的类型),TypeVariable 和WildcardType几种类型代表不能被归一到Class类型中的类型但是又和原始类型齐名的类型,在Class类型中就新增了这些类型的存在能够进行不同的获取操作对于参数和泛型额确定
- ParameterizedType: 表示一种参数化的类型,比如Collection<String>
• GenericArrayType: 表示一种元素类型是参数化类型或者类型变量的数组类型
• TypeVariable: 是各种类型变量的公共父接口
• WildcardType: 代表一种通配符类型表达式,比如?, ? extends Number, ? super Integer【
wildcard是一个单词:就是“通配符”】ParameterizedType: 表示一种参数化的类型,比如Collection<String>
• GenericArrayType: 表示一种元素类型是参数化类型或者类型变量的数组类型
• TypeVariable: 是各种类型变量的公共父接口
• WildcardType: 代表一种通配符类型表达式,比如?, ? extends Number, ? super Integer【
wildcard是一个单词:就是“通配符”】
-
反射中的注解:
- 由于Annotation注解是也是Class的类型,所以对于注解也是可以进行操作的
- 可以通过Class对象操作类的结构信息上的各种的注解结构信息
- // 获得类的所有有效注解
Annotation[] annotations=clazz.getAnnotations();
for (Annotation a : annotations) {
System.out.println(a);
}
// 获得类的指定的注解
SxtTable st = (SxtTable) clazz.getAnnotation(SxtTable.class);
System.out.println(st.value());
// 获得类的属性的注解
Field f = clazz.getDeclaredField("studentName");
SxtField sxtField = f.getAnnotation(SxtField.class);
System.out.println(sxtField.columnName()+"--
"+sxtField.type()+"--"+sxtField.length());
反射机制中的性能问题:
- setAccessible:控制反射中是否需要进行反射中的语言访问检查,进行授权的访问结构
- 启用和禁用访问安全检查机制的开关,值为 true 则指示反射的对象在使用时应该取消 Java 语
言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查。并不是为true就能访问为false就不能访问。
- 禁止安全检查,可以提高反射的运行速度
- 进行字节码操作 ,可以使用其他的解码工具,进行底层的编写
解密底层的类,方法的定义,属性的确定等…使用cglib/javaassist字节码操作
- 底层的类和方法的编写都是通过某种机制进行编写
- 基本使用的都是字符串的操作,进行类型和方法的编写,属性的确定以及对于属性的编写操作都是通过字符串进行编写的,最终进行一定的组合在一起,形成一个类的操作
注解:
什么是注解?Annotation
- Annotation是从JDK5.0开始引入的新技术
- Annotation的作用:
- 不是程序的本身,可以对程序做出一定的解释——->解释程序的执行流程,程序的作用等
- 可以被其他的程序进行读取(比如:编译器等),注解信息处理流程是注解和注释之间最大额区别
- 如果没有注解信息处理流程,则注解毫无作用
- 注解的本身也是一种java类,只不过这个类的的作用是帮助解释其他的类的信息
- 使用注解进行将另外一个类的属性,类,方法,注解等解释成可执行的语句
- 在java中的类的反射机制中,均提供了对应的反射注解的配置,反射进行操作注解类的属性
Annotation的格式:
- 注解是以“@注释名”在代码中存在的,还可以添加一些参数值,例如:@SuppressWarnings(value="unchecked")。
- 注解中也是可以定义类型的,基本数据类型和引用数据类型都可以进行定义
Annotation的使用:
- 可以附加在package, class, method, field等上面,相当于给它们添加了额外的辅助信息,我们可以通过反射机制编程实现对这些元数据的访问。
内置注解:
- @Override 定义在java.lang.Override中,此注释只适用于修辞方法,表示一个方法声明打算重写超类中的另一个方法声明。
- @Deprecated 定义在java.lang.Deprecated中,此注释可用于修辞方法、属性、类,表示不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择。
- @SuppressWarnings 定义在java.lang.SuppressWarnings中,用来抑制编译时的警告信息
- @SuppressWarnings("unchecked")
– @SuppressWarnings(value={"unchecked", "deprecation"})
自定义注解:
- 使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口
- public @interface 注解名 {定义体}
- 注解属性的定义是不一样的,在注解中每个属性就是一个方法
- 定义每个方法实际上就是声明了一个配置参数
- 方法的名称就是参数的名称
- 返回值类型就是参数的类型(类型的确定---基本数据类型,Class,String ,enum)
- 可以通过default来进行声明参数的默认值,也可以不进行声明
- 如果只有一个参数成员,一般参数名为value, 定义如下所示
- public @interface SxtField {
String columnName();
String type();
int length();
}
- 注意:注解元素必须要有值对应信息的使用上:我们定义注解元素时,经常使用空字符串、0作为默认值。
也经常使用负数(比如:-1)表示不存在的含义
元注解:
- 元注解的作用就是负责注解其他注解。 Java定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。
- 元注解中都存在一个属性 固定的属性 value() 属性,里面包含的是属性的枚举值
-@Target @Retention @Documented @ Inherited
- @Target:
- 作用:用于描述注解的使用范围---->注解可以在什么地方进行使用
- 注解中的确定通过枚举进行实现
- 默认值就是不限制,也就是什么类型和位置都能进行配置
- Type修饰的是 :类,接口,注解 ,枚举类
- @Target(value