Java接口

1. 接口概述

class apple implements Edible{
}
class banana implements Edible{
}

定义apple类和banana类的接口为Edible

Object[] object = {new apple(),new banana()};
if(object[1] instanceof Edible) System.out.println("Yes");
if(object[2] instanceof Edible) System.out.println("Yes");

判断apple类和banana类是否为Edible接口

2. Comparable接口

可以使用Arrays.sort()对Byte、Integer、Long、Double和Float等类进行排序,因为这些类中实现了Comparable接口,Arrays.sort()才可以进行排序,例如:

public class Integer implements Comparable<Integer>{
	public int compareTo(Integer o){
		//......
	}
}
public class Double implements Comparable<Double>{
	public int compareTo(Double o){
		//......
	}
}

实现了Comparable接口才可以进行排序。Byet,Short,Integer,Long,Double,Float,Character,String,BigInteger,BigDecimal,Calendar和Date类都实现了Comparable接口

3. 自定义实现Comparable接口

public class Main{
	public static void main(String[] args){
		Circle[] nums = {new Circle(5),new Circle(6),new Circle(3)};
		Arrays.sort(nums);
		for(Circle circle : nums){
			System.out.println(circle.getArea() + " ");
		}
	}
}
class Circle implements Comparable<Circle>{
	private double r;
	public Circle(){
	}
	public Circle(double r){
		this.r = r;
	}
	public double getArea(){
		return Math.PI * r * r;
	}
	public double getPerimeter(){
		return 2 * Math.PI * r;
	}
	@Override
	public int compareTo(Circle o){
		if(getArea() > o.getArea()) return 1;
		else if(getArea() < o.getArea()) return -1;
		else return 0;
	}
}

对Circle类使用implements实现接口Comparable,并在Circle类中重写compareTo方法后,可以使用Arrays.sort()对Circle类的对象根据面积进行排序
在这个例子中,如果不使用接口,很难实现将其根据面积排序

4. Cloneable接口

Cloneable接口的clone方法可用来进行对象拷贝

4.1 clone()方法

ArrayList<Double> list1 = new ArrayList<Double>();
list1.add(3.5);
list1.add(4.5);
list1.add(5.5);
Arraylist<Double> list2 = new ArrayList<Double>();
list2 = (ArrayList<Double>)list1.clone();
ArrayList<Double> list3 = new ArrayList<Double>();
list3 = list1;
list2.add(0.5);
list3.remove(3.5);
System.out.println(list1);
System.out.println(list2);
System.out.println(list3);
输出为:
[4.5,5.5]
[0.5,3.5,4.5,5.5]
[4.5,5.5]

将list1赋值给list3,1和3同时指向一块内存,修改的是同一内存处的数据
list2是拷贝的list1的数据,额外开辟了一块内存,不与1和3共用

4.2 自定义实现Cloneable接口

4.2.1 浅拷贝

public class Main{
	public static void main(String[] args) throws CloneNotSupportedException{
		House house1 = new House(1,5.2);
		House house2 = (House)house1.clone();
		System.out.println(house1.id == house2.id);
		System.out.println(house1.whenBuild == house2.whenBuild);
	}
}

class House implements Cloneable{
	public int id;
	public double area;
	public java.util.Date whenBuild;
	public House(int id,double area){
		this.id = id;
		this.area = area;
		whenBuild = new java.util.Date();
	}
	public void setId(int id){
		this.id = id;
	}
	public void setArea(double area){
		this.area = area;
	}
	public java.util.Date getWhenBuild(){
		return whenBuild;
	}
	public double getArea(){
		return area;
	}
	public int getId(){
		return id;
	}
	@Override
	public Object clone() throws CloneNotSupportedException{
		return super.clone();
	}
}
输出为:
true
true

注意:main函数处和重写clone处要声明异常

如果clone的数据域是基本类型,则复制它的值
如果clone的数据域是对象,则复制它的引用
这里为house2的area和id额外开辟一块空间,但house2的whenBuild复制的是house1的whenBuild的引用,两者指向同一块内存
所以此时的house1.whenBuild == house2.whenBuild为true

4.2.2 深拷贝

public class Main{
	public static void main(String[] args) throws CloneNotSupportedException{
		House house1 = new House(1,5.2);
		House house2 = (House)house1.clone();
		System.out.println(house1.id == house2.id);
		System.out.println(house1.whenBuild == house2.whenBuild);
	}
}

class House implements Cloneable{
	private int id;
	private double area;
	public java.util.Date whenBuild;
	public House(int id,double area){
		this.id = id;
		this.area = area;
		whenBuild = new java.util.Date();
	}
	public void setId(int id){
		this.id = id;
	}
	public void setArea(double area){
		this.area = area;
	}
	public java.util.Date getWhenBuild(){
		return whenBuild;
	}
	public double getArea(){
		return area;
	}
	public int getId(){
		return id;
	}
	@Override
	public Object clone() throws CloneNotSupportedException{
		House tempHouse = (House)super.clone();
		tempHouse.whenBuild = (java.util.Date)whenBuild.clone();
		return tempHouse;
	}
}
输出为:
true
false

