1、简介
在Java和Android中都有关于类的加载方面的知识点,之前也是这块比较模糊现在呢有必要确切的去了解这些信息,到底是怎么样的执行顺序,以及类加载很重要的方式反射。
2、详情
Java语言与传统语言的不同点体现在对于类而言Java程序在使用其前并非完全加载,其各个部分都是在需要的时候动态加载的,这里也必然涉及到加载的时机。类加载的条件是,该类第一次被使用,而且创建了第一个对类静态成员的使用。
反射的概念: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
案例1如下:
class A{
static {
System.out.println("loading A .....");
}
}
class B{
static {
System.out.println("静态域 B .....");
}
public B(){
System.out.println("构造B ...");
}
}
public class Load {
public static void main(String[] args){
System.out.println("类A加载前..");
new A();
System.out.println("类A加载后.. ");
System.out.println("--------------");
System.out.println("类B 反射加载前.. ");
// 从结果可以看出 Class.forName("xxx")
// 类加载了静态的成员和域 并未执行构造方法
try {
Class.forName("review_9_6.B");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println("类B 反射加载后.. ");
}
/*
output:类A加载前..
loading A .....
类A加载后..
--------------
类B 反射加载前..
静态域 B .....
类B 反射加载后..*/
}
这里再次指出,静态域和静态成员变量只会加载一次,并且存放于方法区中
Class.forName("xxx") 是Class(所有Class都属于这一个类 )的一个静态成员方法
案例二如下:
class InitA{
static final int I = 47;
static {
System.out.println("静态域InitA ");
}
}
class InitB{
static final int I = 47;
static {
System.out.println("静态域InitB ");
}
}
class InitC{
static int I = 48;
static {
System.out.println("静态域InitC ");
}
}
public class ClassInitTest {
public static void main(String[] args){
Class<InitA> initAClass = InitA.class;
System.out.println("InitA 加载后 --------");
System.out.println(InitA.I);
try {
Class.forName("review_9_6.InitB");
System.out.println("InitB 加载后 --------");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(InitC.I);
/* InitA 加载后 --------
47
静态域InitB
InitB 加载后 --------
静态域InitC
48*/
}
}
该案例说明: 类.class( ) 不会自动地初始化该Class对象 。
再有观察 InitA 和 InitC 可以发现的是, static final 修饰的 为 编译器常量,不需要对类进行初始化就能读取。
而如果只是一个static 而不是 final的如 InitC类所示,那么在对它访问时,被读取前要先进行链接(为这个域分配存储空间)和初始化(初始化该存储空间)。
案例3 invoke( )使用
public Object invoke(Object obj,
Object... args)
throws IllegalAccessException,
IllegalArgumentException,
InvocationTargetException
public class InvokeTest {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
List<String> mList = new ArrayList<>();
mList.add("aaa");
mList.add("bbb");
Class<? extends List> aClass = mList.getClass();
Method method = aClass.getMethod("add", Object.class);
// invoke为某个对象执行某个方法 args:代表参数列表
method.invoke(mList,1234);
System.out.println(mList);
}
/*[aaa, bbb, 1234]*/
}
这里 getMethod(x1,x2) x1 代表的是方法的字符串,x2代表的是方法的参数列表的类型类