java基础知识巩固-----类加载机制与反射机制

一.类的加载、链接和初始化

1.当我们调用java命令运行某个java程序时,该命令将会启动一个java虚拟机进程,不管该java程序有多么复杂,该进程启动了多少个线程,他们都处于该JVM的进程里,同一个JVM的所有线程、所有变量都处于同一个进程里,他们都使用该JVM进程的内存区。

从上面的这句话中我们可以看出,java程序时运行在java虚拟机的内存区的,同时同一个main方法开始的java程序是运行在同一个java进程当中的,也就是说同一个main方法开始的java程序的所有资源都是存储在这个main方法对应的JVM进程内存区的,这里涉及到一个static资源的问题,举例说明一下:首先定义一个含有static资源的class:

public class Person{
  public static String name="张三";
  public void changeA(){
    Person.name="李四";
  }
}
public class  test1{
  public static void main(String[] args){
     Person p=new Person();
     p.changeA();
     System.out.println(Person.a);
   }
}

public class  test2{
  public static void main(String[] args){
     Person p=new Person();
     System.out.println(Person.name);
  }
}

两次运行结果:tes1的main方法运行结果是 李四,test2的main方法运行结果是 张三

问题所在:可能会有同志这样思考,name是static资源,是属于类的而不属于某一具体对象所以当第一次修改后第二次调用时应该变成李四了。然而奥秘之所在是执行了两个main方法,不同的main方法开始执行时会开启不同的JVM进程,不同的进程是有不同的进程内存区的,所以第二次运行时所有的资源都需要重新加载。

2.

2.1 在 1 中我们提到了资源加载,下面就开始说说类的加载问题:在一个JVM进程当中如果一个类是第一次被使用,那么JVM首先需要加载这个类,类加载指的是将一个类的class文件读入内存区,并为之创建一个java.lang.class对象,也就是说,当程序中使用任何类时,系统都会为之建立一个java.lang.class对象(注class对象中封装了这个类的相关信息,比如构造器、方法、类修饰符等,在反射中会有涉及)。

2.2 类的连接:当类被加载之后,系统为之生成一个对应的class对象,接着将会进入连接阶段,连接阶段负责吧类的二进制数据合并到jre(java runtime Everiment:java运行环境)中。

2.3类的初始化:类的初始化阶段主要负责初始化static资源。注:由于非静态资源是属于特定对象的,所以非静态资源是在运行到相应位置是才被初始化。比如非静态成员变量是在new对象是才被初始化。

二. 类的反射机制

从一我们知道,在JVM加载类的时候会为每个类创建一个class对象,这个class对象里封装了这个类的相关信息。有没有想过这样一个问题,在java编程中通常会有父类引用指向子类对象,也就是会有多态出现,(所谓多态就是当类型相同时在调用同一个方法时出现不同的结果),所以问题在于既然是相同类型的变量,那么JVM怎么知道是该引用指向那个对象呢,解决方案就是使用反射机制了,在运行期间JVM可以使用class对象提供的相关方法获取对应类的信息:

class对象大致提供了以下这些方法:

getClassLoader() 
获取该类的类装载器。 
getComponentType() 
如果当前类表示一个数组,则返回表示该数组组件的 Class 对象,否则返回 null。 
getConstructor(Class[]) 
返回当前 Class 对象表示的类的指定的公有构造子对象。 
getConstructors() 
返回当前 Class 对象表示的类的所有公有构造子对象数组。 
getDeclaredConstructor(Class[]) 
返回当前 Class 对象表示的类的指定已说明的一个构造子对象。 
getDeclaredConstructors() 
返回当前 Class 对象表示的类的所有已说明的构造子对象数组。 
getDeclaredField(String) 
返回当前 Class 对象表示的类或接口的指定已说明的一个域对象。 
getDeclaredFields() 
返回当前 Class 对象表示的类或接口的所有已说明的域对象数组。 
getDeclaredMethod(String, Class[]) 
返回当前 Class 对象表示的类或接口的指定已说明的一个方法对象。 
getDeclaredMethods() 
返回 Class 对象表示的类或接口的所有已说明的方法数组。 
getField(String) 
返回当前 Class 对象表示的类或接口的指定的公有成员域对象。 
getFields() 
返回当前 Class 对象表示的类或接口的所有可访问的公有域对象数组。 
getInterfaces() 
返回当前对象表示的类或接口实现的接口。 
getMethod(String, Class[]) 
返回当前 Class 对象表示的类或接口的指定的公有成员方法对象。 
getMethods() 
返回当前 Class 对象表示的类或接口的所有公有成员方法对象数组,包括已声明的和从父类继承的方法。 
getModifiers() 
返回该类或接口的 Java 语言修改器代码。 
getName() 
返回 Class 对象表示的类型(类、接口、数组或基类型)的完整路径名字符串。 
getResource(String) 
按指定名查找资源。 
getResourceAsStream(String) 
用给定名查找资源。 
getSigners() 
获取类标记。 
getSuperclass() 
如果此对象表示除 Object 外的任一类, 那么返回此对象的父类对象。 
isArray() 
如果 Class 对象表示一个数组则返回 true, 否则返回 false。 
isAssignableFrom(Class) 
判定 Class 对象表示的类或接口是否同参数指定的 Class 表示的类或接口相同,或是其父类。 
isInstance(Object) 
此方法是 Java 语言 instanceof 操作的动态等价方法。 
isInterface() 
判定指定的 Class 对象是否表示一个接口类型。 
isPrimitive() 
判定指定的 Class 对象是否表示一个 Java 的基类型。 
newInstance() 
创建类的新实例。 
toString() 
将对象转换为字符串。

   

   



猜你喜欢

转载自blog.csdn.net/qq_40400960/article/details/79545402