java 反射

.反射简述

2.Class是什么?

3.通过反射获得Field,Constructor,Method

4.反射的应用

 

======================  华丽丽的分割线  ======================

 

1.反射简述

 

类用于描述一类具有相同属性和方法的东西,那么,Java中的类又能否有相应的类去描述?

答案是肯定的,反射(reflect)就是用来把Java类中的各种成分映射成各种相应的Java类.

Java反射涉及的类分别为:Field、Constructor、Method、Class。

Field 类:提供有关类或接口的属性的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)属性或实例属性,简单的理解可以把它看成一个封装反射类的属性的类。

Constructor 类:提供关于类的单个构造方法的信息以及对它的访问权限。这个类和 Field 类不同,Field 类封装了反射类的属性,而 Constructor 类则封装了反射类的构造方法。

Method 类:提供关于类或接口上单独某个方法的信息。所反映的方法可能是类方法或实例方法。这个类不难理解,它是用来封装反射类方法的一个类。

Class 类:类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。

 

======================  华丽丽的分割线  ======================

 

2.Class是什么?

 

Class:简单而言,就是用来描述Java类(与接口)的类.它的实例用来表示正在运行的Java应用程序中的类和接口。

如何获得字节码?
Class cls = Xxx.class;
Class cls = xx.getClass();
Class.forname(类名);  // 返回字节码:若内存中有加载该类,则他找到该类的字节码并返回,若无,则找到该类的路径,加载后返回.

要区别一个概念,这里获得的是类的字节码,与具体的对象无关。

View Code
 
  
1 public class ClassTest { 2 3 public static void main(String[] args){ 4 String str1 = " abc " ; 5 String str2 = " 123 " ; 6 System.out.println( " str1.getClass() 等于 str2.getClass()? " + (str1.getClass() == str2.getClass()); 7 } 8 } 9   /* Output: 10 * str1.getClass()等于str2.getClass()? true 11 */

如前所说,他是用来描述正在运行的Java类。这里这里的getClass()获得的是String类型的字节码,故当然相等.

 

======================  华丽丽的分割线  ======================

 

3.通过反射获得Field,Constructor,Method

 

通过反射获得类得各种成分

View Code
 
  
1 public class ReflectTest{ 2 3 public int a = 47 ; 4 5 private String str = " hello " ; 6 7 public ReflectTest(){} 8 9 public ReflectTest(String str){ 10 this .str = str; 11 } 12 13 public String getStr(String str){ 14 return this .str + " , " + str; 15 } 16 17 public String getStr(){ 18 return str; 19 } 20 21 public static void main(String[] args){ 22 System.out.println( " This is GenericsTest " + args[ 1 ]); 23 } 24 25 }

这里有一个类,用于待会通过反射来获得它的成分,这个类中有属性(公有与私有,基础类型与非基础类型),两个构造方法,两个方法(多态)。

3.1. 通过反射获得Field:

View Code
 
  
1 import java.lang.reflect.Field; 2 3   public class ReflectField { 4 5 public static void main(String[] args) throws Exception { 6 Class clazz = Class.forName( " ReflectTest " ); 7 System.out.println(clazz.getName()); 8 9 // method two: 10 // Class clazz1 = GenericsTest.class; 11 12 // method three: 13 // GenericsTest gt = new GenericsTest(); 14 // Class clazz2 = gt.getClass(); 15   16 Field fieldA = clazz.getField( " a " ); 17 // Can not:Field fieldA = clazz.getField("str"); 18 // Because str's modifiers is private. 19 System.out.println( " 属性名: " + fieldA.getName() + " ; 类型: " 20 + fieldA.getType() + " ; 权限修饰符: " 21 + fieldA.getGenericType() + " ; 值: " + fieldA.get( new ReflectTest())); 22 23 // 既然反射是将类的各种成分映射成相应的类,那么私有的属性理应也可获取(暴力反射): 24 ReflectTest rt = new ReflectTest(); 25 Field fieldStr = clazz.getDeclaredField( " str " ); 26 fieldStr.setAccessible( true ); 27 System.out.println(fieldStr.get(rt)); 28 fieldStr.set(rt, " abc " ); 29 System.out.println(fieldStr.get(rt)); 30 } 31 32 }

在这个类中,演示了如何获得属性,要注意的是,私有属性的获得是需要通过暴力反射。

  

3.2. 通过反射获得构造方法:

View Code
 
  
1 import java.lang.reflect.Constructor; 2 3 4 public class ReflectConstructor { 5 6 public static void main(String[] args) throws Exception { 7 Class clazz = Class.forName( " ReflectTest " ); 8 9 // 获取无参的构造方法 10 Constructor < ReflectTest > constructor = clazz.getConstructor(); 11 ReflectTest rt = constructor.newInstance(); 12 System.out.println(rt.getStr()); 13 14 // 获取有参的构造方法,需指明参数类型 15 constructor = clazz.getConstructor(String. class ); 16 rt = constructor.newInstance( " world " ); 17 System.out.println(rt.getStr()); 18 19 // 可以看出,先通过获取ReflectTest的字节码,然后得到它的构造方法,再调用该构造方法生成对象 20 // 对于无参的构造方法,Class类中提供一个方法可以直接生成该类的对象 21 rt = (ReflectTest)clazz.newInstance(); 22 System.out.println(rt.getStr()); 23 } 24 25 }

  

3.3. 通过反射获得方法:

View Code
 
  
1 import java.lang.reflect.Method; 2 3 4 public class ReflectMethod { 5 6 public static void main(String[] args) throws Exception{ 7 ReflectTest rt = new ReflectTest(); 8 ReflectTest rt2 = new ReflectTest(); 9 Method method = ReflectTest. class .getMethod( " getStr " ,String. class ); 10 String message = (String)method.invoke(rt, " world! " ); 11 System.out.println(message); 12 } 13 }

要补充的是,对于无参的方法,不用写参数;而对于静态方法时,则为:method.invoke(null,参数名...);

因为静态方法是不需要对象的。。。

  

======================  华丽丽的分割线  ======================

 

4.反射的应用

 

反射的应用:框架。就好比建筑一样,我们先建好框架,等待门窗安进来,而在建房时无需知道门与窗长得什么样。

下面通过一个常用的实例来模拟一个小框架,即通过获取properties文件中的类名,来创建对象(框架的基本原理)
#config.properties
className=ReflectTest

在properties中,由于我做这个实例的时候直接丢到默认包,所以路径就直接写,蛋若有包名,则需写全

  

View Code
 
  
1 import java.io.InputStream; 2 import java.util.Properties; 3 4 5 public class ReflectApp { 6 7 public static void main(String[] args) throws Exception { 8 // 从当前类所对应的包中找到config.properties文件.若在前面加上 "/",则从项目的根目录开始. 9 InputStream inStream = ReflectApp. class .getResourceAsStream( " config.properties " ); 10 11 // method two: 12 // 该方法需从根目录开始,也就是得指明包,这里是默认包,所以直接写 13 // InputStream inStream = ReflectApp.class.getClassLoader().getResourceAsStream("config.properties"); 14 Properties props = new Properties(); 15 props.load(inStream); 16 inStream.close(); 17 String className = props.getProperty( " className " ); 18 System.out.println( " 创建一个对象: " + Class.forName(className).newInstance()); 19 } 20 21 }

这就是反射的基本应用,其实在做‘有个饭桶’的时候就用到了,只是当时知其然而不知其所以然。。。现在学框架,懂了这个后回头看,便清晰容易多了。。。

<script type="text/javascript"></script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值