这里的whenBuild再调用一次clone方法,为house2的whenBuild开辟一块空间,此时house1和house2的whenBuild指向不同的内存,所以house1.whenBuild == house2.whenBuild输出为false

5. 接口和抽象类

接口与抽象类很相似,但接口更灵活,一个类只能继承一个父类,但可以实现多个接口

5.1 抽象类举例

abstract class Animal{
	public abstract String howToEat();
}
class Chicken extends Animal{
	@Override
	public String howToEat(){
		System.out.println("Fry it");
	}
}
class Duck extends Animal{
	@Override
	public String howToEat(){
		System.out.println("Roast it");
	}
}
public static void main(String[] args){
	Animal animal = new Chicken();
	animal.howToEat();
	animal = new Duck();
	animal.houToEat();
}

多态可以让你用Animal变量保存Chicken对象或Duck对象
JVM会动态决定调用哪个howToEat()方法
在这里Animal的子类只能是动物类,因为子类必须是父类的一种,而接口就没有此限制

5.2 接口举例

interface Edible{
	public String howToEat();
}
class Chicken implements Edible{
	@Override
	public String howToEat(){
		System.out.println("Fry it");
	}
}
class Duck implements Edible{
	@Override
	public String howToEat(){
		System.out.println("Roast it");
	}
}
class Broccoli implements Edible{
	@Override
	public String howToEat(){
		System.out.println("Stir-fry it");
	}
}
public static void main(String[] args){
	Edible stuff = new Chicken();
	stuff.howToEat();
	stuff = new Duck();
	stuff.howToEat();
	stuff = new Broccoli();
	stuff.howToEat();
}

这里的接口多定义了一个西兰花,相对于抽象类限制更少

6. 设计一个Rational类

Rational类用来表示和处理有理数,有理数的分母不能为0,分子可以为0,在这里,负有理数用正分子+负分母表示,一个整数用该整数/1来表示
将Rational类定义为Number类的子类

public class Main{
	public static void main(String[] args){
		Rational r1 = new Rational(3,-4);
		Rational r2 = new Rational(5,7);
		System.out.println(r1.add(r2));
		System.out.println(r1.sub(r2));
		System.out.println(r1.mul(r2));
		System.out.println(r1.divide(r2));
		System.out.println(r1);
		System.out.println(r2);
	}
}
class Rational extends Number implements Comparable<Rational>{
	private long numerator;
	private long denominator;
	public Rational(){
		this(0,1);
	}
	public Rational(long a,long b){
		long gcd = gcd(a,b);
		numerator = (b > 0 ? 1 : -1) * a / gcd;
		denominator = Math.abs(b) / gcd;
	}
	public long getNumerator(){
		return numerator;
	}
	public long getDenominator(){
		return denominator;
	}
	private long gcd(long a,long b){
		a = Math.abs(a);
		b = Math.abs(b);
		long gcdd = 1;
		for(int k = 2;k <= a && k <= b;k++){
			if(a % k == 0 && b % k == 0)
				gcdd = k;
		}
		return gcdd;
	}
	public Rational add(Rational a){
		long fenmu = denominator * a.getDenominator();
		long fenzi = numerator * a.getDenominator() + a.getNumerator() * denominator;
		
		return new Rational(fenzi,fenmu);
	}
	public Rational sub(Rational a){
		long fenmu = denominator * a.getDenominator();
		long fenzi = numerator * a.getDenominator() - a.getNumerator() * denominator;
		return new Rational(fenzi,fenmu);
	}
	public Rational mul(Rational a){
		long fenmu = denominator * a.getDenominator();
		long fenzi = numerator * a.getNumerator();
		return new Rational(fenzi,fenmu);
	}
	public Rational divide(Rational a){
		long fenmu = denominator * a.getNumerator();
		long fenzi = numerator * a.getDenominator();
		return new Rational(fenzi,fenmu);
	}
	@Override
	public String toString(){
		String str = "";
		if(denominator == 1)
			str = numerator + "";
		else
			str = numerator + "/" + denominator;
		return str;
	}
	@Override
	public int CompareTo(Rational a){
		if(this.sub(a).getNumerator() > 0) return 1;
		else if(this.sub(a).getNumerator() < 0) return -1;
		else return 0;
	}
}
  1. 调用无参构造方法,创建一个分子为0,分母为1的有理数
  2. 调用重载的构造方法,先用gcd判断其最大公约数,然后将该有理数除以最大公约数化为最简形式,再将分母的符号传给分子,保证负有理数的负号在分子上
  3. 重写toString方法和CompareTo方法
    输出结果为:
-1/28
-41/28
-15/28
-21/20
-3/4
5/7
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值