JAVA反射机制

原文地址:http://blog.sina.com.cn/s/blog_6cea21730100s84n.html


JAVA反射机制功能用法解析


1.反射简述
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(类名);  // 返回字节码:若内存中有加载该类,则他找到该类的字节码并返回,若无,则找到该类的路径,加载后返回.
要区别一个概念,这里获得的是类的字节码,与具体的对象无关。


public class ClassTest {
public static void main(String[] args){
String str1 = "abc";
String str2 = "123";
System.out.println("str1.getClass() 等于 str2.getClass()? " + (str1.getClass() == str2.getClass());
}
}
 
如前所说,他是用来描述正在运行的Java类。这里这里的getClass()获得的是String类型的字节码,故当然相等.
 
======================  华丽丽的分割线  ======================
 
3.通过反射获得Field,Constructor,Method
 
通过反射获得类得各种成分


public class ReflectTest{
public int a = 47;
private String str = "hello";
public ReflectTest(){}
public ReflectTest(String str){
this.str = str;
}
public String getStr(String str){
return this.str + "," + str;
}
public String getStr(){
return str;
}
public static void main(String[] args){
System.out.println("This is GenericsTest" + args[1]);
}
}
这里有一个类,用于待会通过反射来获得它的成分,这个类中有属性(公有与私有,基础类型与非基础类型),两个构造方法,两个方法(多态)。
3.1. 通过反射获得Field:


import java.lang.reflect.Field;
 public class ReflectField {
public static void main(String[] args) throws Exception {
Class clazz = Class.forName("ReflectTest");
System.out.println(clazz.getName());
// method two:
// Class clazz1 = GenericsTest.class;
// method three:
// GenericsTest gt = new GenericsTest();
// Class clazz2 = gt.getClass();
 
Field fieldA = clazz.getField("a");
// Can not:Field fieldA = clazz.getField("str");
// Because str's modifiers is private.
System.out.println("属性名:" + fieldA.getName() + "; 类型:"
+ fieldA.getType() + "; 权限修饰符:"
+ fieldA.getGenericType() + "; 值:" + fieldA.get(new ReflectTest()));
// 既然反射是将类的各种成分映射成相应的类,那么私有的属性理应也可获取(暴力反射):
ReflectTest rt = new ReflectTest();
Field fieldStr = clazz.getDeclaredField("str");
fieldStr.setAccessible(true);
System.out.println(fieldStr.get(rt));
fieldStr.set(rt, "abc");
System.out.println(fieldStr.get(rt));
}
}
在这个类中,演示了如何获得属性,要注意的是,私有属性的获得是需要通过暴力反射。
  
3.2. 通过反射获得构造方法:


import java.lang.reflect.Constructor;


public class ReflectConstructor {
public static void main(String[] args) throws Exception {
Class clazz = Class.forName("ReflectTest");
// 获取无参的构造方法
Constructor<ReflectTest> constructor = clazz.getConstructor();
ReflectTest rt = constructor.newInstance();
System.out.println(rt.getStr());
// 获取有参的构造方法,需指明参数类型
constructor = clazz.getConstructor(String.class);
rt = constructor.newInstance("world");
System.out.println(rt.getStr());
// 可以看出,先通过获取ReflectTest的字节码,然后得到它的构造方法,再调用该构造方法生成对象
// 对于无参的构造方法,Class类中提供一个方法可以直接生成该类的对象
rt = (ReflectTest)clazz.newInstance();
System.out.println(rt.getStr());
}
}
  
3.3. 通过反射获得方法:


import java.lang.reflect.Method;


public class ReflectMethod {
public static void main(String[] args) throws Exception{
ReflectTest rt = new ReflectTest();
ReflectTest rt2 = new ReflectTest();
Method method = ReflectTest.class.getMethod("getStr",String.class);
String message = (String)method.invoke(rt,"world!");
System.out.println(message);
}
}
要补充的是,对于无参的方法,不用写参数;而对于静态方法时,则为:method.invoke(null,参数名...);
因为静态方法是不需要对象的。。。
  
======================  华丽丽的分割线  ======================
 
4.反射的应用
 
反射的应用:框架。就好比建筑一样,我们先建好框架,等待门窗安进来,而在建房时无需知道门与窗长得什么样。
下面通过一个常用的实例来模拟一个小框架,即通过获取properties文件中的类名,来创建对象(框架的基本原理)
#config.properties
className=ReflectTest
在properties中,由于我做这个实例的时候直接丢到默认包,所以路径就直接写,蛋若有包名,则需写全


import java.io.InputStream;
import java.util.Properties;


public class ReflectApp {
public static void main(String[] args) throws Exception {
// 从当前类所对应的包中找到config.properties文件.若在前面加上 "/",则从项目的根目录开始.
InputStream inStream = ReflectApp.class.getResourceAsStream("config.properties");
// method two:
// 该方法需从根目录开始,也就是得指明包,这里是默认包,所以直接写
// InputStream inStream = ReflectApp.class.getClassLoader().getResourceAsStream("config.properties");
Properties props = new Properties();
props.load(inStream);
inStream.close();
String className = props.getProperty("className");
System.out.println("创建一个对象: " + Class.forName(className).newInstance());
}
}
这就是反射的基本应用
~
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值