黑马程序员——java中的反射机制

 

 

---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------

1.      什么是Java中的反射?:

反射就是把java类中的各种成分映射成相应的java类。通过反射JAVA能够在运行状态中获取任意一个类的属性和方法。这种动态获取信息以及对象的方法的功能,称为java语言的反射机制。

2.       Java中反射的作用:

Java反射机制主要提供了以下功能:

a)      在运行时判断任意一个对象所属的类;

b)      在运行时构造任意一个类的对象;

c)      在运行时判断任意一个类所具有的成员变量和方法;

d)      在运行时调用任意一个对象的方法;

e)      生成动态代理。

Java反射机制容许程序在运行时加载、探知、使用编译期间完全未知的类。换言之,Java可以加载一个运行时才得知名称的类,获得其完整结构。

没有反射前,必须先有对象才可以通过对象调用类中的方法,从而达到对该对象进行操作的目的;有了反射之后,不需要创建对象就可以通过类的字节码文件获取类中的方法,之后可以把后来才创建的对象作为参数传入,从而达到对对象进行操作的目的;

3.       获取类的字节码实例对象:

获取类的字节码的实例对象的方式共有三种:

a)       类名.class

b)       对象名.getClass();

c)       Class.forName(“类名”);反射中最常用,类名可作为参数传入;

代码示例如下:

public class GetClassDemo {

       public static voidmain(String[] args) throws ClassNotFoundException{

              Stringstr="abc";

              Classc1=str.getClass();

              Class c2=String.class;

              Classc3=Class.forName("java.lang.String");

              System.out.println(c1==c2);   //返回结果为true

              System.out.println(c1==c3);       //返回结果为true

              System.out.println(c1.isPrimitive());  //返回结果为false

              System.out.println(int.class.isPrimitive());  //返回结果为true

              System.out.println(int.class==Integer.class);//返回结果为false

              System.out.println(int.class==Integer.TYPE);  //返回结果为true

              System.out.println(int[].class.isPrimitive());//返回结果为false

              System.out.println(int[].class.isArray());    //返回结果为true

       }

}

程序执行结果分析:a) 程序用通过三种方式获取了获取了String类的字节码实例对象,验证了三种方式获取的对象是同一个对象;b) isPrimitive() 方法可以验证对象所属的类是否基本数据类型,String类不是基本数据类型,int类是基本数据类型,int[] 不是基本数据类型;c) int.class Integer.class 不是同一个字节码对象;d) 可以通过isArray() 方法验证对象所属的类型是不是数组类型;

4.       Java类反射中经常用到的类:

Java的类反射经常用到的类有:ConstructorFieldMethod

Constructor类:封装了反射类的构造方法,提供了类的构造方法的信息以及访问权限。

Field类:封装了反射类的属性,提供了有关类或接口的属性的信息,以及访问权限。反射的字段可能是一个类(静态)属性或实例属性。

Method类:提供关于类或接口上单独某个方法的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。它是用来封装反射类方法的一个类。

5.       通过反射创建一个类的对象:

通过反射创建对象有两种方式:

a)     调用空参数的构造函数:使用了Class类中的newInstance()方法。

b)     调用带参数的构造函数:先要获取指定参数列表的构造函数对象,然后通过该构造函数的对象的newInstance(实际参数) 进行对象的初始化。

第二种方式,必须要先明确具体的构造函数的参数类型,不便于扩展。所以一般情况下,被反射的类,内部通常都会提供一个公有的空参数的构造函数。

通过反射创建一个类的对象代码示例如下,主要用到的内容和方法有Constructor 类,newInstance() 方法。

package advancedvideo;

 

import java.lang.reflect.Constructor;

 

public class GetConstructorDemo {

         publicstatic void main(String[] args)throws Exception {

                   Constructorconstructor1=Class.forName("advancedvideo.Person").getConstructor();

                   Constructorconstructor2=Class.forName("advancedvideo.Person").getConstructor(String.class,int.class);

                   Personp1=(Person)constructor1.newInstance();

                   Personp2=(Person)constructor2.newInstance("wangwu",30);

                   Personp3=Person.class.newInstance();

                   System.out.println(p1);

                   System.out.println(p2);

                   System.out.println(p3);

         }

}

