java中Class与Object及反射机制

来源:互联网 发布:动态效果图制作软件 编辑:程序博客网 时间:2024/06/05 09:11

转:http://blog.csdn.net/xingcaizxc/article/details/8786744 

平时看代码时,总是碰到这些即熟悉又陌生的名次,每天都与他们相见,但见面后又似曾没有任何的交集,所以今天我就来认识下这两个江湖侠客的背景:

CLASS

    在Java中,每个class都有一个相应的Class对象。也就是说,当我们编写一个类,编译完成后,在生成的.class文件中,就会产生一个Class对象,用于表示这个类的类型信息
获取Class实例的三种方式:
    (1)利用对象调用getClass()方法获取该对象的Class实例;
    (2)使用Class类的静态方法forName(),用类的名字获取一个Class实例(staticClass forName(String className) Returns the Classobject associated with the class or interface with the given stringname. );
    (3)运用.class的方式来获取Class实例,对于基本数据类型的封装类,还可以采用.TYPE来获取相对应的基本数据类型的Class实例
    在newInstance()调用类中缺省的构造方法 ObjectnewInstance()(可在不知该类的名字的时候,常见这个类的实例) Creates a new instance of the class represented by this Classobject.
    在运行期间,如果我们要产生某个类的对象,Java虚拟机(JVM)会检查该类型的Class对象是否已被加载。如果没有被加载,JVM会根据类的名称找到.class文件并加载它。一旦某个类型的Class对象已被加载到内存,就可以用它来产生该类型的所有对象

    Class对象的生成方式如下:

    1.Class.forName("类名字符串") (注意:类名字符串必须是全称,包名+类名);
    2.类名.class;
    3.实例对象.getClass();

[html] view plaincopy
  1. package baseJava;  
  2.   
  3. public class TestClass {  
  4.   
  5.     /**  
  6.      * @param args  
  7.      * 2013-4-11 上午10:30:05  
  8.      * @author zhao_xingcai  
  9.      */  
  10.     public static void main(String[] args) {  
  11.         // TODO Auto-generated method stub  
  12.         try {  
  13.           
  14.             //测试Class.forName()    
  15.             Class classForName = Class.forName("baseJava.TestClass");  
  16.             System.out.println("classForName  : [" + classForName + "]");  
  17.               
  18.             //测试类名.class  
  19.             Class classForName2 = TestClass.class;  
  20.             System.out.println("classForName2 : [" + classForName2 + "]");  
  21.               
  22.             //测试Object.getClass()   
  23.             TestClass newInstance = new TestClass();  
  24.             System.out.println("newInstance   : [" + newInstance.getClass() + "]");  
  25.               
  26.             //hashCode指的是内存的地址  
  27.             System.out.println("newInstanceHashCode   : [" + newInstance.hashCode() + "]");  
  28.               
  29.             //toString代表该对象的一个字符串  
  30.             //格式:this.getClass().getName() + '@' + Integer.toHexString(hashCode())  
  31.             System.out.println("newInstanceToString   : [" + newInstance.toString() + "]");  
  32.               
  33.               
  34.         }catch (ClassNotFoundException e) {  
  35.             e.printStackTrace();  
  36.         }  
  37.     }  
  38.     /*  
  39.      * 构造函数  
  40.      */  
  41.     public TestClass() {  
  42.         System.out.println(" 构造函数");  
  43.     }  
  44.       
  45.     /*  
  46.      * 静态的参数初始化    
  47.      */  
  48.     static {  
  49.         System.out.println("静态的参数初始化  ");  
  50.     }  
  51.       
  52.     /*  
  53.      * 非静态的参数初始化    
  54.      */  
  55.     {  
  56.         System.out.println("非静态的参数初始化  ");  
  57.     }  
  58.   
  59. }  



运行结果如下:

静态的参数初始化  
classForName  : [class baseJava.TestClass]
classForName2 : [class baseJava.TestClass]
非静态的参数初始化  
 构造函数
newInstance   : [class baseJava.TestClass]
newInstanceHashCode   : [12677476]
newInstanceToString   : [baseJava.TestClass@c17164]

    也就是说:

    三种方法生成CLASS对象是一样的,因为CLASS在JVM的名称是一样的,但是三种生成的方法略有不同:静态的方法属性初始化,是在加载类的时候初始化。而非静态方法属性初始化,是new类实例对象的时候加载。当我们编写一个新的JAVA类时,JVM就会帮我们编译成CLASS对象,存放在同名的.class文件中,在运行时,当需要生成这个类的对象时,JVM就会检查此类是否装载到内存中,会没有装载,就把.class装载到内存中,若装载过,则根据.class生成对象。

