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(类名);// 返回字节码:若内存中有加载该类,则他找到该类的字节码并返回,若无,则找到该类的路径,加载后返回.
要区别一个概念,这里获得的是类的字节码,与具体的对象无关。
view code
1 public class classtest {
2
3public static void main(string[] args){
4string str1 = "abc";
5string str2 = "123";
6system.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
3public int a = 47;
4
5private string str = "hello";
6
7public reflecttest(){}
8
9public reflecttest(string str){
10this.str = str;
11}
12
13public string getstr(string str){
14return this.str + "," + str;
15}
16
17public string getstr(){
18return str;
19}
20
21public static void main(string[] args){
22system.out.println("this is genericstest" + args[1]);
23}
24
25 }
这里有一个类,用于待会通过反射来获得它的成分,这个类中有属性(公有与私有,基础类型与非基础类型),两个构造方法,两个方法(多态)。
3.1. 通过反射获得field:
view code
1 import java.lang.reflect.field;
2
3public class reflectfield {
4
5public static void main(string[] args) throws exception {
6class clazz = class.forname("reflecttest");
7system.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
16field fielda = clazz.getfield("a");
17// can not:field fielda = clazz.getfield("str");
18// because str's modifiers is private.
19system.out.println("属性名:" + fielda.getname() + "; 类型:"
20+ fielda.gettype() + "; 权限修饰符:"
21+ fielda.getgenerictype() + "; 值:" + fielda.get(new reflecttest()));
22
23// 既然反射是将类的各种成分映射成相应的类,那么私有的属性理应也可获取(暴力反射):
24reflecttest rt = new reflecttest();
25field fieldstr = clazz.getdeclaredfield("str");
26fieldstr.setaccessible(true);
27system.out.println(fieldstr.get(rt));
28fieldstr.set(rt, "abc");
29system.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
6public static void main(string[] args) throws exception {
7class clazz = class.forname("reflecttest");
8
9// 获取无参的构造方法
10constructorreflecttest> constructor = clazz.getconstructor();
11reflecttest rt = constructor.newinstance();
12system.out.println(rt.getstr());
13
14// 获取有参的构造方法,需指明参数类型
15constructor = clazz.getconstructor(string.class);
16rt = constructor.newinstance("world");
17system.out.println(rt.getstr());
18
19// 可以看出,先通过获取reflecttest的字节码,然后得到它的构造方法,再调用该构造方法生成对象
20// 对于无参的构造方法,class类中提供一个方法可以直接生成该类的对象
21rt = (reflecttest)clazz.newinstance();
22system.out.println(rt.getstr());
23}
24
25 }
3.3. 通过反射获得方法:
view code
1 import java.lang.reflect.method;
2
3
4 public class reflectmethod {
5
6public static void main(string[] args) throws exception{
7reflecttest rt = new reflecttest();
8reflecttest rt2 = new reflecttest();
9method method = reflecttest.class.getmethod("getstr",string.class);
10string message = (string)method.invoke(rt,"world!");
11system.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
7public static void main(string[] args) throws exception {
8// 从当前类所对应的包中找到config.properties文件.若在前面加上 "/",则从项目的根目录开始.
9inputstream instream = reflectapp.class.getresourceasstream("config.properties");
10
11// method two:
12// 该方法需从根目录开始,也就是得指明包,这里是默认包,所以直接写
13// inputstream instream = reflectapp.class.getclassloader().getresourceasstream("config.properties");
14properties props = new properties();
15props.load(instream);
16instream.close();
17string classname = props.getproperty("classname");
18system.out.println("创建一个对象: " + class.forname(classname).newinstance());
19}
20
21 }
这就是反射的基本应用,其实在做‘有个饭桶’的时候就用到了,只是当时知其然而不知其所以然。。。现在学框架,懂了这个后回头看,便清晰容易多了。。。
======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/