From:https://www.cnblogs.com/geeksongs/p/9836154.html
一,内部类
其实内部类是十分简单的,我们根据其字里行间的意义就可以知道内部类应该是一个类当中的一个类,相当于一个类进行了嵌套,就如同循环的嵌套一般。
内部类有一个特征:内部类当中可以调用外部类当中的属性和方法,而外部类却不能调用内部类当中的。除了这特征就没啥特征了,我们来看看代码了解一下(点击代码上方的文档小图标就可以复制代码,因为我加了代码的行号看起来整洁一些,但是复制可能不太方便):
package com.company;public class Innerclass {public static void main(String[] args) {System.out.println("下面是是内部类的程序展示");//创建外部类和内部类的方法有点不相同AAA a=new AAA();// 这里开始创建内部类的对象,这是创建内部类对象的专用格式,// 相当于在创建了一个外部类对象的基础上再创建一个内部类对象2AAA.BBB b=new AAA().new BBB();a.say2();b.sayit();}
}class AAA
{int waibu=12;public void say2(){System.out.println("这是外部类当中的方法");}class BBB{int neibu=13;public void sayit(){System.out.println("这是内部类里面的方法");System.out.println("使用内部类和外部类当中的数值进行想加的结果是"+(neibu+waibu));//之所以内部类可以使用外部类的属性是因为在创建对象的时候,//已经给内部类的对象附加了一个外部类的对象,内部类的对象是建立在外部类对象的基础上的。}}
}
最终的sayit()方法输出结果是25=(13+12),从中可以证明内部类确实是可以调用外部类的属性的,但如果外部类调用内部类的属性则会发生报错。
二.匿名内部类
首先我们应该知道匿名内部类匿名是因为匿名内部类的具体名字不会被我们在程序当众编写出来,因为它已经在主方法当中被实例化了。
匿名内部类可以继承两类数据结构:
- 一:抽象类
- 二:接口。
比如我们的代码有:
package com.company;public class Innerclass {public static void main(String[] args) {Chouxiang c = new Chouxiang() {String name = "Geek Song too";public void say3() {System.out.println("这是匿名内部类当中的方法,重写了抽象类的方法");System.out.println(name);}};}
}abstract class Chouxiang
{String name="Geek Song";//抽象类的属性是不会被调用的,除了方法public void say3(){System.out.println("这是抽象类当中的方法,抽象类当中是允许有具体方法来进行实现的,接口不行");}
}
这显然继承了一个抽象类,并且在主方法当中创建了抽象类的对象,本来我们是应该先继承这个抽象类再开始创建对象的,否则对象是无法创建的,但是为了简便,人们创建了了匿名内部类,允许我们在主方法当中进行抽象类的实例化,同时也可以进行对象的创建。这个程序就等同于如下的程序:
package com.company;public class Innerclass {public static void main(String[] args) {System.out.println("下面是是内部类的程序展示");//创建外部类和内部类的方法有点不相同AAA a=new AAA();AAA.BBB b=new AAA().new BBB();a.say2();b.sayit();System.out.println("现在开始匿名内部类程序的编写\n");Chouxiang2 c=new Chouxiang2();c.say3();}
}class AAA
{int waibu=12;public void say2(){System.out.println("这是外部类当中的方法");}class BBB{int neibu=13;public void sayit(){System.out.println("这是内部类里面的方法");System.out.println("使用内部类和外部类当中的数值进行想加的结果是"+(neibu+waibu));//之所以内部类可以使用外部类的属性是因为在创建对象的时候,//已经给内部类的对象附加了一个外部类的对象,内部类的对象是建立在外部类对象的基础上的。}}
}abstract class Chouxiang
{String name="Geek Song";//抽象类的属性是不会被调用的,除了方法public void say3(){System.out.println("这是抽象类当中的方法,抽象类当中是允许有具体方法来进行实现的,接口不行");}}class Chouxiang2 extends Chouxiang
{public void say3(){System.out.println("这是继承的方法");}
}
因此这里就会涉及到多态和向上转型了,我们输出的子类的方法,父类的属性,匿名内部类也是相同的。输出的匿名内部类的方法,以及父类的属性。
完整的程序如下,方便大家进行知识点的理解:
示例代码:
package com.company;public class Innerclass {public static void main(String[] args) {System.out.println("下面是是内部类的程序展示");//创建外部类和内部类的方法有点不相同A a = new A();A.B b = new A().new B();a.say2();b.sayit();System.out.println("现在开始匿名内部类程序的编写\n");Chouxiang c = new Chouxiang() {String name = "Geek Song too";public void say3() {System.out.println("这是匿名内部类当中的方法,重写了抽象类的方法");System.out.println(name);}};//在使用匿名内部类的时候,当这个类在陈述完之后,是需要打分号的。c.say3();System.out.println("我们来看看这个name到底是抽象类当中的name还是匿名内部类当中的" + c.name);//结果果然是父类当中的属性,和我们多态的性质相重合了//这就是所谓的向上转型。现在我们再来试试接口的匿名内部类实现Jiekou yui = new Jiekou() {@Override//由于必须实现接口当中的方法,因此计算机就自动为我们写上了override的标识符了public void say5() {System.out.println("这是继承的接口当中的方法");}};yui.say5();}
}class A {int waibu = 12;public void say2() {System.out.println("这是外部类当中的方法");}class B {int neibu = 13;public void sayit() {System.out.println("这是内部类里面的方法");System.out.println("使用内部类和外部类当中的数值进行想加的结果是" + (neibu + waibu));//之所以内部类可以使用外部类的属性是因为在创建对象的时候,// 已经给内部类的对象附加了一个外部类的对象,// 内部类的对象是建立在外部类对象的基础上的。}}
}// 虽然内部类的程序已经成功了,但是匿名内部类的程序还没有成功,
// 现在我们来创建一个匿名内部类(在主方法当中,首先应该创建一个抽象类或者接口)
abstract class Chouxiang {String name = "Geek Song";//抽象类的属性是不会被调用的,除了方法public void say3() {System.out.println("这是抽象类当中的方法,抽象类当中是允许有具体方法来进行实现的,接口不行");}}interface Jiekou {public void say5();}