00:00
那接着的话呢,咱们来看一下这个第17章啊,叫做反射机制,前面的话呢,我们再讲到,比如说做线程是来解决什么问题的是吧,集合解决什么问题的,L流解决什么问题的,可能我们一两句话呢,都比较形象的能够给大家呢做一个说明,那么关于这个反射机制的话呢,一两句话呢,好像就说不太清楚了。啊,那这块呢,我们来打开看一看,说这一张呢,我们是想解决什么样的问题。诶,这呢是我们这一章呢,对应的几个小的主题,这个我们就先不说,这个说完之后呢,大家现在也是有点懵哈,咱们直接呢就来看看反生呢要解决什么样的问题。OK,那这呢是从我们这个语法这个层面呢,我们做的一个引入哈,所以呢,在这个Java程序当中,咱们所有的这个对象啊,实际上呢,算是有两种类型,第一种呢,就是你编译时候的一个类型,第二呢,就是你实际运行时候的一个类型。很多时候呢,我们发现呢,边行时的类型和运行时的类型呢,是不一致的,实际上呢,这呢,不就是我们所谓的一个多肽吗。没问题是吧,呃,你比如说我们这个呢,在声明的时候啊,我在这简单写个代码啊,这呢是一个object类型,然后实际上呢,你在运营的时候呢,发现你这个务必接啊。
01:07
就是拿拿着一个对的一个字符串呢,负的值。啊,比如这块写个叫hello了,那么编译时的类型呢,咱们的OB那就是object,那运营式的这类型呢,就是string类型的。所以呢,两个类型呢,不一致是吧,那比如说我们在程序当中需要调用该对象运营时类型的方法。啊,那怎么办?你比如说我这块想调一个obj的一个叫compare to的一个方法。这呢,在object当中显然是没有声明过的。说白了,我就想调用人家实打实运行实这个类型的一个方法了。怎么解决这个问题呢?啊,这块呢,提到有两种解决方案,这个方案一呢,也是咱们前面呢,在讲多肽的时候呢,我们用到的一种方式了,那就是向下转型。哎,咱们呢,先使用这个instance of呢进行判断,说呢,你这个V啊,是不是一个string类型的啊,是啊,你要是的话呢,我就强转了。
02:02
上传完以后,诶,我们就可以调用词缀呢,你特有的这些方法了。啊,当然呢,我们要是真正的按照这种方案去实施的话呢,第一个点,我们在代码中呢,你可能会写比较多的这种森错误的这个判断。是吧,这个我们需要写比较多这个判断,第二点的话呢,很多时候呢,可能我也不是特别确定,你写的这个判断呢,是不是就全了,是不是能够满足我们的需求了,万一要是另外又多了一些不确定的一些结构怎么办呢?什么意思啊,你比如说我们这儿呢,现在已经写好这个代码了,这个代码已经写好了啊,然后呢,它的这个行参呢,就是一个object。哎,形态上就是我们这这个类型的,然后呢,在里边呢,我们拿这个V呢去判断说你是不是A类型的,是的话呢,诶里边进去强转,然后呢调方法说你是不是这个B类型的,是不是这个C类型的,好目前的话呢,咱们这个程序当中,哎,我们就会考虑放进去ABC这样三个类的对象,所以你就写了这三了。但是我们后期的话呢,有可能我们又创建了这个DEF啊。
03:04
哎,那么DEF的话呢,也有可能作为参数传进来,那你这个代码这块呢,你得及时的去修改,你要不修改的话呢,这不就不适配吗。是吧,这样的话就比较尴尬一些,那说有没有更好的一种方案呢,来解决这个问题呢?诶这个呢,自然而然的我们就考虑这个方案二了,所以呢,我们希望呢,在程序运行的过程当中。哎,已经运行了,就我们这个O呢,已经在内存里了,我呢可以动态的去获取当前你这个OB呢,它所属的这个类的一个类型。说你这是个对象,你这对象呢,你是哪个类造的呀,是吧,我希望呢,动态的来获取,那一旦动态的获取以后,我知道是哪个类了,那我就把你及时性的转成这个类的一个。声明是吧,比如说我们去判断说这咱们前面呢,也接触过这样的场景了啊,诶我们在运行的过程当中,我调这个oga一个呢,叫get class是吧。这个时候呢,我是不是就获取了它所属的类了。
04:01
诶,我知道你是哪个类之后呢,诶,我就考虑呢,把咱们当前以生命为OB的这个声明的这个变量呢,改成这个类型的。但一旦你改成这个类型之后呢,这个类型里边呢,特有的方法你不就能掉了吗。是吧,诶就是根据运行的时候呢,我们动态的获取它的一个真实的信息,然后呢,我们再去呢,动态的给他做个转换,再去调它特有的一些方法,那么这个操作呢,其实呢,就需要用到我们的反射。或者说呢,我们这个位置调的这个OBg.get class这个方法,虽然说呢,这个方法呢,是在我们这个当中声明的,那它呢,也可以看作是咱们反射的一个现向源头的一个操作了。OK,这呢,就引入了我们反射的内容。啊,通过这个呢,大家简单的去体会一下,我们为什么要讲反射这个事儿啊,其实这里边儿呢,就提到了一个叫动态性。哎,动态的获取在运行时候呢,它的一个类型。啊,那这种动态性啊,其实也就决定了反射这个内容啊,目前呢,咱们都讲到Java这个基础的最后阶段了,在前面的当中,我们似乎呢,说不用到反射也没什么关系,前面呢,就是我们讲这个语言的核心的一些语法和主要的一些使用场景了,所以说这个反射呢,在咱们日常开发当中哈,咱们自己写代码的时候呢,其实用的是比较少的。
05:16
啊,那什么时候用的多呢?因为它是一个动态性体现的,就是比较灵活了,所以呢,我们在后期的框架当中用的就比较多一些。因为框架的话呢,它可以适配我们各个开发的这种场景,那就意味着我们这个框架呢,写的就要通用一些了,但是呢,你又没办法写的特别细。因为呢,你不知道你具体做的是什么样的业务,那这儿呢,我们就希望呢,体现它这种动态性,呃,灵活的根据在运行的时候呢,判断它相关的类型,然后呢,我们再去调相关的一些功能方法。诶,所以这块呢,再强调一下啊,总结一下就是在我们平时的开发当中啊,在业务代码的开发当中啊,我们用反射呢,用的是比较少的,但是呢,我们如果使用相关的一些框架,包括第三方的一些这种炸包的时候呢,你会发现呃,他们的底层呢,就大量的使用了反射了。
06:04
那如果说呢,后边我们除了能够使用框架之外呢,你还想看一看这个框架的源码是什么样子的,需要更深入的去了解这个框架的底层,这个时候呢,你就有必要呢,去接触这个反射,或者叫熟悉这个反射的内容了。再换句话说呢,以后呢,如果你要参与到这个框架的开发当中,是吧,那你肯定是要会反射的。哎,这个呢,就是我们说反射它的一个特点啊,这呢有一句话呢,去介绍它说反射对应的英文呢,叫reflection,被视为动态语言的一个观念,反射机制呢,允许程序在运行期间。运行期间啊,借助于反射相关的API取得任何类的内部信息,并能直接呢操作任意对象的内部的属性和方法。啊,任意的属性和方法。哎,跟我们这个对象的这个属性方法的权限呢,甚至都没有关系。啊,还是有点强大的是吧,好,那下边呢,咱们在展开讲解这个反射之前啊,咱们先给大家呢,举一个例子,让大家能够直观的去感受一下反射呢,它能做什么啊,因为这一章呢,相对来说呢,有点难度,或者说呢,有点抽象啊。
07:10
好,这呢是我们新建的两个这个module啊,这个过来以后呢,它这块报错里边呢,因为我使用了这个单元测试方法了,Al加个回车,哎,我们这样点一下啊OK。好,下边这个我们也同样的这样的去处理。哎,这样啊。哎,奥加个回车,哎这样。好,这就可以了啊行,然后呢,这个代码的话呢,咱们就在下边这个Mo中去写了,在上边这个呢,就大家呢练的时候呢,就打开上面这个来练啊好,然后呢,这个module的话呢,我们首先呢看第一个啊X501啊example咱们呢先啊写个例子啊,这个例子的话呢,对应的一些问题呢,咱们一边写一边说。首先这块呢,我提供了一个类啊,这个类呢比较简单,所以我就提前写好了,简单咱们看一看啊A里边呢,有属性,有构造器,有方法。然后呢,这个属性的话呢,有权限比较小的,有权限比较大的构造器呢,有public的,有private的方法,同样的道理。
08:06
好,那么基于我们这两个类啊,我们看看啊,咱们写了一个具体的代码。这呢是一个这样词,或者你叫reflection是吧,也可以。行,这儿呢,我首先写一个单元测试方法。这个第一个的话呢,我们来演示一下,在有反射之前我们能做什么事,然后呢,使用反射呢,我们考虑做同样的这个事儿。OK啊。说呢,这个使用。反射之前啊,可以执行的这个操作。好,那我们能做什么操作呢?针对咱们这里边儿提供了一个person类呢,首先哎,我们提到了。诶,我们可以呢,去创建咱们person类的实例。啊,这是第一个事儿啊。Person类的这个实例,或者我们要创建person类的对象也可以,然后呢,我们打开以后啊,这个时候呢,我们在其他的这个类里边呢,想调用它这里边这个构造器了,哎,需要考虑到权限的一个问题了啊,比如这块我们就直接呢调用它这个public,哎,空餐的这样的一个构造器。
09:11
哎,咱们这直接我就放到这儿吧。哎,这么着啊好,那我就呢想调用一下这个构造器。嗯,来这边我们就直接写了啊声明呢,就个person,我叫P啊new一个person,诶这就完事了,这呢是我们第一个能做的事,然后第二个呢,我们呢,有了这个对象之后呢,咱们可以调用当前这个类当中的属性和方法。所以下边我们先演示一下调用这个属性的问题。那我们这个类里边呢,有权限比较大的这个A值嘛,所以我们就可以调这个A值了,通过这个P1呢,咱们去A值先赋一个值,比如叫十,这呢是一个赋值操作了,然后对应的我们还可以呢去获取它的值。哎,这个都比较简单了,好这个呢,我们是针对的咱们这个叫age的这样的一个属性的一个调用啊。好,下边的话呢,我们还可以呢,去调用它的方法。
10:02
方法这块的话呢,往下走这呢,有一个叫哎售的一个方法,是一个public权限的,那咱们就调它。啊,其实也比较简单直接呢,通过这个PE呢,我们调一下这个数呢,这不就可以了,这呢有它的对应的一个输出的一个语句,行这个事儿的话呢,大家应该是非常熟悉的,那咱们运行一下。嗯,没问题是吧,上面这块呢,我们在造对象的时候呢,在构造器当中,这有一个输出语句,哎,所以它也就出来了,这呢是调属性,这呢是调方法。啊,这都挺好啊行,这个内容大家很熟悉,然后下边的话呢,我说呢,使用反射呀,我可以做上边相同的这个事儿。哎,所以这块我们说呢,使用反射完成。哎,上述的这个操作。啊,这呢,我们写个二啊。啊,那首先呢,第一个呢,我们要创建person类的对象使用反射啊,其实我们说也得去调用这个构造器,诶这呢我就也把它呢给拿回来了,这个怎么做这个事儿呢?诶这块的话呢,我们说呢,有好几种不同的方式呢,哎这我们就按照前面呢,咱们讲的时候呢,是不是接触过这种结构吗。
11:10
哎,咱们在讲这个多线程的时候呢,叫同步加湿器,我们用过这样的结构呢,作为一个。哎,同步加湿器出现过是吧。OK啊行,然后这块呢,我就这样来写,然后前面呢,诶我们说呢,它呢,其实也是个对象,就是咱们这个大的class这个类的一个对象了。那这个名的话呢,我就不能写成class了,因为这是关键字是吧,所以我就写成那个ZZ了。OK啊好,那这样的话呢,我们就把这个person.class呢,作为我们这个大的class一个实例出现了。下边的话呢,我通过这个叫class点啊,它有一个方法叫new instance这个方法。绿化掉完之后呢,首先它会抛异常,那但是呢,这个异常我们先给它叫肉出去。啊,这个异常信息呢,有两个是吧,挺长,咱们先不用过多关注,咱们只是做个演示啊,其次的话呢,大家似乎发现呢,它加了一个线。
12:03
对,这个线呢,意味着他已经被。Debated了是吧?就过时了啊,这个过时的话呢,就从JDK9开始的。诶八的时候呢,相当于还能用九呢,就不建议去使用了,哎,那我们先用着,后边呢,我来解释为什么说就不建议去使用了啊,我们都可以呢,去解释的好,那么咱就先暂时的用一下他创建好这个对象呢,咱们知道呢,其实就是一个person的一个实例嘛。但是呢,这块呢,Class这块其实它也有泛型啊。还有翻型,但是我现在目前没有用,没有用的话呢,它其实就认为我们这个new ince返回的是一个object了。哎,那这块呢,咱们又知道呢,其实就是个person,所以我这做个强转了就啊。哎,就这个意思,那如果说这块呢,大家你加上这个了。哎,其实这块呢,它就不用了。做这强壮了,能理解是吧。OK啊行,这个呢,加就加也行,不加也可以啊好,那这儿呢,我说呢,就把这个对象呢,我也创建出来了,咱也可以呢,在这个位置上去打印一下这个P1啊,这不就类似于你上边这块,你打印一下这个P1是一样的道理吗?
13:07
然后呢,哎,我们做一个执行,先看一看。行出来了啊,你发现呢,我们这块呢,调的这个方法,它呢创建这个对象,在这个过程当中也执行了这个语句,说明我们其实也调这个构造器了。就是调这个方法的时候呢,调的这个构造器,然后呢,我们打印这P呢,这对应的属性值呢,都是默认值。哎,这是没问题啊,这是第一个操作,第二呢,我们也想调这个A的属性。哎,我也想做这个事儿啊,做这个事儿的话呢,首先啊,通过反射来考虑的话呢,我们得先获取一下当前这个类当中叫age这个名的属性。啊,然后呢,我再让你去调,那怎么办呢?哎,通过这个class。哎,注意注意啊,我是通过这个class来的啊,通过这个class呢,我叫get field属性不是叫field的意思吗?然后什么名呢,叫age这个名呢。哎,这样的话呢,我们就得到了这样的一个属性。
14:02
比如我叫age的一个field吧。哎,就得到了,好,然后这块呢,它有对应的这个异常,我们out加一个回车来把这异常抛一下,这个呢有点多了,咱们干脆呢,就直接给它一个比较大的得了,后边这个呢,我就不要了是吧。哎,就这么着啊行,哎这样的话呢,我就获取到这个属性了,然后接下来呢,哎,我这个属性的点,诶我们上边做什么事的呢,附了个值,好,那我也负个,这个时候呢,我们叫set这样的操作,然后把这个P1呢扔进去,负的值呢是十。就跟咱们上边呢,P1呢,把这个age呢复为十是一样的道理,过完以后的话呢,下边你不是想打印看一下吗?那我们也打印看一下,哎,我们就age.age f的点要get一下,获取咱们这个P这个对象它的这个。属性的值。哎,我说呢,就也能拿到这个尺。你看就也出来了啊,所以这块呢,我们也能够去调用这个属性啊,接着你上面你能调方法,我也能调方法,我也调个兽。
15:01
好,下边首先的话呢,通过反射来做的话呢,我们先要到这个类里边找到一个叫授这个名的方法。但是我可能会说,哎,叫狩猎名方法可能有好多个,因为方法可以重载吗。所以这块你除了告诉我名之外呢,是不是还得告诉我一下这个行山列表啊。对的啊好,那一旦我找到这个方法之后呢,我接着去调就可以了,所以呢,我们还是拿这个class点叫get method。你看这个方法的话呢,这个参数第一个呢,就是你告诉我这个方法名。那另外的话呢,你可能有参数啊,你参数我也不知道你有几个呀,所以这要有一个方法的话呢,是不是就是可变性它了。哎,没问题啊好,那这时候我们这个名呢,叫做受方法。恰好呢,这个方法呢,还没有形参,那我们可变行菜呢,本身也可以不填嘛。哎,那正好我就这样写了,这样呢,我们就得到了一个,哎,它的返回值,那就是一个叫method这样的一个类啊,那这呢,我们叫受的一个method吧。哎,这样就可以了,好,那这样我们就找到这个方法了,下边我就想让这个方法呢调用一下了,这个雕的话呢,我们是叫受method的点,这个调呢叫invoke。
16:09
哎,VO大家看看这个参数哈,稍微了解一下,我们后面的要展开来说的,哎,你要调的话呢,第一个参数是不是就传你这个对象啊。哎,后边这个呢。诶,咱们上面呢有行参,这呢是不是该传实参了是吧,这个方法恰好没有,没有就不用写了诶。好,这样的话呢,我们就能调用这个方法了。哎,上面呢,调离方法显示的就是这样的一句话,那我们这块呢,咱们也调一下,哎,走起。注意我这块呢,跑的这个TEST2就是这个方法啊,不是我们上面写的那个了。诶,看这块儿呢,不就出来了吗。OK,那通过刚才这样一个演示呢,我们能够发现啊说呢,以前咱们说呢,诶面向对象主要的这个套路呢,就是这样的造对象,调属性,调方法,现在你会发现呢,通过反射呢,可以做同样的事。啊,那做同样事呢?没什么稀奇的,说你能不能做点不一样的事儿?
17:00
也可以。啊,什么不一样的事儿呢,你看哈,咱们的这个person类当中,我说呀,有私有的构造器,私有的属性,还有私有的方法。啊,那么对于这样的这个结构的话呢,如果我们用前面呢提到的这个思路来去做的话呢,是不是就搞定了。啊,因为你已经出了当年person类了,私有的结构就调不了了。但是呢,我们说可以通过反射呢,做这样的事儿。啊,这里我们说一下啊。在这写一下。说呢这个哎,出了咱们这个person类之后啊。哎,就不能直接调用,哎,这个person类中。哎,声明的,哎,我们说那叫哎private权限修饰的结构。哎,修饰的这个结构,哎,那这个具体结构的话呢,当然就包括属性啊方法呀,哎构造器啊是吧,就不能掉了,哎我们说呢,但是哎我们可以通过反射的方式,这个调用咱们这个person类中私有的结构。
18:06
好,下边的话呢,我就给大家做一个演示啊。啊,这呢,我们直接再写一个三。哎,首先的话呢,我们调研一下这个P类当中私有的这个构造器,诶,那这不就个私有构造器吗。来我们这块呢,调一下啊,那我们调构造器的目的呢,当然也是为了就找对象了。哎,这种写一下啊,第一个要调用私有的构造器创建。哎,咱们这个a person的这个实例啊。哎,实例呢,就是对象的意思了,好跟咱们上面这个思路一样啊,首先呢,percent.class然后过来以后呢,我们就对应了一个大的class这样的一个实例了。哎,这么着啊好,下边的话呢,我们就调这个构造器了,这个时候呢,我们就不能调上面这个叫newcense这样的一个方法了,这个方法呢,就是仅限于调空餐的构造器了。哎,那我们这儿呢,显然呢是带参数的,怎么办呢?哎,我通过这个class。
19:01
呃,第二还有一个呢,叫get declared constructor哎,这样的一个方法。这个declare呢,就是声明过的啊,他声明过的一个构造器,这个时候呢,你就不用再去填这个构造器的名了,因为跟类名一样嘛,就没必要写了啊,你只需要告诉我你这个参数是什么就行,咱们想调的是string的一个参数和int的一个参数,所以这个位置呢,哎,我就写上这个呢叫string.class。后边呢叫int class,诶这么着。注意啊,这个位置呢,写的是in加class啊,后边我们还会说不要写成点class啊。这个完了以后的话呢,我们就能得到一个呢叫constructor了。那我就要他吧。诶constructor,哎,它呢也有异常,诶我们把这异常呢,就给它抛一下了,诶咱们直接呢就给一个比较大的得了啊好,这个构造器呢,我只是获取到了下边呢,你得造对象呀,是吧?哎,我们拿着那个叫诶constructor这样一个变量,我们呢就去叫new啊instance了。
20:00
那我们这块呢,调离构造器,你得告诉我十参呀,比如我们就叫汤姆吧,哎,12岁吧,哎,这样就行了。创建好的,因为上面我们又用泛型,他认为是object。啊,那这块呢,咱们实际上呢,就是个person了。诶,我就直接呢,再做个强转就可以了。啊,这样就行好,那这块呢,咱们打一下这个P1看一看是不是叫汤姆12岁,注意啊,这个时候呢,我要运行呢,还是会报一个错误的走起。你看报了个错是吧,这个错呢,叫非法的access的exception啊,就是他还是认为啊,毕竟呢,我们当前这个构造器上是一个私有的嘛。吧,私有的话呢,除了这个类呢,就不让掉了,你这块呢,非要调就是非法访问了。那怎么办呢?说是不是访问不了的呢,其实也能访问,我们只需要呢,在诶调我们这个方法之前呢,你通过这个变量呢,咱们来一个呢,叫set一个accessible,写成个你不是说非法的access吗?那我来个true就是允许你去访问了。好,那这时候呢,咱们再去run一下。
21:01
哎,大家一看对象呢,不就造了吗?啊,说进来呢,除了这个类呢,我们还可以调用当前类的四个构造器。啊,原来这个封装呢,感觉受到了一定的冲击是吧?啊一会儿我们去总结这个事儿啊,啊这呢是我们第一个事儿,然后第二事儿的话呢,我们还可以呢,去调用你私有的这个属性哈,那比如说我们这儿呢,不是就有一个。A private修饰的一个词性的name。哎,我就想调你哈,想调你的前提呢,我先得找到你,通过这个class。点我去get declared field叫name这个名的。这样的一个属性,那我呢,就找到了啊,Alt加个回车是不是就是哎,Name的这样的一个。Field我这样来写好,然后这个name的这个field呢,我们就直接呢去调这个set方法,把这个拼音呢放进去,把这个name呢,比如说改个名改成叫Jerry了。哎,这呢我就给改了啊,哎,那我们这块呢,试着执行一下,看行不行。啊,同样的话呢,也报了一个叫非法的access exception也不让我们访问,毕竟呢,你这个属性name的话呢,它也是一个私有的嘛。
22:06
在后边这块你看也写了,是一个私有的。啊,不行,怎么办呢?哎,跟上面这个道理一样啊,我拿着这个name field的点,我叫set,一个叫accessible,然我就写成个出了。呃,写成出以后呢,我们再来去做一个调用。那这时候就可以了,只不过呢,我们设置完以后呢,你看不出来到底改没改,那我们还可呢去获取一下啊,直接就打印了,调没零用费的点get一下我们P这个对象的这个值,看看是不是变成了这个叫Jerry了。啊,没问题啊,所以呢,我们也能够调私有的属性,好接着啊接着这块呢,基本上你也不会有什么怀疑了是吧?呃,调用私有的方法。这个方法的话呢,我们下边写了一个啊,就是这样的一个方法。哎,就它行,那我们呢,就调一下这个方法,那这个方法呢,它对应的有一个输出的语句,我们看下这个语句呢,是不是也正常的,哎,不是输出返回的是吧,哎,我们看它呢,是不是也返回我们的能够获取就知道呢,调用是否是成功了,好,首先的话呢,我得先找到你当前这个类中叫这个名的方法,诶我叫get declared method。
23:12
叫什么名来呀,叫。啊,但是我们知道呢,在一个类当中可能会有重载的这个方法了,管通名呢不行,后边呢就要形态列表,诶这块呢,发现你是有一个string类型的一个参数。哎,就这么着。好了,这样的话呢,我们就找到叫这个名的有一个死锥形参数的这样的一个方法,这呢我们就接收为一个method。哎,这个呢,我就叫做show a nation的一个method吧。哎,这就可以了,好,然后这个方法的话呢,上面咱们也都体会过两次了啊,它因为也是私有的,所以默认呢,也不让我们去调,我呢也去调一个叫setcele,改成个处,这样呢就能调了。那能掉以后呢,我们现在就拿着这个方法,我去做一个执行叫invoke,那我们把这个P对象啊放进去,因为像这种方法这不都是非静态的嘛,所以一定需要呢传个对象了啊,然后呢,在调的时候呢,你这块呢有一个行参,所以这块呢需要附一个实参,比如我们来个叫CN。
24:10
这样就可以了,好,这样呢,我们说呢,就是调用这个方法的调用呢,实际上我们说呢,这个show方法show nation这个方法呢,就会执行,然后我们做一个run。然后执行完以后的话,你发现诶这怎么也没东西呢。因为你这个方法你调用的时候呢,你不也没有输出语句吗。是吧,你是一个返回是吧,你返回呢,我这也返回了,但问题是呢。也没接收啊。对的啊,诶这呢,我们有个小细一点,后边会说大家就先了解一下啊,就是我们调这个方法,它是返回一个string,它的这个方法的返回值呢,就通我们这个in work方法的返回值呢去体现,所以这个in work方法呢,它也有返回值,这个呢你都知道是string呢,这个你也可以呢,就写成是一个string。哎,比如我这写那个叫in。啊,只不过这块呢,我们呃,一直呢,都也没用过相关的这种泛型的特点了哈,所以这块呢,我们他认为是object了,那我就强转一下不完了吗。
25:03
Out,加一个回车。是吧,旋转下就可以了,好旋转完以后的话呢,其实呢,我们这个in for里边就是你这个这句话啊,说我的国籍是。哎,咱们这写了一个叫C嘛。那这块我们就把这个音符呢,给它打印一下就可以了,来我们再跑一下。你看这就出来了。OK啊诶,那么至此呢,咱们关于这样的一个,呃,使用反射能做什么事,就给大家做了一个演示,这个演示当中我们能够看到,以前的时候呢,我们都是直接呢去调这个构造器,然后调属性,调方法,现在呢,我们可以通过反射呢做同样的事儿,而且呢,我们还可以呢调私有的这些结构。那通过刚才这样一个举例呢,大家可能会有一些疑问,这个疑问呢,基本上也就存在我们这个笔记里边了。哎,把这个事儿呢,咱们看一看啊,首先。正态面向对象中创建对象调用指定的这个结构的这个功能,可以呢,不使用反射,也可以使用反射来做,就是咱们刚才那上面写的这个,你可以这样来做,也可以呢,下边这种情况来做说呢,哎,请问有什么区别?
26:07
对,按照咱们刚才这样的一个编写的来看的话呢,你会发现呢,咱们这种写法呢,一个主要区别就是看这个私有结构的调了是吧,另外的话呢,应该也能发现这种结构按说稍微的是不是简洁一些。这个呢,看着好像要稍微的复杂一些是吧,哎,这个也确实呢,就是你必然毕竟要用反射呢,它带来的一些相关的一些问题啊好,那要说主要来讲有什么区别的话呢,咱们也发现了哈,说呢不使用反射的话。啊,不使用反射说呢,我们需要呢,是不是考虑这个封装性是吧。比如说出了。啊,咱们这个person类之后啊。哎,就。哎,不能调用,哎,我们说这哎私有的这个结构啊。哎,Person类中啊。所有的结构了,而我们如果要是使用反射的话。啊使用反射,哎说呢我们,哎可以呢,相当于呢,叫打破这个封装性一样是吧。
27:05
哎,或者呢,直接我们可以说啊,可以呢,叫调用这个person类中,或者这个我们称为它叫运行时类中,什么叫运行时类呢?就是我们在运行这个代码的过程当中啊,这个person这个类呢,就加载到内存中了,放到这个方法区里了,放到这个内存中的这个类呢,其实就称为呢叫运行实类了。因为你不是运行的时候使用咱们这个叫a java.exe这个指令,这呢我们就要把它加载到内存了,运行时呢,进来的就叫做运行实类啊,哎,我们这时候呢,说可以调用运行实类中,呃,任意的这个啊,我们说那叫构造器属性方法。是吧,哎,包括了诶私有的这个,诶。属性和方法啊。啊,这个呢,是我们直观感受到的这样一个区别。行啊,这个我们就先写到这儿啊,这是主要的一个区别了,然后下边这个点,那在以前我们创建对象调用方式,就我们相当于这个测试仪里边这个方式了啊,那现在呢,我们又讲了个反射的方式,那这两种方式呢,对比的话呢,说哪种用的多呀。
28:09
这个我们就放眼到以后呢,我们开发的这个场景当中是吧,然后具体的场景是什么呀。啊,大家呢,可能也会有这样的疑问,既然呢赢通过反射做同样的事儿,那到了以后呢,我们应该怎么去做呢?哎,我们是这样用的多呀,还是这样用的多呀。是吧,诶假设这两个都能用的情况下呢,我想大家应该也都会选择上面这种。最起码能简洁是吧,呃,而且呢,从实际开发来看的话呢,我们这种情况呢,用的就是是最多的啊,这种情况呢,我们其实用的是咱们去写代码用的是比较少的。好回过来这块我们哪种用的多,哎场景是什么,其实通过场景呢,也就说哪种用的多了啊,哎这块呢,我们这样去描述。这个,哎,从我们。哎,从我们,哎作为程序员是吧。哎,开发者的角度。
29:02
啊,角度来讲是吧。哎,我们这个开发中。啊,主要呢是啊完成这个业务代码。啊主要呢是完成业务代码,然后呢,对于啊相关的。哎,对象,哎,还有这个方法的调用呢,都是确定的。所以。哎,我们呢,使用。呃,就是说这个非反射的这个方式呢,要多一些啊。诶或者说呢,极度啊,或者说基本上我们不会用到呢,说用反射的方式来造对象,要方法的,这是我们说的这样一个角度啊,那换一个角度,那什么时候我们才会去用反射的这种方式呢,去做这个事儿呢。啊,这个呢,就提到了一个反射的它的一个另外一个特点了,我们上面说调私有的,这是我们表现出来的,那么内层蕴含的点呢,就是我们在一开始笔记的时候呢,提到过这个事儿,说在这个反射呢,它主要体现了它一个叫动态性。
30:05
我们上面不是有这样的一个需求是吧,说因为呢反射呢,有一个动态性,它可以在运行的时候呢,动态的获取当前对象所属的类,以及呢,我们动态的去调用指定的方法,因为这个所谓的动态性。呃,使得呢,这个呢,呃,这个相关的API呢,就非常的灵活,那既然它很灵活,在哪用呢?那就是我们在这个相关的这种框架当中去使用了。啊,因为相关的这个框架的话呢,我们不能够写一些呃明确的写死的代码,因为这个框架呢,要在不同的业务当中去体现,所以呢,你要体现它的这种灵活性。哎,那这时候我们就在框架当中盎广泛的使用,OK啊,所以这块我们就说啊呃,因为哎反射呢,体现了这个叫动态性。啊,怎么叫动态性,我稍微描述一下啊,就是可以呢在运行时动态的获取这个对象呢,所属的类啊,然后呢,动态的调用相关的方法,哎目前呢,大家来看可能还不太熟悉啊,你现在呢,诶知道有这么回事儿,哎,所以呢,因为呢,反正呢体现了一个动态性这个,所以呢哎,我们在设计框架的时候。
31:15
会大量的使用反射。啊呢,就是我们框架的底层呢,呃,基本上都是使用这个反射的这种结构呢,给它搭建起来的。啊,那么这就意味着呢,如果呢,大家需要呢,学习这个框架的底层源码的时候呢,我们就需要呢,懂反射。哎,这边呢,这边呢,我也就说清楚了,我们什么时候会用法出来,就是框架里边用的啊。啊,那就意味着。呃,如果大家啊需要呢,学习框架的源码。哎,那么呢,哎就需要呢,哎学习这个反射了。哎,那么这个框架这块呢,前面呢,我们应该也给大家呢,抛出过这样的一个公式哈,框架的话呢,我们说有一个公式,诶前面呢,我们讲注解的时候呢,稍微提到过。哎,首先呢,我们使用注解了,然后呢,我们通过反射呢,去获取相关的注解,看你到底是想干什么是吧,然后再加上相应的一些叫设计模式,这呢就相当于是我们框架这样的一个公式,哎,构成的就是一个框架。
32:12
先直观的我们去感受一下啊,以后呢,我们学习相关框架的时候呢,大家你看一看,哎,是不是这么回事儿啊。好,这呢我们就说清楚它这样一个使用场景了,哎,在接下来大家可能也会有一个疑问,刚才我们在前面讲过单利模式啊,单利模式里边呢,讲过鄂汉式,讲过懒汉式,其中呢,构造器呢,都给私有了。说呢,我们就只能是在类的内部呢,造一个对象。然后你外部的话呢,直接用就可以了啊,所以现在通过反射的话呢,发现能够调私有的构造器了,那是不是意味着我们这个单类模式呢,能够创建多个对象呢。哎,这个呢,我们说的,哎,是的。啊,就是咱们前面写的这个饿汉式和懒汉式的方式啊,确实呢,我们就可以呢,呃,直接呢,在内的外部呢,通过反射的方式呢,调这个私有的构造器。啊,当然了,网上呢,也会有避免让你这个单利模式呢,让你通过反射去调啊,它还有一些相关的一些设计方案。
33:05
哎,咱们就先不多说了啊,就在咱们写的这个方式当中,确实是能掉。啊压IG呢,就不是单利了是吧。啊,那时候遇到问题,你看明明是私有的。所有的意思呢,就是不让出了这个类呢去掉,但现在通过反射的方式呢,我们既然能调。而且这块呢,像针对这种我们叫私有的这种结构啊。是不是说调私有这结构呢,我们还给大家专门起了个名字啊,就叫做叫哎暴力反射是吧。啊,相交于我们前面这几个来讲,呃,我们上面呢,直接能够调一些属性方法构造器都不是私有的,然后我们反射的也能做,这呢就不算暴力了,然后下面这个明明是私有的了,你还去掉了,哎,我们就理解成叫暴力了是吧。哎,比较好理解,那你又把我们这个封装性呢,是不是感觉给打破了一样是吧。哎,这呢也是一种体现了啊,那下边这个问题就来了,所以通过反射呢,可以调类中私有的结构,那是否与面向对象的封装性有冲突呢?
34:04
Java语言设计是不是有bug呢?啊。有没有冲突?人说有冲突是吧,有冲突那有bug吗?没bug啊,这个大家还挺坚持的啊,这个立马你就换了一种思维方式。是逆向思维了,要有bug早该解决了是吧,诶所以这样肯定是没有bug的是吧,诶甚至说呢,这块有没有冲突呢,你都应该说呢。不能算有冲突了是吧,反正就往回圆呗。对啊,哎,那肯定呢,我们说呢,是不存在这个bug的是吧。那既然不存在bug了,那你得直面这个问题啊。确实是封装性,不让我们去调私有的结构是吧?比如说单列模式,那就是让你直接用这个现成的对象呢,不让你去再去调过到去造新的对象了。但是你通过反射也确实能够去造它的对象,单利也不能是单利了,封装呢,也不封,也体现不出封装性了,该隐藏的隐藏,该暴露的暴露。
35:04
没有隐藏之说了。带了一个透视镜,什么都能看得见是吧?啊,那这块呢,怎么去解释这个事儿呢。啊,谁能给解释解释。说白了,就是自圆其说。是吧,对自洽的,你说出来有道理,大家就能接受啊,那我们就都统一下思想,那就都接受是吧。好,解释吧。啊,这个问题有的时候呢,咱们要有些面试的老师,我有时候就给他抛这个问题。啊,这个问题呢,倒不是说就多呃高大上多深刻哈,其实呢,就是看看你是不是有过思考。对吧。啊。啊,那当然我们能调这个私有的结构。就是没想着调,你指的是封装这块是吧。嗯。对,有点儿这意思了啊对,能再接着描述描述。
36:05
啊,你说就是正常开发的时候,不让正常发时候也能用啊。只是你没用而已是吧,呃,然后呢,底层要用,你说就是在框架里边就用了是吧。嗯。嗯,但是我还是能用啊,能用为什么还要设计这个封装性呢。啊,没必要用是吧,嗯。嗯,对,这句话说的对,可以不用,但是你不能没有。对,其实大家说的这块已经都是沾这个意思了哈。对,这个你要说这块有什么新的知识点,没啥新的知识点,就是大家看你纯粹是怎么理解的。嗯,诶这块你看我来描述一下啊,其实大家说的都有道理了,这个封装性的话呢,它体现的就是说我们这个是否建议你这样用的问题。啊,你比如说呢,我们这个呢,叫单利模式啊,你就好比是呢,咱们诶CTRLN哎,当初呢,咱们不是有一个现成的一个结构叫runtime嘛,这个runtime的话呢,它其实就设成是一个单立的了。
37:00
哎,然后呢,我们想用这个类的时候呢,你发现呢,他这里边呢,已经写好了相关的这样的结构了,我们只需要呢,调这个方法获取你当前这个类的唯一的实例就行,拿着这个实例呢,如果你有相关的需求,那你就去要相关的方法等等就去做就可以了。哎,这呢,就是相当于我们通过这个反射呢,我们能够看到的点是什么呀,就是它是否建议我去这样调的问题,它私有化这个构造器的言外之意呢,就是不建议我去直接调。你包括呢,我们在相关的这个类当中是吧,里边呢有一些方法,这些方法呢,它写成是public了,实际上呢,就在告诉我们说你可以直接调。是吧,你想调你就调,需要你就用,当然如果有个方法呢,它写的叫private。他想表达的点呢,就是说这个方法呢,我是内部要用的。啊,你呢,其实没必要去用,因为这个方法呢,可能只是属于我们其他方法的一个公用的,公用的一个部分啊,我们在这里边用了,在这里边用了,我就把它抽取出来了,我造成个方法了,这个方法呢,仅仅是我内部用就可以了,我就没有必要呢对外暴露了,第二呢,就是你你就没必要去用,你要用呢,你就用我们哈这样的方法。
38:03
所以呢,封装性给我们的体现呢,就是说是否建议我们去调用的点,建议呢,你就权限大一点,不建议用呢,你就权限小一点。但是反射呢,是另外的一个角度。是说呢,我们能不能调的问题。是吧,既然你当前这个类呢,都加载到内存中了,哎,方法也好,属性也好,构造器也好,一个不少的全进去了,私有的也都在,既然你在内存中有,诶我们呢Java呢就给你提供了相关的API,让你呢可以去调,因为你有吗。有的话呢,我们说呢,就诶可以去调,那这个相关的一篇呢,我们就在反射这块呢去体现的。啊,所以这块呢,你要说解释一下这个事儿的话呢,那就相当于是我们这个,哎,封装性是吧。哎,它呢,体现的是。哎,对,是否建议,哎,我们调用。哎,内部啊,这个API的一个问题。啊,那就意味着呢,比如说哎,我们说呢,这个像private生命的这个结构是吧。
39:03
哎,那就意味着呢,是不是不建议调用啊。啊,因为呢,我有其他一些方法去调就行,包括呢,我们看到一些类,哎,像咱们讲这个上一章的时候呢,提到这个I net address这个类啊,这个类的话呢,诶an address啊。这个类的话呢,它有构造器,毫无疑问只是类都有构造器啊,但是这块你要是调它构造器造对象啊,也能也能造是吧,但是呢,它可能会涉及到相关的一些结构的一些初始化等等的,那我这儿呢,明确给你提供了一个静态方法,你这些调的方法OK。啊,所以这块你就没有必要呢,去调我这个塑造器了,它是这样的一个思路啊。好,所以这块呢,它体现的就是是否建议我们去调用的问题,而这个哎反射呢。哎,它呢,体现的是。啊。哎,我们能否。是吧,诶调用的这个问题。啊说呢,因为咱们这个呃类是吧。的这个完整结构。
40:00
哎,都加载到了内存中。诶,所以呢,我们就有能力是吧。哎,进行调用。诶,所以这块的话呢,我们企业是能不能调,有没有这个能力,而这个呢,是不是建议我们调那个问题,诶你把这个呢,能够自圆其说,能够说清楚,哎能理解就行了,所以呢,以后呢,对于我们来讲啊,因为咱们平时呢,还是写业务代码要多一点,当你看到一个结构呢,它是私有的啦,或者我们这个权限呢,是一个默认权限了,那你除了当前这个包的话呢,也用不了,用不了的话呢,这个你就想啊,那我就算了,就不用了,而不是说呢,你第一反应说那我要用反射,我要暴力用。而不应该是这个啊,而应该是呢,他给你提供其他的方案了,你就按照他给的那种方案建议去用就可以了。好,那么通过刚才这样一个举例呢,大家直观的感受到了反射它的一个作用了,至于说它这种动态性,似乎呢,我们理解的还差一点,这个不用太着急,我们先知道呢,它能干什么,最后的话呢,我们大不了再写个例子,哎,后边的话呢,我们再去体会一下这个所谓的这种哎动态性。
41:03
OK啊。
我来说两句