• java反射(2)+Class.forName( )


    在上一篇文章中说说java反射(1)我们已经了解了反射的基本概念以及它的原理,但是我们知道反射只能能用它来做些什么呢?

             其实在我们很多已经很熟的框架中都有它的身影,例如Hibernate框架中的关联映射,Spring框架:IOC(控制反转).反射可以实现各种框架功能,接下来我们通过一个实例来写一个很小很小的框架,通过此例子来理解反射真正的价值所在.


            接下来的例子主要功能是通过java反射来获取配置文件中的信息.通过配置文件,在程序运行的时候实例化所需要的类型的实例.


             首先先建立一个资源文件,这里我们用config.properties来进行配置相关信息.

              config.properties文件内容如下:指定类型为ArrayList类型.

    1. ClassName=java.util.ArrayList  


              接下来建立一个反射测试类:


    1. package com.tgb.java;  
    2.   
    3. import java.io.FileInputStream;  
    4. import java.io.IOException;  
    5. import java.io.InputStream;  
    6. import java.util.Collection;  
    7. import java.util.Properties;  
    8.   
    9. /** 
    10.  * 通过一个小例子来演示通过反射技术实现一个简单的框架. 
    11.  *  
    12.  * @author jnqqls 
    13.  * @group TGB 
    14.  * @version 1.0 
    15.  *  
    16.  * @comments 
    17.  */  
    18. public class ReflectTest {  
    19.   
    20.     /** 
    21.      * @param args 
    22.      * @throws IOException 
    23.      * @throws ClassNotFoundException 
    24.      * @throws IllegalAccessException 
    25.      * @throws InstantiationException 
    26.      */  
    27.     public static void main(String[] args) throws IOException,  
    28.             InstantiationException, IllegalAccessException,  
    29.             ClassNotFoundException {  
    30.   
    31.   
    32.         // 将文件读入数据流  
    33.         InputStream ipt = new FileInputStream("config.properties");  
    34.         // 创建Properties对象  
    35.         Properties ppt = new Properties();  
    36.         // 将数据流载入到ppt对象中.  
    37.         ppt.load(ipt);  
    38.         // 关闭占用资源.  
    39.         ipt.close();  
    40.   
    41.         // 获取配置文件中的名字.  
    42.         String className = ppt.getProperty("ClassName");  
    43.         // 通过反射创建className所对应的类的一个实例.  
    44.         @SuppressWarnings("unchecked")  
    45.         Collection<String> collections = (Collection<String>) Class.forName(  
    46.                 className).newInstance();  
    47.         collections.add(new String("a"));  
    48.         collections.add(new String("b"));  
    49.         System.out.println(collections.size());  
    50.   
    51.     }  
    52. }  

     

              通过测试,输出的数字为2.也就是集合中有两个对象.这里和我们通常的new是不一样的概念,我们的例子是在运行时所创建的对象,而我们常用的new是在编译的时候所生成的对象,因为可以配置我们想要的类型和生成的对象,这便为各种框架提高了支撑.

              现在对框架有了一个最简单的例子,通过对反射有了一定的了解便会更进一步的了解Spring框架,对于Spring框架的铺垫就是这些.接下来会继续介绍Spring框架的使用.


    Class.forName( )静态方法的目的是为了动态加载类。在加载完成后,一般还要调用Class下的newInstance( )静态方法来实例化对象以便操作。因此,Class.forName( )是动态加载类是没有用的,其最终目的是为了实例化对象。调用 forName("X") 将导致命名为 X 的类被初始化。


    01 package com.java.jvm;
    02  
    03 public class ClassTest {
    04      public  static void main(String[] arg){
    05          try {
    06              Class  userClass = Class.forName("com.java.jvm.User");
    07              System.out.println("userClass="+userClass);
    08              User user = (User) userClass.newInstance();
    09              System.out.println("user="+user);
    10         catch (ClassNotFoundException e) {
    11             e.printStackTrace();
    12         catch (InstantiationException e) {
    13             e.printStackTrace();
    14         catch (IllegalAccessException e) {
    15             e.printStackTrace();
    16         }
    17       }
    18 }
    打印结果:



    1 userClass=class com.java.jvm.User
    2 user=User [name=null, age=null, address=null]
     Class.forName("")返回的是类(Class) 
     Class.forName("").newInstance()返回的是object 其实和new 的关键字作用相同。


    调用 forName("X") 将导致命名为 X 的类被初始化,这句话是官网API上的一句话,很迷茫,有点不理解,所以在User类中,添加了static语句块和User构造函数


    01 package com.java.jvm;
    02  
    03 public class User {
    04      
    05     static{
    06         System.out.println("static ---");
    07     }
    08      
    09     public User(){
    10         System.out.println("name="+name);
    11         name="xiaotian";
    12     }
    13      
    14     private String name;
    15     private Integer age;
    16     private String address;
    17      
    18     public String getName() {
    19         return name;
    20     }
    21     public void setName(String name) {
    22         this.name = name;
    23     }
    24     public Integer getAge() {
    25         return age;
    26     }
    27     public void setAge(Integer age) {
    28         this.age = age;
    29     }
    30     public String getAddress() {
    31         return address;
    32     }
    33     public void setAddress(String address) {
    34         this.address = address;
    35     }
    36     @Override
    37     public String toString() {
    38         return "User [name=" + name + ", age=" + age + ", address=" + address
    39                 "]";
    40     }
    41      
    42 }
    结果打印:
    1 static ---
    2 userClass=class com.java.jvm.User
    3 name=null
    4 user=User [name=xiaotian, age=null, address=null]


    forName("X") 执行的时候,调用了User中的静态语句块,newInstance()执行的时候调用了构造函数。

    连接数据库的简单代码


    01 // 驱动程序名
    02            String driver = "com.mysql.jdbc.Driver";
    03  
    04            // URL指向要访问的数据库名student
    05            String url = "jdbc:mysql://127.0.0.1:3306/student";
    06  
    07            // MySQL配置时的用户名
    08            String user = "root";
    09  
    10            // MySQL配置时的密码
    11            String password = "root";
    12  
    13            try {
    14             // 加载驱动程序
    15             Class.forName(driver);
    16  
    17             // 连续数据库
    18             Connection conn = DriverManager.getConnection(url, user, password);
    19  
    20             if(!conn.isClosed())
    21              System.out.println("Succeeded connecting to the Database!");
    22  
    23             // statement用来执行SQL语句
    24             Statement statement = conn.createStatement();
    25  
    26             // 要执行的SQL语句
    27             String sql = "select * from student";
    28  
    29             // 结果集
    30             ResultSet rs = statement.executeQuery(sql);
    其中加载数据库驱动
    Class.forName(driver);加载mysql驱动,执行static语句块,使将Driver对象注册到DriverManager中,然后上面就获得了数据库连接


    01 package com.mysql.jdbc  
    02   
    03 public class Driver extends NonRegisteringDriver implements java.sql.Driver {  
    04 // ~ Static fields/initializers  
    05 // --------------------------------------------- //   A
    06 // Register ourselves with the DriverManager  
    07 //  
    08 static {  
    09      t ry {   //使将Driver对象注册到DriverManager中
    10                java.sql.DriverManager.registerDriver(new Driver());  
    11            catch (SQLException E) {  
    12               throw new RuntimeException("Can't register driver!");  
    13            }  
    14    }  
    15 // ~ Constructors  
    16 // -----------------------------------------------------------  
    17 /**
    18    * Construct a new driver and register it with DriverManager
    19    *
    20    * @throws SQLException
    21    *              if a database error occurs.
    22    */ 
    23 public Driver() throws SQLException {  
    24      // Required for Class.forName().newInstance()  
    25 }  
    26 }



              

  • 相关阅读:
    2.5星|《无条件增长》:管理学常识+一些自己的管理案例
    3.5星|《壹棉壹世界》:棉花引发罪恶的黑奴贸易,影响美国南北战争
    只运行一个exe应用程序的使用案例
    WPF中使用WPFMediaKit视频截图案例
    Meta http-equiv属性详解
    层级数据模板 案例(HierarchicalDataTemplateWindow)
    ApplicationCommands 应用程序常见命令
    mvvm command的使用案例
    MatserDetail自动展开
    键盘焦点和逻辑焦点(Logic Focus与Keyboard Focus )
  • 原文地址:https://www.cnblogs.com/baoendemao/p/3804804.html
Copyright © 2020-2023  润新知