JavaSE——反射机制(二)

声明:本栏目所使用的素材都是凯哥学堂VIP学员所写,学员有权匿名,对文章有最终解释权;凯哥学堂旨在促进VIP学员互相学习的基础上公开笔记。

Class管理类的其他方法

类的结构如下:

这里将类的结构划分开来了,m表示方法method,f表示属性filed,没有标识返回值的方法表示是构造器

绿色的锁表示权限公开public,红色的锁表示权限私有private

接下来将使用反射机制对类的构造(f,m)全部操作一遍,不论属性或方法,私有或其他权限!

代码示例:

第一件事情,加载类:

Class cls = Class.forName("com.kaige123.daomu.Dog");

可以做的操作:

实例化对象:

1:Object obj = cls.newInstance();

得到的是Dog类对象

2:查看这个实例化对象的方法,如果是有参构造器怎么解决?

解决办法:

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

Object object = constructor.newInstance("小黑狗", "旺财", 1);

getConstructor搜索到某个构造器,返回构造器对象,newInstance实例化出对象

搜索构造器的参数,需要明确:

构造器以及方法不能靠名字搜索因为:重载。需要靠名字以及参数类型和个数定位到方法

这里面是集合参数Class<T>...于是这里的搜索:可以传多个类型的class。他通过传递的类型class以及个数,找到构造器,返回构造器对象,如果找不到抛找不到异常。

如果是基本数据类型,也是传int.class....其他基本数据类型也是

返回构造器对象后,通过构造器对象.newInstance实例化Dog对象

这里介绍了两种实例化对象的方法:有参无无参构造器。无参newInstance实例化,有参找到构造器newInstance实例化。

对象可以实例化出一份。但forName加载的类只有一份。类模板只有一份,重复加载,也是使用加载过的这个类。但对象可以创建出多个。这两个观点不冲突。

操作方法:

实例化出Dog对象,如何操作方法?返回的实例对象Object要转子类吗?并不是的,如果转子类,又回到死代码。

如果子类有独特的方法,父类没有声明,怎么办?需要明确一点,转了子类,再次依赖子类,死代码。想办法划分多个声明,转子类的父类声明也比转子类强。这里按照情况斟酌办法。

这里操作方法代码是:

cls.getMethod指定搜索某个方法,返回方法对象。

这里也需要明确:方法不能仅靠名字判断,因为重载。还需要参数类型以及参数个数。

getMethod(name,paramter...)方法的名字,集合参数(可以传递n个参数)根据方法的名字,参数的类型以及个数,定位到方法,类型以及个数可以避免方法重载的情况

搜索到方法后,返回的方法对象method。

如果是静态方法,发起调用method.invoke(null,null)

如果是实例方法,发起调用method.invoke(object,null)

如果是实例有参方法,发起调用method.invoke(object,param...)

invoke调用方法:前面是调用谁的方法,后面是给方法传递的参数(需:方法有参)

如果是静态,当cls.getmethod在invoke,第一个参数传递null,表示cls类的调用 如果是实例,当cls.getmethod在invoke,第一个参数传递对象,表示对象的调用 如果是有参,invoke传递参数,无参则null。传递的参数给方法形参接收,不是传class

静态传null,表示是类发起调用。如果是实例方法,就需要传递对象,使用对象发起调用。当然静态传对象也行,表示用对象调用静态方法。

如果方法有返回值,前面写上接收的变量即可。 如果方法有形参,paramterType写上类型.class。便于从重载中定位。

我们不难发现,在搜索构造器与方法都有一个参数,那就是paramterType...参数类型(集合)。因为单靠名字不敢搜索,还需要参数的类型以及个数。

这个paramterType是集合参数,我们可以一直往后面添加类型.class。但我们这样直接往后面添加参数可取吗?

不可取!这样直接写不可变!这个应该随要搜索的方法走,要搜索出不同的方法,这里要变!这里的集合参数,不仅是可以直接往后面传参,集合要求可以接收数组类型!我们为了灵活应该使用数组,随需求可以改改,这样可以搜索出不同的方法,如果写参数就定死了!

实例:

Class[] classes = new Class[]{String.class, String.class, int.class};

Constructor constructor = cls.getConstructor(classes);

避免直接给方法传类型.class,来寻找。这样是死的,很明显。当我们使用数组,数组可以随我们改变,于是这样后就可以随着数组的class及个数变化而能搜索出不同的方法。

操作私有属性:

我们从类的构造中,可以得到age属性是私有的

