接口与内部类
1.接口
首先接口不是类,而是对类的一组需求描述。下面是泛型类型的接口代码
public interface Comparable<T>
{
int compareTo(T other);
}
接口中的所有方法自动属于public,在接口中声明方法,不必提关键字public。注意,接口中不能提供实例域和方法实现,这些必须由实现接口的那个类来完成。
这里简单举例说明下实例域的概念:
举个例子:人类是一个类,张三就是人类的一个实例。
人类都有手、脚,可以理解为 人类的域。
张三的手、脚就是张三这个实例的自己的私有的域,比如张三有一个手指是断的,不能说人类的手
这里接口和没有实例域的抽象类类似,但它们还是有所区别。有如下区别:
1.接口是公开的,里面不能有私有的方法或变量,是用于让别人使用的,而抽象类是可以有私有方法或私有变量的。
2.接口可以实现多重继承,而一个类只能继承一个超类,但可以通过继承多个接口实现多重继承。
3.接口可以多继承,抽象类不行。
4.接口中基本数据类型为static 而抽类象不是的。
以下是实现接口方法的语句(注意:在现实接口时,必须把方法声明为public,否则,编译器将认为这个方法的访问属性是包可见性,即类的默认访问属性,之后编译器就会给出试图提供更弱的访问权限的警告信息):
class Employee implements Comparable<Employee>
{
public int compareTo(Employee other)
{
return Double.compare(salary,other.salary);
}
}
我们再来看接口的一些特性:
1.接口不是类,所以不能用x=new Comparable(...);来实例化一个接口,但可以先声明一个接口变量,再对其进行类的实例化。
Comparable x;
x=new Employee(...);
2.我们可以用一下语句来检查对象是否实现了某个特定的接口:
if(anObject instanceof Comparable){...}
3.接口也可以扩展
public interface Moveable
{
void move(double x,double y);
}
public interface Powered extends Moveable
{
doble milePerGallon();
}
public interface Powered extends Moveable{
double milesPerGllon();
double SPEED_LIMIT=95;//a public static final constant,接口中的域将被自动设为public static final.
2.内部类
定义在另一个类中的类,称为内部类。
1.内部类可以对同一个包中的其他类隐藏起来。 (一般的非内部类,是不允许有 private 与protected权限的,但内部类可以)
2.内部类方法可以访问外围类中定义所在作用域中的数据,包括私有的数据。
3.可以实现多重继承
4.可以避免修改接口而实现同一个类中两种同名方法的调用。
5.当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷。
内部类嵌套类的两个重要作用是:命名控制和访问控制
看下面这个C++嵌套类的例子:
Class LinkedList
{
public:
class Iterator
{
public:
void insret(int x);
int erase();
...
};
private:
class Link
{
public:
Link*next;
int data;
}
...
};
Iterator被嵌套在LinkedList类内部,我们可以用LinkedList::Iterator的方式命名来避免与其他名为Iterator的类重复。
即使Link的数据域被设计为公有的,它仍然安全,只能被LinkedList中的方法访问。
注意,JAVA中的内部类还有另外一个功能,内部类的对象有一个隐式引用,通过这个指针可以访问外围类对象的全部状态。请看下面的java内部类的例子:
public class TalkingClock
{
private int interval;
private boolean beep;
public TalkingClock(int interval,boolean beep){...}
public void start(){...}
public class TimePrinter implements ActionListerner
{
public void actionPerformed(ActionEvent event)
{
Date now=new Date();
System.out.println("At the tone,the time is"+now);
if(beep)Toolkit.getDefaultToolkit().beep();//我们把外围类对象的引用称为outer,所以该语句等价于if(outer.beep)Toolkit.getDefaultTookit().beep();
//使用外围类引用的正规语法还要复杂一些。表达式为:OuterClass.this,所该语句可以改写为if(TalkingClock.this.beep)Toolkit.getDefaultTookit().beep();
}
}
从上面的例子看出,内部类可以访问自身的数据域,也可以访问创建它的外围类对象的数据域。注意可以用outerObject.new Inner(construction paramenters)
来编写内部对象的构造器。同样可以用OuterClass.InnerClass的语法来引用内部类。
我们继续来看下面这个局部内部类
public void start()//我们把该语句改成public void start(int interval,final boolean beep), 这样局部类不仅能访问它们的外部类,还可以访问局部变量,注意局部变量必须被
//声明为final,局部变量的访问非常容易,它减少了需要显示编写的实例域,从而使得内部类更加简单。
{
class TimePrinter implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
Date now=new Date();
System.out.println("At the tone,the time is"+now);
if(beep) Toolkit.getDefaultTookit().beep();
}
}
ActionLister listener=new TimePrinter();
Time t=new Timer(interval,listener);
t.start();
}
注意局部类不能用public或者private访问说明符进行声明,它的作用域被限定在声明这个局部类的块中。因此,它有一个更大的优势是,对外部世界完全的隐藏起来,
除start方法之外,没有任何方法知道TimePrinter类的存在。
匿名内部类
创建这个类的一个对象,就不必命名了,我们称为匿名内部类。
public void start(int interval,final boolean beep)
{
ActionListener listener=new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
Date now=new Date();
System.out.println("At the tone,the time is"+now);
if(beep)Toolkit.getDefaultToolkit().beep();
}
};
Timer t=new Timer(interval,listener);
t.start();
}
注意匿名类没有类名,而构造器的名字必须域类名相同,所以匿名类没有构造参数。
静态内部类
如果我们仅仅想把一个类隐藏在另一个类中,而不需要引用外部对象,可以将内部类声明为static,以便取消产生引用。