java反射机制总结

一、Java中反射机制总结:

反射的定义:通过反射,把Java类中的各个组成部分映射到相应的Java类

反射的优点:

1. 减少对象的依赖,调用方法更灵活,改变属性的值。

2. 通过class对象得到该类的对象,从而获取到方法等。

3. 提高程序的扩展性

首先通过程序来演示一下反射原理:

有一个实体类Student.java

[java]  view plain  copy
 print ?
  1. package com.huaxin.reflect;  
  2.   
  3. /** 
  4.  * @author 赵芳 
  5.  * 2015年2月15日 下午5:23:30 
  6.  */  
  7. public class Student {  
  8.   
  9.     public String name = "abcd";  
  10.     /** 
  11.      * @param string 
  12.      */  
  13.     public Student(String name) {  
  14.         System.out.println("调用有一个参数的构造方法创建对象");  
  15.         this.name = name;  
  16.     }  
  17.     public Student() {  
  18.         System.out.println("调用无参数构造方法创建对象");  
  19.     }  
  20.     @Override  
  21.     public String toString() {  
  22.         return "Student [name=" + name + "]";  
  23.     }  
  24.   
  25.     public void study(){  
  26.         System.out.println(name+"学习");  
  27.     }  
  28.       
  29. }  
一个测试类Test.java

[java]  view plain  copy
 print ?
  1. package com.huaxin.reflect;  
  2.   
  3. import java.lang.reflect.Constructor;  
  4. import java.lang.reflect.Field;  
  5. import java.lang.reflect.Method;  
  6.   
  7. /** 
  8.  * java中反射机制的测试 
  9.  * @author 赵芳 
  10.  * 2015年1月24日  上午9:56:15 
  11.  */  
  12. public class Test {  
  13.   
  14.     public static void main(String[] args) throws Exception{  
  15.         //通过反射获取构造方法Constructor   创建对象  
  16.         Class c = Class.forName("com.huaxin.reflect.Student");  
  17.         Constructor cons = c.getDeclaredConstructor(String.class);  
  18. //      cons.setAccessible(true);//访问权限  
  19.         Student stu = (Student) cons.newInstance("bbb");  
  20.         System.out.println(stu);  
  21.           
  22.         //使用new关键字创建对象  
  23.         Student stu1 = new Student("aaa");  
  24.         System.out.println(stu1);  
  25.           
  26.         // 创建此 Class 对象所表示的类的一个新实例,只能是无参  
  27.         Student stu2 = (Student) c.newInstance();  
  28.         System.out.println(stu2);  
  29.           
  30.         //通过反射获取Field,并且该属性在此类中是public的,否则会抛出NoSuchFieldException  
  31.         Field field_name = c.getField("name");  
  32.         System.out.println(field_name.get(stu));  
  33.           
  34.         //通过反射来调用方法Method  
  35.         Method method = c.getMethod("study"null);  
  36.         method.invoke(stu2, null);  
  37.     }  
  38. }  

输出结果:

调用有一个参数的构造方法创建对象
Student [name=bbb]
调用有一个参数的构造方法创建对象
Student [name=aaa]
调用无参数构造方法创建对象
Student [name=abcd]
bbb
abcd学习


每个Java程序执行前都必须经过编译、加载、连接和初始化这几个阶段,后三个阶段如下图:



(1)加载是指将编译后的java类文件(.class文件)中的二进制数据读入内存,并将其放在运行时数据区的方法区内,然后再堆区创建一个java.lang.Class对象,用来封装类在方法区的数据结构。即加载后最终得到的是Class对象,并且更加值得注意的是:该Java.lang.Class对象是单实例的,无论这个类创建了对少个对象,它的Class对象是唯一的!而加载并获取该Class对象可以通过三种途径:Class.forName(类的全名称)、实例对象.class(属性)、实例对象getClass()。

(2)在连接和初始化阶段,其实静态变量经过了两次赋值:第一次是静态变量类型的默认值;第二次是我们真正赋给静态变量的值。

(3)Java对类的使用分为两种方式:主动使用和被动使用。其中主动使用的方式有以下6种,

①创建类的实例

②访问某个类或接口的静态变量,或者对该静态变量赋值

③调用类的静态方法

④反射(如Class.forName(“java.lang.String”))

⑤初始化一个类的子类

⑥Java虚拟机启动时被标明为启动类的类

而类的初始化时机正是java程序对类的首次主动使用,除了以上6种方式,其他对类的使用都是被动使用,都不会导致类的初始化。并且应注意以下几个方面:

①调用ClassLoader类的loadClass方法加载一个类,并不是对类的主动使用,不会导致类的初始化。

②当java虚拟机初始化一个类时,要求它的所有父类都已经被初始化,但是这条规则并不适用于接口。

l  在初始化一个类时,并不会先初始化它所实现的接口。

l  在初始化一个接口时,并不会先初始化它的父接口。

因此,一个父接口并不会因为它的子接口或者实现类的初始化而初始化。只有当程序首次使用特定接口的静态变量时,才会导致该接口的初始化。

在这里可以看出,接口的两重性:可以把接口当做类(因为在接口中有静态变量时,可以被初始化);接口就是接口,和类无关(接口中没有构造方法,所以不能被初始化)。

二、Class.forName、实例对象.class(属性)、实例对象getClass()的异同:

1、相同点

通过这几种方式,得到的都是java.lang.Class对象

例如:






2、区别

① Classc1 = String.class;JVM将使用String类的类装载器,将String类装入内存(前提是String类还没有装入内存),不对String类做类的初始化工作,返回String类的Class对象。

② Class.forName(“类名”);装入类**,并做类的初始化

③ Class= 对象引用o.getClass();返回引用对象o运行时真正所指的对象(因为儿子对象的引用可能会赋给父对象的引用变量中)所属的类的Class对象

 

从JVM的角度看,我们使用关键字new创建一个类的时候,这个类可以没有被加载。但是使用Class对象的newInstance()方法的时候,就必须保证:1.这个类已经加载;2.这个类已经连接了。而完成上面两个步骤的正是Class的静态方法forName()所完成的,这个静态方法调用了启动类加载器,即加载java API的那个加载器。

 

    现在可以看出,Class对象的newInstance()实际上是把new这个方法分解为两步,即首先调用Class加载方法加载某个类,然后实例化。这样分布的好处:我们可以在调用Class的静态加载方法forName时获得更好的灵活性,提供给了一种降耦的手段。

 

    最后,用最简单的描述来区分new关键字和newInstance()方法的区别:

newInstance:弱类型,低效率,只能调用无参构造;

new:强类型,相对高效,能调用任何Public构造。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值