码迷,mamicode.com
首页 > 其他好文 > 详细

匿名内部类

时间:2017-04-06 15:32:02      阅读:155      评论:0      收藏:0      [点我收藏+]

标签:变量   abstract   为我   基本   简化   理论   而且   打印   ace   

匿名内部类,类比于前面我们学过的匿名对象...

匿名内部类,就是内部类的简化写法,前提是存在一个类或者接口,这里的类可以是具体类,也可以是抽象类...

格式:new 类名或者接口名(){重写方法;}

本质是什么呢?
是一个继承了该类或者实现了该接口的子类匿名对象...

下面看匿名内部类的格式...

public class Test{
public static void main(String[] args){
Outer o=new Outer();
o.method();
}
}
interface Inter{
public void print();
}
class Outer{
class Inner implements Inter{
public void print(){
System.out.println("print");
}
}
public void method(){
Inner i=new Inner();
i.print();
}
}

注意:匿名内部类是局部内部类的一种,既然是局部内部类的一种,那么匿名内部类必须位于成员方法里面...

此时,Inner作为Outer类的一个成员内部类,Inner类实现了接口Inter,Inner类存在一个方法print,Outer类还有一个成员方法method,上面已经说了,匿名内部类的前提是存在一个类或者接口,当然这个类可以是具体类也可以是抽象类,我们再来写一遍匿名内部类的代码

先看匿名内部类的格式 格式:new 类名或者接口名(){重写方法;}

前面我们学过抽象类,然后进一步学习了接口,接口是对抽象类的进一步升华,接口是完全抽象的产物,接口里面的成员变量只能是常量,里面的成员方法只能是抽象方法,正儿八经的说,接口不是一个类,但是接口与类有很多的相似之处,从某种意义上说,我们也可以把接口当做一个类来理解,类继承类,类实现接口,接口继承接口,当用一个类去实现一个接口时,我们也可以把这个接口视作一个"特殊的类",我们现在要写一个匿名内部类的代码,我们就按照要求,先写一个接口,在Editplus中编写代码...
前提是存在一个接口或者一个类,那么先从接口入手,写一个接口...接口中的方法没有方法体,是抽象方法,既然匿名内部类是一个局部内部类,那么我们还要写一个外部类...

public class Test{
public static void main(String[] args){

}
}

interface Inter{
public void print();

}

class Outer{

}

先搭建代码框架,首先,我们定义了一个接口,接口中有一个print方法,既然定义了接口,我们的目的肯定是使用接口中的print方法,但是,要想使用接口中的print方法,我们无法直接去使用这个print方法,必须创建一个类去实现这个print方法,这时候,我们可以认为是这个类去继承这个"接口类",由于"接口类"里面都是抽象方法,所以普通类实现接口,一定要重写接口中的方法,那么应该创建一个怎样的普通类去重写接口方法呢,这里,学的是匿名类,因为应该联想到匿名类会派上用场...

public class Test{
public static void main(String[] args){

}
}

interface Inter{
public void print();

}

class Outer{
public void method(){
class Inner implements Inter{
public void print(){
System.out.println("print");
}
}
}

}

这样,method方法作为Outer类的成员方法,在method方法里面还有一个Inner类,该类实现Inter接口,现在我的目的是调用print方法,显然,还是两道关卡,Inner类的对象去调用print方法,然后外部类Outer去调用内部类Inner但是外部类Outer类的对象调用method方法并不代表就调用了Inner对象,那么,该怎么办呢???

Inner i=new Inner();
i.print();

Outer o=new Outer();
o.method();

因为Outer类只有唯一的一个method方法,所以Outer类唯一可以直接调用的只有method方法,前面学过,调用一个方法,除了给形参赋值,执行方法语句,还会获得一个返回值,那么既然Outer类只能调用method方法,那么为了确保在调用method方法的同时,还能实现Inner类的对象调用print方法,我们就把Inner类创建对象并且调用print方法的语句封装到Outer类的method方法中,这样就实现了一举两得的目的,就是一次调用,就可以通过两道关卡...

于是,完整代码为

public class Test{
public static void main(String[] args){

Outer o=new Outer();
o.method();

}
}

interface Inter{
public void print();

}

