接口
一、什么是接口?
接口与抽象类相似,但接口中只包含常量和抽象方法。接口的目的是指明相关或不相关类的多个对象的共同行为。
同样也不能使用new操作符创建接口的实例。
定义接口:
修饰符 Interface 接口名 {
//常量声明
//抽象方法签名
}
类和接口之间的关系称为接口继承,使用implements关键字让对象的类实现这个接口。
在UML图中,接口名称和方法名称使用斜体。虚线和空心三角形用于指向接口。
接口中所有的数据域都是public static final,所有的方法都是public abstract,所以Java允许忽略这些修饰符。
下面代码是一个几何图形接口示例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//一个几何接口 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); } }
二、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
深拷贝和浅拷贝
如果一个数据域是对象,复制的是该域的引用,而不是它的内容,称为浅拷贝。
如下所示示例,一个课程进行复制后其教师只是复制了引用。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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;
}
}
完整代码如下所示:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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引用不一样。