深入理解反射

众所周知,如果没有了java的反射,那么java中的框架将不复存在,所以当我们学好了反射以后对我们日后学习框架是有很多的帮助的,下面,我把我学反射的一些总结分享给大家。

刚接触反射的时候感觉它真是太帅了,尤其是暴力反射我感觉真的很牛x(下面我会介绍的),其实反射说白了点讲,就是通过java中给我们提供的一些类和方法,将我们类的字段、方法以及各种成分映射成相应的它们给我们提供的类和方法。

Class类为反射的基石,下面我将介绍三种方式获得Class对象的方式:

//以String类为例,获得其字节码对象,首先我们定义一个String对象

String str = "getClass";

//第一种方式

Class stringClassOne = str.getClass();

//第二种方式

Class stringClassTwo = String.class;

//第三种方式,forName()方法的参数必须是包名和类名

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

//但是,当我们通过上面的方式获得了字节码对象以后,我们可以怎么用这个对象呢?

String str = "reflect";

//这个方法判断当前的类型是否为原始类型

System.out.println(str.getClass().isPrimitive());

//我们可以看出Integer和int的字节码文件并不是同一份,但是Integer.Type得到的是原始类型的字节码文件

System.out.println(Integer.class == int.class);

System.out.println(Integer.TYPE == int.class);

//通过Class对象看是否为一个数组类型

System.out.println(new int[2].getClass().isArray());

//通过Class对象得到当前对象的类型

System.out.println("The class of " + str +" is " + str.getClass().getName());

//但是上面的getName()这个方法有几点我们应该注意

//首先,如果此类对象表示一个基本类型或 void,则返回的名字是一个与该基本类型或 void所对应的 Java语言关键字相同的 String。

System.out.println(int.class.getName());

System.out.println(void.class.getName());

/*

* 如果此类对象表示一个数组类,则名字的内部形式为:表示该数组嵌套深度的一个或多个 '[' 字符加元素类型名。元素类型名的编码如下:

*  元素类型名   编码

boolean     Z

byte     B

char     C

class or interface Lclassname;

double     D

float     F

int     I

long     J

short     S

*/

System.out.println(new Object[3].getClass().getName());

System.out.println(new int[3][4][5][6][7][8][9].getClass().getName());

//下面,我们可以通过Class的实例对象创建一个对应的类的实例对象:

@SuppressWarnings("unchecked")

//得到String类型的Class对象

Class<String> stringClass = (Class<String>)Class.forName("java.lang.String");

//通过这个Class对象得到一个构造方法,但是构造方法参数类型并不相同,所以我们给这个方法一个参数

Constructor<String> con = stringClass.getConstructor(char[].class);

//用这个构造方法创建一个String类型的实例,参数要与上面给的参数类型相对应

String newValue = con.newInstance(new char[]{'j','a','v','a'});

System.out.println(newValue);

//我们也可以通过Class的实例对象创建一个String类型的实例

//这种方法是用缓存一个无参数的构造方法实现的,所以,由此看出,反射是比较消耗性能的

String str = stringClass.newInstance();

System.out.println(str.length());

下面我们得到对象身上的字段:

public class ClassTest {

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

Point point = new Point(13,14,"javareflect","man");

@SuppressWarnings("unchecked")

Class<Point> pointClass = (Class<Point>) Class.forName("com.java.day01.ClassTest$Point");

//因为y字段是public的,所以我们可以通过这种方式访问

Field yField = pointClass.getField("y");

int y = (Integer) yField.get(point);

System.out.println(y);

//通过下面的这种方式访问私有的字段

Field xField = pointClass.getDeclaredField("x");

xField.setAccessible(true);

int x = (Integer) xField.get(point);

System.out.println(x);

//我们也可以将其私有的字段更改,通过上面这种反射的方式,是不是很帅气!!!

System.out.println(point);

Field[] fields = pointClass.getDeclaredFields();

for(Field field : fields) {

if(field.getType() == String.class) {

field.setAccessible(true);

field.set(point, field.get(point).toString().replace('a', '$'));

}

}

System.out.println(point);

}

static class Point {

private int x;

public int y;

private String name;

private String sex;

public Point(int x, int y, String name, String sex) {

super();

this.x = x;

this.y = y;

this.name = name;

this.sex = sex;

}

@Override

public String toString() {

return "Point [name=" + name + ", sex=" + sex + "]";

}

}

}

下面我们得到对象身上的方法:

String str = "javareflect";

Class<String> strClass = (Class<String>) str.getClass();

//通过Class实例得到String对象的方法

Method method = strClass.getMethod("charAt", int.class);

//方法与对象是没有关系的,它是属于类的,是方法作用在某个对象身上

char printVal = (Character)method.invoke(str, 2);

System.out.println(printVal);

深入理解关于方法的反射

public class ClassTest {

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

//我们通过run配置,给主方法的数组赋值,从而得到其他类的类名,然后运行这个类的主函数

String className = args[0];

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

/*

* 由于jdk1.5之前并没有可变参数这一特性,以前invoke的第二个参数是一个Object数组类型,而高的jdk版本

* 必须向下兼容,所以当我们new一个引用类型的数组时,java会把他认为是一个Object类型的数组,从而导致程序

* 出错,所以我们自己new一个Object数组将正确的参数类型给放进去,这样程序就不会出错了,但是基本类型并没有继承

* Object类型,所以基本类型的数组并不存在这样的问题。

*/

mainMethod.invoke(null, new Object[] {new String[] {"hxl","znb"}});

Method m1 = Class.forName(className).getMethod("say",char[].class);

m1.invoke(null, new char[] {12});

}

}

class TestMain {

public static void main(String[] args) {

for(String arg : args) {

System.out.println(arg);

}

}

public static void say(char[] i) {

System.out.println("i am primitive type test");

}

}

关于数组的反射:

public class ClassTest {

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

//利用Array类实现数组的反射

Object obj = new int[] {12,14};

//将obj这个不知道的类型打印输出

if(obj.getClass().isArray()) {

int length = Array.getLength(obj);

for(int i = 0;i < length;i++) {

Object arrVal = Array.get(obj, i);

System.out.println(arrVal);

}

} else {

System.out.println(obj);

}

}

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 223,604评论 6 521
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 95,650评论 3 401
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 170,578评论 0 366
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 60,469评论 1 300
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 69,486评论 6 399
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,030评论 1 314
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,414评论 3 426
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 40,382评论 0 278
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,920评论 1 322
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,967评论 3 343
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,104评论 1 354
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,758评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,433评论 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,920评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,040评论 1 275
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,590评论 3 380
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,134评论 2 362

推荐阅读更多精彩内容