00:03
好,那这节课的话呢,我们来学习内部类。什么是内部类呢?这个内部类的话呢,我们可能都用过,但是呢,并没有呃系统的把它做一个,呃就单独摘出来做一个梳理啊,所以这节课的话呢,就一起来看一下这个内部类,它的这个呃,它的相关的一些内容。我们平时写程序的话呢,这个程序呢,都是由一个一个的类这样的构成的这样一个结构,这些类呢之间是互相独立的关系。类之间呢,是互相独立的关系,那么我们说什么是内部类呢?内部类的话呢,其实就是打破了这种互相独立的这样一个关系,这种这样一种概念,让其中的一个类呢,成为另外一个类的一个,呃,一个相当于内部的一个元素,就就相当于跟它的成员变量,跟它的方法是一样的啊。我们来首先来说一下,就是一般情况下呢。
01:06
一般情况情况下。我们说类和类之间是互相独立的。对对,互相独立的,但是累不累?内部类的意思呢?是打破这种独立。让一个类成为。另外一个类的。呃,属性或者叫或叫一个内部的一个信息,对吧,内部信息和成员变量对吧,包括什么。成员变量以及什么乘员方法对不对,同等。这样一个,呃,同等一个级别吧。就这意思。那么接下来我们就来通过具体的,呃,不同的内部类呢,我们来看到底是怎么一回事啊,首先来看这个非静态内部类。
02:09
首先来看C静态内部类。内类的话呢,我们刚才说过,内部类是指一个类是另外一个内类的一个内部的一个成员,我们应该成员吧,可能更合理一些。然后呢,是把它定义在某个类的内部的。把它定在某个类的内部了,对外的话呢,可以设置为可见,也可以设置为不可见,对不对,那比如说我们这边又来写一个内部类好。我们来新建一个包。我们来写一个内部的一个例子啊,比如我叫al class。All class指的是外部类,呃,外部的内内层外面那层类,然后的话呢,现在我们在里边呢,去定义一些属性,比如说定义一个。
03:06
啊。它外部类的一个名字对吧,比如说我们再定一个方法叫display。这类的话,我们这边输出说。Class。OK,好。同时的话呢,我把这个name啊给它输出。对不对,看这个就是一个乘员变量,真实成员方法对吧?来记一下啊,这是一个成员变量。这是一个乘船方法。成员方法,然后我们说内部类什么呢?内部类就是跟成员变量,成员方法是同等级别这个东西,内部类就这么一个关系。我们在这去写一个内部类public class,我们叫inner class啊,什么内部类,OK,在里边定一个类,然后这个类的它的这个作用啊,或者它的这个呃,级别就跟我们这个成员变量成员方法是一样的,对不对,都属于我们类的。
04:17
这个auto class内部的一个成员。这里边儿是不是也是可以去定义它的各种属性的,对不对,因为它也是一个类嘛,只不过说它是一个内部类啊name,比如我们这边再定一个这个。嗯,定一个还是那个类也可以啊,可以定一个外面一样的。Display方法,方法里边我们去输出说inner class display。完了之后呢,把这个inner name是不是也可以输出啊,没问题。然后这边的话,我再给他写一个它的构造器啊。结构造器啊,结inner的一个构造器,在构造器当中啊,我们去给这个inner。
05:04
给这个阴道内,给它赋一个值吧。Innername等于。Dinner class。OK,这样就行好。然后的话呢,我们接下来写个闷方法,在闷方法当中啊,大家注意看,我们现在呢,去初始化一个auto class。Auto class等于又一个auto class。好。然后比如说我们来教auto class display方法对吧,这个的话呢。分解钠直接来运行。对吧,大家可以看到啊,我们是输出了这个,呃,Auto class display,然后输出auto name auto name,因为没有给它赋值嘛,所以他说now没问题,好,那如果说接下来我要去定义这个,我要去初始化这个inner class的话,怎么办呢?大家注意看啊。直接inner class inner class inner class等于六一个inner class,诶,你会发现他直接报错了。
06:04
对吧,也就是说这个移动class它不能创建。对不对,这边为什么报错呢。为什么这边不能去创建呢?啊,其实就是因为我们现在这个创建的方法是有问题的,因为我们现在要创建的是一个什么呢?是一个内部类,所以说你就不能像创建外部类一样直接这样写,因为它已经不是一个独立的类了,不,不是一个独立的类了啊,它必须依赖于这个auto class,所以呢,我们在写的时候呢,也必须在它的前面加一个前缀auto class,点音的class,这样写这边也是一样的auto class。怎么去扭呢,看。我们必须借助于auto class的对象去用auto class.new一个in the class必须这样写哈,这样也是OK的,对不对?所以大家要注意啊,就是首先你在这儿需要去加前缀。
07:02
需要去加一个前缀,或者说你这个前缀不加也可以对吧,但是一般来讲我们为了区分它还是加上去,因为表明它就是一个内部类嘛,对吧,要不然你后面这个东西可能看起来不是特别清晰啊,加个前缀就表明它是这个auto class的一个内部类,Auto class点移动class,然后呢,这是我们的成人变量名字,完了之后我们说。这个内部类它跟这个成员变量,包括成员方法,它们的作用是一一样的,对不对,它们作用是一样的,而且的话,我们现在写的是一个什么呢?非静态内部类,所以非静态内部类是不是它不属于我们这个auto class,它是不是属于一个对象啊,一定要搞清楚啊,跟这跟跟这边是一样的。对不对?比如说你要访问auto name或者display,这个方法是不是必须先得有对象才可以啊,因为它是非静态的,那么in诺class也作为一个成员,他也是非静态的,那么他的访问也必须依赖于一个auto class对象才OK,对不对?所以你这边是auto class点内。对吧,是不是才能才能写出来,然后再new,是不是就创建一个in class对象,所以你看这种写法的话呢,跟我们去访问这个display,包括auto class.auto name是不是一样的。
08:10
对吧,你看这些东西都是一样的啊。只不过说后面我们这边换成方法,这边换成成员变量,这边是不是换成一个创建对象的一个操作,但是前缀都要加这个东西。OK吧,好这样去写啊,好创建出来之后的话,我们可以去调用它的方法。比如说呢,我们来创建一个in class,呃,调用它的方法,Display,这个方法大家来看一眼走。对不对,你看auto class display,然后now in the class display,然后呢,它的值是有有有这个值的啊,它不是now,因为我们在构造器里边是不是给它附一个值。对吧,所以这就是啊,我们叫非静态内部类的一个操作。其实很简单。很简单。
09:03
就是把这个内部类呢,当做我们类里边的一个员变量,或者一个成员方法去操作就OK了,对吧。内部类的使用,这种非静态内部类的使用。使用就是。将内部类当做。外部类的一个。成员变量。或者说成员方法来使用,对不对来使用,因为它是非静态的,所以所以啊呃,必须呢。依赖于。外部类的。对象才能创建才能才能调用吧,对不对,必须依赖于外部类的对象才能调用啊,而不能说直接去调对不对,所以用法上。和这个乘变量以及乘分方法。
10:01
是一致的。OK吧?非常的简单啊,那么接下来我们来说一下,为什么需要内部类呢?我们这边直接创建了两个外部类,不一样的吗?就是我单独呢,是不是在在这再写一个奥,呃,再写一个in class是不是也一样的?对,为什么要非得把这inner class作为auto class一个内部的成员呢?为什么要这样一做呢?如果说从程序的角度来说来来说的话,确实是一样的,对不对,那么我们应该怎么去理解这一块呢?使用这个内部类的技术呢?它可以更好的隐藏细节和内部的结构,它的封装性就更好一些。让程序呢,可以更加的这个合理啊,包括它的设计呢,可以更加的优雅啊,那我们简单写一下。呃,使用累不累啊。为什么要使用内部类?这就是一个相当于是一个理论了啊,为什么要使用内部类呢,采用内部类这种技术。
11:08
可以隐藏细节和内部结构。可隐藏内部呃细节和内部结构,它的封装性更好。红装性更好。让程序呢?让程序的结构呢更加合理。让程序的结构更加合理。在现实生活中呢,一个事物内部都是有很多部件组成的,然后呢,这个每个部件都可能包含它的子部件,同时这些子部件并不需要全部暴露出来。对不对,内部类的思想呢,其实也是借助借鉴了这个,呃,现实世界里边的一个一个概念啊,这个同一性呢,让他更好理解。对吧,所以说他就是他就是做这样一件事情的,就是你把它放到外面也可以。
12:01
这种方式也可以,但是呢,如果说我们采用内部类的话呢,可以去隐藏它的细节和内部的结构,这样的话封装性更好啊,因为我们程序呢。咱们的程序呢,肯定是需要去互相调用的,对不对,比如说我们三有三个模块化的一个调用,OK,然后这这个里边呢,包含了它不可能是一个类组成的嘛,它可能是有很多类组成的啊,然后呢,我们这个第二个模块要调用第一个模块对不对,如果说你这边把写了很多个类。写了很多个类,可能我我第二个模块要调用第一个的话,我是不是要去操作很多个类啊,因为你这些类全部都是暴露在外面嘛,对不对,那么我为了更好的去呃做这个程序的一个结构,让它的结构更加合理和优雅,怎么办呢?我就可以用内部类的方式,哎,我只给你暴露出一个,然后呢,把其他东西全部隐藏到里边,这样的话呢,你在你看来是不是你只需要操作一个类就OK了,而不是那么多类。对不对,就大概这样一个意思啊,就是这样一个意思,好呃,然后呢,还有一点要说明的什么呢?就是很多同学到这儿呢,可能会产生一个误区啊,什么误区呢,就是我们有的时候也会在这儿去写一个类,比如说写个A。
13:07
注意这个A啊,它可不是内部类,大家一定要注意这个A啊,它跟这个auto class没有任何关系,它也是一个独立的类,它跟这个auto class是彼此独立的,只不过说我们把它放到了一个文件里边。对不对,只不过说我们把它放到一个文件里边,你通过这idea的结构也能看出来,A idea结构打开之后呢,看是不是有个A,有个auto class,它俩是彼此独立的,只不过说你恰好把这俩给它放到一个Java文件当中了。对,就是这样一个区别,仅此而已,它俩之间没有任何的关联关系啊,你也不能说创建A的时候你还auto class.a那不用A就是a auto class与auto class它俩是独立的,只不过说在一个文件里边。对不对,这就这个意思啊,只有说我们把它把这个类的定义啊,把这个类的定义完全放到我们另外一个类的内部,才可以看它俩,它俩现在等于是没有任何的交集嘛,对不对,没有任何交集,所以说这个东西不是内部类,大家一定要去注意啊。
14:06
这个东西不叫内部类,只有说我们这个诺class,它才叫做内部类。同时的话呢,我们说啊,这个累不累啊,还可以在一个方法体内进行定义。基本的累不累?还可以。在一个方法体中定义。比如说呢,我可以把这个内部类呢,写到一个方法里面,也是OK的,来我们来看怎么写啊。比如说我们就把它改造一下吧。把这个东西删掉。
15:10
在这边怎么改造呢?哎,我们就可以直接在这个,呃,Display方法里边呢,我去定义一个内部类。但是注意啊,这边你就不能去加这个public了。对吧,这边你就不能去加这个public,写出来之后它就报错啊,对吧,所以呢,我们要把它干掉,因为它这边防权限修符必须是默认好class in class。然后呢,它是一个内部类嘛,对,然后我们在这里边可以定义方法。就是定一个print打印。杂音的话,这边我们来写一个说method。Dinner。对吧,Class OK,是一个内部的一个方法啊好。
16:00
完了之后呢?我们接下来。在这呢?我们去。创建一个。一诺class等于六一个1CLASS。对不对,所以你看大家一定要注意啊,我们这种写法是OK的。就是你在内部内部类的内部,在内部类的里边去创建它自己的话呢,就不用去加auto class这样一个前缀,这边也不用去加。对不对,因为我是在内部创建的,所以说我就不用去再加这个外面的,不需要依赖于外面一个对象,我在内部去处理的嘛,对吧,然后调用in class。调用class。我我是我是放到这个display方法里边的。
17:01
我是先声明一个内部类,然后呢再去,呃,这边去创建一个内类,然后呢,我再去调它的方法啊,在这去创建的话,我们不需要去加这个auto class对象好了。然后接下来在梦方法里边,我们来创建一个auto class,等于用一个auto class。然后的话,我们来调用auto class.display方法,大家来看一下会不会去直接我们这个print呢走。对不对,我们可以看到是不是同样的去执行了这个method in the class,也就是说这个内部类定义到方法。体内部呢,也是OK的,可以对应到方案体内部啊,当然这种写法可能比较少见啊。刚才我们上面这两个都是这个非静态内部类啊,所以接下来我们来看静态内部类。净战内部类,它的使用呢,就完全不同了,因为它这个这边呢,就已经属于外部类了,而不是属于外部类对象啊,就这一点点的区别了,我们在创建的时候呢,它的方式是完全不同的。
18:04
上面我们说的内部类它的构造器啊,它的构造呢,必须依赖于外部类的一个对象,对吧,就上面这个东西,当然这个就这个就排除在外了啊,因为我们呃是它是在这个。呃,Dis方法内部呢,去创建这个对象的。对不对,因为因为什么呢?就是这个东西怎么去理解啊。因为我们这个in class是不是就属于这个方法。对不对,然后呢,我是不是同样是在方法内部去创建它,所以等于在自己的这个地方是不是使用它,所以说这边直接创建就OK了,但是这个不一样了啊,这个完全不同了,这个是不是我们已经。是不是已经出了这个。已经出了这个内部类的一个这个结构了,对不对,已经出了内部类的结构了,我们是在闷方法里边调用这个时候的,它的调用呢,就必须依赖于外部类的一个对象才可以。啊,所以这个大家要记住,如果说你是在方法里边去定义这个内部类,那么你在同一个方法里边去创建它,就不用不用去加这个外部类的对象,但是如果说你是在方法体外面去定义内部类,那么你再去创建内部类对象的时候,就就必须依赖于外部类的对象。
19:14
对吧,这个大家记住就OK了啊,接下来我们来看静态内部类。静态内部类的话呢,我们很显然就不需要依赖于外部类对象了。内部类的创建的构造不需要依赖于。外部类对象。对不对,因为我们说静态东西属于这个类本身的,而不是属于对象的,对不对,好,那怎么办呢。静态组件不需要依赖任何对象,这是我们的概念啊,所以呢,我们只需要去定义成静态内部类就OK了。因为我们说静态组件类中的所有静态组件。都不需要。依赖于。任何对象可以。
20:00
直接通过。类本身是不是进行构造啊。好。来,我们来看一下怎么去写。我们还是叫这个display啊,我把这个代码再改一下啊,我把它删掉,这里边的话我们还是去输出。Autumn class。Display。对吧,好,然后呢,我先把这个方法留着。这边我们来定一个啊。Static。Class。In class。对不对,静态的内部的private string。You name。Public in class。
21:01
给他写一个构造器嘛。构造器里边的话,我们同样是给这个阴道内去赋一个值叫阴道。In class。再来写个方法,Public void display。我们来输出。In class。制造的。然后呢,把这个内我们同样的去打印出来好。这个就是一个。这个非静态的。啊,是一个静态内部类,好,那么静态内部类我们这边怎么去构造呢。这边构造的话呢,就完全不需要去依赖于外部的这样一个类了,直接in class in class等于new一个in class对不对啊,后面就不用去加这个。后面就不用去加这个auto class了啊,当然前面的话你看加加行不行。
22:05
看前面你加没问题啊,所以这个前缀你可以加也可以不加,对不对,因为这个结构表示的是in class,就是auto class,一个内部类嘛,它的区别主要在后面,这样的话呢,是不是就跟我们单独去创建一个类是一样的,对不对,不需要依赖于外部类的对象了啊OK。我们加上去。把它的这个呃,标志更加明显一些啊,然后移动class display,你看直接调方法。走。对吧,没有问题吧,跟刚才是一模一样的啊,跟刚才我们第一个写的这个结果是一样的,但是呢,你看现在调用的话呢,是不用去依赖于外部类对象的,因为它现在已经变成了一个静态的内部类了。对吧,OK,好。那结果呢,也记录一下。
23:04
OK吧?然后接下来的话呢,咱们再来看啊。第三种叫做匿名内部类。内部类,内部类啊,匿名内部类,这个匿名内部类啥意思呢?指的是没有名字的一个内部类,匿名内部类主要应用在哪呢?应用在我们这个接口的一个实现,所以呢,我们先来定义一个接口。咱们先来定一个接口。我来定义一个这个,比如说my interface。OK,好,In my interface interface里边呢,我们来写一个方法,Test。那正常的话呢,我们是不是需要需要去实践了,需要去实践它,所以我们要需要去写一个实现类叫my employment。MYMY。
24:08
然后我们在这儿呢去实现它,比如说输出一个test,对吧,这是我们常规的一个写法,OK,那么如果说我们使用这个匿名内部类之后的话,我们就可以对这个代码呢,做一个简化啊,看怎么简化来写一下。比如说我们现在写一个。通过时间类的方式呢,去创建它来inter.test OK,这是通过时间类的方式啊。下来。然后呢,再来一个匿名内部类。一名内部类怎么写呢?直接去写my interface等于啥?等于new,一个买interface。这种写法第二个啊,打回车,你看my interface好。
25:03
然后你看这个东西是不是new了一个my interface,我们正常说接口是不能去new的,但是这边它其实不是在new接口,它是在new接口的一个实现类,并且这个实现实现类就在后面,这叫匿名类部类,看这边是不是没有名字,你看这个东西是不是一个完整的一个类啊。你看这一部分代码,它是不是一个完整类,你看跟这边这个东西有什么区别啊。是不是单纯从我这个鼠标框住的这一部分来讲。他们两个代码是不是一模一样的,你看是不是一模一样的代码,对不对,所以说这个东西它就是一个类,它是一个内部类,而且是一个匿名内部类,没有名字,前面这个意思呢,就是我们这个匿名内部类是这个接口的一个实现类,OK吧,就把太子输出。好,你看两个操作是完全一样的。myinterface1.text来。
26:00
对不对。这个方式是不完全一样的啊,所以说这就是匿名内部类的一个操作。匿名内部类的好处是什么呢?就是我们定义接口之后呢,它的实现类,我不需要去单独创建一个文件去写它的实现了,我就可以把这个实现类的操作呢,直接写到我们调用的这一块就OK了。不用把这一部分单独分出去了,直接写到一起。对不对,那这样的好处呢,就是写起来更加简简洁嘛,啊,更加方便直接就写对不对,但是缺点呢,就是是不是耦合度太高了,对吧,因为你是把这个时间类呢,和这个使用者跟这个T子写到一起了,然后我们这边的话呢,是不是分开的啊,这个是一个单独的时间类,这个是单独test,它俩是分开的。对吧,所以说这是匿名内部类的一个对接口的一个实现啊。我们来记一下。使用。这是匿名,累不累?
27:06
那同样的这个接口我们也可以使用,使用内部类来实现,也可以。对吧,使用内部类。也可以实现接口,我问他怎么去实现。比如说我们就在这个test里边去实现它。那么我先把这里边儿东西清掉啊。把林波先清掉。我们使用一个内部类呢,这时候不是匿名内部类了,而是一个内部类啊,正儿八经的一个类,所以我们叫class my employment。Impairment。实现买啊。那这边呢,我们去实现这个方法,你看对不对,直接这样去写啊,这边的话,比如说我们来输出一个还是输出一个test。
28:02
然后在我们的嫩方法当中啊,嫩方法当中的话,我们来去呃,创建它首先的话,我们需要去创建T的对象。等于new test好完了之后,我们是不是去创建my interface对象,买interface对象就等于谁呢?等不等于直接拗一个买买。直接用myment啊。对吧,你看这边它是不是又报错了,为啥呢?因为它是一个内部类,并且是一个非静态内部类,非静态内类是不是它的创建必须依赖于外部类的对象,所以说这边必须加test.new是不是才可以啊。对不对,是不是这样去创建的,好,创建出来之后的话,我们再来去写点test。对吧,也是一样的啊,所以说你使用内部类也同样去也可以去实现这个接口,所以这个东西它是比较灵活,它是比较灵活的,呃,总之呢,就是对接口的一个实现,你可以。
29:04
在外面去单独去定义一个类,去写它的时间类没问题,也可以呢,把这个时间类呢,放到我们test的里边,就成为一个内部类也可以,然后呢,你还可以用用匿名内部类的方式,对吧?用匿名内部类是不是最简洁,这个代码最简单,写的东西最少。对吧,但是他们的功能都是一样的啊。所以呢,以上这几种情况,我们一共写了三种。我们因为写了三种啊,把这三种标注出来。
30:02
那通过我们这三种非静态内部类,静态内部类以及匿名内部类的一个操作呢,相信大家对于内部类这一块的,呃,这个技术呢,就没有任何问题了,OK吧,好。
我来说两句