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

来源:互联网 发布:yes淘宝刷信用 编辑:程序博客网 时间:2024/06/05 13:28

---------------Android培训、java培训、期待与您交流---------------


反射技术


一、Class类

    Class类代表java类,它的各个实例对象对应各个类在内存中的字节码。

一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是字节码,

不同的类的字节码是不同的,所以它们在内存中的内容是不同的,这一个个的空间分别用一个个的对象来表示。

获取字节码实例对象Class类的方法:

方式一:

    通过对象的getClass方法进行获取。

    麻烦在于每次是不是都需要具体的类和该类的对象,以及调用getClass方法。

Person p = new Person();

Class clazz = p.getClass();

方式二:

    任何数据类型都具备着一个静态的属性class,这个属性直接获取到该类型的对应Class对象。

    比第一种简单,不用创建对象,不用调用getClass方法。

    但是还是要使用具体的类,和该类中的一个静态属性class完成。 

Class clazz = Person.class;

方式三:

     这种方式较为简单,只要知道的类的名称即可。

    不需要使用该类,也不需要去调用具体的属性和行为。

     就可以获取到Class 对象了。 

    这种仅知道类名就可以获取该类字节码对象的方式,更有利于扩展。

String className = "cn.itheima.bean.Person";

Class clazz = Class.forName(className);

总之,只要在源程序中出现的类型,都有各自的Class实例对象。


二、反射技术概念

    JAVA反射机制是在运行状态中对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,

都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

反射技术可以对类进行解剖。

反射就是把java类中的各种成分映射成相应的java类。

    表示java类的Class类提供了一系列的方法来获得其中变量、方法、构造方法、包等信息。

变量---------Field

方法---------Method

构造方法-------Contructor

包------------Package

通过Class创建对象

以前的方法:

1、查找并加载Person.class文件进内存,并将该文件封装成Class对象。

2、在依据Class对象创建该类具体的实例。

3、调用构造函数对对象进行初始化。 

Person p = new Person();


三、反射方法:

1、查找并加载指定名字的字节码文件进内存,并被封装成Class对象。

2、通过Class对象的newInstance方法创建该Class对应的类的实例。

3、调用newInstance()方法会去使用该类的空参数构造函数进行初始化。

String className = "cn.itheima.bean.Person";

Class clazz = Class.forName(className);//一下的clazz都是这个类clazz

Object  obj = clazz.newInstance();

//Object obj = Class.forName("cn.itheima.bean.Person").newInstance();

    如果指定的类中没有空参数的构造函数。

    或者要创建的类对象需要通过指定的构造函数进行初始化。

    既然要通过指定的构造函数进行对象的初始化。

    就必须先获取这个构造函数。

//获取指定类中的指定的构造函数。

    Constructor constructor = . Class.forName( "cn.itheima.bean.Person").getConstructor(String.class,int.class);

//创建对象。对象的建立都需要构造函数的初始化。 怎么创建对象可以通过构造器对象完成。

    Object obj = constructor.newInstance("lisi",20);

//获取指定类中的指定的构造函数。

    Constructor constructor = clazz.getConstructor(String.class,int.class);

//创建对象。对象的建立都需要构造函数的初始化。 怎么创建对象可以通过构造器对象完成。

    Object obj = constructor.newInstance("lisi",20);

获取Person类中的age字段:

    Field ageField =Class.forName("cn.itcast.bean.Person").getDeclaredField("age");

改变变量赋值:

必须先要有对象

    Object obj = Class.forName("cn.itcast.bean.Person").newInstance();

对该私有字段进行取消权限检查的能力。

    ageField.setAccessible(true);//暴力访问。

    ageField.set(obj, 19);

    Object o = ageField.get(obj);

获取类中的公共,空参数的方法

    Method method = clazz.getMethod("toString", null);

    Object obj = clazz.newInstance();

    Object returnValue = method.invoke(obj, null);

带参数的方法:

    Method method = clazz.getMethod("function", String.class,int.class);

    Object obj = clazz.newInstance();

    method.invoke(obj, "haha",89);

获取静态方法:

Method method = clazz.getMethod("show", null);

method.invoke(null, null);//静态空参时

用反射方式执行某个类中的main方法:

写一个程序,能根据用户提供的类名,去执行该类中的main方法

普通方法:

TestArguments.main(new String[] ("11","22"));

反射方法:

String startingClassName = args[0];

Method mainMethod = Class.forName(startingClassName).getMethod("main",String[].class);

方法解决一:mainMethod.invoke(null,new Object(new String[]{"11","22"});

方法解决二:mainMethod.invoke(null,(Object)(new String[]{"11","22"});

(Object) 编译器会作特殊处理,编译时不把参数当作数组看待,也就不会把数组打开散成若干个参数了。


数组的反射

    具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。

代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class。

    基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用。

    非基本类型的一维数组,既可以当作Object类型使用,又可以当作Object[]类型使用。

Array工具类用于完成对数组的反射操作。

Array.getLength();//获取长度

Array.get(obj,i);//获取元素

反射的作用:实现框架功能

因为在写程序时无法知道要被调用的类名,所以在程序中无法直接new某个类的实例对象,要用反射来做。

hashCode与HashSet

    HashSet就是采用哈希算法存储对象的集合,它内部采用对某个数字n进行取余的方式对哈希码进行分组和划分

对象的存储区域,Object类中定义了一个hashCode()方法来返回每个java对象的哈希码,当从HashSet集合中

查找某个对象时,java系统首先调用对象的hashCode()方法获得该对象的哈希码,然后根据哈希码找到相应的

存储区域,最后取出该存储区域内的每个元素与该对象进行equals方法比较,这样不用遍历集合就可以得到结论。

因为不能修改原程序,所以提供properties配置文件,只需要写入类名,就可以查找给定名称的类文件,

1、加载这个类

2、创建该类的对象

3、调用类中的内容

部分代码:

InputStream ips = FileInputStream("config.properties");

Properties props = new Properties();
props.load(ips);
ips.close();
String className = props.getProperty("className");
Collection collections = (Collection)Class.forName(className).newInstance();






0 0
原创粉丝点击