反射

反射的介绍

   说道反射,我想起第一次接触的时候是在自学Java的时候,不知道算不算是Java的高级部分,还有当时的jdbc。说下我当时使用反射的例子吧,也侧面说明了反射的用处和好处。但是用Java写过一个俄罗斯方块和坦克大战,其中我当时是这样使用反射的。就说俄罗斯方块吧,界面中有好多正方形或者长方形的窗口,每个窗口里的显示的内容不一样,每一个框框其实是都是一个很小很小的图片经过切割和拉上组合成的(这个Java里的不说了),我就是想说在主界面中有好多需要小窗口需要在主界面的画笔下画自己的界面。每个窗口去继承父类,去重写自己的draw方法,然后把这些窗口的类(包括全类名、位置啥的)写在一个xml文件里(当做配置文件),然后在主界面的draw里去通过外部的配置文件去反射实例化出这些窗口类,然后通过反射找到各自的draw方法去调用。你知道这样有什么好处吗?当你把Java这个程序做成exe可执行程序时,要是想在界面中再显示一个框框或者内容,直接在安装目录中找到配置文件,然后加上一行信息(指定全类名和位置),什么都不用管,也不用编译,在打开程序的时候,你会惊奇的发现,恩,多了一个新的界面窗口内容.....不知道你们能在这个例子里提取到反射的哪些好处呢?
  是不是很灵活呢
  而且反射也符合高内聚和低耦合。

   简单的说, 反射机制就是程序在运行时能够获得自身信息,在Java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息。

反射的基本使用(简单明了)

  在这里我尽量以最简单介绍给大家怎么使用
  首先我们要了解三个反射包里的类:

* 

Constructor : 代表类的单个构造方法,通过Constructor我们可以执行一个类的某个构造方法(有参或者无参)去构造一个类
*
Method : 代表类中的单个方法,可以用于执行类的某个普通方法,有参或者无参,并可以接收返回值。
*
Field : 代表类的单个属性,用于得到或者设置该属性。
*
AccessibleObject : 以上三个类的父类,提供了构造方法,普通方法,属性的访问控制的能力(即通过反射访问到类中私有的构造方法、方法、属性)。

   在这里我还想说以点,也很重要的一点:
          在写代码的时候不管去得到构造方法还是方法还是属性,都会有两个类似的方法,一个是getxxx(), 另一个是getDeclaredxxx()。 这两个有非常非常明显的区别,一定要记好了,getxxx();只能得到类中公开,而getDeclaredxxx()除了得到公共的还可以得到私有呀。

我们通过例子来说:

用于测试的类,测试涉及到的如下:
*
私有属性
*
公共的构造方法
*
私有的构造方法
*
带参数的构造方法
*
公共的方法
*
带有参数的公共方法
*
私有方法
*
带有参数的私有方法
*
带有返回值的方法

package cn.xiaoxige.a2017_2_28demo.demno1;

/**

  • Created by 小稀革 on 2017/3/2.
    */

public class User {

private String name;
private boolean sex;

public User() {
}


private User(String name) {
    this.name = name;
}

private User(boolean sex) {
    this.sex = sex;
}

public User(String name, boolean sex) {
    this.name = name;
    this.sex = sex;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public boolean isSex() {
    return sex;
}

public void setSex(boolean sex) {
    this.sex = sex;
}

public void saySomething() {
    System.out.println("我是 " + this.name);
}

public void saySomething(String say) {
    System.out.println("我想说:" + say);
}

private void doSomething(String thing) {
    System.out.println("我在做 " + thing);
}

private void doSomething() {
    System.out.println("我什么都没做...");
}

}

第一步什么都不要说,先Class.forName(String);新建一个Class 类,其中一定要注意参数为全类名,因为一个程序中唯一的能准确的找到一个类就是包名+类名了。
Class clazz = Class.forName(“cn.xiaoxige.a2017_2_28demo.demno1.User”);

   通过Class 类去找到并加载构造方法,我们先不去说代码,就现在想想应该怎么做吧,每一个构造方法的名字都是一样的哦,我们怎么才能去知道一个唯一指定就是调用哪一个构造方法呢,想到Java的重载方法了吗?对就是靠的是参数的类型或者多少!

得到公共没有参数的构造方法:

Constructor declaredConstructor = clazz.getDeclaredConstructor();

通过得到的构造方法去实例化该类:

Object o = declaredConstructor.newInstance();

对了,这么简单就可以了,现在这个 o 就是User通过没有参数实例化的对象了,比如下面的简单调用来验证:

Constructor declaredConstructor = clazz.getDeclaredConstructor();
Object o = declaredConstructor.newInstance();
((User)o).saySomething();

那么带参数的构造方法怎么去实例化一个类呢?
先得到带一个参数且参数类型个是是String类型的构造方法

Constructor constructor =
clazz.getDeclaredConstructor(String.class);

通过构造方法去实例化对象:

Object xiaoxige = constructor.newInstance(“xiaoxige”);

这样就可以了吗? 不可以!!!

首先你要注意一下几点呀:
*
我们一定要注意到这个String 参数的构造方法是私有的哦
*
我们一定要用getDeclaredConstructor(…),去得到构造方法,因为是私有的,不然会报找不到该构造方法的错误

在这里是会报错的,因为我们没有权限去访问的,Ok
我们要把权限给取消了!!!

constructor.setAccessible(true);

对,这样就 可以了。通过这样就实例化了一个带有String参数的类了。

我们该如何去访问方法呢:

对我们要使用Method这个类了,去用Class去得到里面所有方法或者我们指定的方法。

得到saySomething方法:

Method saySomething = clazz.getDeclaredMethod(“saySomething”, String.class);

好了这些就和构造方法一样了,所以就不在多说了,得到方法后我们去调用这个方法了:

saySomething.invoke(xiaoxige, “今天是个好日子…”);

调用带有参数的私有方法并使用:

Method method =
clazz.getDeclaredMethod(“doSomething”);
method.setAccessible(true);
method.invoke(xiaoxige);

至于属性:其实都一样,代码如下:

Field name = clazz.getDeclaredField(“name”);
name.setAccessible(true);
name.set(xiaoxige, “hahahahahahhaha”);

Method saySomething1 = clazz.getDeclaredMethod(“saySomething”);
saySomething1.setAccessible(true);
saySomething1.invoke(xiaoxige);

这样给私有参数赋值,然后又去调用方法验证。

最基础的使用就这样说完了,在使用反射的时候一定要注意:
1.
Class.forname(…), 参数一定要是全类名
2.
要得到所有方法一定要调用getDecalredxxx()
3.
调用私有的属性一定要把权限关闭了:设置setAccessible(true)为true。

参考资料:
http://blog.youkuaiyun.com/a997208868/article/details/48133129

   JDK API
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值