从类中搜索属性:

搜索公开属性:cls.getField(name)

搜索私有属性:cls.getDeclaredField(name)

于属性来说,没有像方法一样,方法可能存在方法重载,需要靠方法名字以及方法参数类型及个数来定位方法。而属性在整个类来说,凭属性名就能定位到属性了。

于是搜索只需要属性名即可,从Class类中搜索,不依靠不对Object操作。这是Dog类这也是Object类。如果直接对Object也便于于以后操作。这里使用反射还能灵活的搜不同属性。

从Class类Dog类的管理类搜索出属性后,这是一个私有属性,如何操作?

首先需要setAccessible,true设置对私有属性产生操作

当设置这个后,就可以直接操作这个搜索出来的属性了。返回的Field对象

比如:

能不经过setAge方法直接给属性赋值。Set(object,value);

能不经过getAge方法获得属性赋值。get(object);

如果是静态属性,则不需要object获得的实例对象。表示从类发起操作

如果是实例属性。则需要传入实例的对象。表示从对象发起操作

操作公开也是这样,不过方法改为getFiled即可。也不需要设置setAccessible权限。

操作私有方法:

操作私有方法也是雷同,getDeclanMethod搜索私有方法,setAccessible设置权限,在操作。

总结:

实例化对象,分有参无参构造器:

无参可以直接使用Class类的管理类调用实例化方法,从类中加载一个对象出来。

有参需要从Class管理类(=Doge)类搜索到指定构造器,由构造器对象构造对象出来。

操作公开方法:

Class.getMethod(name,...)根据名字与参数类型个数,拿到找到的方法对象

Invoke(obj,value)调用方法:如果是静态可以不传对象(由类)。如果是实例需要传对象(由对象)。

如果方法有返回值,在invoke前准备接收的变量接收。

操作私有的方法,与前面大致一致,额外改变:

由getMethod改成getDeclareMethod。在invoke前Method.setAccessible让私有允许调用

操作公开属性,与操作方法一致,额外改变:

getField(name);根据属性名就能搜到属性,返回Field对象。

属性可以Field.get(obj)得到值,可以Field.set(obj,value)设置值。

如果是静态属性,则不需要obj由类对Filed对象发起操作

如果是实例属性,则需要obj由对象对Filed对象发起操作

操作私有属性,与前面大致一致,额外改变:

由getField改成getDeclareField。在操作前Field.setAccessible让私有属性允许操作

观察,实例化返回Object基本没有任何操作。我们的操作是通过Class锁定要操作的对象,进行操作。Object让他一直保持父类,由类的管理类操作对象。

当给实例属性或方法赋值,才需要obj实例后对象帮忙。因为一个加载的类,可以构建出多个对象,不知道给哪个对象赋值。我们赋值也保持Object父类,通过Class管理类传递对象,给对象上赋值,将一直保持Object类,通过Class对Object对象及类操作。都是为了灵活。

搜索方法是集合参数,因为单靠名字无法确定方法,构造器也是。需要靠方法需求的参数类型.class再靠集合参数的个数定位到方法,构造器也是。集合参数我们不直接写参数的class,通常是传递写好的Class[]过去。为了可变,改变数组引用,就能搜索不同的实例。

需要明确一点,我们不直接操作对象,通过Class管理类,搜索到操作的对象。如果是静态,直接操作表示由Class操作。如果是实例传递obj对象,表示要操作这个对象的这个实例。传递对象因为一个类可以造多个对象。需要明确类模板只有一个。

他静态与实例的关系如下图:

如果是null,反正搜索我Field的对象是Class,表示是得到Class身上的静态属性

如果是obj,表示是得到对象身上的这个Field对象属性的值。

这就是传null与obj的区别,一个是从类操作,一个从传递的对象身上操作对象。

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

推荐阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,670评论 0 9
  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,802评论 6 13
  • #还乡手记# 一个教师的返乡手记 我的老家在豫南盆地的一个县城唐河。这里是中国哲学大师冯友兰的故乡,冯友兰都不用介...
    山上石头阅读 1,639评论 4 8
  • 第一次发文,略激动。真实原创 事情是这样,我是一个热血质的微胖女生。因为我想减肥,所以当我看到每天晚上操场上热闹的...
    风淡淡的吹过阅读 408评论 2 2
  • 最近几部迪士尼的动画风格与以前迥然不同,每一部的内容都愈发的深刻,不再是那种王子公主的简易格局,而是朝着多元化的方...
    尚巾林阅读 324评论 0 0