java为啥需要反射机制_Java基础--反射机制的知识点梳理

什么是反射?

正常编译执行java文件时,会生成一个.class文件,反射就是一个反编译的过程,它可以通过.class文件得到一个java对象.一个类会有很多组成部分,比如成员变量,成员方法,构造方法等,反射可以通过加载类,解剖出类的各个组成部分.

为什么要用反射?

我们需要访问一个类的方法或字段的时候,直接new一个该类的对象然后调用就好了,干嘛要用反射呢,刚学的时候我也不懂,并且学了也没机会用到,或者根本用不到,后来开始接触strut2,hibernate等一些框架的时候,才慢慢懂得了一点反射的强大之处,在框架中会有很多配置文件,而配置文件中一般只有一些类的全路径的字符串,而就是通过这些个字符串,就能得到这个类的对象,以及类中所有的信息.我给你这个类,当然你可以轻松得到它的实例,但如果我给你的只是这个类的路径的字符串呢?没有反射你就傻眼了吧.学习反射一般只会在写框架的时候用到,如果你没有到达写框架的高度,能够看懂别人的框架也是极好的.

这里面还涉及到一个静态编译和动态编译的概念,前者的意思就是在编译的时候已经绑定了对象,确定了对象,而动态编译就是知道运行的时候,才根据需要去绑定对象.

加载类:

加载类就是获得类的字节码,要想通过反射获取到一个类的内部信息,首先得先获取到这个类的字节码对象.

加载类有三种方式:

现在我有一个类User,我希望加载这个类,获得它的字节码对象:

packagecom.wang.reflect;public classDemo01 {public static void main(String[] args) throwsClassNotFoundException {//第一种方式 通过Class的forName方法,注意使用目标类的全路径

Class clazz=Class.forName("com.wang.reflect.User");//第二种方式 通过Object类的getClass()方法

Class clazz1=newUser().getClass();//第三种方式 通过类的.class属性

Class clazz2=User.class;

}

}

一般第一种方式最常用,也最好用,因为看代码我们可以发现,后两种在编译前就必须要知道具体的类的,否则就无法通过编译,而第一种方式,没有那么大的强制性,他只是提供了一个空间,运行时你可以想把谁传给它就把谁传给它,这个类甚至可以不存在,后果只是抛出一个异常.

反射类的构造函数(Constructior):

获得了Class对象以后就可以调用class的很多方法了,比如getConstructor(..),方法就可以获得构造器的对象.下面分别通过获取User类的无参和带参构造器,进而得到该类对象的例子,感受一下反射技术.

public classUser {privateString name;publicUser(){

System.out.println("无参构造函数");

}publicUser(String name){this.name=name;

System.out.println("带一个参数的构造函数:::"+name);

}

}//-----------------------------------------------------------------------------

@Testpublic void test01() throwsException{//通过Class的forName方法,注意使用目标类的全路径

Class clazz=Class.forName("com.wang.reflect.User");//通过无参构造器得到该类对象,

Constructor c=clazz.getConstructor(null);

User user=(User) c.newInstance(null);//通过带参构造器获得该类对象

Constructor c1=clazz.getConstructor(String.class);

User user1=(User)c1.newInstance("nick");

}

注意.在通过无参构造函数获得对象时,还可以直接调用User user=(User)clazz.newInstance();得到,内部的原理也是先调用了无参构造器,如上.注意,使用"newInstance"方法只能调用类的无参构造方法,这个操作实际相当于使用了new进行对象实例化.

反射类的方法(Method):

一个类中总会有实现某些功能的方法,这些方法可能有返回值也可能没有返回值,可能有参数也可能没参数,可能是静态方法也可能是普通方法.下面通过例子分别讲解:

packagecom.wang.reflect;public classUser {privateString name;publicUser(){

System.out.println("无参构造函数");

}publicUser(String name){this.name=name;

System.out.println("带一个参数的构造函数:::"+name);

}//1无参无返回值的方法login

public voidlogin(){

System.out.println("用户登陆了");

}//2带参有返回值的方法eat

publicString eat(String name){

System.out.println("name"+"去吃饭去了");return "eat";

}//3带参无返回值的静态方法

public static voidsleep(String name){

System.out.println(name+"去睡觉了");

}

}//-----------------------------------------------------------------

@Testpublic void test02() throwsException{

User u=newUser();//通过Class的forName方法,注意使用目标类的全路径

Class clazz=Class.forName("com.wang.reflect.User");//1获取无参无返回值的方法login//获得一个方法名为"login"但是没有参数的Method对象

Method method=clazz.getMethod("login", null);//第一个参数:要想执行这个login方法你总得告诉她是哪个User的login方法吧,第二个参数就是login方法的参数,这里为null

method.invoke(u, null);//2获取有参有返回值的方法eat

Method method1=clazz.getMethod("eat", String.class);

String agrs=(String)method1.invoke(u, "超人");//3获取带参无返回值的静态方法sleep,

//静态方法 可以不提供User对象,传一个null即可

Method method2=clazz.getMethod("sleep", String.class);

method2.invoke(null, "蝙蝠侠");

}

//执行之后打印结果为:

无参构造函数

用户登陆了

超人去吃饭去了

蝙蝠侠去睡觉了

反射类的字段:

@Testpublic void test03() throwsException{

User u=newUser();

u.setName("钢铁侠");//通过Class的forName方法,注意使用目标类的全路径

Class clazz=Class.forName("com.wang.reflect.User");

Field f=clazz.getField("name");

String name=(String)f.get(u);

System.out.println(name);

}

下面介绍一个使用反射的简单例子:

packagecom.wang.reflect;importjava.lang.annotation.Annotation;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.util.ResourceBundle;interfacePerson {public voidlocation(String location);

}class Student implementsPerson{

@Overridepublic voidlocation(String location) {

System.out.println("学生的工作地点是"+location);

}

}class Teacher implementsPerson{

@Overridepublic voidlocation(String location) {

System.out.println("老师的工作地点是"+location);

}

}classFactory{public static Person getInstance(String str) throwsException, IllegalAccessException, ClassNotFoundException{

Person person=(Person)Class.forName(str).newInstance();returnperson;

}

}public classTestReflect {public static void main(String[] args) throwsException {//Person p=(Person)Class.forName("com.wang.reflect.Student").newInstance();//p.location("学校");

Person p=(Person)Class.forName("com.wang.reflect.Teacher").newInstance();

p.location("学校");

}

}

这个例子使用了简单的工厂模式,调用person的location方法,通过反射,实际应用中并不会出现这样的代码,这里只是做一个反射的运用的演示.在测试代码中,只要简单的修改ForName方法中的字符串,就可以调用相应的方法.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值