OBJECT对象

    在Java中有这样一个类,它是所有类的祖先,任何类都是其子孙类,它就是java.lang.Object,如果一个类没有显式地指明其父类,那么它的父类就是Object。如同我们称自己为炎黄子孙一样,所有的类都可以称为Object子孙,^_^。在java中除了基本型别(数字、字符、布尔值,primitive type)不是对象之外,其它的均为对象(class type)。那么,这个Object到底给我们留下了什么“遗产”呢?下面将从最基本的讲起:

    1.  public boolean equals(Object obj).

    所有的类均可以按照自己的需要对equals方法进行覆盖,顾名思义,这个方法可用来比较两个对象是否“相等”,至于什么才叫“相等”,各个类可以根据自己的情况与需要自行定义。例如String,就是要求两个对象所代表的字符串值相等,而对于一个雇员类(Employee),则可能是要求姓名、年龄、工资等一样才算是“相等”。尽管不同的类有不同的规则,但是有一条规则却是公用的,它就是:如果两个对象是“一样”(identical)的,那么它们必然是“相等”(equals)的。那么什么才叫“一样”?如果a==b,我们就说a和b是“一样的”,即a和b指向(refer to)同一个对象。Object类中的equals方法实施的就是这一条比较原则,对任意非空的指引值a和b,当且仅当a和b指向同一个对象时才返回true。

    2.  public int hashCode()

    每个类都可以复写Object类中的hashCode方法,Object类中的hashCode方法就是简单

地将对象在内存中的地址转换成int返回。这样,如果一个类没有复写hashCode方法,那么它的hashCode方法就是简单地返回对象在内存中的地址。在JDK中,对hashCode也定义了一系列约束,其中有一条就是如果两个对象是“equal”的,那么它们的hashCode方法返回的整数值必须相同,但是如果两个对象是“unequal”,那么hashCode方法的返回值不一定必须不同。正因为这个约束,我们如果复写了equals()方法,一般也要复写hashCode方法。
    3.public String toString()

    toString方法是一个从字面上就容易理解的方法,它的功能是得到一个能够代表该对象的一个字符串,Object类中的toString方法就是得到这样的一个字符串:this.getClass().getName() + '@' + Integer.toHexString(hashCode()),各个类可以根据自己的实际情况对其进行改写。

 

JAVA的反射机制

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
    Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。

