zoukankan      html  css  js  c++  java
  • 理解class.forName()


    使用jdbc方式连接数据库时会使用一句代码Class.forName(String className).这句话是什么意思呢?首先说一点Class.forName(String className)这种方法的作用是装载className这个字符串指定的类。


    官方文档


    返回与带有给定字符串名的类或接口相关联的 Class 对象。调用此方法等效于:

      Class.forName(className, true, currentLoader)

     当中 currentLoader 表示此类的定义类载入器。

    比如,下面代码片段返回 java.lang.Thread 类的执行时 Class 描写叙述符。


       Class t = Class.forName("java.lang.Thread")

     调用 forName("X") 将导致名为 的类被初始化。


    參数:

    className - 所需类的全然限定名。

    返回:

    具有指定名的类的 Class 对象。


    通俗的说就是:获得字符串參数中指定的类,并初始化该类


    类装载


    类装载就是把一个类或是一个接口的字节码文件,通过解析该字节码来构建代表这个类或是这个接口的实例的过程。 这个字节码文件来源可能是压缩包、网络、执行时编译出的或者自己主动生成的class文件,jvm spec没有规定必须从什么地方载入。

    类装载的两种方式:

    1.Class c1 = Class.forName ("java.lang.String"); 

    2.ClassLoader cl = new  ClassLoader(); 

    Class cl.loadClass( String name, boolean resolve );


    两种装载方法的差别:


    不同的类装载器


      Class.forName是从指定的classloader中装载类,假设没有指定,也就是一个參数的时候,是从装载当前对象实例所在的classloader中装载类

      而ClassLoader的实例调用loadclass方法,是指从当前ClassLoader实例中调用类,而这个实例与装载当前所在类实例的Classloader或许不是同一个

          说白了就是他们实现装载的时候,使用的类装载器的指定是不同的。那为什么使用不同的ClassLoader来装载类呢?

          事实上使用多个classloader载入类的情况很常见,比方说我们的app server都是这种WebEJB他们的classLoader就是不同的,这样做的目的就是为了避免两者间类装载的相互干扰


    是否实例化类


          Class的装载分了三个阶段,loading(装载),linking(连接)和initializing(实例化)分别定义在The Java Language Specification12.212.312.4

     Class.forName(className)实际上是调用Class.forName(className, true, this.getClass().getClassLoader())。注意第二个參数,是指Classloading后是不是必须被初始化。

        ClassLoader.loadClass(className)实际上调用的是ClassLoader.loadClass(name, false),第二个參数指出Class是否被link

        差别就出来了。Class.forName(className)装载的class已经被实例化,而ClassLoader.loadClass(className)装载的class还没有被link,所以就更谈不上实例化了。

      普通情况下,这两个方法效果一样,都能装载Class。但假设程序须要Class实例化,就必须用Class.forName(name)了。

    比如,在JDBC中载入mysql的驱动类时(关于注冊jdbc驱动请參看另外一篇文章,jdbc注冊驱动的三种方式)Class.forName("com.mysql.jdbc.Driver"),假设换成getClass().getClassLoader().loadClass("com.mysql.jdbc.Driver"),就不行,由于它仅仅是向jvm装载了Driver并没有实例化,就不能运行响应的操作。

     打开com.mysql.jdbc.Driver的源码看看,

    //

    // Register ourselves with the DriverManager

    //

    static {

        try {

            java.sql.DriverManager.registerDriver(new Driver());

        } catch (SQLException E) {

            throw new RuntimeException("Can't register driver!");

        }

    }

    能够看到,Driverstatic块中会注冊自己到java.sql.DriverManager。而static块就是在Class的初始化中被运行。所以这个地方就仅仅能用Class.forName(className)


    资源


  • 相关阅读:
    【Codeforces 349B】Color the Fence
    【Codeforces 459D】Pashmak and Parmida's problem
    【Codeforces 467C】George and Job
    【Codeforces 161D】Distance in Tree
    【Codeforces 522A】Reposts
    【Codeforces 225C】Barcode
    【Codeforces 446A】DZY Loves Sequences
    【Codeforces 429B】Working out
    【Codeforces 478C】Table Decorations
    【Codeforces 478C】Table Decorations
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4065806.html
Copyright © 2011-2022 走看看