首页 > 编程语言 > 详细

《疯狂Java讲义》(三十六)---- 类加载机制与反射

时间:2017-02-23 18:46:45      阅读:156      评论:0      收藏:0      [点我收藏+]

  当使用Java命令运行某个程序时,该命令将会启动一个Java虚拟机进程,不管该Java程序多么复杂,该程序启动了多少线程,它们都处于该Java虚拟机进程里。同一个JVM的所有线程,所有变量都处于同一个进程里,他们都使用该JVM进程的内存区。当系统出现以下几种情况时,JVM进程将被终止:

  1. 程序运行到最后正常结束。
  2. 程序运行到使用System.exit()或Runtime.getRuntime().exit()代码出结束程序。
  3. 程序执行过程中遇到未捕获的异常或错误而结束。
  4. 程序所在平台强制结束了JVM进程。

  类加载指的是将类的class文件读入内存,并为之创建一个Class对象,也就是说,当程序中使用任何类时,系统都会为之建立一个Class对象。

  当程序主动使用某个类时,如果该类还未被加载到内存中,则系统会通过以下3个步骤来对类进行初始化。

  1. 加载
  2. 连接
  3. 初始化

  JVM初始化一个类包含以下步骤:

  1. 假如这个类还没有被加载和连接,则程序先加载并连接该类。
  2. 假如该类的直接父类还没有被初始化,则先初始化其直接父类。
  3. 假如类中有初始化语句,则系统依次执行这些初始化语句。

  JVM最先初始化的总是Object类。

 

  • 类加载器

  当JVM启动时,会形成由3个类加载器组成的初始类加载器层次结构:

  1. Bootstrap ClassLoader: 根类加载器
  2. Extension ClassLoader: 扩展类加载器
  3. System ClassLoader: 系统类加载器

  Bootstrap加载器被称为引导类加载器,它负责加载Java的核心类。

package com.ivy.reflection;

import java.net.URL;

public class BootstrapDemo {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();
        for(int i = 0; i < urls.length; i++) {
            System.out.println(urls[i].toExternalForm());
        }
    }

}

输出结果:

file:/C:/Program%20Files%20(x86)/Java/jdk1.7.0_45/jre/lib/resources.jar
file:/C:/Program%20Files%20(x86)/Java/jdk1.7.0_45/jre/lib/rt.jar
file:/C:/Program%20Files%20(x86)/Java/jdk1.7.0_45/jre/lib/sunrsasign.jar
file:/C:/Program%20Files%20(x86)/Java/jdk1.7.0_45/jre/lib/jsse.jar
file:/C:/Program%20Files%20(x86)/Java/jdk1.7.0_45/jre/lib/jce.jar
file:/C:/Program%20Files%20(x86)/Java/jdk1.7.0_45/jre/lib/charsets.jar
file:/C:/Program%20Files%20(x86)/Java/jdk1.7.0_45/jre/lib/jfr.jar
file:/C:/Program%20Files%20(x86)/Java/jdk1.7.0_45/jre/classes

 

  Extension负责加载JRE的扩展目录(%JAVA_HOME%/jre/lib/ext或者由java.ext.dirs系统属性指定的目录)中JAR包中的类。

  System类加载器负责在JVM启动时加载来自java命令的-classpath选项/java.class.path系统属性,或CLASSPATH环境变量所指的JAR包和类路径。

 

  URLClassLoader是ClassLoader的一个实现类,它既可以从本地文件系统获取二进制文件来加载类,也可以从远程主机获取二进制文件来加载类。

 

  •  通过反射查看类信息

获得Class对象的3种方式:

  1. Class.forName(String clazzName), clazzName必须是全限定名
  2. 调用某个类的class属性来获取该类对应的Class对象。
  3. 调用某个对象的getClass()方法

大部分时间使用第二种方式。

package com.ivy.reflection;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

@SuppressWarnings(value="unchecked")
@Deprecated
public class ClassDemo {

    private ClassDemo() {
        
    }
    
    public ClassDemo(String name) {
        System.out.println("constructor with param");
    }
    
    public void info() {
        System.out.println("method info without param");
    }
    
    public void info(String str) {
        System.out.println("method info with a param");
    }
    
    class Inner {
        
    }
    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub

        Class<ClassDemo> clazz = ClassDemo.class;
        Constructor[] ctors = clazz.getDeclaredConstructors();
        System.out.println("all constructors of ClassDemo : ");
        for (Constructor c : ctors) {
            System.out.println(c);
        }
        
        Constructor[] publicCtors = clazz.getConstructors();
        System.out.println("all public constructors of ClassDemo : ");
        for (Constructor c : publicCtors) {
            System.out.println(c);
        }
        
        Method[] mtds = clazz.getMethods();
        System.out.println("all public methods of ClassDemo : ");
        for (Method m : mtds) {
            System.out.println(m);
        }
        
        System.out.println("info method with a param in ClassDemo : " + clazz.getMethod("info", String.class));
        
        Annotation[] anns = clazz.getAnnotations();
        System.out.println("all annotations in ClassDemo : ");
        for (Annotation an : anns) {
            System.out.println(an);
        }
        
        System.out.println("@SuppressWarning comment in ClassDemo : " + clazz.getAnnotation(SuppressWarnings.class));
        
        Class<?>[] inners = clazz.getDeclaredClasses();
        System.out.println("all inner classes in ClassDemo : ");
        for (Class c : inners) {
            System.out.println(c);
        }
        
        Class inClazz = Class.forName("com.ivy.reflection.ClassDemo$Inner");
        System.out.println("inClazz outer class : " + inClazz.getDeclaringClass());
        System.out.println("ClassDemo package : " + clazz.getPackage());
        System.out.println("ClassDemo parent class : " + clazz.getSuperclass());
    }

}

 

  • 通过反射生成并操作对象

通过反射来生成对象有两种方式:

  1. 使用Class对象的newInstance()方法来创建该Class对象对应类的实例,这种方式要求该Class对象的对应类有默认构造器。(较常见)
  2. 使用Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance方法来创建实例。

 

《疯狂Java讲义》(三十六)---- 类加载机制与反射

原文:http://www.cnblogs.com/IvySue/p/6434684.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!