Java.lang.Class类

                 Java.lang.Class类

    Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识。这项信息纪录了每个对象所属的类。虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类。Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建。

      Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象。 
      虚拟机为每种类型管理一个独一无二的Class对象。也就是说,每个类(型)都有一个Class对象。运行程序时,Java虚拟机(JVM)首先检查是否所要加载的类对应的Class对象是否已经加载。如果没有加载,JVM就会根据类名查找.class文件,并将其Class对象载入。
      基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也都对应一个 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对象已被加载到内存,就可以用它来产生该类型的所有对象

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. public class ClassTest {  
  2.      public static void main(String [] args)throws Exception{  
  3.          String str1="abc";  
  4.          Class cls1=str1.getClass();  
  5.          Class cls2=String.class;  
  6.          Class cls3=Class.forName("java.lang.String");  
  7.          System.out.println(cls1==cls2);  
  8.          System.out.println(cls1==cls3);  
  9.      }  
  10.  }  

返回结果为:true,true.
解释: 虚拟机只会产生一份字节码, 用这份字节码可以产生多个实例对象。

二、Class类的常用方法
    1、getName() 
    一个Class对象描述了一个特定类的属性,Class类中最常用的方法getName以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。

    2、newInstance()
    Class还有一个有用的方法可以为类创建一个实例,这个方法叫做newInstance()。例如:
    x.getClass.newInstance(),创建了一个同x一样类型的新实例。newInstance()方法调用默认构造器(无参数构造器)初始化新建对象。
    3、getClassLoader() 
    返回该类的类加载器。
    4、getComponentType() 
    返回表示数组组件类型的 Class。
    5、getSuperclass() 
    返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。
    6、isArray() 
    判定此 Class 对象是否表示一个数组类。
三、Class的一些使用技巧
    1、forName和newInstance结合起来使用,可以根据存储在字符串中的类名创建对象。例如
    Object obj = Class.forName(s).newInstance();
    2、虚拟机为每种类型管理一个独一无二的Class对象。因此可以使用==操作符来比较类对象。例如:
    if(e.getClass() == Employee.class)...

反射

      反射就是把Java类中的各种成分映射成相应的java类。例如,一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类。表示Java类的Class类显示要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor、Package等等。

      一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以的得到这些实例对象后,得到这些实例对象后有什么用呢?怎么用呢?这正是学习和应用反射的要点。

构造方法的反射应用

Consturctor(构造器)类代表某个类中的一个构造方法

@1@ 得到某个类所有的构造方法:例如:Constructor [] constructors = Class.forName("java.lang.String").getConstructors();

@2@ 得到某一个构造方法:例如:Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class);

@3@ 创建实例对象:通常方式:String str=new String(new StringBuffer("abc"));
                            反射方式:String str=(String) constructor.newInstance(new StringBuffer("abc"));

