接口

一、什么是接口?

接口与抽象类相似,但接口中只包含常量和抽象方法。接口的目的是指明相关或不相关类的多个对象的共同行为。

同样也不能使用new操作符创建接口的实例。

定义接口:

修饰符  Interface 接口名 {

      //常量声明

     //抽象方法签名

}

类和接口之间的关系称为接口继承,使用implements关键字让对象的类实现这个接口。

在UML图中,接口名称和方法名称使用斜体。虚线和空心三角形用于指向接口。

接口中所有的数据域都是public static final,所有的方法都是public abstract,所以Java允许忽略这些修饰符。

下面代码是一个几何图形接口示例:

//一个几何接口
interface GeometricInterface {
    double getArea();
    double getPerimeter();
}

//一个几何对象
public abstract class GeometricObject {
  private String color = "white";
  private boolean filled;
  private java.util.Date dateCreated;

  /** Construct a default geometric object */
  protected GeometricObject() {
    dateCreated = new java.util.Date();
  }

  /** Construct a geometric object with color and filled value */
  protected GeometricObject(String color, boolean filled) {
    dateCreated = new java.util.Date();
    this.color = color;
    this.filled = filled;
  }

  /** Return color */
  public String getColor() {
    return color;
  }

  /** Set a new color */
  public void setColor(String color) {
    this.color = color;
  }

  /** Return filled. Since filled is boolean,
   *  the get method is named isFilled */
  public boolean isFilled() {
    return filled;
  }

  /** Set a new filled */
  public void setFilled(boolean filled) {
    this.filled = filled;
  }

  /** Get dateCreated */
  public java.util.Date getDateCreated() {
    return dateCreated;
  }

  @Override
  public String toString() {
    return "created on " + dateCreated + "\ncolor: " + color +
      " and filled: " + filled;
  }
 
}

//一个矩形类,继承GeometricObject 类,实现GeometricInterface 接口
public class Rectangle extends GeometricObject   implements GeometricInterface {
  private double width;
  private double height;

  public Rectangle() {
  }

  public Rectangle(double width, double height) {
    this.width = width;
    this.height = height;
  }

  /** Return width */
  public double getWidth() {
    return width;
  }

  /** Set a new width */
  public void setWidth(double width) {
    this.width = width;
  }

  /** Return height */
  public double getHeight() {
    return height;
  }

  /** Set a new height */
  public void setHeight(double height) {
    this.height = height;
  }

 @Override /** Return area */
  public double getArea() {
    return width * height;
  }

 @Override /** Return perimeter */
  public double getPerimeter() {
    return 2 * (width + height);
  }
}

//一个圆类,继承GeometricObject 类,实现GeometricInterface 接口
public class Circle extends GeometricObject  implements GeometricInterface {
  private double radius;

  public Circle() {
  }

  public Circle(double radius) {
    this.radius = radius;
  }

  /** Return radius */
  public double getRadius() {
    return radius;
  }

  /** Set a new radius */
  public void setRadius(double radius) {
    this.radius = radius;
  }

 @Override /** Return area */
  public double getArea() {
    return radius * radius * Math.PI;
  }

  /** Return diameter */
  public double getDiameter() {
    return 2 * radius;
  }

 @Override /** Return perimeter */
  public double getPerimeter() {
    return 2 * radius * Math.PI;
  }

  /* Print the circle info */
  public void printCircle() {
    System.out.println("The circle is created " + getDateCreated() +
      " and the radius is " + radius);
  }
}
View Code

 二、Comparable接口

        Java提供了Comparable接口,接口的定义如下所示:

        package java.lang;

       public interface Comparable<E> {

             public int compareTo(E o);

      }

      compareTo方法判断这个对象相对于给定对象o的顺序,并且当这个对象小于、等于或大于给定对象o时,分别返回负整数、0或正整数。

     Java类库中的许多类实现了Comparable接口以定义对象的自然顺序。Byte、Short、Integer、Long、Float、Double、Character、BigInteger、BigDecimal、Calendar、String以及Date类都实现了Comparable接口。

     例:实现Circle的Comparable,然后利用sort进行多个圆的排序。

    

public class Circle   implements Comparable<Circle> {
  private double radius;

  public Circle() {
  }

  public Circle(double radius) {
    this.radius = radius;
  }

  /** Return radius */
  public double getRadius() {
    return radius;
  }

  /** Set a new radius */
  public void setRadius(double radius) {
    this.radius = radius;
  }

 /** Return area */
  public double getArea() {
    return radius * radius * Math.PI;
  }

  /** Return diameter */
  public double getDiameter() {
    return 2 * radius;
  }

  /** Return perimeter */
  public double getPerimeter() {
    return 2 * radius * Math.PI;
  }

   @Override//实现在Comparable中定义的CompareTo方法
   public int compareTo(Circle o) {
           if (this.getArea()>o.getArea())  return 1;
           else  if (this.getArea()<o.getArea())  return -1;
           else return 0;
   }
   @Override
   public String toString() {
           return "Circle: the radius  is "+radius+", the area is "+getArea();
   }
   public static void main(String[] args) {
           Circle[] circles = {new Circle(1),new Circle(3),new Circle(7),new Circle(2)};
           java.util.Arrays.sort(circles);
           for (Circle c:circles)
           System.out.println(c);
   }
}

  结果为:

Circle: the radius  is 1.0, the area is 3.141592653589793
Circle: the radius  is 2.0, the area is 12.566370614359172
Circle: the radius  is 3.0, the area is 28.274333882308138
Circle: the radius  is 7.0, the area is 153.93804002589985

    三、Cloneable接口

    在Java.lang包中的Cloneable接口的定义是空的,如下所示:

    package  java.lang;

    public  interface Cloneable {

    }

    一个带空体的接口称为标记接口。它用来表示一个类拥有某些特定的属性。

   实现Cloneable接口的类标记为可克隆的,而且它的对象可以使用在Object类中定义的clone()方法克隆。

   应用clone()方法实现数组复制:

