当前位置:七道奇文章资讯编程技术Java编程
日期:2011-03-22 16:17:00  来源:本站整理

<b>java的匿名内部类</b>[Java编程]

赞助商链接



  本文“<b>java的匿名内部类</b>[Java编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
至此,我们已基本理解了内部类的典型用处.对那些触及内部类的代码,普通表达的都是“纯真”的内部类,非常简单,且极易理解.但是,内部类的计划非常全面,不可避免地会碰到它们的其他大量用法——假如我们在一个办法乃至一个肆意的作用域内成立内部类.有两方面的缘由促使我们这样做:
(1) 正如前面展示的那样,我们预备实现某种情势的接口,使自己能成立和返回一个句柄.
(2) 要办理一个复杂的问题,并但愿成立一个类,用来帮助自己的程序筹划.同时不肯意把它公开.

在下面这个例子里,将改正前面的代码,以便利用:
(1) 在一个办法内定义的类
(2) 在办法的一个作用域内定义的类
(3) 一个匿名类,用于实现一个接口
(4) 一个匿名类,用于扩大拥有非默许构建器的一个类
(5) 一个匿名类,用于履行字段初始化
(6) 一个匿名类,通过实例初始化举行构建(匿名内部类不可拥有构建器)

全部这些都在innerscopes包内发生.首先,来自前述代码的通用接口会在它们自己的文件里得到定义,使它们能在全部的例子里利用:
//: Destination.java
package c07.innerscopes;

interface Destination {
  String readLabel();
} ///:~

由于我们已认为Contents大概是一个抽象类,所以可采纳下面这种更自然的情势,就象一个接口那样:
//: Contents.java
package c07.innerscopes;

interface Contents {
  int value();
} ///:~

固然是含有具体实施细节的一个普通类,但Wrapping也作为它全部衍生类的一个通用“接口”利用:
//: Wrapping.java
package c07.innerscopes;

public class Wrapping {
  private int i;
  public Wrapping(int x) { i = x; }
  public int value() { return i; }
} ///:~

在上面的代码中,我们注意到Wrapping有一个要求利用自变量的构建器,这就使情形变得越发风趣了.
第一个例子展示了如安在一个办法的作用域(而不是另一个类的作用域)中成立一个完好的类:
//: Parcel4.java
// Nesting a class within a method
package c07.innerscopes;

public class Parcel4 {
  public Destination dest(String s) {
    class PDestination
        implements Destination {
      private String label;
      private PDestination(String whereTo) {
        label = whereTo;
      }
      public String readLabel() { return label; }
    }
    return new PDestination(s);
  }
  public static void main(String[] args) {
    Parcel4 p = new Parcel4();
    Destination d = p.dest("Tanzania");
  }
} ///:~

PDestination类属于dest()的一部份,而不是Parcel4的一部份(同时注意可为相同目录内每个类内部的一个内部类利用类标识符PDestination,这样做不会发生命名的冲突).因此,PDestination不可从dest()的外部拜候.请注意在返回语句中发生的上溯造型——除了指向底子类Destination的一个句柄之外,没有任何东西超越dest()的边界之外.当然,不能由于类PDestination的名字置于dest()内部,就认为在dest()返回之后PDestination不是一个有效的对象.
下面这个例子展示了如安在肆意作用域内嵌套一个内部类:
//: Parcel5.java
// Nesting a class within a scope
package c07.innerscopes;

public class Parcel5 {
  private void internalTracking(boolean b) {
    if(b) {
      class TrackingSlip {
        private String id;
        TrackingSlip(String s) {
          id = s;
        }
        String getSlip() { return id; }
      }
      TrackingSlip ts = new TrackingSlip("slip");
      String s = ts.getSlip();
    }
    // Can't use it here! Out of scope:
    //! TrackingSlip ts = new TrackingSlip("x");
  }
  public void track() { internalTracking(true); }
  public static void main(String[] args) {
    Parcel5 p = new Parcel5();
    p.track();
  }
} ///:~

TrackingSlip类嵌套于一个if语句的作用域内.这并不意味着类是有条件成立的——它会伴随其他全部东西得到编译.但是,在定义它的那个作用域之外,它是不可以利用的.除这些以外,它看起来和一个普通类并没有什么辨别.
下面这个例子看起来有些奇特:
//: Parcel6.java
// A method that returns an anonymous inner class
package c07.innerscopes;

public class Parcel6 {
  public Contents cont() {
    return new Contents() {
      private int i = 11;
      public int value() { return i; }
    }; // Semicolon required in this case
  }
  public static void main(String[] args) {
    Parcel6 p = new Parcel6();
    Contents c = p.cont();
  }
} ///:~

cont()办法同时归并了返回值的成立代码,以及用于表示那个返回值的类.除此以外,这个类是匿名的——它没闻名字.并且看起来仿佛更让人摸不着头脑的是,我们预备成立一个Contents对象:
return new Contents()
但在这之后,在碰到分号之前,我们又说:“等一等,让我先在一个类定义里再耍一下把戏”:

return new Contents() {
private int i = 11;
public int value() { return i; }
};

这种奇特的语法要表达的意思是:“成立从Contents衍生出来的匿名类的一个对象”.由new表达式返回的句柄会自动上溯造型成一个Contents句柄.匿名内部类的语法其实要表达的是:

class MyContents extends Contents {
private int i = 11;
public int value() { return i; }
}
return new MyContents();

在匿名内部类中,Contents是用一个默许构建器成立的.下面这段代码展示了底子类需求含有自变量的一个构建器时做的事情:
//: Parcel7.java
// An anonymous inner class that calls the 
// base-class constructor
package c07.innerscopes;

public class Parcel7 {
  public Wrapping wrap(int x) {
    // Base constructor call:
    return new Wrapping(x) { 
      public int value() {
        return super.value() * 47;
      }
    }; // Semicolon required
  }
  public static void main(String[] args) {
    Parcel7 p = new Parcel7();
    Wrapping w = p.wrap(10);
  }
} ///:~

也就是说,我们将得当的自变量简单地传送给底子类构建器,在这儿表现为在“new Wrapping(x)”中传送x.匿名类不能拥有一个构建器,这和在调用super()时的通例做法差别.
在前述的两个例子中,分号并不标志着类主体的完毕(和C++差别).相反,它标志着用于包含匿名类的那个表达式的完毕.因此,它完好等价于在其他任何地方利用分号.
若想对匿名内部类的一个对象举行某种情势的初始化,此时会呈现什么情形呢?由于它是匿名的,没闻名字赋给构建器,所以我们不能拥有一个构建器.但是,我们可在定义自己的字段时举行初始化:
//: Parcel8.java
// An anonymous inner class that performs 
// initialization. A briefer version
// of Parcel5.java.
package c07.innerscopes;

public class Parcel8 {
  // Argument must be final to use inside 
  // anonymous inner class:
  public Destination dest(final String dest) {
    return new Destination() {
      private String label = dest;
      public String readLabel() { return label; }
    };
  }
  public static void main(String[] args) {
    Parcel8 p = new Parcel8();
    Destination d = p.dest("Tanzania");
  }
} ///:~

若试图定义一个匿名内部类,并想利用在匿名内部类外部定义的一个对象,则编译器要求外部对象为final属性.这恰是我们将dest()的自变量设为final的缘由.假如忘掉这样做,就会得到一条编译期出错提醒.
只要自己只是想分配一个字段,上述办法就必定可行.但假定需求采纳一些近似于构建器的行动,又应怎样操作呢?通过Java 1.1的实例初始化,我们可以有效地为一个匿名内部类成立一个构建器:
//: Parcel9.java
// Using "instance initialization" to perform 
// construction on an anonymous inner class
package c07.innerscopes;

public class Parcel9 {
  public Destination 
  dest(final String dest, final float price) {
    return new Destination() {
      private int cost;
      // Instance initialization for each object:
      {
        cost = Math.round(price);
        if(cost > 100)
          System.out.println("Over budget!");
      }
      private String label = dest;
      public String readLabel() { return label; }
    };
  }
  public static void main(String[] args) {
    Parcel9 p = new Parcel9();
    Destination d = p.dest("Tanzania", 101.395F);
  }
} ///:~
在实例初始化模块中,我们可看到代码不能作为类初始化模块(即if语句)的一部份履行.所以实际上,一个实例初始化模块就是一个匿名内部类的构建器.当然,它的功效是有限的;我们不能对实例初始化模块举行过载处理,所以只能拥有这些构建器的此中一个.
  以上是“<b>java的匿名内部类</b>[Java编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
  • <b>hosts是什么 hosts文件在什么位置 若何改正hosts</b>
  • <b>在 Windows 8 中手动安装语言包</b>
  • <b>五个常见 PHP数据库问题</b>
  • Windows中Alt键的12个高效快速的利用本领介绍
  • <b>MySQL ORDER BY 的实现解析</b>
  • <b>详解MySQL存储历程参数有三种范例(in、out、inout)</b>
  • <b>Win8系统恢复出来经典的开始菜单的办法</b>
  • <b>Win8系统花屏怎么办 Win8系统花屏的办理办法</b>
  • <b>Windows 7系统下无线网卡安装</b>
  • <b>为什么 Linux不需求碎片整理</b>
  • <b>Windows 8中删除账户的几种办法(图)</b>
  • <b>教你如安在win7下配置路由器</b>
  • 本文地址: 与您的QQ/BBS好友分享!
    • 好的评价 如果您觉得此文章好,就请您
        0%(0)
    • 差的评价 如果您觉得此文章差,就请您
        0%(0)

    文章评论评论内容只代表网友观点,与本站立场无关!

       评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
    Copyright © 2020-2022 www.xiamiku.com. All Rights Reserved .