在java中,接口可以看作为多个类的公共规范,是一种运用数据类型
public interface IShape{
voud func1();
}
接口不能直接使用,必须要有一个"实现类"来"实现"该接口,实现接口中的所有抽象方法。
class Rect implements IShape{
// 重写接口的抽象方法
}
注意:子类和父类之间是extends 继承关系,类与接口之间是 implements 实现关系。
下面是一个简单的接口定义以及实现的代码
实例:请实现笔记本电脑使用USB鼠标、USB键盘的例子
1. USB接口:包含打开设备、关闭设备功能
2. 笔记本类:包含开机功能、关机功能、使用USB设备功能
3. 鼠标类:实现USB接口,并具备点击功能
4. 键盘类:实现USB接口,并具备输入功能
1.定义接口IUsb类
public interface IUsb {
// 1.打开设备
void openDevice();
// 2.关闭设备
void closeDevice();
}
2.定义笔记本类
pulic class computer{
public void open(){
System.out.println("开机功能")
}
public void close(){
System.out.println("关机功能")
}
public void useDevice(IUsb usb){
usb.openDevice();
if(usb instanceof Mouse){
Mouse mouse = (Mouse)usb;
}else (usb instanceof KeyBoard){
KeyBoard keyBoard = (KeyBoard)usb;
keyBoard.input();
}
usb.closeDevice();
}
}
3.定义键盘类
class Mouse implements IUsb{
// 1.重写打开设备的方法重写
@Override
public void openDevice() {
System.out.println("打开键盘");
}
// 2.重写关闭设备的方法重写
@Override
public void closeDevice() {
System.out.println("关闭键盘");
}
// 3.键盘自身功能方法
public void input(){
System.out.println("敲击键盘");
}
}
4.定义鼠标类
public class Mouse implements IUsb {
// 1.重写打开设备的方法重写
@Override
public void openDevice() {
System.out.println("打开鼠标服务");
}
// 2.重写关闭设备的方法重写
@Override
public void closeDevice() {
System.out.println("关闭鼠标服务");
}
// 3.键盘设备自身功能
public void click(){
System.out.println("鼠标点击服务");
}
}
以上接口与设备类都构建完成。在IDEA的文件结构为:
5.test
public class test {
public static void main1(String[] args) {
Computer computer = new Computer();
Mouse mouse = new Mouse();
KeyBoard keyBoard = new KeyBoard();
System.out.println("============================");
// 方式1
// 这个是 在将mouse 这个引用作为参数传递到computer.useDevice(IUsb usb)时发生向上转型
// 此时 IUsb usb = mouse 即 IUsb usb = new Mouse(); 发生向上转型
computer.useDevice(mouse);
computer.useDevice(keyBoard);
}
public static void main(String[] args) {
Computer computer = new Computer();
// 方式2
// 先向上转型 IUsb usb = new Mouse() ,
// 转型之后usb类型为IUsb,传递到computer.useDevice(IUsb usb) ,此时参数类型和形参的类型是一样的,都是IUsb类型
IUsb usb = new Mouse();
computer.useDevice(usb);
}
}
上面分别有两种方式进行调试接口功能。
第一种:
首先是实例化计算机类、鼠标类、键盘类,将mouse,keyboard两个引用传入到computer中的useDevice()方法里,在这个传参的过程实现了向上转型,然后在useDevice()方法里判断是Mouse类型还是KeyBoard类型,然后向下转型为子类类型,实例化子类,调用自己本身的方法,分别调用自己本身的方法( click()和input()方法)。
第二种:
在main函数里先进行向上转型,然后转型之后usb类型为IUsb,传递到computer.useDevice(IUsb usb) ,此时参数类型和形参的类型是一样的,都是IUsb类型,然后判断是Mouse类型还是KeyBoard类型,然后向下转型为子类类型,实例化子类,调用自己本身的方法,分别调用自己本身的方法( click()和input()方法)。
1. 接口类型是一种引用类型,但是不能直接new接口的对象
2. 接口中每一个方法都是public的抽象方法, 即接口中的方法会被隐式的指定为 public abstract(只能是public abstract,其他修饰符都会报错) (jdk8之前的版本,在jdk8之后,接口当中可以有static修饰的方法(这里面可以实现具体内容))
3.接口中的方法是不能在接口中具体实现的,只能由实现接口的类来实现
4.重写接口中方法时,不能使用默认的访问权限
原因:因为接口中方法都是public修饰的,重写此方法权限一定要大于等于被重写方法的权限,所以只可以是public权限
5.接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 修饰的变量
6.接口中不能有静态代码块和构造方法
原因:因为静态代码块和构造方法都是用来初始化成员变量的,但是在接口中成员变量都是被public static final修饰的常量。
7.接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是.class
8.如果类没有实现接口中的所有的抽象方法,则类必须设置为抽象类
例如:public abstract class KeyBoard implements IUsb{}
9.jdk8中:接口中还可以包含default方法
10.接口当中可以有static修饰的方法 (jdk8之后的版本的新特性)
例如:
default void func(){
System.out.println("haha");
}
例如:public static void staticFunc(){
System.out.println("static修饰的方法");
}
11.jdk8之后,接口可以包含static修饰的方法,还有default的方法。
在Java中,类和类之间是单继承的,一个类只能有一个父类,即Java中不支持多继承,但是一个类可以实现多个接口。
abstract class Animal{
public String name;
public Animal(String name){
this.name = name;
}
}
// class Dog extends Animal,A
// 上面是错误的,java没有多继承上面是错误的
// 可以把跑写成一个接口
interface IRunning{
void run();
}
interface ISwimming{
void swimming();
}
interface IFly{
void fly();
}
class Dog extends Animal implements IRunning{
public Dog(String name){
super(name);
}
public void eat(){
System.out.println(name+"正在吃饭");
}
// 重写IRunning接口的方法
@Override
public void run() {
System.out.println(name+"正在用四条狗腿在跑");
}
}
class Fish extends Animal implements ISwimming{
public Fish(String name) {
super(name);
}
@Override
public void swimming() {
System.out.println(name+"正在游泳");
}
}
class Bird extends Animal implements IFly{
public Bird(String name) {
super(name);
}
@Override
public void fly() {
System.out.println(name+"正在飞!");
}
}
// 类实现多个接口
class Duck extends Animal implements IRunning,ISwimming,IFly{
public Duck(String name) {
super(name);
}
@Override
public void run() {
System.out.println(name+"鸭子正在跑");
}
@Override
public void swimming() {
System.out.println(name+"鸭子正在游泳");
}
@Override
public void fly() {
System.out.println(name+"鸭子正在飞");
}
}
class Robot implements IRunning{
public String name;
public Robot(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println(name+"用机器腿在跑");
}
}
public class test {
public static void walk(IRunning iRunning){
iRunning.run();
}
public static void swim(ISwimming iswimming){
iswimming.swimming();
}
public static void main(String[] args) {
walk(new Dog("旺财"));
walk(new Duck("唐老鸭"));
swim(new Fish("七秒"));
swim(new Duck("唐老鸭"));
walk(new Robot("小爱同学"));
}
}
以上代码包含Animal类,Dog类,Fish类,Bird类,Duck类,Robot类,以及IRunning,ISwimming,IFly,三个接口。
Dog类继承Animal类,可以使用IRunning接口
Fish类继承Animal类,可以使用ISwimming接口
Bird类继承Animal类,可以使用IFly接口
Duck类继承Animal类,可以使用IRunning,ISwimming,IFly,三个接口
Robot类可以使用IRunning接口
这就实现了继承父类的子类可以使用多个接口。
注意:一个类实现多个接口时,每个接口中的抽象方法都要实现,否则类必须设置为抽象类。
在Java中,类和类之间是单继承的,一个类可以实现多个接口,接口与接口之间可以多继承。即:用接口可以达到
多继承的目的。
interface A{
public abstract void funcA();
}
interface B{
void funcB();
}
interface C extends A,B{
// C 这个接口不仅仅有funC这个功能,还包含了接口A,B的功能
void funC();
}
class CC implements C{
// 类实现接口C时,不仅要把C的方法重写,还要把C接口的父类的方法重写
@Override
public void funcA() {
System.out.println("funcA");
}
@Override
public void funcB() {
System.out.println("funcB");
}
@Override
public void funC() {
System.out.println("funcC");
}
}
public class test {
}
此时C 这个接口不仅仅有funC这个功能,还包含了接口A,B的功能。
注意:CC类实现接口C时,不仅要把C的方法重写,还要把C接口的父类的方法重写,就是要把A,B接口都要重写,不然只能加上abstract就是抽象类了。
给对象数组排序
1.有一个Student类
class Student implements Comparable{
public String name;
public int age;
public int sore;
public Student(String name, int age, int sore) {
this.name = name;
this.age = age;
this.sore = sore;
}
}
让他为数组对象,重写toString方法
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", sore=" + sore +
'}';
}
再给定一个学生对象数组, 对这个对象数组中的元素进行排序(按分数降序).
public static void main(String[] args) {
Student[] students = new Student[3];
students[0] = new Student("张三",19,10);
students[1] = new Student("李四",9,90);
students[2] = new Student("王五",39,60);
}
按照我们之前的理解, 数组我们有一个现成的 sort 方法, 能否直接使用这个方法呢?
答案是不能的,普通的整数不一样, 两个整数是可以直接比较的, 大小关系明确. 而两个学生对象的大小关系怎么确定? 需要我们额外指定.指定按照一定的规则进行比较。
Student 类实现 Comparable 接口,并实现其中的 compareTo 方法
class Student implements Comparable{
public String name;
public int age;
public int sore;
public Student(String name, int age, int sore) {
this.name = name;
this.age = age;
this.sore = sore;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", sore=" + sore +
'}';
}
@Override
public int compareTo(Student o) {
// 根据年龄比较
if(this.age>o.age){
return 1;
}else if (this.age0){
return 1;
}else if (this.name.compareTo(o.name)<0){
return -1;
}else {
return 0;
}*/
}
}
实现 Comparable 接口语法:class Student implements Comparable
在Student类内重写compareTo()方法
1.根据年龄比较
@Override
public int compareTo(Student o) {
// 根据年龄比较
if(this.age>o.age){
return 1;
}else if (this.age
public static void main(String[] args) {
Student[] students = new Student[3];
students[0] = new Student("张三",19,10);
students[1] = new Student("李四",9,90);
students[2] = new Student("王五",39,60);
// 按照年龄排序
Arrays.sort(students);
sort(students);
System.out.println(Arrays.toString(students));
}
可以用Arrays.sort(students);进行排序
下面自己写一个冒泡排序实现的
pubic static void sort(Comparable[] array){
//冒泡排序实现
//Comparable[] array;实现Comparable接口的数组都可以传进去
for(int i = 0;i < array.length-1; i++){
for(int j = 0;j < array.length-1-i;j++){
if(array[j].compareTo(array[j+1]>0){
Comparable tmp = array[j];
array[j] = array[j+1];
array[j+1] = TMP;
}
}
}
}
2.使用String作为比较
if(this.name.compareTo(o.name)>0){
return 1;
}else if (this.name.compareTo(o.name)<0){
return -1;
}else {
return 0;
}*/
String也提供了Comparable接口