接口--行为标准
Java中:为了限定某些类(这些类之间可能没有继承关系,甚至都不是一个派系),但是这些类都具有相同的行为特征
例如:
bird类---鸟
Plane类---飞机
Kite类---风筝
这些类不是同一个父类派生出来的,但是又希望它们具有相同的行为特征,这个时候就可以设计接口。
这个时候通过这个接口就可以管理这些类
例如:JDBC
Java中,设计了很多接口,Connction(连接数据库),Statement(执行sql语句),ResultSet(返回结果)
声明接口
【权限修饰符】 interface 接口名{
接口的成员列表
}
接口的成员
jdk1.8之前,只能有两种成员
1).全局的静态常量 【public static final】---比如:public static final long MAX_SPEED = 7900000;
为什么只能是常量?---因为接口是个定义行为标准的引用类型,在该类型中只能写“定死的”
2).公共的抽象的方法:【public abstract】
为什么只能是抽象方法?---标准中只规定有什么行为标准,行为特征,至于怎样实现,由实现者决定
如何实现接口?
语法格式:【修饰符】 class 实现类 implements 接口1,接口2...{}
接口的特点
1.接口是标准,就是用来被遵守的,即就是用来被实现的,那么要求实现类在实现接口时,必须实现/重写所有的抽象方法,否则这个实现类就得时一个抽象类
2.接口是不能直接创建对象的
3.接口类型的变量与实现类的对象构成多态引用
4.一个类继承父类时,只能单继承,但是一个类实现接口,可以同时实现多个接口
5.一个类如果同时继承父类,实现接口,那么继承在前,实现在后
语法格式:【修饰符】 class 实现类 extends 父类 implements 接口1,接口2....{}
6.接口可以继承接口,多继承---比如:接口A,B,C, A enctends B, C
语法格式:【权限修饰符】 interface 子接口 extends 接口1,接口2.....{}
案例:
package com.interfacesample.test;
/*
* (1).声明一个接口MyRunnable,包含抽象方法void run()
(2).声明它的实现类Car,实现MyRunnable接口,自己顺便打印点什么东西
(3).声明它的实现类Person,实现MyRunnable接口
(4).声明它的实现类Dog,实现MyRunnable接口
(5).在测试类中创建MyRunnable[]数组,元素赋值为各种实现类对象,遍历数组,调用元素的run()方法
*/
public class A{
public interface MyRunnable {
void run(); //省略了public abstract
}
class Car implements MyRunnable{
@Override
public void run() {
System.out.println("汽车跑的很快!!!");
}
}
class Person implements MyRunnable{
@Override
public void run() {
System.out.println("靠人跑过去,会很慢!!!");
}
}
class Dog implements MyRunnable{
@Override
public void run() {
System.out.println("狗跑的比人快,比车要慢!!!");
}
}
public void test(){
MyRunnable[] my = new MyRunnable[3];
//多态引用
my[0] = new Car();
my[1] = new Person();
my[2] = new Dog();
for (MyRunnable myRunnable : my) {
myRunnable.run();
}
}
public static void main(String[] args) {
A a = new A();
a.test();
}
}
结果为:
汽车跑的很快!!!
靠人跑过去,会很慢!!!
狗跑的比人快,比车要慢!!!
常见的接口
1.java.util.Comparator<T>:定制比较,定制顺序---抽象方法:int compare(T o1,T o2)
这个接口是代表Java中比较两个对象的大小标准,而且是一种“定制”比较标准
这个接口中没有规定如何比较两个对象的大小
但是规定了,如果o1>o2,则返回正数
如果o1<o2,则返回负数
如果o1等于o2,则返回0
注意:Arrays中调用sort(Object[],Comparator c)方法时:
1.第一个形参:需要排序的数组
2.第二个形参:比较器对象,Comparator接口不能创建对象,只能传入实现类对象
案例:
package com.interfacesample.test;
import java.util.Arrays;
import java.util.Comparator;
public class ComparatorSample {
public static void main(String[] args) {
Person[] p = new Person[5];
p[0] = new Person("张三", 18,99);
p[1] = new Person("李四", 17,66);
p[2] = new Person("王五", 17,33);
p[3] = new Person("赵六", 15,89);
p[4] = new Person("李一", 14,99);
Arrays.sort(p,new B()); //对象之间排序
for (int i = 0; i < p.length; i++) {
System.out.println(p[i]);
}
}
}
class B implements Comparator<Object>{
@Override
public int compare(Object o1, Object o2) {
Person p1 = (Person)o1; //强制转型
Person p2 = (Person)o2;
//先按年龄排序,后按成绩排序
if(p1.getAge() > p2.getAge()){
return 1;
}else if (p1.getAge() < p2.getAge()) {
return -1;
}else {
if(p1.getScore() > p2.getScore()){
return 1;
}else if (p1.getScore() < p2.getScore()) {
return -1;
}else {
return 0;
}
}
}
}
class Person{
private String name;
private int age;
private float score;
public Person(){}
public Person(String name,int age,float score){
this.name = name;
this.age = age;
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public float getScore() {
return score;
}
public void setScore(float score) {
this.score = score;
}
@Override
public String toString() {
return "name =" + this.getName() + "\t" + "age =" + this.getAge() + "\t" + "score = " + this.getScore();
}
}
结果为:
name =李一 age =14 score = 99.0
name =赵六 age =15 score = 89.0
name =王五 age =17 score = 33.0
name =李四 age =17 score = 66.0
name =张三 age =18 score = 99.0
上面只要将new B()放入Arrays.sort(p,new B())中就可以,但是不知道sort中为什么可以升序,下面代码实现:----自己手动
Student类:
package com.interfacesample.sort;
public class Student {
private String name;
private int age;
private float salary;
public Student(String name,int age,float salary){
this.name = name;
this.age = age;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public float getSalary() {
return salary;
}
public void setSalary(float salary) {
this.salary = salary;
}
@Override
public String toString() {
return "name" + this.getName() + "\t"
+ "age" + this.getAge() + "\t"
+ "salary" + this.getSalary();
}
}
AgeSalaryComparator类----先按age排序,后按salary排序
package com.interfacesample.sort;
import java.util.Comparator;
public class AgeSalaryComparator implements Comparator<Object>{
@Override
public int compare(Object o1, Object o2) {
Student p1 = (Student)o1;
Student p2 = (Student)o2;
//先按年龄排序,后按成绩排序
if(p1.getAge() > p2.getAge()){
return 1;
}else if (p1.getAge() < p2.getAge()) {
return -1;
}else {
if(p1.getSalary() > p2.getSalary()){
return 1;
}else if (p1.getSalary() < p2.getSalary()) {
return -1;
}else {
return 0;
}
}
}
}
MyArrays类----相当于实现Arrays中的sort方法
package com.interfacesample.sort;
import java.util.Comparator;
public class MyArrays {
public static void sort(Object[] obj,Comparator<Object> c){
for (int i = 1; i < obj.length; i++) {
for (int j = 0; j < obj.length - 1; j++) {
if(c.compare(obj[j], obj[j + 1]) > 0){
Object object = obj[j];
obj[j] = obj[j + 1];
obj[j + 1] = object;
}
}
}
}
}
TestComparator类---测试类
package com.interfacesample.sort;
public class TestComparator {
public static void main(String[] args) {
Student[] students = new Student[5];
students[0] = new Student("张三", 34, 2000);
students[1] = new Student("李四", 21, 2500);
students[2] = new Student("王五", 56, 2600);
students[3] = new Student("张柳", 24, 4000);
students[4] = new Student("张三", 24, 3000);
AgeSalaryComparator ageSalary = new AgeSalaryComparator();
MyArrays.sort(students, ageSalary);
for (Student student : students) {
System.out.println(student.toString());
}
}
}
结果为:
name李四 age21 salary2500.0
name张三 age24 salary3000.0
name张柳 age24 salary4000.0
name张三 age34 salary2000.0
name王五 age56 salary2600.0
2.java.lang.Comparable:自然比较,自然排序----int compareTo(Object obj),this与obj比较:比如:
this.getAge() > obj.getAge() 返回整数
this.getAge() < obj.getAge() 返回负数
this.getAge() == obj.getAge() 返回0
总结:
Arrays的sort方法有两种:
1.void sort(Object[] arr)---根据元素的自然顺序指定对象数组按升序进行排序,数组中的所有元素都必须实现Comparable接口
2.void sort(Object[] arr,Comparator c)---根据“指定比较器"产生的顺序对指定对象数组进行排序。数组中的所有元素都必须是通过指定比较器可相互比较的
手动实现Comparable
Employee类----实现Comparable
package com.interfacesample.comparabletest;
public class Employee implements Comparable<Object> {
private int id;
private String name;
private int age;
private float salary;
public Employee(int id,String name,int age,float salary){
this.id = id;
this.name = name;
this.age = age;
this.salary =salary;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public float getSalary() {
return salary;
}
public void setSalary(float salary) {
this.salary = salary;
}
@Override
public String toString() {
return "id = " + this.getId() + "\t"
+ "name = " + this.getName() + "\t"
+ "age = " + this.getAge() + "\t"
+ "salary = " + this.getSalary();
}
@Override
public int compareTo(Object o) {
Employee employee = (Employee)o;
return this.getId() - employee.getId();
}
}
MyArraysComparable---手写sort方法
package com.interfacesample.comparabletest;
public class MyArraysComparable {
public static void sort2(Object[] obj){
for (int i = 1; i < obj.length; i++) {
for (int j = 0; j < obj.length - 1; j++) {
Employee employee1 = (Employee)obj[j];
Employee employee2 = (Employee)obj[j + 1];
if(employee1.compareTo(employee2) > 0){
Object tmp = obj[j];
obj[j] = obj[j + 1];
obj[j + 1] = tmp;
}
}
}
}
}
TestComparable类---测试
package com.interfacesample.comparabletest;
public class TestComparable {
public static void main(String[] args) {
Employee[] employee = new Employee[5];
employee[0] = new Employee(3, "张三", 30, 15000);
employee[1] = new Employee(1, "李四", 20, 5000);
employee[2] = new Employee(2, "王五", 10, 0);
employee[3] = new Employee(7, "赵柳", 22, 10000);
employee[4] = new Employee(4, "七八", 35, 25000);
MyArraysComparable.sort2(employee);
for (Employee employee2 : employee) {
System.out.println(employee2.toString());
}
}
}
结果如下:
id = 1 name = 李四 age = 20 salary = 5000.0
id = 2 name = 王五 age = 10 salary = 0.0
id = 3 name = 张三 age = 30 salary = 15000.0
id = 4 name = 七八 age = 35 salary = 25000.0
id = 7 name = 赵柳 age = 22 salary = 10000.0
字符串的比较
因为String类型是引用数据类型,是无法直接用<和<,等于等比较符比较大小的
java.lang.String类型,实现了Comparable接口,所以可以调用comparaTo方法进行比较
Java8对接口进行了修改
Java8之前,接口中的成员只有两种;
(1).全局的静态的常量 public static final 可以省略
(2).公共的抽象的方法:public abstract 可以省略
java8之后,接口又增加了两种新成员:
(3).静态方法:public static 不可以省略
调用方式:接口名.静态方法
(4).默认方法:public default 不可省略
调用方式:实现类.默认方法
为什么要加入静态方法:
因为jdk发展了一段时间后,发现类库中,多了很多这样的承租的API
(1).Path接口和Paths工具类
(2).Collection接口和Collections工具类
一般工具类都是静态方法,这些静态方法,基本上都是为前面这个对应接口服务的。
这样的话,就会出现很多的API,使得程序员的学习成本增加了,使用成本也增加了
开始把这样的静态方法,直接挪到接口中定义,减少了这样的工具类的出现
为什么要加入默认方法
是因为有的时候,一个接口它的大多数实现对接口的抽象方法的实现代码是一样的,那么写好几次就太麻烦了,如果有一个实现类与默认方法的实现不一样,则这个实现类重写这个方法就可以了,相当于,默认方法是原来的抽象方法有了一个默认实现。如果实现类的实现和接口一样,就不需要重写,如果不样,则重写
冲突问题
1.两个接口中有相同的默认方法(即方法名一样),一个类实现了这两个接口,那么必须在这个实现类中,必须做出选择:
1).保留一个,放弃另一个
接口A---test方法,接口B---test方法,实现类C
public class C implements A,B{
public void test(){ //重写test方法时,必须将default去掉
A.super.test(); //保留A中的test方法,去掉B中的test方法
// B.super.test(); //保留B中的test方法,去掉B中的test方法
注意:这里可以同时写入: A.super.test(); B.super.test(); //即两个都保留
2).两者都不要,完全重写一个
public void test(){
System.out.println("dfhjfkj");
2.当一个类同时继承了父类,又实现了接口,那么当父类中出现了和接口中方法签名一样的方法
选择:
1).默认选择,编译器默认选择父类
2).改选保留接口的
3).完全自己重写
接口A----test方法,父类B---test方法
public class C extends B implements A{
public void test(){
A.super.test(); //保留接口的
}
}