黑马程序员-----------------反射

来源:互联网 发布:实验室数据管理制度 编辑:程序博客网 时间:2024/06/03 13:08

android培训、java培训、期待与您交流!

反射:就是把Java类中的各种成分映射成相应的Java类,通过这种能力可以彻底了解自身的情况为下一步动作做准备。

Java的反射机制实现主要是借助:Class(类对象),Construct(类的构造器对象),Field(属性字段对象),Method (类的方法对象)四个类。

Class:Java中用Java类来描述同一类的事物,描述这一类事物的Java类名就是Class。

如何知道Java类是否属于的同一类事物就可以通过Class类中的方法

由于Class类中没有构造函数,因此不能使用new Class()这种形式来创建Class类对象。

实例化Class类的方式有点特殊,实例化Class类得到得是字节码的形式,得到字节码的三种方式:

1.对象.getClass();new Date().getClass()//得到创建Date对象的字节码

2.类.class;//System.class//得到某个类的字节码

3.forName();//Class.forName("java.util.Date");得到Date类的字节码。

除了类.class获取字节码Java中还有8个基本类型booleanbytecharshortintlongfloatdouble和关键字 void 也表示为 Class 对象。 


package com.leo.blog;public class ClassDemo {public static void main(String[] args) {String str = "abc";Class cls = str.getClass();Class cls1 = String.class;Class cls2 = null;try { cls2 = Class.forName("java.lang.String");} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}//查看结果三个实例化对象是否是属于同一份字节码System.out.println(cls==cls1);//trueSystem.out.println(cls==cls2);//true//检查是一个基本类型字节码System.out.println(cls.isPrimitive());//falseSystem.out.println(int.class.isPrimitive());//trueSystem.out.println(int.class==Integer.class);//falseSystem.out.println(int.class==Integer.TYPE);//true}}

只要是在源程序中出现的类型,都具有各自的Class实例对象,由于使用forName的方式,会抛出ClassNotFoundException异常,是为了避免找不到类名。

Construct类

通过反射得到String类型中的构造方法获得字符串中的某个字符。

package com.leo.blog;import java.lang.reflect.*;public class ReflectConstructDemo {public static void main(String[] args) {//创建一个Construct类型对象Constructor cons = null;try {cons = String.class.getConstructor(StringBuffer.class);String str = (String)cons.newInstance(new StringBuffer("LEO"));System.out.println(str.charAt(2));//得到第三个字符:0} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
注:在获得方法跟调用方法时所用到的实例类需要相同。

Field:通过反射修改类中的属性。

package com.leo.blog;public class ReflectPoint {private int x;public int y;public String str1 = "ball";public String str2 = "basketball";public String str3 = "LeoBall";public ReflectPoint(int x, int y) {super();this.x = x;this.y = y;}@Overridepublic String toString() {return "ReflectPoint [str1=" + str1 + ", str2=" + str2 + ", str3="+ str3 + "]";}}
先创建一个类,利用反射机制对类中的属性进行修改。

package com.leo.blog;import java.lang.reflect.Field;public class ReflectDemo {/** * @param args */public static void main(String[] args) throws Exception{// TODO Auto-generated method stubReflectPoint rp = new ReflectPoint(3,5);Field fdY =rp.getClass().getField("y");System.out.println(fdY.get(rp));Field fdX =rp.getClass().getDeclaredField("x");fdX.setAccessible(true);System.out.println(fdX.get(rp));System.out.println(rp);changeStrValue(rp);System.out.println(rp);}public static void changeStrValue(Object obj) throws Exception{//获取对象所有字段Field[] fds = obj.getClass().getFields();for (Field fd:fds) {//遍历对象中的所有字段//同一份字节码的比较使用==号if(fd.getType()==String.class){//比较是否是字符串类型字段String oldVal = (String)fd.get(obj);//获取对象的字段的值String newVal = oldVal.replace('b','a');//替换字段值中b为afd.set(obj, newVal);//设置对象中字段值}}}}
getDeclaredFields方法可以获取全部的属性包括私有的,getDeclaredField获取的是类中的单个属性,getField跟getFields只能是获取公共的属性。而通过setAccessible可以强制的对私有属性进行修改。

Method类:通过反射得到一个方法。

package com.leo.blog;import java.lang.reflect.Method;class MethodPerson{public void play(String str){System.out.print(str);}public static void play(int times){System.out.print("玩"+times+"局");}}public class ReflectMethod {/** * @param args */public static void main(String[] args)throws Exception {// TODO Auto-generated method stubMethodPerson mp = new MethodPerson();Class c = mp.getClass();//创建Method类对象,通过getMethod方法传入方法名,和参数类型Method me = c.getMethod("play", int.class);//使用invoke去调用类中的paly参数为int类型的方法,me.invoke(null, 10);Method me1 = c.getMethod("play", String.class);//使用invoke去调用类中的paly参数为String类型的方法,me1.invoke(mp, "BASKETBALL");}}
执行结果就会是:玩10局BASKETBALL


0 0
原创粉丝点击