import java.util.Arrays;
public class ArrayClone {
      public static void main(String[] args) {
           int[] list1 = {1,2,3,4,5,6};
           int[] list2 = list1.clone();
           System.out.println(Arrays.toString(list1));
           System.out.println(Arrays.toString(list2));
           System.out.println("list1:"+list1+",list2:"+list2);
           System.out.println(list1==list2);
           }
    }

运行结果:
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6]
list1:[I@2a139a55,list2:[I@15db9742
false

应用clone()方法实现Circle对象的复制:

class Circle implements Cloneable {
  private double radius;

  public Circle() {
  }

  public Circle(double radius) {
    this.radius = radius;
  }

  /** Return radius */
  public double getRadius() {
    return radius;
  }

  /** Set a new radius */
  public void setRadius(double radius) {
    this.radius = radius;
  }

 /** Return area */
  public double getArea() {
    return radius * radius * Math.PI;
  }

  /** Return diameter */
  public double getDiameter() {
    return 2 * radius;
  }

  /** Return perimeter */
  public double getPerimeter() {
    return 2 * radius * Math.PI;
  }

  @Override
  public Object clone() throws CloneNotSupportedException{
      try {
          return super.clone();
      }
      catch (CloneNotSupportedException ex) {
        return null;
        }
  }

}
public class TestCircleClone {
   public static void main(String[] args) {
           Circle  circle1 = new Circle(4);
        try {
               Circle circle2 = (Circle)circle1.clone();
               System.out.println("circle1:"+circle1+",radius:"+circle1.getRadius());
                System.out.println("circle2:"+circle2+",radius:"+circle2.getRadius());
        }
          catch (CloneNotSupportedException ex) {
          }
   }
}

运行结果:

circle1:Circle@2a139a55,radius:4.0
circle2:Circle@15db9742,radius:4.0

 深拷贝和浅拷贝

如果一个数据域是对象,复制的是该域的引用,而不是它的内容,称为浅拷贝。

如下所示示例,一个课程进行复制后其教师只是复制了引用。

class Teacher {
    String id;
    String name;
    public Teacher(String id,String name){
        this.id = id;
        this.name = name;
    }
}
class Course implements Cloneable{
     String name;
      int credit;
     Teacher teacher;

    public Course(String name,int credit,Teacher teacher) {
        this.name = name;
        this.credit = credit;
        this.teacher = teacher;
    }
    //浅拷贝
    public Object clone() throws CloneNotSupportedException {
        try {
            return super.clone();
        }
        catch (CloneNotSupportedException ex) {
                return null;
        }

    }
}
public class CopyTest {
    public static void main(String[] args) {
        Teacher teacher = new Teacher("1001","zhanghong");
        Course course1 = new Course("Java",3,teacher);
        System.out.println(course1.name+" "+course1.credit+" "+course1.teacher.id+" "+course1.teacher.name);
        System.out.println(course1.teacher);
        try {
            Course course2 = (Course)course1.clone();
            System.out.println(course2.name+" "+course2.credit+" "+course2.teacher.id+" "+course2.teacher.name);
            System.out.println(course2.teacher);
        }
        catch (CloneNotSupportedException ex) {
        }


    }
}
浅拷贝程序示例

运行结果:

Java 3 1001 zhanghong
Teacher@2a139a55
Java 3 1001 zhanghong
Teacher@2a139a55

其中Teacher的引用相同。

若要完全复制,即深拷贝,则修改Course类中的clone()方法如下:

//深拷贝
public Object clone() throws CloneNotSupportedException {
try {
Course courseClone = (Course)super.clone();
courseClone.teacher =(Teacher)(teacher.clone());
return courseClone;
}
catch (CloneNotSupportedException ex) {
return null;
}
}

完整代码如下所示:

class Teacher implements Cloneable{
    String id;
    String name;
    public Teacher(String id,String name){
        this.id = id;
        this.name = name;
    }
    public Object clone() throws CloneNotSupportedException {
        try {
            return  super.clone();
        }
        catch (CloneNotSupportedException ex) {
                return null;
        }

    }
}
class Course implements Cloneable{
     String name;
      int credit;
     Teacher teacher;

    public Course(String name,int credit,Teacher teacher) {
        this.name = name;
        this.credit = credit;
        this.teacher = teacher;
    }
    //深拷贝
    public Object clone() throws CloneNotSupportedException {
        try {
            Course courseClone = (Course)super.clone();
            courseClone.teacher  =(Teacher)(teacher.clone());
            return  courseClone;
        }
        catch (CloneNotSupportedException ex) {
                return null;
        }
    }
}
public class CopyTest {
    public static void main(String[] args) {
        Teacher teacher = new Teacher("1001","zhanghong");
        Course course1 = new Course("Java",3,teacher);
        System.out.println(course1.name+" "+course1.credit+" "+course1.teacher.id+" "+course1.teacher.name);
        System.out.println(course1.teacher);
        try {
            Course course2 = (Course)course1.clone();
            System.out.println(course2.name+" "+course2.credit+" "+course2.teacher.id+" "+course2.teacher.name);
            System.out.println(course2.teacher);
        }
        catch (CloneNotSupportedException ex) {
        }


    }
}
深拷贝程序示例

运行结果如下:

Java 3 1001 zhanghong
Teacher@2a139a55
Java 3 1001 zhanghong
Teacher@15db9742

可看出复制内容一样,但两个Course类中的teacher引用不一样。

posted @ 2018-10-23 19:36  yinweifeng  阅读(265)  评论(0编辑  收藏  举报