class Outer{
public void method(){
class Inner implements Inter{
public void print(){
System.out.println("print");
}
}
Inner i=new Inner();
i.print();
}

}

但是,尽管我在上面代码中也达到了调用print方法的目的,但是我发现,我写出来的代码和匿名内部类没有任何关系,那么,究竟如何,我才能使用匿名内部类呢???

先来看一段匿名内部类的代码

class Demo1_NoNameInnerClass {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}

interface Inter {
public void print();
}

class Outer {
class Inner implements Inter {
public void print() {
System.out.println("print");
}
}
public void method(){
new Inter() {
public void print() {
System.out.println("print");
}
}.print();
}
}

其实看到这段代码,不要懵逼,为什么呢,因为我们的最终目的是要调用print方法,来看以前的代码


public class Test{
public static void main(String[] args){

Outer o=new Outer();
o.method();

}
}

interface Inter{
public void print();

}

class Outer{
public void method(){
class Inner implements Inter{
public void print(){
System.out.println("print");
}
}
Inner i=new Inner();
i.print();
}

}

既然匿名内部类是一个局部内部类,那么我们先创建一个方法,并且在这个方法里面按照标准格式写一个匿名内部类...并且还要定义一个接口...

来看下面的框架

class Demo1_NoNameInnerClass {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}

interface Inter {
public void print();
}

class Outer {

public void method(){
new 类名或接口名() {重写方法;}
}
}

这里面,定义了接口Inter,并且在Outer类中定义方法method,然后就是看看在method方法中填写什么内容了,此处的难点在于,new 类名或接口名() {重写方法;}这里的类名或者接口名,到底该填什么类或者什么接口,此处既然定义了一个接口,那么我们必然有所目的,因为接口存在的意义在于有一个类去实现这个接口,并且重写这个接口的方法,为什么要重写这个接口的方法呢,当然是我们需要用这个方法,才去重写他,不然重写的意义就不大,所以,这里缺少一个类,需要这个类去实现Inter接口,于是,看下面一段代码

class Inner implements Inter{
public void print(){

System.out.println("print");
}
}

然后就是考虑到底该把上面这段代码摆放在什么位置,假如Inner和Outer平级,如下面

class Test {
public static void main(String[] args) {
Inner i=new Inner();
i.print();
}
}

interface Inter {
public void print();
}
class Inner implements Inter{
public void print(){

System.out.println("print");
}
}

class Outer {

public void method(){

}
}

这时候,其实根本就和匿名内部类扯不上关系,因为如果Outer类和Inner类平级,那么此时Outer类这段代码完全成了多余的,砍掉这段代码,程序照样能运行,看下面

class Test {
public static void main(String[] args) {
Inner i=new Inner();
i.print();
}
}

interface Inter {
public void print();
}
class Inner implements Inter{
public void print(){

System.out.println("print");
}
}

所以,Inner类和Outer类正确的关系应该是Outer类包含Inner类,也就是说,Inner类是一个内部类,这样,匿名内部类的出现才显得更有意义。。。于是,看下面代码,虽然下面只是一段不完整而且不规范的代码,但是,他对我们该如何编写正确的格式提供了启发

class Test {
public static void main(String[] args) {
Inner i=new Inner();
i.print();
}
}

interface Inter {
public void print();
}


class Outer {
class Inner implements Inter{
public void print(){

System.out.println("print");
}
}
public void method(){

}
}

此时,要想调用print方法,需要Inner类的对象去调用print方法,但是,触发Inner类需要外部类的对象去调用内部类,于是,又回到了最开始我们学内部类的地方,但是如果按照最开始的格式,看下面

class Test {
public static void main(String[] args) {
Outer.Inner i=new Outer().new Inner();
i.print();
}
}

interface Inter {
public void print();
}


class Outer {
class Inner implements Inter{
public void print(){

System.out.println("print");
}
}
public void method(){

}
}

这段代码也能成功编译运行,但是这样,我发现,method方法成了多余,匿名内部类也没有出现,那么,要想改变这种格局,必须从

Outer.Inner i=new Outer().new Inner();
i.print();

