1 min to read
Java若干特性
类加载机制
类加载器
用于加载类文件(一般是指class字节码文件,但实际上也可能是动态生成的或者网络传输来的)的类。其作用就是在运行时加载类,将class文件转为Class对象(并不是实例对象),Java类加载器的三个机制:
-
委托机制:某个类加载器接收到加载类的请求时,首先将加载任务交给父类,并依次递归,如果父类可以完成类加载任务,就成功返回,否则自己加载。启动类加载使用loadClass方法,而真正加载类使用defineClass方法;前者抛出classNotFound,后者抛出noClassdefine;加载成功之后,会将类缓存起来,对于一个类加载器实例来说,相同全名的类只加载一次.。
-
可见性:子类的类加载器可以看见父类加载器加载的类,但是父类的类加载器不可以看到子类加载器加载的类。
-
单一性:一个类仅加载一次;
每一个类对象都对应一个类加载器;虚拟机判定两个类是否相同的依据是:类全名相同并且两个类的类加载器相同(执行definedClass的类加载器,而不是loadClass的加载器)即便是同一类型加载器的两个不同实例,也会认为是不同的类。这也是采用委托机制的原因,目的是保证核心库的安全;
在虚拟机内部,不同的类加载器加载类时会赋予类一个额外的名称空间,相同的类可以通过不同的类加载器加载,并存于java虚拟机中;但是二者不兼容,不可转换;这在许多框架中被用到;
四种预定义类型的类加载器:
- Bootstrap 引导类加载器:使用native代码实现,负责加载rt.jar中的类;
- Extension(ExtClassLoader),扩展类加载器:用于加载jre/ext文件夹下或者java.ext.dir指向的类;
- System(AppClassLoader 静态类),系统类加载器:用于加载环境变量下的类(classPath 或者 -cp);
- Context,线程上下文类加载器;
开发者可以通过继承java.lang.ClassLoader的方式实现自己的类加载器,,一般来说只需要重写findClass方法即可,调用的时候,仍然调用loadClass;最好不要复写loadClass方法,有可能会破坏代理模式;
动态代理
反射机制
Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, and to use reflected fields, methods, and constructors to operate on their underlying counterparts, within security restrictions.
通过java代码获取已加载类的属性、方法、构造函数、注解等,并且可以使用他们。简单来说,在运行状态可以做到:
- 对于任意一个类,都能够知道这个类的所有属性、方法、注解、限定符、实现的接口、父类等;
- 对于任意一个对象,都能够调用它的任意一个方法和属性;
For every type of object, the Java virtual machine instantiates an immutable instance of java.lang.Class which provides methods to examine the runtime properties of the object including its members and type information. Class also provides the ability to create new classes and objects. Most importantly, it is the entry point for all of the Reflection APIs.
获取Class的几种方式:
- 实例对象的 .getClass() 基本类型不能使用这种方法
- .class 基本类型及包装类型都可以使用,如:boolean.class、String.class
- Class.forName(“java.lang.String”); 通过全限定名称
- 数组:Class.forName(“[D”); //相当于double[].class; Class.forName(“[[Ljava.lang.String;”); //相当于String[][].class
Reflection defines an interface java.lang.reflect.Member which is implemented by java.lang.reflect.Field, java.lang.reflect.Method, and java.lang.reflect.Constructor .
Member接口的三个实现类:
- java.lang.reflect.Field :对应类变量
- java.lang.reflect.Method :对应类方法
- java.lang.reflect.Constructor :对应类构造函数
反射就是通过这三个类来调用实例对应的方法、访问实例的属性、构造新的实例。
参考链接
反射的副作用:
- 性能开销大一些
- 安全性问题
Comments