天上飘来4个字,offer不是事!!
-
java基础
-
spring & springMVC
-
mybatis、mybatisplus
-
springboot & springcloudAlibaba
-
redis & mongodb & mysql
-
rabbitmq & kafka
-
docker & linux
一:java基础
1.1:java 面向对象三大特性(封装,继承,多态)?
封装:隐藏对象的属性和实现细节,仅对外公开接口,增强安全性和简化编程,使用者不必了解具体的实现细节,而只是要通过外部接口,一特定的访问权限来使用类的成员
继承:实现代码的复用,但特别注意的是,父类的私有属性和构造方法并不能被继承。另外子类可以写自己特有的属性和方法,目的是实现功能的扩展,子类也可以复写父类的方法即方法的重写。子类不能继承父类中访问权限为private的成员变量和方法
多态:相同的事物,调用其相同的方法,参数也相同时,但表现的行为却不同,例如方法重写重载。
1.2:抽象类和接口的区别?
1、接口可以多实现,而抽象类只能单继承
2、抽象类可以有非抽象的方法和构造方法、变量,但是接口只能有抽象方法,静态常量。
3、抽象类和子类具有父子关系,子类能拥有父类中一些属性。接口虽然某个类实现一个接口,但是由于接口中的变量都为静态常量,
不存在继承关系。
1.3: 重写和重载?
重载: 在同一个类中,方法名必须相同,参数类型、个数、顺序不同,与返回值类型,访问修饰符无关,发生在编译时。
重写: 发生在父子类中,方法名、参数列表必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类;如果父类方法访问修饰符为 private 则子类就不能重写该方法。
1.4 :String、StringBuffer、StringBuilder的区别?
可变性:三个都是处理字符串的方法,String底层使用final修饰了,所以是不可变的;StringBuilder 与 StringBuffer是可变的字符串;
安全性:String 中的对象是不可变的,也就可以理解为常量,线程安全。StringBuffer 对方法加了同步锁,所以是线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是不线程安全
性能:每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的String 对象,修改内容时性能低。StringBuffer、StringBuilder 每次都会对对象本身进行操作,而不是生成新的对象并改变对象引用;StirngBuilder的效率会高一些,而StringBuffer的底层加了同步的关键字,性能会有所下降
所以呢,一般我们操作少量的字符串的时候用String ,在单线程环境下操作大量数据时使用StringBuilder,在多线程操作大量数据使用StringBuffer。
1.5:java中的集合?
java 中的集合分为单列集合和双列集合,单列集合顶级接口为 Collection,双列集合顶级接口为 Map。
Collection 的子接口有两个:List 和 Set。
Ø List 接口的特点:元素可重复,有序(存取顺序)。 list 接口的实现类如下:
Ø ArrayList:底层实现是数组,查询快,增删慢,线程不安全,效率高;
Ø Vector:底层实现是数组,查询快,增删慢,线程安全,效率低;【废弃】
Ø LinkedList:底层实现是链表,增删快,查询慢,线程不安全,效率高;
Ø Set 接口的特点:元素唯一,不可重复,无序。 Set 接口实现类如下:
Ø HashSet:底层实现 hashMap,数组+链表实现,不允许元素重复,无序。
Ø TreeSet:底层实现红黑二叉树,实现元素排序
Ø Map 接口的特点:key-value 键值对形式存储数据 Map 接口实现类如下:
Ø HashMap:底层数组+链表实现,线程不安全效率高;
Ø TreeMap:底层红黑二叉树实现,可实现元素的排序;
Ø LinkedHashMap:底层hashmap+linkedList 实现,通过 hashmap 实现 key-value 键值对存储,通过链表实现元素有序。
1.6:ArrayList和Linkedlist区别?
相同点:
1、二者都是 List 接口的实现类,具有元素可重复,有序(存取顺序)特点;
2、二者都是线程不安全,效率高;
不同点:
1、数据结构:ArrayList底层数据结构是动态数组,LinkedList底层数据结构是双向链表;
2、随机访问效率:ArrayList比 LinkedList 在随机访问的时候效率要高,因为LinkedList 是线性的数据存储方式,所以需要移动指针从前往后依次查找。
3、增加和删除效率:在非首尾的增加和删除操作,LinkedList 要比ArrayList 效率要高,因为ArrayList 增删操作要影响数组内的其他数据的下标。
综合来说,在需要频繁读取集合中的元素时,更推荐使用 ArrayList,而在插入和删除操作较多时,更推荐使用LinkedList。
1.7:HashMap底层原理?
HashMap 底层是数组+链表(LinkedList)实现,hashMap 默认初始化容量为 16,也就 是说数组索引值为0-15,每个数组中存储一个链表。jdk1.8后当hash表的单一链表长度超过 8 个的时候,链表结构就会转为红黑树结构;当 hashmap 空间使用达到 0.75 后,会对数组进行扩容,新建数组,然后将元素拷 贝到新的数组中,每次扩容翻倍;在存储元素时有可能发生 hash 碰撞现象(即两个元素不相同,却有一样的 hash 值),这样的话,就将元素在数组中存入链表中,以链表的形式进行元素的存储,第一个entry 存在链表顶端,再有hash 值一致的entry 存入,则链接在第一个元素之后。
1.8:Java 到底是值传递还是引用传递?
Java 只支持值传递。
Java 程序员之所以容易搞混值传递和引用传递,主要是因为 Java 有两种数据类型,一种是基本类型,比如说 int,另外一种是引用类型,比如说 String或对象。
基本类型的变量存储的都是实际的值,而引用类型的变量存储的是对象的引用——指向了对象在内存中的地址。值和引用存储在 stack(栈)中,而对象存储在 heap(堆)中。
1.9:== 和equals有什么区别?
:判断两个对象是不是内存中同一个对象。但如果有基本数据类型参与比较,无论是基本数据类型相互比较,还是基本数据和他们的封装类比较,都比较的是值,引用数据类型之间比较的是内存地址。
equals():作用也是判断两个对象是否相等。但它一般有两种使用情况,一种这个类没有重写equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。
另一种就是类重写了 equals() 方法,重写了之后就按照重写的逻辑来判断了。
一般,我们都覆盖 equals() 方法来比较两个对象的内容相等;若它们的内容相等,就认为两个对象是相等的。
1.10:java的类加载机制?
加载
ClassLoader通过一个类的完全限定名查找此类字节码文件,并利用字节码文件创建一个class对象。
验证
目的在于确保class文件的字节流中包含信息符合当前虚拟机要求,不会危害虚拟机自身的安全,主要包括四种验证:文件格式的验证,元数据的验证,字节码验证,符号引用验证。
准备
为类变量(static修饰的字段变量)分配内存并且设置该类变量的初始值,(如static int i = 5 这里只是将 i 赋值为0,在初始化的阶段再把 i 赋值为5),这里不包含final修饰的static ,因为final在编译的时候就已经分配了。这里不会为实例变量分配初始化,类变量会分配在方法区中,实例变量会随着对象分配到Java堆中。
解析
这里主要的任务是把常量池中的符号引用替换成直接引用
初始化
这里是类记载的最后阶段,如果该类具有父类就进行对父类进行初始化,执行其静态初始化器(静态代码块)和静态初始化成员变量。(前面已经对static 初始化了默认值,这里我们对它进行赋值,成员变量也将被初始化)
1.11:java的类加载顺序?
1:所有的类都会优先加载基类;
2:静态成员的初始化优先;
3:成员初始化后,才会执行构造方法;
4:静态成员的初始化与静态块的执行,发生在类加载的时候;成员加载在对象创建时;类对象的以及静态块的访问,都会触发类的加载。
1.12: 手写排序算法?
//冒泡排序
public void bubbleSort(int []a){
int len=a.length;
for(int i=0;i<len;i++){
for(int j=0;j<len-i-1;j++){
if(a[j]>a[j+1]){
int temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
}
//选择排序
public void selectSort(int[]a){
int len=a.length;
for(int i=0;i<len;i++){
//循环次数
int value=a[i];
int position=i;
for(int j=i+1;j<len;j++){
//找到最小的值和位置
if(a[j]<value){
value=a[j];
position=j;
}
}
a[position]=a[i];//进行交换
a[i]=value;
}
}
1.13:设计模式
单例模式是保证一个类仅有一个实例,并自行提供访问该实例全局访问点的创建型模式。
//懒汉式(线程安全)
public class Singleton {
private static Singleton instance;
private Singleton (){
}
public static synchronized Singleton getInstance() {
//加线程锁
if (instance == null) {
//判断如果没有实例
instance = new Singleton(); //新建一个实例
}
return instance; //返回实例
}
}
工厂模式是为创建对象提供过渡接口,根据用户需求动态创建实例的设计模式。我们项目中接入短信服务是接入的是厂家或第三方的短信渠道ÿ