Java匿名内部类原理与用法详解

本文实例讲述了Java匿名内部类原理与用法。分享给大家供大家参考,具体如下:

一 点睛

匿名内部类适合创建那种只需要一次使用的类,定义匿名内部类的语法格式如下:

new 父类构造器(实参列表) | 实现接口()
{
   //匿名内部类的类体部分
}

从上面的定义可以看出,匿名内部类必须继承一个父类,或实现一个接口,但最多只能继承一个父类,或实现一个接口。

两条规则。

  • 匿名内部类不能是抽象类。
  • 匿名内部类不能定义构造器。由于匿名内部类没有类名,所以无法定义构造器,但匿名内部类可以初始化块,可以通过初始化块来完成构造器需要完成的工作。

二 实战

1 点睛

最常用的创建匿名内部类的方式是创建某个接口类型的对象。

2 代码

interface Product
{
  public double getPrice();
  public String getName();
}
public class AnonymousTest
{
  public void test(Product p)
  {
   System.out.println("购买了一个" + p.getName()
     + ",花掉了" + p.getPrice());
  }
  public static void main(String[] args)
  {
   AnonymousTest ta = new AnonymousTest();
   // 调用test()方法时,需要传入一个Product参数,
   // 此处传入其匿名内部类的实例
   ta.test(new Product()
   {
     public double getPrice()
     {
      return 567.8;
     }
     public String getName()
     {
      return "AGP显卡";
     }
   });
  }
}

3 运行

购买了一个AGP显卡,花掉了567.8

4 说明

定义匿名内部类无须class关键字,而是在定义匿名内部类时直接生成该匿名内部类的对象。

由于匿名内部类不能是抽象类,所以匿名内部类必须实现它的抽象父类或接口里包含的所有抽象方法。

三 实战

1 点睛

当通过接口来创建匿名内部类时,匿名内部类不能显示创建构造器,因此匿名内部类里只有一个隐式的无参构造器,故new接口名后的括号里不能传入参数值。

如果通过继承父类来创建匿名内部类时,匿名内部类将拥有和父类相似的构造器,此处的相似指的是拥有相同的形参列表。

2 代码

abstract class Device
{
  private String name;
  public abstract double getPrice();
  public Device(){}
  public Device(String name)
  {
   this.name = name;
  }
  // 此处省略了name的setter和getter方法
  public void setName(String name)
  {
   this.name = name;
  }
  public String getName()
  {
   return this.name;
  }
}
public class AnonymousInner
{
  public void test(Device d)
  {
   System.out.println("购买了一个" + d.getName()
     + ",花掉了" + d.getPrice());
  }
  public static void main(String[] args)
  {
   AnonymousInner ai = new AnonymousInner();
   // 调用有参数的构造器创建Device匿名实现类的对象
   ai.test(new Device("电子示波器")
   {
     public double getPrice()
     {
      return 67.8;
     }
   });
   // 调用无参数的构造器创建Device匿名实现类的对象
   Device d = new Device()
   {
     // 初始化块
     {
      System.out.println("匿名内部类的初始化块...");
     }
     // 实现抽象方法
     public double getPrice()
     {
      return 56.2;
     }
     // 重写父类的实例方法
     public String getName()
     {
      return "键盘";
     }
   };
   ai.test(d);
  }
}

3 运行

购买了一个电子示波器,花掉了67.8
匿名内部类的初始化块...
购买了一个键盘,花掉了56.2

当创建以Device为父类的匿名内部类时,既可以传入参数,代表调用父类带参数的构造器;也可以不传入参数,代表调用父类无参数的构造器。

当创建匿名内部类时,必须实现接口或抽象父类里的所有抽象方法。如果有需要,也可以重写父类中的普通方法。

四 实战

1 点睛

在Java 8之前,Java要求被局部内部类、匿名内部类访问的局部变量必须使用final修饰,从Java 8开始这个限制取消了,Java 8更加智能:如果局部变量被匿名内部类访问,那么该局部变量相对于自动使用了final修饰。

2 代码

interface A
{
  void test();
}
public class ATest
{
  public static void main(String[] args)
  {
   int age = 8;   // ①
   // 下面代码将会导致编译错误
   // 由于age局部变量被匿名内部类访问了,因此age相当于被final修饰了
   //age = 2;
   A a = new A()
   {
     public void test()
     {
      // 在Java 8以前下面语句将提示错误:age必须使用final修饰
      // 从Java 8开始,匿名内部类、局部内部类允许访问非final的局部变量
      System.out.println(age);
     }
   };
   a.test();
  }
}

3 结果

8

4 说明

Java 8将这个功能称为“effectively final”,它的意思是对于被匿名内部类访问的局部变量,可以用final修饰,也可以不用final修饰,但必须按照有final修饰的方式来使用——也就是一次赋值后,以后不能重新赋值。

更多java相关内容感兴趣的读者可查看本站专题:《Java面向对象程序设计入门与进阶教程》、《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》、《Java文件与目录操作技巧汇总》和《Java缓存操作技巧汇总》

