java-反射
静态语言(强类型语言)
静态语言是在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型。 例如:C++、Java、Delphi、C#等。
动态语言(弱类型语言)
动态语言是在运行时确定数据类型的语言。变量使用之前不需要类型声明,通常变量的类型是被赋值的那个值的类型。 例如PHP/ASP/Ruby/Python/Perl/ABAP/SQL/JavaScript/Unix Shell等等
强类型定义语言
强制数据类型定义的语言。也就是说,一旦一个变量被指定了某个数据类型,如果不经过强制转换,那么它就永远是这个数据类型了。举个例子:如果你定义了一个整型变量a,那么程序根本不可能将a当作字符串类型处理。强类型定义语言是类型安全的语言。
弱类型定义语言
数据类型可以被忽略的语言。它与强类型定义语言相反, 一个变量可以赋不同数据类型的值。强类型定义语言在速度上可能略逊色于弱类型定义语言,但是强类型定义语言带来的严谨性能够有效的避免许多错误。
什么是反射(反射机制)
-
Java时静态语言,通过反射,Java成为了准动态语言
-
反射禁止允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
-
加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。
1
Class c = Class.forName("java.lang.String")
-
这个存在内存中的Class类型的对象就是一面镜子,我们通过镜子的反射能看到类的结构。
-
反射机制的功能:
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时获取泛型信息
- 在运行时调用任意一个对象的成员变量和方法
- 在运行时处理注解
- 生成动态代理
-
反射的优点和缺点:
- 可以实现动态创建对象和编译,很灵活
- 对性能有影响,反射基本上是一种解释操作
理解Class类并获取Class实例
-
发射相关的主要API
- java.lang.Class:代表一个类
- java.lang.reflect.Method:代表类的方法
- java.lang.reflect.Field:代表类的成员变量
- java.lang.reflect.Constructor:代表类的构造器
-
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
class User{ private String name; private int id; private itn age; public User(){} public User(String name,int id,int age){ this.name = name; this.id = id; this.age = age; } //省略get,set方法,toString()方法 } public class Test{ public static void main(String[] args){ Class c1 = Class.forName("com.jack.User"); c1.get } }
-
Class类是Java反射的源头。所谓反射实际就是:可以通过对象反射求出类的名称
类的加载与ClassCloader
-
对象照镜子后可以得到的信息:某个类的属性,方法和构造器,某个类实现了哪些接口。
-
对于一个类而言,JRE都为其保留一个不变的Class类型的对象,一个Class对象包含了特定某个结构的有关信息。
- Class本身也是一个类
- Class对象只能由系统建立对象
- 一个加载的类在JVM中只会有一个Class实例
- 一个Class对象对应的是一个加载到JVM中的一个.class文件
- 每个类的实例都会记得自己是由哪个Class实例所生成
- 通过Class可以完整地得到一个类中的所有被加载的结构
- Class类是Reflection地根源,针对任何逆向动态加载,运行的类,唯有先获得相应的Class对象
1 2 3 4 5 6 7 8 9 10
//Class类的常用方法 static Class forName(String name); Object newInstance(); getName(); Class getSuperClass(); Class[] getinterfaces(); ClassLoader getClassLoader(); Constructor[] getConstructor(); Method getMethod(String name,Class T); Field[] getDeclaredFields();
1 2 3 4 5 6 7 8 9
//获取Class类的实例 //通过类的clas属性获取(多用于传参) Class c1 = Person.class; //用类的实例的getClass获取Class对象(多用于对象获取字节码) Class c2 = person.getClass(); //用Class类的静态方法forName通过一个类的全类名获取Class对象(多用于读取配置文件) Class c3 = Class.forName("jack.Person"); //内置基本数据类型的包装类可以直接用类名.Type //还可以利用ClassLoader
类加载内存分析
类初始化的时机
类加载器ClassLoader
|
|
双亲委派机制
创建运行时类的对象
- 通过反射获取运行时类的完整结构
- Field:全部的属性
- Method:全部的方法
- Constructor:全部的构造器
- Superclass:所继承的父类
- Interface:实现的全部接口
- Annotation:注解
|
|
动态创建对象执行方法
|
|
-
反复执行类中获取名字的方法的三种方式的效率对比:
通过反射操作泛型
- Java采用的泛型擦除机制来引入泛型,Java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换问题。但是,一旦编译完成,所有和泛型相关的类型会全部擦除。
- 为了通过反射来操作这些类型,Java新增了Parameterized,GenericArrayType,TypeVariable和WildcaredType几种类型来代表不能被归一到Class类中的类型但是又和原始类型齐名的类型
- ParameterizedType:表示一种参数化类型,比如
Collection<String>
- GenericArrayType:表示一种元素类型是参数化类型或者类型变量的数组类型
- TypeVaraible:是各种类型变量的公共父接口
- WildcaredType:代表一种通配符类型表达式
|
|
通过注解反射操作注解
**小例子:**通过注解和反射完成类和表结构的映射关系
ORM:Object Relationship Mapping——》对象关系映射
- 类和表结构对应
- 睡醒和字段对应
- 对象和记录对应
|
|