(六)接口与内部类

1. 接口:

  • 在Java中,接口不是类,而是对类的一组需求描述,这些类要遵从接口描述的统一格式进行定义。
  • 接口中的方法自动的属于public,因此在接口中声明方法时,不必提供关键字public
  • 接口中可以定义常量,但是绝对不能含有实例域,也不能在在接口中实现方法
  • 接口中的常量被自动设定为public static final 类型
  • 提供实例域和方法实现的任务应该由实现接口的那个类来完成

2. 将一个类实现某个接口,需要:

  • 将类声明为实现给定的接口
  • 对接口中的所有方法进行定义,而且需要将多有方法定义为public

3. 在比较两个对象的大小是,使用整数域进行比较比较巧妙,大于返回1,小于返回-1,相等返回0,但是对于浮点类型的比较不一定,因为即使可能不相等,但是四舍五入之后最终结果也可能相等。

4. 实现接口的好处:Java程序设计语言是一种强类型语言,在调用方法的时候,编译器将会检查这个方法是否存在,但是每个实现接口的类必须提供这个方法。

5. 例子。Employee 类实现了Comparable接口,因此可以调用Array.sort();方法对Employee数组进行排序

  • public class Employee implements Comparable<Employee>{
    
        private String name;
        private double salary;
    
        public Employee(){
    
        }
    
        public Employee(String name, double salary){
            this.name = name;
            this.salary = salary;
        }
    
        public void setName(String name){
            this.name = name;
        }
    
        public void setSalary(double salary){
            this.salary = salary;
        }
    
        public String getName(){
            return this.name;
        }
    
        public double getSalary(){
            return this.salary;
        }
    
        public int compareTo(Employee other){
            return Double.compare(this.salary,other.salary);
        }
    
        public static void main(String[] args) {
    
        }
    
    }
    import java.util.*;
    
    public class Test{
        public static void main(String[] args) {
            Employee[] staff = new Employee[3];
            staff[0] = new Employee("zhang san",5000);
            staff[1] = new Employee("lisi",3000);
            staff[2] = new Employee("wangwu",6000);
    
            Arrays.sort(staff);
    
            for (Employee e : staff) {
                System.out.println("name= " + e.getName() + "     salary= " + e.getSalary());
            }
    
        }
    }

6. 接口的一些特性:

  • 接口不是类,尤其不能使用new运算符实例化一个接口
  • 可以声明接口变量Comparable x = new Employee();//Employee类实现了接口Comparable。
  • 与检查一个对象是否属于一个特定的类一样,也可以使用instanceof检查一个对象是否是实现了某个接口if(object instanceof Comparable)
  • 接口也可以被其他接口继承扩展

7. 每个类只能够拥有一个超类,但是却可以实现多个接口。也就是所谓的单继承多实现,使用,号将需要实现的的多个接口分隔开,需要有克隆功能实现Cloneable接口,需要有比较功能实现Comparable接口 public class  Employee implements Cloneable,Comparable{}

8. 为什么不将interface接口直接声明为abstract抽象类,子类继承的时候也就必须实现其中的抽象方法了?

  • 每个类只能扩展于一个类
  • 但是每个类可以实现多个接口
  • Java的设计者选择了不支持多继承,其主要原因是多继承会让语言本身变得非常复杂,效率也会降低
  • 使用接口的方式可以提供多继承的大多数好处,同时还能避免多继承的复杂性和低效性

9. 接口与回调:需要实现ActionListener接口,然后需要执行的语句放在actionPerformed方法中,下面是示例代码,通过定时器调用监听器对象,执行其中的方法

  • public class TimerPrint implements ActionListener{
        public void actionPerformed(ActionEvent event){
            Date now = new Date();
            System.out.println("At the tone, the time is:"+now);
            Toolkit.getDefaultToolkit().beep();
        }
    }
    public class Test{
        public static void main(String[] args) {
            ActionListener listener = new TimerPrint();
    
            Timer t = new Timer(5000,listener);
            t.start();
    
            JOptionPane.showMessageDialog(null,"Quit program");
            System.exit(0);
        }
    }

     

10. 内部类:定义在另一个类中的类

  • 内部类方法可以访问该类定义所在的作用域中的数据,包括私有数据
  • 内部类可以对同一个包中的其他类隐藏起来
  • 当想用定义一个回掉函数且不想编写大量代码时,使用匿名内部类比较便捷
  • 内部类既可以访问自身的数据域,也可以访问创建他的外围类对象的数据
  • public class InnerClassTest{
        public static void main(String[] args) {
            TalkingClock clock = new TalkingClock(5000,false);
            clock.start();
    
            JOptionPane.showMessageDialog(null,"Quit program");
    
            System.exit(0);
        }
        class TalkingClock{
            private int internal;
            private boolean beep;
    
            public TalkingClock(int internal,boolean beep){
                this.internal = internal;
                this.beep = beep;
            }
    
            public void start(){
                ActionListener listener = new TimerPrint();
                Timer t = new Timer(internal,listener);
                t.start();
            }
    
            public class TimerPrint implements ActionListener{
                public void actionPerformed(ActionEvent event){
                    Date now = new Date();
                    System.out.println("At the tone, time is :"+now);
                    if(beep) Toolkit.getDefaultToolkit().beep();
                    beep = !beep;
                }
            }
        }
    }

    如果一个内部类只在创建对象的时候用了一次,那么可以在一个方法中定义局部类

  • 局部类不能使用public或者private访问说明符进行声明,他的作用域被限定在声明这个局部类的块中
  • 局部类有一个优势,即对外部世界可以完全的隐蔽起来。即使TalkingClock类中的其他代码也不能访问他
  • 除了start方法之外,没有任何方法知道TimerPrint类的存在
  • public void start(){
        class TimerPrint implements ActionListener{
            public void actionPerformed(ActionEvent event){
                Date now = new Date();
                System.out.println("At the tone, time is :"+now);
                if(beep) Toolkit.getDefaultToolkit().beep();
                beep = !beep;
            }
        }
        ActionListener listener = new TimerPrint();
        Timer t = new Timer(internal,listener);
        t.start();
    }

     

11. 匿名内部类:将局部内部类的使用再深入一点,假如只创建这个类的对象,就不必命名了。这种类称为匿名内部类。

  • public void start(){
        ActionListener listener = new ActionListener(){
            public void actionPerformed(ActionEvent event){
                Date now = new Date();
                System.out.println("At the tone, time is :"+now);
                if(beep) Toolkit.getDefaultToolkit().beep();
                beep = !beep;
            }
        };
        Timer t = new Timer(internal,listener);
        t.start();
    }

 

posted @ 2016-03-24 11:46  桃源仙居  阅读(118)  评论(0)    收藏  举报