00:00
那么我们就直接来看它这个新特性叫局部变量的类型推断,类型推断我们知道是什么意思呢,前面也见过一些例子,现在呢,主要是针对于局部变量啊,这个是非趁的一个特性啊,这个特性呢也会一直的应用下去啊,我们看看说呢,开发者经常抱怨Java中引用代码的一个程度,说局部变量的显示类型声明常常被认为是不必须的。啊,多一个式啊是不必须的说给一个好听的名字啊,经常可以很清楚的表达,表达出下面应该怎么去继续啊,这呢名字叫标识符,呃,言外之意想说就是标识符比这个类型啊还重要,说类型啊有点多余,什么叫多余呢?大家你直接看我们这点说明啊,咱这呢创建了一个叫link的哈希set,你换成别的也一样啊,我右边呢,New的是link的哈希set,左边这块呢,呃,你要么呢写成link哈set,要么呢你就写成它的一个副类,或者是接口的方式都行。都没问题啊,那我们想说的是左边这块呢,有点多余,因为你左边呢,肯定是它要么就是它的负类或者是接口了,这块其实我们可以忽略掉的。
01:10
那关心的就是变量名你不能忽略了啊,变量忽略呢,成匿名对象了啊,匿名变量了,那你下边想掉掉不了了啊,这个不能忽略,左边这块可以忽略,这就我们现在想干掉的这个东西,再看下边这个,这个的话呢,是咱们讲set的时候,这其实是我们map当中key构成的这个set。啊呃,不是,是这个entry啊,看这就知道了,是咱们这个entry构成的这个set,这个set的话,我们调这个特这方法的时候呢,返回的类型你看到哇,好长啊,泛型里套泛型,其实这个结构你想想我们掉一圈返回你也不能写别的呀,这个是不是感觉有点多余呢?哎,现在就想把它干掉。啊,这就说的这个事儿啊,那还有一个具体的例子,这呢是咱们涉及到关于这个URL啊,我new一个URL赋值给的这个类型,那也只能是个UR啊,你也写不了别的呀。
02:03
啊,但是这个变量你不能省,因为下边还要调这个方法,你调了一个open connection返回的,那不就是个ul connection吗?这个呢也想省,然后呢,这个buffer的reader你完以后你得到的是一个reader,或者就写成一个buffer reader,好像也没有必要非得要把它写出来,想着呢,通过右边去直接推断左边这个类型。这呢就是我们讲的局部变量的类型推断啊,类型推断下边你看也写了相关一些说明啊,说太多的类型声明只会分散分散注意力,不会带来额外的好处,就相当于上面这段代码的话呢,你写完以后啊,你可能老师去关注前面这个类型这块了啊,这个没有了啊,关注这三个类型了,实际上来说这个类型呢,完全可以忽略掉,你主要关注右边这个new的是什么调的什么方法,这是咱们写代码的中心。那你像我平时写代码的时候,不是老师经常的也是直接al enter是吧,那你在这直接al enter就出来了,相当于我们通过右边直接不就相当于推断出来左边应该是什么了吧,否则的话呢,你点奥德它也不会出来左边的东西吧,既然呢,我这个奥德enter能出来左边的东西,左边呢就相当于可以推断,那就可以省,哎,就这意思,OK,来src新建一个package。
03:19
哎,这呢,我叫JAVA1啊,在这个里边呢,咱们去写这个十的这些新特性。啊,这个我们直接就Java。JAVA10的一个test。哎,Test一个一好,这呢,我们就说明叫局部变量的类型推断。那例型推断啊成,那这呢,我们这个就开始写具体的例子了啊,那以前呢,咱们写int一个number,这个是个十,是这样写的,那现在的话呢,这已经是个十的左边呢,一般呢也都是个整形,我们就想左边这个呢,给它省略掉啊,这个省略掉咱们用谁替换呢?哎,这我们引入一个叫VAR。
04:12
啊,你可以念VR或叫Y啊,这个GS当中你会见到这个多啊,哎,这就是Y,然后呢,这样写肯定这目前是错的啊,因为咱们目前用的这个是九里的啊,你看这是我们换到这个十,大家看在这个十这块呢,它就明显的告诉我们了,说这个你的主要特性是什么啊,这就写出来了,诶OK一下,那这块就不报错了。哎,我们就可以定义这个啊,它是一个腕类型的。哎,这呢,就相当于是我们在声明变量时。哎,生命变量时这个局部变量的类型啊,哎,根据这个所赋的值,哎,然后呢,去推断。哎,推断这个变量的类型,哎,这是一个例子啊,那咱们还可以再举一个,比如说叫a list。
05:04
Ear list呢,我们先这样写啊,那左边呢,是不是也一定付给的是一个ear list或者它的接口啊,哎,那么这块呢,要原来你可能就需要写一个a list,哎,当然这个发型呢,咱们原来可能得这样写上啊,得这么着了,对吧,这个位置小心点啊,这个位置是根据它推断的,所以这块呢我们省略掉了,那现在的话呢,我们左边呢,说是个list或者是你的这个负接口,当然我们你是负接口也好,还是一个list也好,其实对我来讲都无所谓。反正我调方法的时候呢,你你调接口呢,可能方法就更少了是吧,这我们都可以去推断得到的啊,所以这块呢,我就直接写一个VR了。哎,这是OK的,那我写VR有没有同学会感觉有点。那这这这个咋整呢?哎,因为呢,咱们这个位置呢,是靠左边去推断的,现在把左边干掉了,那这呢,对这呢,你看我艾的时候,他是不是就认为是object了,哎对,他首先没有报错哈,没报错呢,就相当于是他就认为你这块呢,忽略掉这个发型这个事儿了,那我这块呢,认为你就是object,你要不想是object呢,那你就写上谁他就是谁呗。
06:18
那这时候我们再去点,你看。他就引起这了,就哎这呢,相当于也是咱们这个定义变量的时候,左边这个类型呢,咱们就给省了。啊省了好下边啊下边呢,我们再举一个,比如说叫便利啊,这个是一个一第二个呢,呃,这个便利操作。便利操作,比如说咱们现在写一个增强for循环啊,增强for循环我就想便利咱们上边这个list当中的元素,那上来呢,是不是要写这个元素类型,正常来讲这应该是。呃,然后呢,写个I冒号,然后写一个list,这个相当于你把这个类型呢给明确写出来了,那现在呢,我往这个集合里去加数据,我都知道我加的是什么类型,那你这块没有必要去写了,因为我跟你这个list里边艾什么是不是就确定了一下。
07:08
也可以了,哎,在这呢,你可以输出一下这个I啊,你也可以,怎么着呢,你看我输出I,既然是个对象了,我就可以get上class。是不是就元素的是不是类型啊,来我们执行。哎,对,输出的是不是应该就是integer了,哎,那你这里边123它不就是一个integer类型的嘛,这呢都是给他推断出来的。啊这样啊,然后然后呢,我们可以写一个这个普通的一个便利操作,哎,普通比如我们写个for循环,原来呢,我int一个I等于零,I呢小于100啊I加加,哎这是原来的这种写法啊,里边你去输出一下这个I,现在的话呢,这个in特型玩一下。那就可以了。哎,这呢,就是一个叫呃这个呃类型推断啊,但是你注意在咱们Java当中啊,这个哇,你现在还不能省啊。
08:08
你说那个Y干脆也省了得了,Y就别省了,因为呢,咱们在Java当中呢,你就要呃,加上这个Y,这相当于是个类型了,咱们知道你现在的定义变量。然后你后边呢,直接用这个nu number的时候呢,知道你是在用它,就是定义的时候呢,需要带上类型,所以这个你就别省了啊,这跟Python不一样是吧?哎,这个你注意一下这个问题啊,就就别省了,嗯,行,这呢是我们举的这样的三个例子啊,大家能够看到呢,关于我们这里边局部变量啊,局变量的一个类型推断,行,然后下呢,我们是一些适用情况,举了例子了,下边呢再说一些什么情况下不能用。哎,这呢列举出来是不能用的情景,我这呢是用这个JSH呢做的一个演示,咱们在这个idea当中也是可以的啊,写一个单元测试,好,我现在呢来一个one number诶。
09:03
这么着说你不是要力行推断吗?是不是现在连给你推断机会都没有,他右边不写东西啊,你说我要写一个hello,你是不是就知道我们这个它不管不能看变量的这个名了啊,变量名呢,不能决定类型啊,名字你想怎么起怎么起啊,这块呢,我们直接get class哟,你看它既然能get BA,那其实它也就是个字符串了嘛。我就get class,诶,咱们这个类型推断啊,你是通过右边来判断的,左边这个类型。那这是spring啊,通过右边的是双引号,我就知道你是spring,那现在呢,他把这个位置啊不写了。你不写我我上哪推呀是吧?哎,所以这里边呢,明确说这个局部变量啊,不赋值是不行的啊哎不赋值,哎诶赋值啊,哎就哎不能哎实现这个类型的推断,那压呢,就这种写法是错误的啊行,这是一个,然后呢,再举个例子,关于这个拉姆达表达式。
10:11
哎,拉姆达表达式这块呢,我们举一个,嗯,什么情况呢?哎,我这里边呢,是没有放东西,然后返回一个东西了,哎,先看这个吧,啊,这是一个返回的东西,这个有点像什么呢?有点像我们这个叫供给型的是吧?啊plaer啊这个供给型我们这返回的,呃,RH是一个随机数,是一个double类型的是吧。Up,咱们先写一个前面讲过的这个啊,嗯,这呢是一个拉姆达表达式,不放东西,然后返回math点。R。这个应该都能看得懂是吧?行,这呢是我们说的一个叫拉姆达表达式,然后现在呢,说诶右边这个东西,左边A省掉哇一下。
11:04
就挖失败了,就啊这个是不允许的,这个我们把这个正确的保留一下先啊,然后给它复制一份。那为什么?你不是能推断吗?这怎么没有不行呢?这为什么错误呢?对接口你像这样整的话,这完全不知道你要干什么呀,我们写了一个接口,咱们是,哎,知道接口中的那个抽样方法,知道有没有参数啊,有没有反应类型啊,根据这个咱们写的这个结构,你现在把这个接口都干掉了,那我哪知道你这是什么东西啊,你是不是一个函数式接口我都不知道啊,是吧。你右边这咱们说拉姆的表达式,你只能是赋给一个函数式接口,你忘了,那这是啥呀,你假设你还是一个函数接口,你那个方法有没有返回值类型啊,有没有参数啊,你这块需要匹配的啊,你这样写可能是需要return,那我这要没return呢。
12:03
是吧是吧,就完全就确定不了了啊,所以说呢,你在这个拉姆达表达式当中,左边可千万不要写成Y了啊。拉姆达。表达式。呃,表达式中这个,我们说这个左边的这个函数式接口。哎,不能,哎生命,哎生命为这个腕啊,这个呢,也是这样一个例子。行,那那拉姆的表达式都不行了,那方法引用呢,又是它的更进一步,那就更不行了,比如我这举了个例子,嗯,咱这是用了一个print LA,这相当于是一个呃,放一个值,呃,Print LA放一个数,然后呢,做一个print LA,这相当于一个消费型的啊。这是一个方法引用。哎,这个三,哎方黑。
13:00
哎,方法引用当中啊,来看一下,哎方法引用这呢是一个消费型的,我们就叫一个哎consumer,哎consumer这里边呢,比如咱们放一个string,哎,然后呢,我这个con,哎等于右边的话呢,我们直接用方法语用了al啊print。诶,这不就这样写的啊,这呢是我们写的一个方案引用,那方案引用的话呢,这是正确的,那现在的话呢,说左边我也想把它给干掉,说你不是推断吗?你就推吧,推不动是吧?嗯,跟咱们上面说的是一个意思哈,你这样写呢,咱们说方案有用要求你这里边抽样方法的形态列表啊,反之类型啊,跟你这个方法得一样,那你现在都给它去掉了,我哪知道你这是个什么结构啊。里边连有没有出款方法都不知道,这完全推不出来啊,现在还没有智能到这种程度啊,所以这块呢,在方法引用当中,还是左边的这个函数接口还不能生命为二啊。哎,这个也不OK,搞不定,哎,这是我们说的这个第三点,然后再接着说为数组静态初始化,哎,数组。
14:10
在静态初始化哎当中,比如说咱们前面呢,写一个int型的数组啊,你一个int,哎,然后这里边啊1234好,这呢是一个正常情况,现在的话呢,你想说把这个干掉,右边呢,New个int这块呢,来一个Y。这可以是吧,这没问题啊,但是你要现在想把这个也干掉,想用的东西都不知道了,那这个Java虚拟机给你在内存分配值分配什么呀,这他也懵了,哎,这样的也不行啊,所以这个呢也是一个错误的,所以说叫数组的静态初始化啊,咱们呢,原来省的时候呢,比如像这个打开啊,说这块你可以省,这块省的原因是因为我靠左边呢,已经写了,对,是通过前面推的后边。啊,你现在可好,后边这个省了以后呢,你把前面推的这个结果也给干掉了。
15:04
这就完全找不到了。哎,这个应该好理解啊,咱们通过前面呢,推到后边,后边你省啊,现在你把前面也干掉了,那后边这块不也就懵了吗?哎,这就成了这种情况了啊,所以数组的静态初始化当中啊,这个我们呃,这个注意如下的情况呢,也不可以。也不可以啊行,这呢是我们这个说的这样的几种情况,其实呢,也比较好理解啊,总之一个点就是咱们呢需要呢,给我们这个数据一个明确的一个指示,整体上来讲,我们的这个哎局部类型,局部变量的一个类型推断呢,主要是通过右边来推左边,只要你让右边右边呢别迷糊啊,它呢不会出现一些奇异的情况呢,哎就都可以实现啊,以这样三个例子来说啊,这块呢是我们提到呢,也是局变量,但是呢不能这样做。哎,把这个范围再扩大一点,说还有哪些不能做,哎这块有好几个情况。
16:06
这些情况呢,都不行。哎,说第一个说没有初始化的局部变量的声明。没有初始化的啊,这个不赋值,这个咱们刚才已经提到这个问题了,是吧?啊这呢,比如说你这个Y一个啊S啊右边呢,什么也不写,哎,你这样写行吗。是不是也不行啊,这也不行啊,这块呢,我们这个没有赋值,或者你这块写成个no,这这也不OK啊,你no的引用类型都是no,那我到底你知道你是什么类型啊,不行啊,下一个方法在返回值这块也不行。这个呢,咱们演示还不能放里边了,放外边了。哎,这是这个情况二啊,嗯,这呢,比如我们public。Public,我得写个T,写一个method。哎,MR1啊,这个里边啊,你是in的形,我就听一个零,哎,这是OK的啊,现在我把这个位置改成个Y。
17:04
哎,这他也不行,哎它这个呢,你可以列解为咱们是根据它判断的这个,比如咱们原来你要写个int这块,你写一个ABC,它就报错了,说我这要int,你给我输这个返回的是ABC,它是由这块来决定这的,而我们这个Y呢,正好反过来了。腕呢,是由里边决定,外边这个就改变了我们方法的这样一个思路了啊。嗯,这个这成啥了,成你返回什么都行。你返回什么呢?我这块就动态的去用R表示这个变了方法呢,不是这样的方法是由这个来决定里边的啊,所以这个呢也不可以啊下一个。下个呢,说这个方法的这个参数位置也不行啊,这个咱们把这个也得注释啊。那public这个是个word method2这个呢,我们定一个in型的一个number,这个呢是非常明确的一个情况,现在你把它改成个Y。
18:04
也不OK,这个能理解不?就还是咱们说的那个事儿哈,就是呃,咱们这写int呢,相当于就是你要是传别的是不是就不行啊。对,你现在写成万呢,就成了说你传什么,我这就都可以。这个地位完全变了。是吧,嗯,你就相当于比如说这个。比如说什么呀。比如这有一个学校,这个学校呢,就是呃画画的,哎教画画这个学校原来在我们这儿呢,写的是int,就相当于是哎你你想过来来这学习,但是人家有一个考核,就你得是画画的才行,他考核你过了,你就能进来,相当于我这是要求int,你放的是个int型值,就让你进来,那现在呢,你要改成腕,那成啥了,说你过来了,你看看你能干什么,你能画画画画就画画,你要说能这个,呃这个开这个挖掘机啊,那我这就是叫挖掘机的是吧,完全变了啊,这个呢,它就不占有主导地位了啊,原来我们这块写一个in的,它是一个主导的,就是放别类型是不允许的,你写成腕的话呢,这个就啥都行了,成了啊。
19:15
这不可以。再下一个说构造器的参数类型啊,这个很好理解,方法不行,那构造器也不行。这个在形态这块呢,方法跟构造器呢,我们说是类似的。哎,当前咱们还这个叫这个类啊。在这里边,哎,这个写个Y,哎,写一个I,哎,这都不可以啊,这个跟方法一样,这个就不多说了。下边说这个属性,属性也不行。啊属性属性的话呢,我们直接就放这了啊,那个属性相当于是放下边了,我们定义当前类的一个属性,比如说叫int型的一个,哎number,哎,这个你负个值是十,哎这是OK的,现在你想把这个改成这个Y。
20:04
哎,不允许。哎,咋属性还不让呢。对,咱们现在说的叫局部变量的类型推断啊,当然你要这样说的话呢,这个那就没法解释了啊,是因为属性不行,所以咱们才叫局部变量啊,就是反了有是吧,那你想一下说为什么属性不让用呢?因为属性呢,有时候是不是有默认值啊。那你要说要用,那我就意味着我就可以写个默认值,那默认值这块又懵了,那那这个你得先告诉我类型,我才知道默认值,你这个类型都没告诉我这个呢,就成了说你告诉我值,我才能知道你的类型。哎,这又又不行了啊,这个不OK,下一个catch块,哎,Catch块呢,咱们可以写这里边了啊,就是如果在这个方法里边,你写个串,哎,这是一个大括号,在这呢写个cash,咱们所谓的这个异常啊,比如你这个叫exception啊E,哎后边呢,就是处理你这个异常一点,哎,Print stas啊这是这样说,现在呢这样呢,哎,我不知道你大概是个什么异常啊,我真的就忘一下。
21:10
得不行。啊,这不行啊,所以这个呢也不OK,这呢,就我们说的这个不可以的这样的几种情况啊,呃,这个OK的情况呢,就除了这个之外,咱们就是呃,老老实实的你这块有一个呃值往回返这样行,再举个例子。哎,这就咱们后边呢说的这个情况啊,诶把这个呢,我们拿过来你可以看看啊,CTRLC。看看哎,这直接粘过来啊,把这个呢,我们再。行看ctrl shift f行调完了,调完一块呢,它这块有这个异常哈,那异常我们整个给大家这个包一下al shift z。Try catch一下。
22:00
出开,其实这我就check开,它就不不去关这个这个资源了。嗯,T3已经定义了四好,你看这里边啊,这里边呢,右边你用了一个URL啊,左边呢就可以省了,哎,然后你获取个连接啊,这个也可以省,这呢是右了一个八的reader啊,左边也能省,这就我们说的一个正常的一种情况。哎,正常的一个情况呢,这样都是可以的啊行啊,那这呢,我们就把这几种情况呢说了说,然后我们看这样的一个总结或者一个原理啊,为什么就OK了,原理是什么呢?主要呢,就是我们提到了由右边来决定左边。在处理这个VR这个Y类型的变量的时候,编译器呢,先看一下右边的部分,根据右边变量值的类型进行推断,作为左边变量的类型,然后将该类型写入字解码当中。这个注意写入自解码当中,言外之意,我们现在编写的时候呢,你看我这都是这个Y是吧,你说我们要真正这个编译完以后,是不是都会生成自解码文件呀,文件里边这还是这个wa吗?对就不是了啊,这个咱们在idea当中,这个自解码文件都在这个out,咱们当前工程下啊,Out点开。
23:19
哎,这呢点开咱们现在是DAY13,嗯,在com艾特硅谷张二一,这呢是我们这个当前的测试啊,这个呢,你拿拿开啊,拿出来以后大家看。这呢是自解码文件啊,我现在双击呢,是因为我们idea呢,它内置了一个反编译工具,直接把我们这个代码呢,自解码文件正常我们是看不了的啊,它就反编译出来了,因为看到底层它其实就不是VR了。啊,这个位置呢,因为我们这儿你下边也没有特意的去调啊,它这块就没有再去给你生成相当于是个匿名对象了。啊,这没事啊,主要你就看这块,诶此时呢,确实给我们做了一个翻译啊,诶这块你看这不没用吗?没用他就没给你再翻译出来一个显示的对象了啊行,这里就相当于底层自解码文件当中,其实是有确定类型的。
24:07
好,下边说这个事儿,这个VAR。VAR,注意不是一个关键字。诶,这怎么又往关键字这块扯了呢,因为咱们说这个类型,像这个特呀波尔啊,像这些啊,是不是都是关键字啊,你现在出来一个叫腕类型的,这个腕呢,它不是一个关键字,它就仅仅是一个标识符。啊,这个标识符的话呢,我们可以用它来表示一个类型,或者说白了就是咱们在Java当中,你定一个变量的时候,前面一定得有类型,那这个类型呢,说可以推断了,那我们就拿一个东西来挡一下啊,就拿了这个VR这个三个字母呢挡了一下,那在编译以后呢,人家这个类型其实又出现了,说白了就是这个类型不用咱们程序员写了,编译器呢做了一个事儿了。啊,这样子啊,那既然你不是关键字了,大家呢,去给这个其他的标识符去命名的时候,哎,你可以使用这个VR啊,当然一般情况下,大家你别把这个类名叫VR了啊。
25:08
你要有个方法叫VR啊,有个变量叫VR都可以,你这个类名不要叫VR,为啥呀。最好类类名不要叫VR啊,你要累叫VR了,你这不就成了一个VR的这个类型的了吗?是吧,啊,你这个类不成了叫VR了吗?所以不要造一个类叫VR啊,人家这块就是一个标志符,你叫class VR,这不成了全是VR类了,是吧,就错了啊行,其他的可以方法名啊,变量名啊,你愿意叫VR,你叫VR,反正我这也不是这个关键字啊,标志符呢,咱们说这个不让关键字,你不是关键字就可以用,下面说这不是javascript,这个什么意思呢?就是javascript,它是一个解释性的语言啊,它没有这种这个,这个先编译啊,后运行啊,它直接呢就可以执行了啊,它属于这种这个像解释性的语言啊,没有这种这个。
26:03
这个这个叫什么,它或者算是一种动态语言啊,那有了这个VR以后呢,说难道我们这个Java它就是一个呃,变成一个动态语言了吗?也不是哈啊,Java呢,仍然是一个静态语言,咱们讲反射的时候呢,也提过啊,这块呢,只是由于不用我们程序员写了,在我们这个呃,生成的这个自解码文件里边呢,还是确定的类型的啊,这个我们刚才通过反编译这块也看到了啊成这呢,就咱们把这个局部变量的类型推断这个事儿呢,就说清楚了啊,说的相对比较多一些。
我来说两句