nginx面试题腾讯,day13教程
接口定义的是多个类共同的公共行为规范,这些行为规范是与外部交流的通道,这就意味着接口里通常是定义一组公共方法。可以理解为:接口是从多个相似类中抽象出来的规范,不需要提供具体实现
在JDK8之前,接口中只允许出现:
- 静态常量:接口中的变量,默认被 public static final 修饰,可以省略不写。我们可以使用接口名称.变量名 访问常量值。因为接口是标准规范,那么在规范中需要声明一些底线边界值,当实现者在实现这些规范时,不能去随意修改和触碰这些底线,否则就有“危险”。例如:USB1.0规范中规定最大传输速率是1.5Mbps,最大输出电流是5V/500mA
- 抽象方法:接口中的抽象方法 默认被 public abstract 修饰,可以省略不写。
在JDK1.8时,接口中允许声明默认方法和静态方法:
- 默认的方法:其中public 可以省略,建议保留,但是default不能省略。
- 我们要在已有的老版接口中提供新方法时,如果添加抽象方法,就会涉及到原来使用这些接口的类就会有问题,那么为了保持与旧版本代码的兼容性,只能允许在接口中定义默认方法实现。比如:Java8中对Collection、List、Comparator等接口提供了丰富的默认方法。
- 当我们接口的某个抽象方法,在很多实现类中的实现代码是一样的,此时将这个抽象方法设计为默认方法更为合适,那么实现类就可以选择重写,也可以选择不重写。
- 静态的方法:其中public 可以省略,建议保留,但是static不能省略
- 因为之前的标准类库设计中,有很多Collection/Colletions或者Path/Paths这样成对的接口和类,后面的类中都是静态方法,而这些静态方法都是为前面的接口服务的,那么这样设计一对API,不如把静态方法直接定义到接口中使用和维护更方便。
在JDK1.9时,接口又增加了:
- **私有方法:**因为有了默认方法和静态方法这样具有具体实现的方法,那么就可能出现多个方法由共同的代码可以抽取,而这些共同的代码抽取出来的方法又只希望在接口内部使用,所以就增加了私有方法。
除此之外,接口中不能有其他成员,没有构造器,没有初始化块,因为接口中没有成员变量需要初始化。
接口的使用
接口的使用,它不能创建对象,但是可以被实现(implements
,类似于被继承)。类与接口的关系为实现关系,即类实现接口,该类可以称为接口的实现类,也可以称为接口的子类。实现的动作类似继承,格式相仿,只是关键字不同,实现使用 implements
关键字。
实现接口语法格式
注意:
- 如果接口的实现类是非抽象类,那么必须重写接口中所有抽象方法。如果一个类实现了继承了多个接口的接口 那么 不仅要实现 此接口的抽象方法 也要实现继承接口的抽象方法
- 一个类实现接口后 如果不想实现接口中的抽象方法 则 自己必须变为抽象类。
- 默认方法可以选择保留,也可以重写。重写时,default单词就不要再写了,它只用于在接口中表示默认方法,到类中就没有默认方法的概念了
- 不能重写静态方法
package demo02;
public class DemoClass implements DemoInterface {
@Override
public void read() {
System.out.println("我会读");
}
@Override
public void write() {
System.out.println("我会写");
}
}
如何调用对应的方法
- 对于接口的静态方法,直接使用“接口名.”进行调用即可。也只能使用“接口名."进行调用,不能通过实现类的对象进行调用
- 对于接口的抽象方法、默认方法,只能通过实现类对象才可以调用。接口不能直接创建对象,只能创建实现类的对象
package demo02;
public class Test {
public static void main(String[] args) {
//创建实现类对象,多态
DemoInterface b = new DemoClass();
//通过实现类对象调用重写的抽象方法,以及接口的默认方法,
// 如果实现类重写了就执行重写的默认方法,如果没有重写,就执行接口中的默认方法
b.start();
b.read();
//通过接口名调用接口的静态方法
DemoInterface.show();
}
}
接口的多实现
之前学过,在继承体系中,一个类只能继承一个父类。而对于接口而言,一个类是可以实现多个接口的,这叫做接口的多实现。并且,一个类能继承一个父类,同时实现多个接口。
其他注意事项:
- 一个类可以先继承一个父类 再去实现多个接口 顺序不能改变
- 当一个类,既继承一个父类,又实现若干个接口时,父类中的成员方法与接口中的抽象方法重名,子类就近选择执行父类的成员方法
- 当一个类同时实现了多个接口,而多个接口中包含方法签名相同的默认方法时.。要么选择保留其中一个,通过“接口名.super.方法名"的方法选择保留哪个接口的默认方法,要么选择自己完全重写。
class C implements A,B{
@Override
public void d() {
A.super.d();
}
}
- 一个接口能继承另一个或者多个接口,接口的继承也使用
extends
关键字,子接口继承父接口的方法。 - 实现类实现接口,类似于子类继承父类,因此,接口类型的变量与实现类的对象之间,也可以构成多态引用。通过接口类型的变量调用方法,最终执行的是你new的实现类对象实现的方法体。
Comparable(内部比较器)
我们知道基本数据类型的数据(除boolean类型外)需要比较大小的话,之间使用比较运算符即可,但是引用数据类型是不能直接使用比较运算符来比较大小的。那么,如何解决这个问题呢?Java给所有引用数据类型的大小比较,指定了一个标准接口,就是java.lang.Comparable接口:
public interface Comparable{
int compareTo(Object obj);
}
那么我们想要使得我们某个类的对象可以比较大小,怎么做呢?步骤:
**第一步:**哪个类的对象要比较大小,哪个类就实现java.lang.Comparable接口,并重写方法。方法体就是你要如何比较当前对象和指定的另一个对象的大小
**第二步:**对象比较大小时,通过对象调用compareTo方法,根据方法的返回值决定谁大谁小。
- this对象(调用compareTo方法的对象)大于指定对象(传入compareTo()的参数对象)返回正整数
- this对象(调用compareTo方法的对象)小于指定对象(传入compareTo()的参数对象)返回负整数
- this对象(调用compareTo方法的对象)等于指定对象(传入compareTo()的参数对象)返回零
案例:
声明一个Employee员工类,包含编号、姓名、薪资,实现Comparable接口,要求,按照薪资比较大小,如果薪资相同,按照编号比较大小。
package com.wrg.oop5;
public class Employee implements Comparable {
private int id;
private String name;
private double salary;
public Employee(int id, String name, double salary) {
super();
this.id = id;
this.name = name;
this.salary = salary;
}
public Employee() {
super();
}
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 double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", salary=" + salary + "]";
}
@Override
public int compareTo(Object o) {
//这些需要强制,将o对象向下转型为Employee 类型的变量,才能调用Employee 类中的属性
Employee emp = (Employee) o;
//排序规则
if(this.getSalary() != emp.getSalary()){
return Double.compare(this.getSalary(), emp.getSalary());
}
return this.id - emp.id;
}
}
声明一个测试类TestEmployee类,在main中创建Employee[]数组,长度为5,并且存储5个员工对象,现在要求用冒泡排序,实现对这个数组进行排序,遍历结果。
package com.wrg.oop5;
public class TestComparable {
public static void main(String[] args) {
Employee[] arr = new Employee[5];
arr[0] = new Employee(1,"张三",13000);
arr[1] = new Employee(2,"李四",13000);
arr[2] = new Employee(3,"王五",14000);
arr[3] = new Employee(4,"赵六",7000);
arr[4] = new Employee(5,"钱七",9000);
//原顺序
System.out.println("员工列表:");
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
//冒泡排序
for (int i = 1; i < arr.length; i++) {
for (int j = 0; j < arr.length-i; j++) {
//因为Employee类型实现了Comparable接口,所以有compareTo()方法
if(arr[j].compareTo(arr[j+1])>0){
Employee temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
System.out.println("排序后员工列表:");
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
**自定义一个数组工具类MyArrays,**它包含一个静态方法,可以给任意对象数组用冒泡排序实现从小到大排序,该怎么定义这个方法呢?
/**
* 接收所有引用类型数据
* 通用的排序方法,
*
* @param objArr
*/
//实现了Comparable接口一定是其子类
public static void sort(Comparable[] objArr) {//Comparable arr = student;
//冒泡排序
for (int i = 0; i < objArr.length - 1; i++) {
for (int j = 0; j < objArr.length - 1 - i; j++) {
//当前一个数大于后一个数
if (objArr[j].compareTo(objArr[j + 1]) > 0) {
Comparable temp = objArr[j];
objArr[j] = objArr[j + 1];
objArr[j + 1] = temp;
}
}
}
}
Comparator(外部比较器)
如果一个类,没有实现Comparable接口,而这个类你又不方便修改(例如:一些第三方的类,你只有.class文件,没有源文件),那么这样类的对象也要比较大小怎么办?如果一个类,实现了Comparable接口,也指定了两个对象的比较大小的规则,但是此时此刻我不想按照它预定义的方法比较大小,但是我又不能随意修改,因为会影响其他地方的使用,怎么办?JDK在设计类库之初,也考虑到这种情况了,所以又增加了一个java.util.Comparator接口
public interface Comparator{
int compare(Object o1,Object o2);
}
那么我们想要比较某个类的两个对象的大小,怎么做呢?步骤:
第一步:编写一个类,我们称之为比较器类型,实现java.util.Comparator接口,并重写compare方法。方法体就是你要如何指定的两个对象的大小
**第二步:**比较大小时,通过比较器类型的对象调用compare()方法,将要比较大小的两个对象作为compare方法的实参传入,根据方法的返回值决定谁大谁小。
- o1对象大于o2返回正整数
- o1对象小于o2返回负整数
- o1对象等于o2返回零
/*
如何使用外部比较器比较:
外部比较器: 因为在 比较对象类的外面 新建了一个类专门用于比较
1.定义一个类 实现 Comparator接口
public class PersonSortOfAge implements Comparator {}
2.重写compare()传递两个参数
3.制定比较规则
4.先去创建 比较规则的对象
# 最后总结
## ActiveMQ+Kafka+RabbitMQ学习笔记PDF
![image.png](https://www.icode9.com/i/ll/?i=img_convert/a571de6e16a673744c81f4d5a9ff13d2.png)
* ### RabbitMQ实战指南
![image.png](https://www.icode9.com/i/ll/?i=img_convert/7c25c504f090c3248a54e76e3c87081f.png)
* ### 手写RocketMQ笔记
![image.png](https://www.icode9.com/i/ll/?i=img_convert/f1c25f3af6b2e3e4ccbe7acb34d65a58.png)
* ### 手写“Kafka笔记”
![image](https://www.icode9.com/i/ll/?i=img_convert/0bdb34f66f242377af352f1789bba63e.png)
关于分布式,限流+缓存+缓存,这三大技术(包含:ZooKeeper+Nginx+MongoDB+memcached+Redis+ActiveMQ+Kafka+RabbitMQ)等等。这些相关的面试也好,还有手写以及学习的笔记PDF,都是啃透分布式技术必不可少的宝藏。以上的每一个专题每一个小分类都有相关的介绍,并且小编也已经将其整理成PDF啦
sonSortOfAge implements Comparator {}
2.重写compare()传递两个参数
3.制定比较规则
4.先去创建 比较规则的对象
# 最后总结
## ActiveMQ+Kafka+RabbitMQ学习笔记PDF
[外链图片转存中...(img-Hfy9AS0V-1628224994169)]
* ### RabbitMQ实战指南
[外链图片转存中...(img-ZWpjp2cg-1628224994171)]
* ### 手写RocketMQ笔记
[外链图片转存中...(img-DeSoqKkQ-1628224994173)]
* ### 手写“Kafka笔记”
[外链图片转存中...(img-x9ufpzqQ-1628224994175)]
关于分布式,限流+缓存+缓存,这三大技术(包含:ZooKeeper+Nginx+MongoDB+memcached+Redis+ActiveMQ+Kafka+RabbitMQ)等等。这些相关的面试也好,还有手写以及学习的笔记PDF,都是啃透分布式技术必不可少的宝藏。以上的每一个专题每一个小分类都有相关的介绍,并且小编也已经将其整理成PDF啦
**[资料领取方式:戳这里免费领取](https://gitee.com/vip204888/java-p7)**