打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
JAVA反射基础

能够分析类能力的程序被称为反射(reflective)。


反射是一种功能强大且复杂的机制,使用它的主要对象是工具构造者。如果你编写的程序必须要与编译时未知的类一起工作,如有可能,就应该仅仅使用反射机制来实例化对象,而访问对象时则使用编译时已知的某个接口或者超类。(读者:比如在抽象工厂设计模式中,在编译的时候你并不知道将来要用到哪一个类,所以应该使用反射机制根据输入条件或者配置文件来实例化对象,但是在代码的其余部分中,你并不需要直接和这个类打交道,而是可以访问这个类的超类或者是这个类实现的某个接口,这样就使得代码具有相当的灵活性比如你要实例化类java.util.TreeSet,你可以这样使用:

Java代码
 
  1. Set<String> s = (Set<String>) Class.forName("java.util.TreeSet")   
  2.                     .newInstance();  
 

先说Class类,获得Class对象三种方法,一是Class e1 = e.getClass(); 二是Class.forName("java.util.Date"), 括号中的类名是完整名(包括包名), 三是Class cl1 = Date.class; Class cl2 = int.class;

一个Class对象实际上表示的是一个类型,而这个类型未必是一种类,如它可以是一个int类型,int.class代表一个Class类型的对象。比如:

Java代码
 
  1. int[] ia = new int[3];   
  2. int[] ib = new int[6];   
  3. // true   
  4. System.out.println(ia.getClass() == ib.getClass());  

 因为ia和ib都是int类型,所以它们返回相同的Class类型。

 

我们一般使用JDBC连接mysql数据库时,代码是这样的

 

Java代码
 
  1. Class.forName("com.mysql.jdbc.Driver"); // 注册驱动   
  2. Connection conn = DriverManager.getConnection(   
  3.                     "jdbc:mysql://localhost:3306/test""root""pass"); // 获得连接对象   
  4.    

 那么Class.forName("")到底做了什么呢?返回与带有给定字符串名的类或接口相关联的 Class 对象。调用此方法等效于

Java代码
 
  1. Class.forName(className, true, currentLoader)   

其中 currentLoader 表示当前类的定义类加载器,调用 forName("X") 将导致命名为 X 的类被初始化。接着我们看看com.mysql.jdbc.Driver的代码:

Java代码
 
  1. public class Driver extends NonRegisteringDriver implements java.sql.Driver {   
  2.     // ~ Static fields/initializers   
  3.     // Register ourselves with the DriverManager   
  4.     static {   (这是静态初始化代码
  5.         try {   
  6.             java.sql.DriverManager.registerDriver(new Driver());   
  7.         } catch (SQLException E) {   
  8.             throw new RuntimeException("Can't register driver!");   
  9.         }   
  10.     }   
  11.   
  12.     /**  
  13.      * Construct a new driver and register it with DriverManager  
  14.      *   
  15.      * @throws SQLException  
  16.      *             if a database error occurs.  
  17.      */  
  18.     public Driver() throws SQLException {   
  19.         // Required for Class.forName().newInstance()   
  20.     }   
  21. }   

 在初始化类Driver时,静态块中的代码会被执行

Java代码
 
  1. java.sql.DriverManager.registerDriver(new Driver());  
 

  于是Driver类被注册到DriverManager中,接着就可以建立连接。

 

Class类还有一个很有用的方法newInstance(),可以用来快速的创建一个类的实例。newInstance()方法需要一个默认的构造器来初始化创建的对象。可以参考一个例子(取自effective java 2):

 

Java代码
 
  1. import java.util.Arrays;   
  2. import java.util.Set;   
  3.   
  4. /**  
  5.  * 参数列表  
  6.  * java.util.TreeSet        
  7.  * qwe  
  8.  * asd  
  9.  * sdf  
  10.  * asw  
  11.  * zza  
  12.  * asq   
  13.  * aqw  
  14.  */  
  15. public class SetTest {   
  16.     @SuppressWarnings("unchecked")   
  17.     public static void main(String[] args) {   
  18.         Class<?> cl = null;   
  19.         try {   
  20.             cl = Class.forName(args[0]);   
  21.         } catch (ClassNotFoundException e) {   
  22.             e.printStackTrace();   
  23.             System.exit(1);   
  24.         }   
  25.         Set<String> s = null;   
  26.         try {   
  27.             s = (Set<String>) cl.newInstance();   
  28.         } catch (InstantiationException e) {   
  29.             e.printStackTrace();   
  30.             System.exit(1);   
  31.         } catch (IllegalAccessException e) {   
  32.             e.printStackTrace();   
  33.             System.exit(1);   
  34.         }   
  35.         s.addAll(Arrays.asList(args).subList(1, args.length));   
  36.         System.out.println(s);   
  37.     }   
  38. }   
  39. //输出: [aqw, asd, asq, asw, qwe, sdf, zxc, zza]  

 

 

 

在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中:

Class类:代表一个类。

Field 类:代表类的成员变量(成员变量也称为类的属性)。

Method类:代表类的方法。

Constructor 类:代表类的构造器。

Array类:提供了动态创建数组,以及访问数组的元素的静态方法


在core java卷一种介绍了反射的几种用法:

1、利用反射分析类的能力

2、在运行时使用反射分析对象

3、使用反射编写泛型数组代码


这里不贴代码了,事实上看看书也就基本了解反射的基础了,要熟悉一些常用的API运用。


假设有一个某一类型的数组已经填满,现在希望扩展它的长度,自动扩展。

Java代码
 
  1. Class cl = a.getClass();   
  2.       if (!cl.isArray()) return null;   
  3.       Class componentType = cl.getComponentType();   
  4.       int length = Array.getLength(a);   
  5.       // 扩展的长度(根据需要扩展)   
  6.       int newLength = length * 11 / 10 + 10;   
  7.   
  8.       Object newArray = Array.newInstance(componentType, newLength);   
  9.       System.arraycopy(a, 0, newArray, 0, length);   
  10.       return newArray;  
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Java反射
吊打面试官系列:说说反射的用途及实现?
使用JDBC时Class.forName()的作用 - 达观.平和 - JavaEye技术...
Class.forName和ClassLoader.loadClass区别
在Java的反射中,Class.forName和ClassLoader的区别
java中class.forName和classLoader加载类的区分
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服