黑马程序员---java反射机制(一)

来源:互联网 发布:基恩士plc软件下载 编辑:程序博客网 时间:2024/06/16 09:08
-------------------- Android培训、java培训、期待与您交流! ----------------------

       java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制.就相当于一个人站在镜子面前可以看到五脏六腑一样,对于一个java的一个Class字节码文件一样,可以运用反射动态获取它里面的任意对象,任意方法。(嘿嘿!大笑比喻不太恰当,就是想象!!!)

     java程序中的各个java类,它们属于同一类事物,所以它们可以用一个类去描述,这个类就是Class。Class对应的是各个类在内存中的字节码。一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以它们在内存中的内容是不同的,这一个个的空间可分别用一个个的对象来表示,这些对象显然具有相同的类型,这个相同类型的类就是Class类。

Class类(获得一个类对象有四种方式)

对象名.getClass()

Class.forName(“类名”)(最常被使用)(会抛异常ClassNotFoundException)

类名.class语法

如果是Java封装类型,使用TYPE语法。(八个基本数据类型和void类型实例对象的获取)

String str1 = "abc";Class cls1 = str1.getClass();Class cls2 = String.class;Class cls3 = Class.forName("java.lang.String")Int.class = Integer.TYPE;

【java反射中的信息类】

Field,Method,Contructor,Package等等。一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象。(在java.lang.reflect包下)

Constructor类

<通过反射获取某个类中的构造方法>

得到某个类所有的构造方法:

Constructor[] constructors = Class.forName("java.lang.String").getConstructors();
得到某一个构造方法:
Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class);
创建实例对象:
通常方式:String str = new String(new StringBuffer("abc"));反射方式:String str = constructor.newInstance(new StringBuffer("abc"));
Constructor getConstructor(Class[] params)//获取使用特殊的参数类型的公有的构造函数。
Constructor[] getConstructors()  //获得类的所有公共构造函数
Constructor getDeclaredConstructor(Class[] params)//获取使用特定参数类型的构造函数(不限制访问    级别)
Constructor[] getDeclaredConstructors() //获得类的所有构造函数(不限制访问级别)

Field类

<通过反射获取属性信息>

getFields()://获得所有公有的属性
getDeclaredFields();//获得所有的属性
getField(String name);//获得指定名字的公有的属性
getDeclaredField(String name);//获得指定名字的属性(不限制访问级别)

class ReflectPoint{private int x;public int y;public ReflectPoint(int x,int y){this.x = x;this.y = y;}}
main方法中的代码:
ReflectPoint pt1 = new ReflectPoint(3,5);Field fieldY = pt1.getClass().getField("y");//fieldY的值是多少?是5,错!fieldY不是对象身上的变量,而是类上的,要用它去取某个对象上对应的值。System.out.println(fieldY.get(pt1));//Field fieldx = pt1.getClass().getField("x");会报一个NoSuchFieldExceptioon异常。因为x是私有的,就看不见,所以是找不到。//getField()只能得到那些看得见(非私有)的成员变量。//getDeclaredField()管你可见不可见都能得到。Field fieldX = pt1.getClass().getDeclaredField("x");//用getDeclaredField()得到了私有的变量X,这时能够看得见了,但之后通过fieldX.get(pt1)还是会报错,//是因为x是私有的,之前只是让你能够看得见,但还是不让你拿到。//通过setAccessible()设置为true就能够拿到,可以访问,这就俗称的暴力反射,不管你是私有还是非私有都要访问。fieldX.setAccessible(true);System.out.println(fieldX.get(pt1));
Method类
<通过反射获取成员方法>
getMethods();//获得所有公有的成员方法,包括从父类或者接口继承过来的公有方法。
getDeclaredMethods();//获得所有的成员方法
getMethod(name,parm);//获得指定参数类型的公有的成员方法
getDeclaredMethod(name,parm);//获得指定参数类型的成员方法,可以使私有的。
得到类中的某一个方法:Method charAt = Class.forName("java.lang.String").getMethod("CharAt",int.class);
调用方法:
    通常方式:System.out.println(str.charAt(1));
    反射方式:System.out.println(charAt.invoke(str,1));

如果传递给Method对象的invoke()方法的第一个参数为null则说明该Method对象对应的是一个静态方法。

 jdk1.5:public Object invoke(Object obj,Object...args)
 jdk1.4:public Object invoke(Object obj,Object[] args),
 需要将一个数字作为参数传递给invoke方法时,数组中的每个元素分别对应被调用方法中的一个参数,所以,调用charAt方法的代码也可以用jdk1.4改写为charAt.invoke("str",new Object[]{1})形式。

String str = "abc"; Method methodCharAt = String.class.getMethod("charAt",int.class); System.out.println(methodCharAt.invoke(str,1));//b System.out.println(methodCharAt.invoke(str,new Object[]{2}));//c
Interface
<通过反射获取接口信息>
getGenericInterfaces()//返回表示某些接口的Type,这些接口由此对象所表示的类或接口直接实现。

getInterfaces//确定此对象所表示的类或接口实现的接口

c = Class.forName("Person");Class[] interfaces = c.getInterfaces();for(int i = 0;i<interfaces.length;i++){   System.out.println(interface[i].toString());}
SuperClass
<通过反射获取父类信息>

getSuperclass//  返回表示此Class 所表示的实体(类、接口、基本类型或 void)的超类的Class

c = Class.forName("Person");System.out.println("获得父类信息");Class sc = c.getSuperclass();System.out.println(sc.toString());
Array类
<Array工具类>
Person[] persons = new Person[]{new Person("张三",18);new Person("李四",19);new Person("王五",20);};System.out.println("对象数组的长度:"+Array.getLength(persons));//对象数组的长度:3Class c2 = Person.class;//c2是一个类类型。System.out.println("是否是数组类型:"+c2.isArray());//是否是数组类型:falseClass c = persons.getClass();System.out.println("是否是数组类型:"+c.isArray());//是否是数组类型:true//使用Array类遍历数组for(int i=0;i<Array.getLength(persons);i++){System.out.println(Array.get(persons,i);//姓名:张三,年龄:18//姓名:李四,年龄:19//姓名:王五,年龄:20}

【总结】反射就是对java所有类(包括接口)、方法、属性的一个映射表现形式,可以对所有类、方法、属性进行操作, 使得java语言更加灵活,更易于对事物的操作和描述,既而更深化它本身成为面向对象语言的特性。反射重点在Class、Field、Construct、Method、Interface、SuperClass、Array等的描述,灵活运用以上的类及方法,反射基础这一关应该就过了!!!

---------------------- Android培训、java培训、期待与您交流! ----------------------详细请查看:www.itheima.com

0 0
原创粉丝点击