希望本文所述对大家java程序设计有所帮助。

(0)

相关推荐

  • java中匿名内部类详解

    java匿名内部类: 1:匿名内部类,匿名内部类也就是没有名字的内部类. 2:匿名内部类的作用 正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写. 3:匿名内部类的实现 匿名内部类的两种实现方式:第一种,继承一个类,重写其方法:第二种,实现一个接口(可以是多个),实现其方法. 4:匿名内部类的创建 匿名类是不能有名称的类,所以没办法引用它们.必须在创建时,作为new语句的一部分来声明它们. package com.mianshi.test; /** * 类名称:Anonymou

  • Java局部内部类和匿名内部类定义与用法实例分析

    本文实例讲述了Java局部内部类和匿名内部类.分享给大家供大家参考,具体如下: 一 局部内部类 1 点睛 内部类不仅可以在类中定义,也可以定义在方法体或作用域内.这样的内部类作用范围仅限于方法体或特定的作用域内,因此也称为局部内部类. 2 代码 class InnerClassTest { int score = 95; void inst() { class Inner { void display() { System.out.println("成绩: score = " + sc

  • Java匿名对象与匿名内部类

    匿名对象:没有名字的对象. 非匿名对象: ClassName c=new ClassName(); c.run(); 匿名对象: new ClassName().run(); 注意事项: 1.当对象对方法仅进行一次调用的时候,就可以简化成匿名对象. 2.两个匿名对象不可能是同一个对象. 3.一般不给匿名对象赋予属性值,因为永远无法获取到. 4.运行一次,直接就被回收掉了,节省内存空间. 匿名对象使用的代码例子: public class Anony{ int a=1; int b=2; void

  • java中的匿名内部类详细总结

    匿名内部类也就是没有名字的内部类 正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写 但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口 实例1:不使用匿名内部类来实现抽象方法 复制代码 代码如下: abstract class Person {     public abstract void eat(); } class Child extends Person {     public void eat() {         System.out.printl

  • Java 匿名内部类详解及实例代码

    Java  匿名内部类详解 匿名内部类也就是没有名字的内部类 正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写 但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口 实例1:不使用匿名内部类来实现抽象方法 abstract class Person { public abstract void eat(); } class Child extends Person { public void eat() { System.out.println("eat someth

  • 简单谈谈java中匿名内部类构造函数

    先看看下面的代码能不能编译通过: public static void main(String[] args) { List l1 = new ArrayList(); List l2 = new ArrayList(){}; List l3 = new ArrayList(){{}}; System.out.println(l1.getClass() == l2.getClass() ); System.out.println(l2.getClass() == l3.getClass() );

  • Java中的匿名内部类小结

    java内部类分为: 成员内部类.静态嵌套类.方法内部类.匿名内部类 . 在java的世界里,提供了匿名内部类语法,用于帮助大家简化代码,本文简要从接口,抽象类以及常规类以代码的形式描述其常用模式. 1. 接口模式 public interface IWriter { void write(); } public static void main(String[] args) { IWriter writer = new IWriter() { @Override public void wri

  • java 中匿名内部类的实例详解

    java 中匿名内部类的实例详解 原来的面貌: class TT extends Test{ void show() { System.out.println(s+"~~~哈哈"); System.out.println("超级女声"); } TT tt=new TT(); tt.show(); 只是说我们这里采用的是匿名的形式来处理. 重写了Test的show()方法,在重写好了以后,又调用了重写后的show()方法 实现代码: package cn.com; c

  • java中的匿名内部类总结

     java中的匿名内部类总结 匿名内部类也就是没有名字的内部类 正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写 但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口 实例1:不使用匿名内部类来实现抽象方法 abstract class Person { public abstract void eat(); } class Child extends Person { public void eat() { System.out.println("eat somet

  • 详谈Java编程之委托代理回调、内部类以及匿名内部类回调(闭包回调)

    最近一直在看Java的相关东西,因为我们在iOS开发是,无论是Objective-C还是Swift中,经常会用到委托代理回调,以及Block回调或者说是闭包回调.接下来我们就来看看Java语言中是如何实现委托代理回调以及闭包回调的.当然这两个技术点虽然实现起来并不困难,但是,这回调在封装一些公用组件时还是特别有用的.所以今天,还是有必要把Java中的委托代理回调以及闭包回调来单独的拿出来聊一下. 本篇博客我们依然依托于实例,先聊聊委托代理回调的实现和使用场景,然后再聊一下使用匿名内部类来进行回调

  • 在java中 利用匿名内部类进行较简洁的双括弧初始化的方法

    java的collection集合框架如set.map.list没有提供任何简便的方法供初始化.而每次建立集合都要将值一个个add进去.如 复制代码 代码如下: Set<Character> letter=new HashSet<Character>();letter.add('a');letter.add('b');//... 非常繁琐. 但用匿名内部类的话.可以略为简便些. 复制代码 代码如下: Set<Character> letter=new HashSet&l

随机推荐