目录
前言
Hi~ 你好!
欢迎点击我的博客 : )
这是我的学习总结,希望也能帮助到你
我的博客地址:hi~,我在这里~,欢迎关注哦,
三连不迷路,优质内容持续更新!
一. 接口
1. 接口的概念
多个类的公共规范,是一种引用数据类型
接口就是公共行为的规范标准,只要符合规范,就可以使用
如usb的接口,雷电接口,插座接口等待,都遵循相应的协议
2. 语法定义
与定义类的格式基本相同,将class关键字换成 interface 关键字,就定义了一个接口
public interface TestInterface {//接口名
String name = "s.";//接口不能被实例化
public static final String gender= "男";//接口当中的成员默认public static final 是静态常量
public abstract void method1();//接口当中的方法,默认为public abstract
void method2();
// void method3(){//接口当中的方法,不能有具体的实现
//
// }
}
3. 接口使用
接口不能直接使用,要有一个类来实现接口中的所有抽象方法
class Rect implements IShape{
@Override
public void draw() {
System.out.println("矩形");
}
@Override
public void func() {
System.out.println("重写func()方法");
}
}
子类和父类之间是extends 继承关系,类与接口之间是 implements 实现关系
练习:模拟电脑和使用USB接口的硬件
public interface IUSB {//USB接口
void openDevice();
void closeDevice();
}
public class Mouse implements IUSB{
@Override
public void openDevice() {
System.out.println("打开鼠标");
}
@Override
public void closeDevice() {
System.out.println("关闭鼠标");
}
public void click(){
System.out.println("点击鼠标");
}
}
public class KeyBoard implements IUSB{
@Override
public void openDevice() {
System.out.println("打开键盘");
}
@Override
public void closeDevice() {
System.out.println("关闭键盘");
}
public void input(){
System.out.println("打字");
}
}
public class Computer {
public void powerOn(){
System.out.println("开机");
}
public void powerOff(){
System.out.println("关机");
}
public void useDevice(IUSB usb){
usb.openDevice();
if (usb instanceof Mouse){
Mouse mouse = (Mouse) usb;//向下转型
mouse.click();
} else if (usb instanceof KeyBoard) {
KeyBoard keyBoard = (KeyBoard) usb;
keyBoard.input();
}
usb.closeDevice();
}
}
public class TestUSB {
public static void main(String[] args) {
Computer computer = new Computer();
Mouse mouse = new Mouse();
KeyBoard keyBoard = new KeyBoard();
computer.powerOn();
computer.useDevice(keyBoard);
computer.useDevice(mouse);
computer.powerOff();
}
}
开机
打开键盘
打字
关闭键盘
打开鼠标
点击鼠标
关闭鼠标
关机
4. 接口特性
1.使用关键字interface来定义接口
2.接口不能被实例化
3.接口当中的成员,默认是public static final修饰,是静态常量
4.接口当中的方法,默认为public abstractd的
5.接口当中的方法,不能有具体的实现,但是从JDK8开始,可以写 通过default修饰的方法
6.接口当中不能有构造方法和静态代码块
7.创建接口时,接口名一般为"I"开头,一般使用形容词
8.接口中的方法和属性尽量不加修饰符,保持简洁性.
9.接口需要被类实现,使用关键字implements
10.接口当中,可以有static修饰的方法
11.重写接口中方法时,不能使用默认的访问权限(重写子类的访问权限>=父类的)+public
12. 如果类没有实现接口中的所有的抽象方法,则类必须设置为抽象类
5. 实现多个接口
public interface IRunning {
void run();
}
public interface IFlying {
void fly();
}
public interface ISwimming {
void swim();
}
public abstract class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
}
public class Bird extends Animal implements IFlying{
public Bird(String name) {
super(name);
}
@Override
public void fly() {
System.out.println(name+"在飞");
}
}
public class Dog extends Animal implements IRunning{
public Dog(String name) {
super(name);
}
@Override
public void run() {
System.out.println(name+"在跑");
}
}
public class Fish extends Animal implements ISwimming{
public Fish(String name) {
super(name);
}
@Override
public void swim() {
System.out.println(name+"在游泳");
}
}
ublic class Duck extends Animal implements IFlying,ISwimming,IRunning{//实现多个接口
public Duck(String name) {
super(name);
}
@Override
public void fly() {
System.out.println(name+"在飞");
}
@Override
public void run() {
System.out.println(name+"在跑");
}
@Override
public void swim() {
System.out.println(name+"在游泳");
}
}
public class Robot implements IRunning{
@Override
public void run() {
System.out.println("机器人在跑");
}
}
public class Test {
public static void walk(IRunning iRunning){
iRunning.run();
}
public static void fly(IFlying flyer){//只要实现了Iflying接口的,都可以接收
flyer.fly();
}
public static void main(String[] args) {
Dog dog = new Dog("大黄");
dog.run();
walk(dog);
fly(new Bird("麻雀"));
walk(new Robot());//机器人不是动物的子类,因为实现了run的接口,所以也可以接收//撇开了类型
}
}
Java中不支持多继承,但是一个类可以实现多个接口
6. 接口间的继承
interface A{
void func1();
}
interface B{
void func2();
}
interface C extends A,B{//可多继承(拓展)接口
//具备三个接口的功能
void func3();
}
class D implements C{
@Override
public void func1() {
}
@Override
public void func2() {
}
@Override
public void func3() {
}
}
类和类之间是单继承的,一个类可以实现多个接口,接口与接口之间可以多继承用接口可以达到多继承(扩展)的目的。 接口间的继承相当于把多个接口合并在一起接口可以继承一个接口 , 达到复用的效果 . 使用 extends 关键字
7. 接口的使用实例
7.1 给对象数组排序
让 Student 类实现 Comparable 接口 , 并实现其中的 compareTo 方法
如果当前对象应排在参数对象之前 , 返回小于 0 的数字 ;如果当前对象应排在参数对象之后 , 返回大于 0 的数字 ;如果当前对象和参数对象不分先后 , 返回 0;
public class Student implements Comparable<Student> {
public String name;
public int age;
public int score;
public Student(String name, int age, int score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public int compareTo(Student o) {
// if (this.age > o.age) {//按年龄比较
// return 1;
// } else if (this.age < o.age) {
// return -1;
// } else {
// return 0;
// }
if (this.name.compareTo(o.name)>0) {//年龄比较
return 1;
} else if (this.name.compareTo(o.name)<0) {
return -1;
} else {
return 0;
}
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
}
public class Test{
public static void main(String[] args) {
Student[] students = new Student[3];
students[0]=new Student("z小明",18,99);
students[1]=new Student("a小红",20,55);
students[2]=new Student("c小华",10,77);
Arrays.sort(students);
System.out.println(Arrays.toString(students));
// System.out.println(students[0].compareTo(students[1]));
}
对于 sort 方法来说 , 需要传入的数组的每个对象都是 " 可比较 " 的 , 需要具备 通过重写 compareTo 方法的方式 , 就可以比较
自己实现 sort 方法来完成排序(使用冒泡排序)
public static void sort(Comparable[] arr) {//口数组来接受
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j].compareTo(arr[j + 1]) > 0) {
Comparable temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
但是这样子写对类的侵入性很强,不灵活,不便于修改需求,所以改用比较器
public class ScoreComparator implements Comparator<Student> {//分数比较器
@Override
public int compare(Student o1, Student o2) {
return o1.score-o2.score;
}
}
public class AgeComparator implements Comparator<Student> {//年龄比较器
@Override
public int compare(Student o1, Student o2) {//重写compare
return o1.age- o2.age;
//return o2.age- o1.age;
}
}
public static void main(String[] args) {
Student[] students = new Student[3];
students[0] = new Student("z小明", 18, 99);
students[1] = new Student("a小红", 20, 55);
students[2] = new Student("c小华", 10, 77);
AgeComparator ageComparator = new AgeComparator();//比较器
Arrays.sort(students,ageComparator);
System.out.println(Arrays.toString(students));
System.out.println("--------------------------");
ScoreComparator scoreComparator = new ScoreComparator();//分数比较器
Arrays.sort(students,scoreComparator);
System.out.println(Arrays.toString(students));
}
[Student{name='c小华', age=10, score=77}, Student{name='z小明', age=18, score=99}, Student{name='a小红', age=20, score=55}]
--------------------------
[Student{name='a小红', age=20, score=55}, Student{name='c小华', age=10, score=77}, Student{name='z小明', age=18, score=99}]
这样重新写一个类来实现Comparator接口,不在Student类中修改
8. Clonable 接口和深拷贝
Object 类中存在一个 clone 方法 , 调用这个方法可以创建一个对象的 " 拷贝 ". 但是要想合法调用 clone 方法 , 必须要先实现 Clonable 接口 ,否则就会抛出 CloneNotSupportedException 异常 .Cloneable空接口,叫标记接口:表示当前对象是可以被克隆的
调用clone方法前,要先重写
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public class Test {
public static void main(String[] args)throws CloneNotSupportedException {
Student student1 = new Student();
student1.name="aaa";
Student student2 = (Student) student1.clone();//后面的类型是父类,向下转型
System.out.println(student1);
System.out.println(student2);
}
}
Student{name='aaa'}
Student{name='aaa'}
1.浅拷贝
public static void main(String[] args)throws CloneNotSupportedException {
Student student1 = new Student("丁真",140);
Student student2 = (Student) student1.clone();//后面的类型是父类,向下转型
System.out.println(student1.m.money);
System.out.println(student2.m.money);
student2.m.money = 10;
System.out.println(student1.m.money);
System.out.println(student2.m.money);
100.12
100.12
10.0
10.0
拷贝了学生对象,此时,两个学生对象的地址值不同,但是其中存储的money的地址值并没有改变,同时指向了一个地址,因此都发生了改变
2.深拷贝
此时Money也必须支持克隆,在Money类中实现Cloneable接口,重写父类的克隆方法
同时在重写克隆方法的时候,克隆Money和Student
public class Money implements Cloneable {
public double money=100.12;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Student implements Cloneable{
public String name;
public Money m = new Money();
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
//return super.clone();
Student student = (Student) super.clone();//向下转型
student.m = (Money) this.m.clone(); //克隆Money
return student;
}
}
public static void main(String[] args)throws CloneNotSupportedException {
Student student1 = new Student();
Student student2 = (Student) student1.clone();//后面的类型是父类,向下转型
System.out.println(student1.m.money);
System.out.println(student2.m.money);
System.out.println("==============");
student2.m.money = 10;
System.out.println(student1.m.money);
System.out.println(student2.m.money);
}
}
100.12
100.12
==============
100.12
10.0
9. 抽象类和接口的区别
抽象类中可以包含普通方法和普通字段 , 这样的普通方法和字段可以被子类直接使用 ( 不必重写 ), 而接口中不能包含普通方法, 子类必须重写所有的抽象方法
1.抽象类:普通类+抽象方法,接口:抽象方法+全局常量
2.抽象类有各种权限,接口是Public访问权限
3.一个抽象类可以实现多个接口
4.接口不能继承抽象类,但是接口能使用extends继承多个父接口
5.一个子类只能继承一个抽象类,但是一个子类可以实现多个接口
二. Object类
Object是 Java 默认提供的一个类。 Java 里面除了 Object 类,所有的类都是存在继承关系的。默认会继承 Object 父类。即所有类的对象都可以使用Object 的引用进行接收。
1.获取对象信息
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
将父类的toString方法进行重写,在打印时,println内部的valueOf方法的形参是Object,同时返回tostring方法,此时,传进去一个对象,和object类型构成向上转型,同时重写了toString方法,发生了动态绑定,因此会调用我们自己写的toString方法,实现多态.
2. 对象比较equals方法
1. 如果 == 左右两侧是基本类型变量,比较的是变量中值是否相同2.如果 == 左右两侧是引用类型变量,比较的是引用变量地址是否相同3.如果要比较对象中内容,必须重写 Object 中的 equals 方法,因为 equals 方法默认也是按照地址比较的
比较对象中内容是否相同的时候,一定要重写equals方法
3. hashcode方法
1.hashcode方法用来确定对象在内存中存储的位置是否相同2.事实上hashCode() 在散列表中才有用,在其它情况下没用。在散列表中hashCode() 的作用是获取对象的散列码,进而确定该对象在散列表中的位置。
后记
看到这里,希望能帮到你~
您的点赞 ,收藏 ,关注 是我创作的最大动力!
同时也欢迎在评论区进行交流,共同进步~