Java反射机制创建对象

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. package lxf;    
  2. import java.lang.reflect.Constructor;    
  3. import java.lang.reflect.Field;    
  4. import java.lang.reflect.Method;    
  5.     
  6. class Person {    
  7.     private String name;    
  8.     private int age;    
  9.     
  10.     public Person(String name, int age) {    
  11.         this.name = name;    
  12.         this.age = age;    
  13.     }    
  14.     
  15.     public Person() {    
  16.         // TODO Auto-generated constructor stub    
  17.     }    
  18.     
  19.     public String getName() {    
  20.         return name;    
  21.     }    
  22.     
  23.     public void setName(String name) {    
  24.         this.name = name;    
  25.     }    
  26.     
  27.     public int getAge() {    
  28.         return age;    
  29.     }    
  30.     
  31.     public void setAge(int age) {    
  32.         this.age = age;    
  33.     }    
  34.     
  35. }    
  36.     
  37. /**  
  38.  * 使用反射机制来创建对象  
  39.  *   
  40.  * @author lxf  
  41.  * @time 2014-4-8下午05:08:41  
  42.  *   
  43.  */    
  44. public class CreateObject {    
  45.     
  46.     /**  
  47.      * Java的反射机制是指:反射就是把Java类中的各种成分映射成相应相应的Java类, 然后就可以获取这个类的所有信息  
  48.      *   
  49.      * @throws Exception  
  50.      */    
  51.     public static void createObj1() throws Exception {    
  52.         // 返回与带有给定字符串名的类或接口相关联的 Class 对象。    
  53.         // Class classType = Person.class;    
  54.         Class classType = Class.forName("lxf.Person");    
  55.         Object obj = classType.newInstance();    
  56.         System.out.println("使用反射反射机制创建出来的对象是否是Person类的对象:"    
  57.                 + (obj instanceof Person));    
  58.     }    
  59.     
  60.     /**  
  61.      * 创建带有构造参数的对象的时候我们需要使用另外一种方式即: 1.先获取操作类的Class对象即字节码文件  
  62.      * 2.使用Class对象的getConstructor  
  63.      * (parameterTypes)方法获取该对象的构造方法的对象,注意括号中可以带不等的可变参数,  
  64.      * 3.使用构造方法对象的newInstance(initargs)方法就可以实例化一个对象 4.注意,使用这些方法都不可以访问被  
  65.      * private修饰的方法,需要设置某些访问权限setAccessable()方法  
  66.      *   
  67.      * @throws Exception  
  68.      */    
  69.     public static void createObj2() throws Exception {    
  70.         @SuppressWarnings("rawtypes")    
  71.         Class classType = Person.class;    
  72.     
  73.         @SuppressWarnings("unchecked")    
  74.         Constructor<Person> con = classType.getConstructor(String.class,    
  75.                 int.class);    
  76.         Object obj = con.newInstance("lxf"23);    
  77.         System.out.println("使用constructor对象的newInstance方法创建对象的信息:"    
  78.                 + ((Person) obj).getName());    
  79.     }    
  80.     
  81.     /**  
  82.      * 操作方法包括(private方法) 步骤: 1.首先获取要操作类的Class对象  
  83.      * 2.然后通过Class对象的getMethod方法获取要操作的方法的Method对象(两个参数,第一个参数是方法名,第二个参数是参数类型)  
  84.      * 3.调用Method的方法的invoke方法(两个参数,第一个参数是该方法属于的类对象,具体参数)  
  85.      * 4.当方法被private修饰的时候,首先需要调用getDeclaredMethod()方法获取要操作的被private修饰的类。  
  86.      * 在这里要注意这个getDeclaredMethod方法,它既可以用作获取普通方法的对象也可以用来操作private修饰的方法,  
  87.      * 但是操作private修饰的方法的时候,必须使用这个方法,其它方法不可以。普通方法还可以使用getMethod方法,  
  88.      * 且属性操作也是如此。另外,还需要设置访问权限setAccessable(true)才可以  
  89.      *   
  90.      * @throws Exception  
  91.      */    
  92.     public static void methodDo() throws Exception {    
  93.         Person p = new Person();    
  94.         Class classType = Person.class;    
  95.         Method method = classType.getMethod("setName", String.class);    
  96.         method.invoke(p, "ckl");    
  97.         System.out.println("使用反射操作SetName方法后,Person对象的name值是:" + p.getName());    
  98.     
  99.         Method method2 = classType.getDeclaredMethod("test");    
  100.         method2.setAccessible(true);    
  101.         method2.invoke(p);    
  102.     }    
  103.     
  104.     /**  
  105.      * 操作字段  
  106.      *   
  107.      * @throws Exception  
  108.      */    
  109.     public static void FieldDo() throws Exception {    
  110.         Person p = new Person();    
  111.         Class classType = Person.class;    
  112.         Field field = classType.getDeclaredField("name");    
  113.         Field field2 = classType.getDeclaredField("age");    
  114.         field.setAccessible(true);    
  115.         field2.setAccessible(true);    
  116.         field.set(p, "lxf");    
  117.         field2.set(p, 23);    
  118.         System.out.println("使用反射机制操作被private修饰的对象字段后得到的属性值是:" + p.getName());    
  119.         System.out.println("使用反射机制操作被private修饰的对象字段后得到的属性值是:" + p.getAge());    
  120.     }    
  121.     
  122.     public static void main(String[] args) throws Exception {    
  123.         new CreateObject().FieldDo();    
  124.     }    
  125.     
  126. }  


根据以上代码:.使用反射机制创建对象的步骤如下:
1、先声明你要创建的对象的类全称;使用Class类的静态方法forName(String.className)加载这个类的字节码(注意,加载字节码不等于实例化对象) ,返回 一个Class对象,这个对象代表的是一个字节码文件。

2、调用这个类对象(字节码)的方法newInstance()方法(注意:这里的这个newInstance方法默认调用默认的构造方法即调用无参的构造方法, 一旦构造方法有参数时,此方法行不通,需要使用构造方法的对象的相关方法来 实例化)实例化类Person,返回的是Object类型
3、强制转换成Person类型即你所需类型
而获得Class对象的方法还有:
Class c = Class.forName("java.lang.String");这条语句得到一个 String 类的类对象。还有另一种方法,如下面的语句:Class c = int.class; 或者 Class c = Integer.TYPE;它们可获得基本类型的类信息。其中后一种方法中访问的是基本类型的封装类 (如 Integer) 中预先定义好的 TYPE 字段。
到此反射基本操作就结束了,详细方法可参看API。


参考:http://lavasoft.blog.51cto.com/62575/15433/
     http://blog.csdn.net/smartboy_01/article/details/23201391
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值