在上一篇文章中说说java反射(1)我们已经了解了反射的基本概念以及它的原理,但是我们知道反射只能能用它来做些什么呢?
其实在我们很多已经很熟的框架中都有它的身影,例如Hibernate框架中的关联映射,Spring框架:IOC(控制反转).反射可以实现各种框架功能,接下来我们通过一个实例来写一个很小很小的框架,通过此例子来理解反射真正的价值所在.
接下来的例子主要功能是通过java反射来获取配置文件中的信息.通过配置文件,在程序运行的时候实例化所需要的类型的实例.
首先先建立一个资源文件,这里我们用config.properties来进行配置相关信息.
config.properties文件内容如下:指定类型为ArrayList类型.
-
ClassName=java.util.ArrayList
接下来建立一个反射测试类:
-
package com.tgb.java;
-
-
import java.io.FileInputStream;
-
import java.io.IOException;
-
import java.io.InputStream;
-
import java.util.Collection;
-
import java.util.Properties;
-
-
-
-
-
-
-
-
-
-
-
public class ReflectTest {
-
-
-
-
-
-
-
-
-
public static void main(String[] args) throws IOException,
-
InstantiationException, IllegalAccessException,
-
ClassNotFoundException {
-
-
-
-
InputStream ipt = new FileInputStream("config.properties");
-
-
Properties ppt = new Properties();
-
-
ppt.load(ipt);
-
-
ipt.close();
-
-
-
String className = ppt.getProperty("ClassName");
-
-
@SuppressWarnings("unchecked")
-
Collection<String> collections = (Collection<String>) Class.forName(
-
className).newInstance();
-
collections.add(new String("a"));
-
collections.add(new String("b"));
-
System.out.println(collections.size());
-
-
}
-
}
通过测试,输出的数字为2.也就是集合中有两个对象.这里和我们通常的new是不一样的概念,我们的例子是在运行时所创建的对象,而我们常用的new是在编译的时候所生成的对象,因为可以配置我们想要的类型和生成的对象,这便为各种框架提高了支撑.
现在对框架有了一个最简单的例子,通过对反射有了一定的了解便会更进一步的了解Spring框架,对于Spring框架的铺垫就是这些.接下来会继续介绍Spring框架的使用.
Class.forName( )静态方法的目的是为了动态加载类。在加载完成后,一般还要调用Class下的newInstance( )静态方法来实例化对象以便操作。因此,Class.forName( )是动态加载类是没有用的,其最终目的是为了实例化对象。调用 forName("X") 将导致命名为 X 的类被初始化。
03 |
public class ClassTest
{ |
04 |
public static void main(String[]
arg){ |
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) { |
12 |
} catch (InstantiationException
e) { |
14 |
} catch (IllegalAccessException
e) { |
打印结果:
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构造函数
06 |
System.out.println( "static
---" ); |
10 |
System.out.println( "name=" +name); |
16 |
private String
address; |
18 |
public String
getName() { |
21 |
public void setName(String
name) { |
24 |
public Integer
getAge() { |
27 |
public void setAge(Integer
age) { |
30 |
public String
getAddress() { |
33 |
public void setAddress(String
address) { |
34 |
this .address
= address; |
37 |
public String
toString() { |
38 |
return "User
[name=" +
name + ",
age=" +
age + ",
address=" +
address |
结果打印:
2 |
userClass= class com.java.jvm.User |
4 |
user=User
[name=xiaotian, age= null ,
address= null ] |
forName("X") 执行的时候,调用了User中的静态语句块,newInstance()执行的时候调用了构造函数。
连接数据库的简单代码
02 |
String
driver = "com.mysql.jdbc.Driver" ; |
05 |
String
url = "jdbc:mysql://127.0.0.1:3306/student" ; |
11 |
String
password = "root" ; |
15 |
Class.forName(driver); |
18 |
Connection
conn = DriverManager.getConnection(url, user, password); |
21 |
System.out.println( "Succeeded
connecting to the Database!" ); |
24 |
Statement
statement = conn.createStatement(); |
27 |
String
sql = "select
* from student" ; |
30 |
ResultSet
rs = statement.executeQuery(sql); |
其中加载数据库驱动
Class.forName(driver);加载mysql驱动,执行static语句块,使将Driver对象注册到DriverManager中,然后上面就获得了数据库连接
01 |
package com.mysql.jdbc |
03 |
public class Driver extends NonRegisteringDriver implements java.sql.Driver
{ |
10 |
java.sql.DriverManager.registerDriver( new Driver()); |
11 |
} catch (SQLException
E) { |
12 |
throw new RuntimeException( "Can't
register driver!" ); |
18 |
*
Construct a new driver and register it with DriverManager |
20 |
*
@throws SQLException |
21 |
*
if a database error occurs. |
23 |
public Driver() throws SQLException
{ |