`
gel543626548
  • 浏览: 3523 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Class.forName的含义

阅读更多
Class.forName(xxx.xx.xx) 返回的是一个类, .newInstance() 后才创建一个对象 Class.forName(xxx.xx.xx);的作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的静态代码段

Class aClass = Class.forName(xxx.xx.xx);
Object anInstance = aClass.newInstance();


Class.forName("").newInstance()返回的是object
but there is some limit for this method to create instance
that is your class constructor should no contain parameters, and you should cast the instance manually.

Class Driver{
protected static Driver current;
public static Driver getDriver(){
return current;
}
}

Class MyDriver extends Driver{
static{
Driver.current=new MyDriver();
}
MyDriver(){}
}

用时:
Class.forName("MyDriver");
Driver d=Driver.getDriver();

有的jdbc连接数据库的写法里是Class.forName(xxx.xx.xx);而有一些:Class.forName(xxx.xx.xx).newInstance(),为什么会有这两种写法呢?

Class.forName(xxx.xx.xx) 返回的是一个类,
.newInstance() 后才创建一个对象

Class.forName(xxx.xx.xx);的作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的静态代码段

在JDBC规范中明确要求这个Driver类必须向DriverManager注册自己,即任何一个JDBC Driver的Driver类的代码都必须类似如下:
public class MyJDBCDriver implements Driver {
static {
DriverManager.registerDriver(new MyJDBCDriver());
}
}

所以我们在使用JDBC时只需要Class.forName(XXX.XXX);就可以了

we just want to load the driver to jvm only, but not need to user the instance of driver, so call Class.forName(xxx.xx.xx) is enough, if you call Class.forName(xxx.xx.xx).newInstance(), the result will same as calling Class.forName(xxx.xx.xx), because Class.forName(xxx.xx.xx).newInstance() will load driver first, and then create instance, but the instacne you will never use in usual, so you need not to create it.

在JDBC驱动中,有一块静态代码,也叫静态初始化块,它执行的时间是当class调入到内存中就执行(你可以想像成,当类调用到内存后就执行一个方法)。所以很多人把jdbc driver调入到内存中,再实例化对象是没有意义的。


Class clazz = Class.forName("XXX.XXX");

ClassLoader cl = Thread.currentThread().getContextClassLoader();
Class clazz = cl.loadClass("XXX.XXX");
都可以装载一个类那么他们的区别是什么呢?
进一步研究Class.forName()是调用
Class.forName(name, initialize, loader);也就是Class.forName("XXX.XXX"); 等同与Class.forName("XXX.XXX", true, CALLCLASS.class.getClassLoader());

第二次参数表示装载类的时候是否初始化该类, 即调用类的静态块的语句及初始化静态成员变量。

Class clazz = cl.loadClass("XXX.XXX");没有指定是否初始化的选项。只有执行clazz.newInstance();时才能够初始化类。可以说Class.forName("XXX.XXX", false, cl)执行过程是一致的。只是ClassLoader.loadClass()是更底层的操作。

看一下JDBC驱动的装载。
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbcurl");
当调用Class.forName("com.mysql.jdbc.Driver");是Driver已经被初始化并注册到DriverManager中。MySQL Driver的代码
public class Driver extends NonRegisteringDriver
     implements java.sql.Driver
{

     public Driver()
         throws SQLException
     {
     }

     static
     {
         try
         {
             DriverManager.registerDriver(new Driver());
         }
         catch(SQLException E)
         {
             throw new RuntimeException("Can't register driver!");
         }
     }
}
改修JDBC驱动的装载
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Class clazz = cl.loadClass("com.mysql.jdbc.Driver");
clazz.newInstance();
Connection conn = DriverManager.getConnection("jdbcurl");
同样可以执行。但是这样就多构造了一个com.mysql.jdbc.Driver实例。同Class.forName("com.mysql.jdbc.Driver").newInstance()是一样的。是没有任何意义的。


类名.class是Class对象的句柄,每个被加载的类,在jvm中都会有一个Class对象与之相对应,如果要创建新的对象,直接使用Class对象的局部class.forName就可以了,不需要用new       类名。


在java中,每个class都有一个相应的Class对象,当编写好一个类,编译完成后,在生成的.class文件中,就产生一个class对象,用来表示这个类的类型信息。获得Class实例的三中方式:
1.利用对象调用getClass()方法获取该对象的Class实例
2.使用Class的静态方法forName(),用类的名字获取一个Class实例
3.运用.calss的方式获取Class实例,对基本数据类型的封装类,还可以采用.TYPE来获取对应的基本数据类型的Class实例

calss ClassTest
{
                public static void main(String[] args)
                {
                        /*
                        //利用对象调用getClass()方法获取该对象的Class实例
                        Point pt=new Point();               
                        Class c1=pt.getClass();
                        System.out.println(c1.getName());                        //结果:Point
               
                        //使用Class的静态方法forName(),用类的名字获取一个Class实例
                        try
                        {
                                Class c2=Class.forName("Point");
                                System.out.println(c2.getName());                //结果:Point
                        }
                        catch(Exception e)
                        {
                                e.printStackTrace();
                        }

                        //运用.calss的方式获取Class实例(类)
                        Class c3=Point.calss;
                        System.out.println(c3.getName());                        //结果:Point

                        //运用.calss的方式获取Class实例(基本类型)
                        Class c4=int.calss;
                        System.out.println(c4.getName());                        //结果:int

                        //运用.calss的方式获取Class实例(基本数据类型的封装类)
                        Class c5=Integer.TYPE;
                        System.out.println(c5.getName());                        //结果:int
               
                        Class c6=Integer.class;
                        System.out.println(c6.getName());                        //结果:java.lang.Integer
                        */
               
                        //以下结果是:          before new Point()
                                        loading point
                                        after new Point()
                                        loading Line       
                        //当new Point()的时候加载这个类,用forName构造实例的时候也加载该类。
                        System.out.println("before new Point()");
                        new Point();
                        System.out.println("after new Point()");

                        try
                        {
                                Class.forName("Line");
                        }catch(Exception e)
                        {
                                e.printStackTrace();
                        }
               
                }
}
class Point()
{
                static
                {
                        System.out.println("loading point");
                }
                int x,y;
}
class Line
{
                static
                {
                        System.out.println("loading Line");
                }
}

在运行期间,如果我们要产生某个类的对象,java虚拟机会检测该类型的Class对象是否已被加载。如果没有加载,java虚拟机会根据类的名称找到.class文件并加载它。一旦某个类型的Class对象已经被加载到内存,就可以用它来产生该类型的所有对象。
newInstance()调用内中缺省的构造方法。

newInstance()调用类中缺省的构造方法,如果要实例的对象中有了自己定义的构造方法(除重写的和默认构造方法相同的构造方法外)
创建此 Class 对象所表示的类的一个新实例
class ClassTest
{
               public static void main(String[] args)
               {
                       if(args.length!=1)
                       {
                               System.out.println("args.length!=1");
                               return;
                       }
                       try
                       {
                               Class c=Class.forName(args[0]);
                               Point pt=(Point)c.newInstance();
                               pt.output();
                       }catch(Exception e)
                       {
                               e.printStackTrace();
                       }
               }
}
class Point
{
               int x;
               int y;
               static
               {
                       System.out.println("Loading point");
               }
               void output()
               {
                       System.out.println("x="+x+",y="+y);
               }
}
当我们在命令提示符下面编译好该类之后,输入java ClassTest Point的时候,此时会输出Loading point和x=0,y=0


Class clazz = Class.forName("XXX.XXX");

ClassLoader cl = Thread.currentThread().getContextClassLoader();
Class clazz = cl.loadClass("XXX.XXX");
都可以装载一个类那么他们的区别是什么呢?
进一步研究Class.forName()是调用
Class.forName(name, initialize, loader);也就是Class.forName("XXX.XXX"); 等同与Class.forName("XXX.XXX", true, CALLCLASS.class.getClassLoader());

第二次参数表示装载类的时候是否初始化该类, 即调用类的静态块的语句及初始化静态成员变量。

Class clazz = cl.loadClass("XXX.XXX");没有指定是否初始化的选项。只有执行clazz.newInstance();时才能够初始化类。可以说Class.forName("XXX.XXX", false, cl)执行过程是一致的。只是ClassLoader.loadClass()是更底层的操作。

看一下JDBC驱动的装载。
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbcurl");
当调用Class.forName("com.mysql.jdbc.Driver");是Driver已经被初始化并注册到DriverManager中。MySQL Driver的代码
public class Driver extends NonRegisteringDriver
          implements java.sql.Driver
{

          public Driver()
              throws SQLException
          {
          }

          static
          {
              try
              {
                  DriverManager.registerDriver(new Driver());
              }
              catch(SQLException E)
              {
                  throw new RuntimeException("Can't register driver!");
              }
          }
}
改修JDBC驱动的装载
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Class clazz = cl.loadClass("com.mysql.jdbc.Driver");
clazz.newInstance();
Connection conn = DriverManager.getConnection("jdbcurl");
同样可以执行。但是这样就多构造了一个com.mysql.jdbc.Driver实例。同Class.forName("com.mysql.jdbc.Driver").newInstance()是一样的。是没有任何意义的。

分享到:
评论

相关推荐

    Log4j日志管理系统简单使用说明

     log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class  log4j.appender.appenderName.layout.option1 = value1  …  log4j.appender.appenderName.layout.option = valueN    以上是...

    二十三种设计模式【PDF版】

    主要是介绍各种格式流行的软件设计模式,对于程序员的进一步提升起推进作用,有时间可以随便翻翻~~ 23种设计模式汇集 如果你还不了解设计模式是什么的话? 那就先看设计模式引言 ! 学习 GoF 设计模式的重要性 ...

    jpivot学习总结.doc

    providerClass 否 String 是 如果存在该属性,这个类的实例将会从当前的 member 中获取 SessionParam 对象的实例,这里的类必须实现 com.tonbeller.jpivot.table.navi.ClickableMember.ParameterProvider 接口。...

    新版Android开发教程.rar

    蓝牙 (class 1) ;四频 (850 , 900 , 1800 , 1900) ;支持 3G , 802.11b 和 802.11g 。----------------------------------- Android 编程基础 5 互联网 支持 HTTP 、 WAP Push 和 xHTML ;支持 POP 、 IMAP 、 ...

    oracle数据库经典题目

    20. 在定义游标时使用的FOR UPDATE子句的作用是______。( C ) A.执行游标 B. 执行SQL语句的UPDATE语句 C.对要更新表的列进行加锁 D. 都不对 21. 如果允许用户对视图进行更新和插入操作,但是又要防止用户将不...

    freemarker总结

    sort_by(name) 表示所有的user按user.name进行排序 hashes内置方法 hash?keys 返回hash里的所有keys, 返回结果类型sequence hash?values 返回hash里的所有value, 返回结果类型sequence 模板 使用FTL(freeMarker...

    java 混淆工具,不可逆 jocky 也许是最好的了

    但笔者强烈建议: 针对这些有特殊含义不能够被混淆的 private级别的方法或者字段,请以@preserve指令予以保护。 注1:建议通过IDE的JavaDoc设置,来辅助@preserve指令的书写。 三、Jocky的限制 正如前文所说,...

    2009 达内Unix学习笔记

    二、特殊字符含义 文件名以“.”开头的都是隐藏文件/目录,只需在文件/目录名前加“.”就可隐藏它。 ~/ 表示主目录。 ./ 当前目录(一个点)。 ../ 上一级目录(两个点)。 ; 多个命令一起用。 > >> 输出重定向...

    joc eclipse plugin

    Java Obfuscate Compiler Kit for You 一、前言 1.1 什么是Jocky? 我们知道,Java是一种跨平台的编程语言,其源码(.java文件)被编译成与平台无关的字节码(.class文件),然后在运行期动态链接。这样,编译后的...

    jocky 混肴编译rar包(ant和插件俩个版本)

    Jocky混淆JAVA代码(保护你的JAVA项目) 一、前言 1.1 什么是Jocky? 我们知道,Java是一种跨平台的编程语言,其源码(.java文件)被编译成与平台无关的字节码(.class文件),然后...但笔者强烈建议: 针对这些有特殊含义不...

    java经典面试2010集锦100题(不看你后悔)

    D) Java语言中的多态的含义可以表达为:对外一个接口,内部多种实现。Java语言支持两种多态:运行时多态和编译时多态。 题目8:a 程序如下: public class Demo extends Base { private int count; public Demo()...

    基于JAVA的搜索引擎 lucene-2.2.0

    throw new LockObtainFailedException("Index locked for write: " + writeLock); this.writeLock = writeLock; // 重新保存写锁文件 try { if (create) { // 如果create为true,表示重写索引文件。重写索引...

    XML轻松学习手册--XML肯定是未来的发展趋势,不论是网页设计师还是网络程序员,都应该及时学习和了解

    #PCDATA, element-name 包含文本和其它子元素 (#PCDTATA,TITLE)> MYFILE元素必须包含文本和TITLE子元素 , 使用逗号分隔排序 (TITLE,AUTHOR,EMAIL)> MYFILE元素必须依次包含TITILE,AUTHOR,EMAIL三个子元素 | 使用"|...

    对组态王OPC服务器值的读取c#版本

    public partial class Form1 : Form { /// /// 与组态王建立连接 /// 每次应用程序启动时,必须用该函数与组态王建立连接 /// /// <param name="node">node为节点(IP),如果是本机,其值为空 /// 返回错误...

    一个java正则表达式工具类源代码.zip(内含Regexp.java文件)

    * [abc] a, b, or c (simple class) [abc] a, b, 或 c (简单字符串) * [^abc] Any character except a, b, or c (negation) [^abc] 除了 a, b, 或 c 之外的任意字符(否定) * [a-zA-Z] a ...

    代码语法错误分析工具pclint8.0

    2)在Name栏中输入“PC-lint ”,原则上这个名称可以随便起,只要你能搞清楚它的含义 就可以了。 3)在Run栏中输入“c:\lint\lint-nt -u -ic:\lint std env-si %f”其中c:\lint是你P C-LINT的安装目录。 4)...

    jquery插件使用方法大全

    jQuery就是如此强大,你可以轻易地找到DOM中的任何元素,而这也是jQuery设计之初query的真实含义(查询)。 编辑本段Jquery对象  jquery提供了很多便利的函数,如each(fn),但是使用这些函数的前提是:你使用的对象...

    LINGO软件的学习

    Setname是你选择的来标记集的名字,最好具有较强的可读性。集名字必须严格符合标准命名规则:以拉丁字母或下划线(_)为首字符,其后由拉丁字母(A—Z)、下划线、阿拉伯数字(0,1,…,9)组成的总长度不超过32个...

    java面试800题

    do, double, else, extends, final, finally, float, for, goto, if, implements, import, instanceof, int, interface, long, native, new, package, private, protected, public, return, short, static, strictfp...

    HGE_系列教材(1-9)

    HGE 系列教材(1) --- 简介 HGE 是一个硬件加速(Hardware accelerated)的2D 游戏引擎(Game Engine), HGE 是一个富有特性的中间件,可以用于开发任何类型的2D 游戏。HGE 封装性良好, 以至于你仅仅需要关系游戏...

Global site tag (gtag.js) - Google Analytics