博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
匿名内部类
阅读量:5248 次
发布时间:2019-06-14

本文共 4130 字,大约阅读时间需要 13 分钟。

一、 内部类特性

  1.  内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号 。
  2.  内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论是否是private的 。
  3.  内部类声明成静态的,就不能随便的访问外部类的成员变量了,此时内部类只能访问外部类的静态成员变量 。

二、 匿名内部类

1. 

 

1 public class Parcel7 2 { 3     public Contents contents() 4     { 5         return new Contents() 6         { 7             private int i = 11; 8             public int value() { return i; } 9         };10     }11     public static void main(String[] args)12     {13         Parcel7 p = new Parcel7();14         Contents c = p.contents();15     }16 }

 

在上述代码中, contents() 方法将返回值的生成与表达这个返回值的类定义结合在一起。另外,这个类是匿名的,它没有名字。

语法:创建一个继承自Contents的匿名类的对象。通过new表达式返回的引用被自动向上转型为对Contents的引用。(向上转型内容参照:)

关于分号的说明:在匿名内部类末尾的分号,并不是用来标记此内部类结束的。实际上,它标记的是表达式的结束,只不过这个表达式正巧包含了匿名内部类,因此,这与别的地方使用的分号是一致的。

上述匿名内部类的代码,是下面代码的简化版本:

1 public class Parcel7 2 { 3     public MyContents implements contents 4     { 5         private int i = 11; 6         public int value() { return i; } 7     } 8     public Contents contents() { return new MyContents(); } 9     public static void main(String[] args)10     {11         Parcel7 p = new Parcel7();12         Contents c = p.contents();13     }14 }

在这个匿名类中,使用了默认的构造器来生成Contents。

 

2. 下面代码展示了基类需要一个有参数的构造器

1 public class Wrapping 2 { 3     private int i; 4     public Wrapping(int x) { i = x; } 5     public int value() { return i; } 6 } 7 // 8 public class Parcel8 9 {10     public Wrapping wrapping(int x)11     {12         return new Wrapping(x)13         {14             public int value()15             { 16                 return super.value() * 47; 17             }18         };19     }20     public static void main(String[] args)21     {22         Parcel8 p = new Parcel8();23         Contents w = p.wrapping();24     }25 }

在该例子中,可以看到Wrapping拥有一个要求传递参数的构造器。

这里是将x传进new Warpping(x)。

在匿名内部类中,只需要简单地传递合适的参数给基类的构造器即可。

 

3. 在匿名内部类定义中,对其进行初始化操作

1 public class Parcel9 2 { 3     public Destination destination(final String dest) 4     { 5         return new Destination() 6         { 7             private String lable = dest; 8             public String readLable() { return lable; } 9         };10     }11     public static void main(String[] args)12     {13         Parcel9 p = new Parcel9();14         Destination d = p.destination("Tasmaina");15     }16 }

在new Destination()中,使用到了在其外部定义的变量dest,编译器要求我们引用的参数是final的

即: 如果定义一个匿名内部类,并且希望他使用一个在其外部定义的对象,那么编译器会要求其参数引用final的。

 

4. 

如果只是简单的给一个字段赋值,那么3例中的方法是很好的。但是,如果想做一个类似构造器的行为,但是匿名类中不可能有命名构造器(其原因是因为它根本就没有名字)。通过实例初始化,就能够达到为匿名内部类创建一个构造器的效果。具体实例如下:

1 abstract class Base 2 { 3     public Base(int i) 4     { 5         System.out.println("Base coustructor. i = " + i); 6     } 7     public abstract void f(); 8 } 9 public class AnonymousConstructor10 {11     public static Base getBase(int i)12     {13         return new Base(i)14         {15             { System.out.println("Inside instance initializer "); }16             public void f()17             {18                 System.out.println("In anonymous f()");19             }20         };21     }22         public static void main(String[] args)23         {24             Base base = getBase(47);25             base.f();26         }27 }

注意: 在此例中,并没有要求变量 i 一定是final的,因为 i 被传递给匿名类的基类的构造器,并没有在匿名类内部被直接使用。

 

5. 下面代码为带实例初始化的形式

1 public class Parcel10 2 { 3     public Destination destination(final String dest, final float price)  4     { 5         return new Destination() 6         { 7             private int cost; 8             { 9                 cost = Math.round(price);10                 if(cost > 100)11                     System.out.println("Over budget");12             }13             private String lable = dest;14             public String readLable() { return lable; }15         };16     }17     public static void main(String[] args)18     {19         Parcel10 p = new Parcel10();20         Destination d = p.destination("Tasmaina", 101.395F);21     }22 }

其中 destination 的参数必须是 final 的,因为他们在匿名类中被使用到了。

在实例初始化的内部,有 if 语句,它们不能作为实例初始化动作的一部分。所以对于匿名类而言,实例初始化的实际效果就是构造器。(但是,你不能重载实例初始化方法,所以仅有一个这样的构造器)

 

匿名内部类与正规继承相比是受到限制的,因为匿名内部类既可以扩展类,也可以实现接口,但是不能二者兼备。并且,如果是实现接口,也只能实现一个接口。

 

转载于:https://www.cnblogs.com/Leo-Xia/p/10966723.html

你可能感兴趣的文章
自定义OffMeshLink跳跃曲线
查看>>
寄Android开发Gradle你需要知道的知识
查看>>
简述spring中常有的几种advice?
查看>>
牛客网——华为机试(题21:简单密码)(Java)
查看>>
学习Redux之分析Redux核心代码分析
查看>>
ABAP 创建和调用WebService
查看>>
C# 实例化顺序
查看>>
CSS水平垂直居中总结
查看>>
委托又给我惹麻烦了————记委托链的取消注册、获取返回值
查看>>
ps怎么把白色背景变透明
查看>>
gource 安装教程
查看>>
字符串转 Boolean 的正确方式
查看>>
给你的网站404页面加上“宝贝寻亲”公益页面
查看>>
整理推荐的CSS属性书写顺序
查看>>
协程, IO阻塞模型 和 IO非阻塞模型
查看>>
NSLog 和printf区别
查看>>
NSArray 与字符串
查看>>
Floyd(稠密图,记录路径)
查看>>
SQLite中的表达式
查看>>
window.open()新窗口属性大全
查看>>