从上面这两句代码上入手,当然,在这里,i.print();表示直接调用print方法,虽然我的目的是发挥print方法的作用,或者说调用print方法,但是,我可以不直接调用print方法,通过调用另一个方法method,然后在method方法体中封装直接调用print方法的语句,前面我说过,调用方法相当于代码移植,这样通过调用method方法来间接调用print方法,看看下面的代码

class Test {
public static void main(String[] args) {
Outer o=new Outer();
o.method();
}
}

interface Inter {
public void print();
}


class Outer {
class Inner implements Inter{
public void print(){

System.out.println("print");
}
}
public void method(){
Inner i=new Inner();
i.print();

}
}

这个代码功能是一样的,通过Outer类对象去调用method方法从而达到调用print方法的目的,但是,还是没有使用匿名内部类,到底怎么才能让匿名内部类发挥作用呢??????

前面我们学过 new 类名();这个格式表示一个对象,因此,再来看匿名内部类的格式

new 类名或者接口名(){重写方法;}

这看起来也像是一个对象的格式,但是,对于上面的代码,这个格式中的类名和接口名到底是哪一个呢,是Outer Inner 还是Inter呢,此处比较难以理解的是,匿名内部类的前提是存在一个类或者一个接口,关于前提为什么是存在一个类或者一个接口,不用深究,因为这是java中的规定,我们要用java,就必须按照他的规则办事,我们先不要管什么前提,先来研究匿名内部类,其实就是一个位于成员方法中的匿名类,匿名类我们可以类比于前面学过的匿名对象,但是,如果空想怎么去定义匿名类,相信绞尽脑汁也难以想出匿名类的语法结构,但是,java中一般不用直接利用class关键字去定义一个匿名类,往往是在定义匿名类时同时伴随着匿名类对象的产生,前面学过对象的格式,new 类名();这种格式就是表示一个对象,但是,匿名内部类依赖的是接口或者父类,所以,创建匿名内部类对象必然会与接口或者父类捆绑,如果是通过接口实现匿名内部类对象,或者说创建匿名内部类对象是与接口有关,那么,这里我们就不用再去纠结语法结构了,上面的代码已经定义好了接口Inter,那么,我们编写代码的目的是为了实现我们到底想干嘛,我的目的无非是调用print方法,前面我讲过,是通过Outer类对象调用method方法,从而间接调用print方法,根据代码移植理论,那么必须在method方法中封装直接调用print方法的代码,谁能直接调用print方法,当然是拥有print方法的对象,比如,一个类中定义了print方法,那么,这个类和这个类生成的对象就具备print功能,因此,该对象就可以调用print方法,现在我们是用一个匿名类的对象去直接调用这个print方法,这个匿名类是没有名字的,我也不知道怎么去表示它,因为匿名类本来就没有名字,你还怎么去表示它,但是,我知道表示这个匿名类对象的格式,知道格式就好办,因为已经定义了接口Inter,就用这个Inter作为前提去表示一个匿名类对象

new Inter(){}

虽然这个匿名类对象表示出来了,这个对象没有名字,只有一个表示形式,正因为没有名字,才叫匿名,这时候,这个匿名类对象我们是创建出来了,但是我并不知道这个对象的形态特性,它里面的成员变量和成员方法并没有直接说明,那么此时,关键的地方来了,前面我说过,接口可以当做一个特殊的类来理解,继承和实现其实意义相近,那么Inter这个"接口类",当一个匿名类对象生成时,首先这个匿名类可以认为是继承了这个特殊的"接口类",那么,这个类继承接口类,其方法来源于接口,但是必须重写接口中的方法才有意义,于是重写接口方法,代码完善成

new Inter(){public void print(){System.out.println("你妹");}}

那么这时候,我们已经完全看透了这个匿名类对象,其实就是重写了接口的方法,其他的和接口一模一样,也就是说,这个匿名类对象具有print方法,或者说具有print功能,那么,既然这个匿名类对象具有print功能,这个匿名类对象当然可以调用print方法,所以,下面

new Inter(){public void print(){System.out.println("你妹");}}.print()

这个匿名类对象的print功能是打印出 你妹

完整代码为

class Test {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}

interface Inter {
public void print();
}

class Outer {


public void method(){



new Inter(){public void print(){System.out.println("你妹");}}.print();

}
}

