接口与内部类
-
接口
接口不是类,而是对类的一组需求描述,这些类要遵从接口描述的统一格式进行定义。
public interface Comparable{ int comparTo(Object other); }
接口中的所有方法自动的属于
public
接口中可以定义常量,但是不能含有实例域,也不能在接口中实现方法。提供实例域和方法实现的任务应该由实现该接口的那个类来完成。
让类实现接口需要用到关键字:
implements
-
接口的特性
- 不能使用
new
运算符实例化一个接口 - 可以声明接口变量,但是接口变量必须引用实现了该接口的类的对象
- 可以使用
instanceof
检查一个对象是否实现了某个接口 - 接口可以继承另一个接口,也是通过
extends
实现 - 接口中可以包含常量,且接口中的域会被自动设为
public static final
- 每个类只能继承自一个超类,但是可以实现多个接口。使用
,
将实现的接口分隔开
- 不能使用
-
对象克隆
Object
类对clone
方法的实现只能将各个域进行对应的拷贝。如果对象中的域全为数值或基本类型,这个拷贝没有问题,但是如果对象中包含了子对象的引用,那么拷贝的结果会使两个域引用同一个子对象,这是一种浅拷贝。如果原始对象与浅克隆对象共享的子对象是不可变的,这样的拷贝没有问题。当子对象为可变的子对象时,对于每个类都要做如下的判断:- 默认的clone方法是否满足要求
- 默认的clone方法是否可以通过调用可变子对象的clone得到修补
- 是否不应该使用clone
如果要选择第1或第2中情况,需要:
- 实现
Cloneable
接口 - 使用
public
访问修饰符重新定义clone
方法。
改为
public
是因为Object类的clone
方法是protected
,该方法只能在子类自身的方法中被调用,无法在其他发放中调用,所以需要改为public
。 接口与回调
-
内部类
内部类 是一个定义在另一个类中的类。
为什么需要使用内部类:
- 内部类方法可以访问该类定义所在的作用域中的数据,包括私有数据(内部类对象总有一个隐式引用,指向创建他的外部类对象);
- 内部类可以对同一个包中的其他类隐藏起来(只有内部类可以是私有的,其他类都必须是包可见,或者公有);
- 当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较
-
内部类的特殊语法规则
内部类中使用外围类引用的正规语法:
OuterClass.this
实例化内部类的语法格式:
outerObject.new InnerClass(construction parameters)
;如果内部类是公有的,还可以通过该语法格式为该内部类传递不同的外围类引用。在外围域的作用域之外,还可以这样引用内部类:
OuterClass.InnerClass
-
局部内部类
在方法中定义的类称为:局部内部类
局部内部类不能用
public
或者private
访问说明符进行声明。它的作用域被限定在声明这个局部类的块中。优点:
- 对外部世界可以完全隐藏起来
- 可以访问局部变量,不过这些变量必须被声明为
final
为什么必须是
final
呢? -
匿名内部类
在局部内部类的基础上进一步深入,只创建这类的一个对象,而不命名,这样的类就叫 匿名内部类。通常的语法格式为:
new SuperType(construction parameters){ //inner class methods and data }
其中,
SuperType
可以是接口,那么内部类就要实现这个接口的方法,也可以是一个类,内部类就要扩展它。由于匿名内部类没有类名,所以没有构造函数。继承自类的匿名内部类将构造器参数传给超类构造器;实现接口的匿名内部类不能传递构造器参数,且应该是如下的语法格式:
new interfaceType(){ //methods and data; }
-
静态内部类
当内部类不需要引用外围类对象,或者其他任何对象时,可以将内部类定义为静态内部类(也应该这样)。
class OuterClass{ public static class InnerClass{ } }
此后,通过
OuterClass.InnerClass
来访问内部类OuterClass.InnerClass p = new OuterClass.InnerClass();
只有静态内部类可以声明为
static
-
代理
后期单独总结