Java内部类详解:成员内部类、静态内部类、方法内部类及匿名内部类的使用与区别
Java内部类的几种类型:成员内部类,静态内部类,内部类,匿名内部类。

成员内部类:成员的内部类是类内的非静态类。成员的内部类无法定义静态方法和变量(最终修改除外)。这是因为成员的内部类是非静态的。初始化课程时,静态成员将初始化。如果允许成员的内部类定义静态变量,则成员内部类的静态变量初始化顺序是模棱两可的。示例如下:
操作的结果是:在外部类A:99中访问,内部类访问B:2
如何使用内部成员类别:
1。内部类的内部定义在外类内部,这等同于外部类的成员变量的位置。内类可以使用任何访问控制符号,例如公共,保护,私人等。
2。内部类中定义的test()方法可以直接访问外部类中的数据而不会受到访谈控制符号的影响,例如直接访问校正类中的私人属性
3。定义成员的内部类后,必须使用外部类对象来创建内部类对象,而无需直接进入内部类对象,即内部类对象名称=外部类别class Object。 );;);
4。编译上述程序后,您会发现生成了两个.class文件
其中,第二个是外部类的.class文件。第一个是内部类的.class文件,即成员内部类的.class文件。
此外,友谊提醒:
1。外部类不能直接在内部类中滴入。喜欢:
那么如何使用外部类的内部类成员和方法?路口
答:您可以首先创建一个内部类对象,然后通过内部类的对象访问成员变量和方法。
当Java编译器创建一个内部类对象时,对外部类对象的引用也将传递并保留。这样,内部类对象总是可以访问其外部类对象。同时,这就是为什么必须创建外部类对象以在外部类范围之外创建外部类对象的原因。
2。如果外部和内部类具有相同的成员变量或方法,则默认情况下,内部类将访问其成员变量或方法。如果要访问外部类的成员变量,则可以使用此关键字。喜欢:
运行结果:
静态内部类:静态内部类是静态修改的内部类。该内部类的特征是:
1。静态内部类无法直接访问外部类的非静态成员,但是可以通过新的外部类()访问它们。
2。如果外部类的静态成员与内部类的名称相同,则可以通过“类名称。静态成员”访问外部类的静态成员; “成员名称”直接调用外部类的静态成员。
3。创建静态内部类的对象时,不需要外部类对象。您可以直接创建一个内部类对象名称= new Internal class();
运行结果:
方法内部类:该方法的内部类是外部类方法中的内部类定义。该方法的内部类只能在方法内看到,也就是说,它只能在此方法中使用。
请确保注意:由于该方法的内部类不能在外部类方法之外使用,因此该方法的内部类不能用于使用访问控制符号和静态修饰符。
匿名内部类:匿名类别不能具有名称,因此没有办法引用它们。创建时,必须将其声明为新声明的一部分。
但是,还有使用匿名内部类的先决条件:必须继承父类或实现接口。
这是使用另一种形式的新语句的必要条件,如下所示:
新的
这种新语句形式声明了一个新的匿名类,该类别扩展给定类或实现给定界面。他还创建了一个班级的新例子,并将他归还了声明的结果。课程扩展,要实现的接口是
新语句的操作数量,然后是匿名类型的主体。
请注意,匿名语句是在汇编过程中执行的,并在运行时实例化。这意味着
for循环中的一个新语句创建了相同匿名类的几个示例,而不是创建一些不同匿名类别的示例。
从技术上讲,匿名类别可以被视为非静态内部类别,因此它们具有相同的权限和对被声明为内部声明的非静态内部类的限制。
如果要执行的任务需要一个对象,但是不值得创建一个新对象(原因是所需类太简单,或者因为他仅在一种方法中使用),则匿名类非常有用。匿名类特别适合在Swing应用程序中快速创建事件处理程序。以下是匿名内部类的实例:
1。匿名内部类的基本实现:
运行结果:
可以看出,我们可以直接在括号中的抽象人员中实现该方法,以便我们可以忽略一类写作,并且也可以在接口上使用匿名的内部类。
2。在接口上使用匿名内部类:
运行结果:
从上面的示例可以看出,只要类是抽象的或接口,可以使用匿名内部类实现其子类中的方法。
在使用匿名内部类的过程中,我们需要注意以下几点:
1。当使用匿名内部类时,我们必须继承一个类或实现接口,但是两者不能同时继承,并且我们只能继承一个类或实现一个界面。
2。在匿名内部类中,无法定义构造函数。
3。在匿名内部类中没有静态成员变量和静态方法。
4。匿名内部类是本地内部类(即该方法的内部类),因此本地内部类的所有限制也对匿名内部类也有效。
5。匿名内部类不能抽象。它必须实现接口的继承类或所有抽象方法。
匿名内部类别关键困难:
1。如果它是一种方法的匿名内部类,则可以使用此方法传递到所需的参数中,但请记住,这些参数必须将其声明为最终。
为什么使用使用参数?路口
当我们将参数传递给匿名内部类时,如果需要在内部类中使用人参,则该参数必须是最终的。换句话说,当需要在内部类中使用该方法的参数时,该参数必须是最终的。
首先,我们知道,在内部类汇编成功后,它将产生一个类文件。类文件和外部类不是同一类文件,而仅保留对外部类的引用。当需要由内部类调用外部类的参数时,它是从Java程序的角度直接调用的:
公共类超类{
public void display(最终字符串名称,字符串年龄){{
类InnerClass {
void display(){
system.out.println(name);
从上面的代码中,似乎应该由内部类直接调用名称参数?实际上,Java汇编后的实际操作如下:
公共类超越$ inninclass {
public innerclass(字符串名称,字符串年龄){{
this.innerClass $ name = name;
this.innerclass $ age = age;
public void display(){
system.out.println(this.innerClass $ name +“ ----” + this.innerClass $ age);
因此,从上述代码中,内部类不是该方法直接传输的参数,而是使用自己的构造函数备份传递参数。参数。
直到没有解释为什么它是最终的。内部类中的参数和外部方法的参数从外部是相同的,但实际上不是,因此它们可以任意更改,即在内部类中,我更改了内部类中的属性。它不会影响外部参数,从程序员的角度来看,这是不可行的。毕竟,从程序的角度来看,这两个基本上是相同的。外部方法的形式参数尚未更改。这很难理解和不可接受。因此,为了维持参数的一致性,规定使用最终来避免非变化参数。
简单的理解是,为了避免参考值的变化,例如通过外部类的方法进行修改,内部类的值是不一致的,因此它用于使参考文献不变。
因此,如果定义了匿名内部类并希望它使用外部定义参数,则编译器将需要最终参数参考。
2。在匿名内部类中使用初始化代码块
我们通常使用构造函数来完成特定实例的初始化,但是匿名内部类没有构造函数!那么如何初始化匿名内部类?使用构造函数块!使用构造函数块可以实现为匿名内部类创建构造函数的效果。
公共类超越{
public innerclass getinnerClass(最终int年龄,最终字符串名称){{{
返回new inningClass(){
int age_;
字符串名称_;
//施工代码块完成初始化工作
如果(0 <ge && age <200){{{
age_ =年龄;
name_ = name;
公共字符串getName(){
返回名称_;
public int getage(){
返回年龄_;
};
公共静态void main(string [] args){{{
outClass out = new OutClass();
InnerClass Inner_1 = out.getInnerClass(201,“ Chenssy”);
system.out.println(inne_1.getName());
InnerClass Inner_2 = out.getInnerClass(23,“ Chenssy”);
system.out.println(inne_2.getName());
5。内部班级摘要
在学习了上述四种类型的内部类别后,我们知道如何使用每个内部类,那么为什么要使用内部类呢?路口
首先,举一个简单的例子。如果要实现接口,但是此接口中的方法与您受孕的此类方法中的方法相同。你该怎么办?目前,您可以构建一个内部类来实现此接口。由于外部类的所有内容都可以访问内部类,因此可以完成您意识到此接口的所有功能。
但是您可能必须质疑,更改方法还不够吗?确实,出于设计内部阶级的原因,确实没有说服力。
真正的原因是,这是Java中内部类和接口的增加,并且可以通过C ++程序员通常抱怨的问题来解决它,即Java中存在问题 - 不再有继承。实际上,C ++的继承更加复杂,Java可以通过内部类和界面实现多个继承的效果。
内部类:内部类的定义是在另一个内部定义的类。
原因是:
1。内部类的对象可以访问创建它的对象的实现,包括私有数据。
2。对于同一软件包中的其他类,可以隐藏内部类。
3。可以轻松定义匿名内部类。
4。使用内部类可以轻松编写事件驱动程序。
内部类使您可以更优雅地设计程序结构。以下各个方面引入以下内容:
首先查看此示例:
1个公共接口内容{
2 int value();
3}
5个公共接口目标{
6字符串readlabel();
7}
1个公共班级商品{
2个私人值= 2;
4个私人类内容{
5个私有int i = 11 *值;
6公共int值(){
7返回i;
8}
9}
10
11受保护的类Gdestintion实现目标{
12个私人字符串标签;
13私人gdestination(string whereto){{{
14标签= whereto;
15}
16公共字符串readlabel(){
17返回标签;
18}
19}
20
21公共目的地dest(字符串S){
22返回新的gdestination;
23 }
24
25公共内容cont(){
26返回新内容();
27}
28}
在此示例中,类内容和gdestination是在商品类型中定义的,并且有受保护和私人修饰符来控制访问级别。内容代表货物的内容,gdestination代表货物的目的地。他们分别实现两个接口内容和目的地。在后来的主要方法中,使用Conneits C和Destination D直接操作,您甚至没有看到这两个内部类的名称!这样,内部类的第一个好处就反映了 - 避免您不想让别人知道的操作,即封装。
非静态内部类对象具有对其外部类对象的引用
修改上述示例:
1个公共班级商品{
2个私人值= 2;
4个私人类内容{
5个私有int i = 11 *值;
6公共int值(){
7返回i;
8}
9}
10
11受保护的类Gdestintion实现目标{
12个私人字符串标签;
13私人gdestination(string whereto){{{
14标签= whereto;
15}
16公共字符串readlabel(){
17返回标签;
18}
19}
20
21公共目的地dest(字符串S){
22返回新的gdestination;
23 }
24
25公共内容cont(){
26返回新内容();
27}
28}
在这里,我们向商品类添加私人成员变量值,这意味着货物的价值系数。当内部类内容方法值()计算值时,它会乘以。我们发现值()可以访问值,这也是内部类的第二好 - 一个内部类对象可以访问创建它的外部类对象的内容,甚至是私有变量!这是一个非常有用的功能,在设计时为我们提供了更多的想法和快捷方式。为了实现此功能,内部对象必须引用外部类对象。当Java编译器创建一个内部类对象时,对外部类对象的引用也将传递并保留。这样,内部类对象总是可以访问其外部类对象。同时,这就是为什么必须创建外部类对象以在外部类范围之外创建外部类对象的原因。