class Person{

         privateString name;

         privateint age;

        

         publicPerson(){

                   this.name= "defaul:zhangshan";

                   this.age= 20;

         }

         publicPerson(String name, int age) {

                   this.name= name;

                   this.age= age;

         }

         publicString getName() {

                   returnname;

         }

         publicvoid setName(String name) {

                   this.name= name;

         }

         publicint getAge() {

                   returnage;

         }

         publicvoid setAge(int age) {

                   this.age= age;

         }

         publicString toString() {

                   return"name=" + name + ", age=" + age;

         }

        

}

6.       通过反射对一个类中的属性值进行设置和获取:

若要通过反射对类中的属性值进行设置和获取,主要使用到以下几种方法:

getfield(stringname): 传入的参数为属性的名称,可获得被public修饰的指定属性;

getfields(): 返回的是属性的数组,该方法可获得类中被public修饰的所有属性,包括父类;

getdeclaredfield(stringname): 获得类的特定属性;

getdeclaredfields():field[]:获得某个类的所有声明的属性,包括被publicprivateproteced修饰的,但是不包括父类的申明属性。

get(Objectobj):返回指定对象上此 Field 表示的字段的值。

set(Objectobj, Object value):将指定对象变量上此 Field 对象表示的字段设置为指定的新值。

下面通过反射对类中的公有和私有属性值进行设置和获取,代码示例如下:

importjava.lang.reflect.Field;

 

public classGetFieldDemo {

       public static void main(String[] args)throws Exception{

              ReflectDemo rd=newReflectDemo(3,4);

              Field fieldX=rd.getClass().getField("x");

              fieldX.set(rd, 10);

              System.out.println(fieldX.get(rd));      //获取非私有成员变量方法

              FieldfieldY=rd.getClass().getDeclaredField("y");

              fieldY.setAccessible(true);              //获取私有成员变量方法

              fieldY.set(rd,20);

              System.out.println(fieldY.get(rd));

       }

}

classReflectDemo{

       public int x;

       private int y;

       public ReflectDemo(int x, int y) {

              super();

              this.x = x;

              this.y = y;

       }

}

7.       通过反射调用类中的方法:

若要通过反射调用类中的方法,主要使用到以下几种方法:

getmethod(stringname, class... parametertypes): 传入的参数为方法的名称和方法所需的参数类型,可获得被public修饰的指定方法;

getmethods(): 返回的是方法类型的数组,该方法可获得类的public类型的所有方法,包括父类。

getdeclaredmethods():返回的是方法类型的数组,该方法可获得类中所有声明的方法,即包括被publicprivateproteced修饰的,但是不包括父类的声明的方法。

getdeclaredmethod(stringname, class ...parametertypes): 获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。

invoke(Objectobj, Object... args):传入的第一个参数为对象,即调用哪个对象的该方法,之后的参数为所调用的方法中所需的参数类型;

下面以String类型为例,获取并应用其中的charAt方法,代码如下:

importjava.lang.reflect.InvocationTargetException;

importjava.lang.reflect.Method;

 

public classGetMethodDemo {

       public static void main(String[] args){

              Method method1=null;

              try {

                     method1 =java.lang.String.class.getMethod("charAt", int.class);

              } catch (SecurityException e) {

                     e.printStackTrace();

              } catch (NoSuchMethodException e){

                     e.printStackTrace();

              }

              String str="abc";

              try {

                     System.out.println(method1.invoke(str,1));

              } catch (IllegalArgumentExceptione) {

                     e.printStackTrace();

              } catch (IllegalAccessException e){

                     e.printStackTrace();

              } catch (InvocationTargetExceptione) {

                     e.printStackTrace();

              }

       }

}

 

---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------

详细请查看:<a href="http://edu.csdn.net" target="blank">http://edu.csdn.net</a>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值