[html] view plaincopy
  1. package baseJava;  
  2.   
  3. import java.lang.reflect.Array;  
  4. import java.lang.reflect.Constructor;  
  5. import java.lang.reflect.Field;  
  6. import java.lang.reflect.Method;  
  7.   
  8. public class Reflect {  
  9.   
  10.     /**  
  11.      * @param args  
  12.      *            2013-4-11 上午11:20:59  
  13.      * @author zhao_xingcai  
  14.      */  
  15.     public static void main(String[] args) {  
  16.         // TODO Auto-generated method stub  
  17.           
  18.   
  19.     }  
  20.       
  21.     /**  
  22.      * 得到某个对象的属性  
  23.      * @param owner  
  24.      * @param fieldName  
  25.      * @return  
  26.      * @throws Exception  
  27.      * 2013-4-11 上午11:25:48  
  28.      * @author zhao_xingcai  
  29.      */  
  30.     @SuppressWarnings("unchecked")  
  31.     public Object getProperty(Object owner, String fieldName) throws Exception {  
  32.         //得到该对象的Class  
  33.         Class ownerClass = owner.getClass();  
  34.         //通过Class得到类声明的属性  
  35.         Field field = ownerClass.getField(fieldName);  
  36.         //通过对象得到该属性的实例,如果这个属性是非公有的,这里会报IllegalAccessException。  
  37.         Object property = field.get(owner);  
  38.         return property;  
  39.     }  
  40.       
  41.     /**  
  42.      * 获得某个类的静态属性  
  43.      * @param className  
  44.      * @param fieldName  
  45.      * @return  
  46.      * @throws Exception  
  47.      * 2013-4-11 上午11:35:10  
  48.      * @author zhao_xingcai  
  49.      */  
  50.     @SuppressWarnings("unchecked")  
  51.     public Object getStaticProperty(String className, String fieldName)  
  52.             throws Exception {  
  53.         //首先得到这个类的Class  
  54.         Class ownerClass = Class.forName(className);  
  55.         //通过Class得到类声明的属性  
  56.         Field field = ownerClass.getField(fieldName);  
  57.         //静态属性,直接从类的Class里取  
  58.         Object property = field.get(ownerClass);  
  59.         return property;  
  60.     }  
  61.       
  62.     /**  
  63.      * 获取某个对象的方法  
  64.      * @param owner  
  65.      * @param methodName  
  66.      * @param args  
  67.      * @return  
  68.      * @throws Exception  
  69.      * 2013-4-11 上午11:39:05  
  70.      * @author zhao_xingcai  
  71.      */  
  72.     @SuppressWarnings("unchecked")  
  73.     public Object invokeMethod(Object owner, String methodName, Object[] args)  
  74.             throws Exception {  
  75.         //或得这个类的Class  
  76.         Class ownerClass = owner.getClass();  
  77.         //配置参数的Class数组,作为寻找Method的条件  
  78.         Class[] argsClass = new Class[args.length];  
  79.         for (int i = 0j = args.length; i < j; i++) {  
  80.             argsClass[i] = args[i].getClass();  
  81.         }  
  82.         //通过Method名和参数的Class数组得到要执行的Method  
  83.         Method method = ownerClass.getMethod(methodName, argsClass);  
  84.         //执行该Method,invoke方法的参数是执行这个方法的对象,和参数数组。返回值是Object,也既是该方法的返回值  
  85.         return method.invoke(owner, args);  
  86.     }  
  87.       
  88.     /**  
  89.      * 执行某个类的静态方法  
  90.      * @param className  
  91.      * @param methodName  
  92.      * @param args  
  93.      * @return  
  94.      * @throws Exception  
  95.      * 2013-4-11 上午11:40:31  
  96.      * @author zhao_xingcai  
  97.      */  
  98.     @SuppressWarnings("unchecked")  
  99.     public Object invokeStaticMethod(String className, String methodName,  
  100.             Object[] args) throws Exception {  
  101.         //获取该类的class  
  102.         Class ownerClass = Class.forName(className);  
  103.         Class[] argsClass = new Class[args.length];  
  104.             for (int i = 0j = args.length; i < j; i++) {  
  105.         }  
  106.         Method method = ownerClass.getMethod(methodName, argsClass);  
  107.         //invoke的一个参数是null,因为这是静态方法,不需要借助实例运行  
  108.         return method.invoke(null, args);  
  109.     }  
  110.       
  111.     /**  
  112.      * 新建实例,执行带参数的构造函数来新建实例的方法。  
  113.      * 如果不需要参数,可以直接使用newoneClass.newInstance()来实现。  
  114.      * @param className  
  115.      * @param args  
  116.      * @return  
  117.      * @throws Exception  
  118.      * 2013-4-11 上午11:41:27  
  119.      * @author zhao_xingcai  
  120.      */  
  121.     @SuppressWarnings("unchecked")  
  122.     public Object newInstance(String className, Object[] args) throws Exception {  
  123.         //得到要构造的实例的Class  
  124.         Class newoneClass = Class.forName(className);  
  125.         //得到参数的Class数组  
  126.         Class[] argsClass = new Class[args.length];  
  127.             for (int i = 0j = args.length; i < j; i++) {  
  128.         }  
  129.         //得到构造函数   
  130.         Constructor cons = newoneClass.getConstructor(argsClass);  
  131.         //新建实例  
  132.         return cons.newInstance(args);  
  133.     }  
  134.       
  135.     /**  
  136.      * 判断是否为某个类的实例  
  137.      * @param obj  
  138.      * @param cls  
  139.      * @return  
  140.      * 2013-4-11 上午11:42:59  
  141.      * @author zhao_xingcai  
  142.      */  
  143.      @SuppressWarnings("unchecked")  
  144.     public boolean isInstance(Object obj, Class cls) {  
  145.         return cls.isInstance(obj);  
  146.     }  
  147.        
  148.      /**  
  149.       * 得到数组中的某个元素  
  150.       * @param array  
  151.       * @param index  
  152.       * @return  
  153.       * 2013-4-11 上午11:43:33  
  154.       * @author zhao_xingcai  
  155.       */  
  156.      public Object getByArray(Object array, int index) {  
  157.         return Array.get(array, index);  
  158.     }  
  159. }  

0 0