只要认清楚,匿名内部类其实只是一个匿名类,只不过位置位于方法中...

但是匿名内部类只针对重写一个方法时使用...

匿名内部类在开发中的应用(当做参数传递)

看下面代码

class Test {
public static void main(String[] args) {

PersonDemo pd = new PersonDemo ();

pd.method(new Person() {
public void show() {
System.out.println("show");
}
});
}
}

abstract class Person {
public abstract void show();
}

class PersonDemo {

public void method(Person p) {
p.show();
}
}

class Student extends Person {
public void show() {
System.out.println("show");
}
}

上面我说过,匿名内部类总是伴随着类或者接口,而且匿名内部类一定会重写方法,这说明,匿名内部类与抽象类有关,因为重写一般是与抽象方法有关,因此,我们用抽象类或者抽象接口都好说...
写一个抽象类,含有抽象方法的类一定是抽象类...

abstract class Person{
public abstract void show();
}


再来写一个类
class PersonDemo{
public void method(Person p){p.show();}

}

这个类中含有一个method方法,method方法的参数是Person类的一个对象,其实Person p和int a
这样的格式类似,可以把Person当做一个数据类型,p是变量名,只不过,int a这里的a是int型,也就是基本数据类型,而p是一个引用数据类型,所以,也可以称之为Person类的引用p,我们通常说成Person类的对象p,在method方法的方法语句中,是利用对象p去调用show方法...这里的函数参数是Person类的引用变量p,前面我们学过,函数参数可以是基本数据类型,也可以是引用数据类型...

再来写一个类Student,作为Person类的子类...

class Student extends Person{
public void show(){
System.out.println("show");
}

}

现在我们注意到,在PersonDemo这个类中,method方法里面,该方法参数是Person类的对象,我现在就是需要调用这个方法,看看怎么调用...如果将匿名内部类对象作为参数传递给method方法

PersonDemo pd=new PersonDemo();
pd.method(匿名内部类对象);

那么,现在应该想办法,怎么去表示这个匿名内部类对象,前面学过,匿名内部类其实就是一个位于成员方法中的匿名类,因此,我们应该研究匿名类的特性,匿名类因为没有名字,所以不能使用通用格式去定义它,比如class Test{} 这是定义一个Test类,我们一般不单独定义匿名类,因为单独定义匿名类,根本就没有一种格式去表示它,一般是定义一个匿名类的对象,也就是说,匿名类的定义其实是通过定义匿名内部类对象来实现,前面,我们学过,new 类名();这样的格式就是表示一个对象,所以,此处我们也使用new关键字,来表示一个匿名内部类的对象,由于匿名内部类与重写方法有一定的关联,所以,必须找一个类或者接口,作为这个匿名类的父类或者干爹,也就是说,匿名类的产生不是凭空产生,必须借助一个类或者接口作为父类,并且遗传父类的特性,这也是匿名类产生的依据...

于是,我们在这里,选取抽象类Person作为匿名类的父类,也就是说,抽象类Person就是匿名类的依据,于是,格式就出来了

new Person(){public void show()

{System.out.println("show");}}
然后就把这个匿名类对象作为参数传递给method方法...

于是完整代码为

class Test {
public static void main(String[] args) {

PersonDemo pd = new PersonDemo ();

pd.method( new Person(){public void show()

{System.out.println("show");}} );
}
}


abstract class Person{
public abstract void show();
}

class PersonDemo{
public void method(Person p){p.show();}

}

class Student extends Person{
public void show(){
System.out.println("show你妹");
}

}

 

注意分析

new Person(){public void show()

{System.out.println("show");}}

这段语句整体是一个匿名类对象,这个对象没有名字,new Person()说明这个匿名类是以Person类作为父类,或者说Person类是这个匿名类的产生依据,然后这个匿名类除了重写父类Person类的show方法,其他的特性和父类一模一样,也就是说匿名类的特性遗传于父类或者遗传于接口,当匿名类对象调用show方法时,前面学过,调用方法就是代码移植,也就是发挥匿名类对象show方法的功能,所以会打印出 show 字符串...

 

匿名内部类

标签:变量   abstract   为我   基本   简化   理论   而且   打印   ace   

原文地址:http://www.cnblogs.com/asdxyz/p/6673570.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!