| 5 | 接口强调的是特定功能的实现,抽象类强调的是所属关系 |
| 6 | main 方法:接口不能有 main 方法;抽象类可以有 main 方法,并且可以运行它 |
| 7 | 接口中定义的成员变量,只能是静态常量,默认修饰符 public static final,而且必须给其赋初值;接口中定义的成员方法,抽象方法,默认修饰符为public abstract;抽象类中成员变量默认default(默认,什么也不写,同一包中可见),可在子类中被重新定义,也可被重新赋值;抽象类中抽象方法被abstract修饰,不能被private、static、synchronzed和native等修饰,必须以分号结尾,不带花括号 |
| 8 | 接口中不包含构造器;抽象类里可以包含构造器,抽象类中的构造器并不是用于创建对象,而是让其子类调用这些构造器来完成属于抽象类的初始化操作 |
| 9 | 接口被用于常用的功能,便于日后维护和添加删除;抽象类更倾向于充当公共类的角色,不适用于日后重新对立面的代码修改;功能需要累积时用抽象类,不需要累积时用接口 |
相同点:
| 序号 | 相同点 |
| — | — |
| 1 | 接口和抽象类都不能被实例化;接口的实现类或抽象类的子类都只有实现了接口或抽象类中的方法后才能被实例化 |
| 2 | 接口和抽象类都可以包含抽象方法 |
8、Java中" == "与equals()方法的区别?
" == “: 对于八大基本数据类型来说,直接比较值;如果是引用数据类型,则是比较内存地址;(因为 Java只有值传递 ,所以对于” == "来说,不管是比较基本数据类型,还是引用数据类型的变量,本质都是比较值,只是引用类型变量存的值是对象的地址)
equals():equals()是Object类提供的方法之一;每一个Java类都继承自Object类,所以每一个对象都具有equals方法。Object中的equals方法是直接使用" == “运算符比较的两个对象,所以在没有重写equals方法的情况下,equals与” == "运算符一样,比较的是地址; 可以通过重写equals方法来比较两个对象的内容是否相等
9、为什么重写equals()方法时必须重写hashCode()方法?
equals()和hashCode()方法要遵循如下的 原则 :
1、如果两个对象equals()方法相等,它们的hashCode返回值一定要相同
2、如果两个对象的hashCode返回值相同,但它们的equals()方法不一定相等
3、两个对象的hashcode()返回值不相等,则可以判定两个对象的内容一定不相等
如果只重写equals()方法而不重写hashCode()方法,将会造成equals()方法判断出的结果是true,但hashCode()返回值不同的情况,也可能会出现hashCode()方法返回值相等,但equals()方法相同的情况,因此equals()方法与hashCode()方法都要进行修改,使两者遵循上述原则; 即:equals方法被覆盖,则hashCode方法也必须被覆盖
问题:为什么需要hashCode()方法?
答:使用hashCode()方法提前校验,避免每一次比较都调用equals方法,提高效率
面试官:你有没有重写过equals()和hashcode()?
答: 在使用HashMap的“key”的部分存放自定义的对象时,重写过hashCode和equals方法,从而保证key是唯一的
10、Java中的八大基本数据类型
Java有8中基本数据类型,其中包括
6种数字类型:byte(1)、short(2)、int(4)、long(8)、float(4)、double(8)
1种字符类型:char(2)
1种布尔型:boolean
对于boolean型,官方文档未明确定义,它依赖于JVM厂商的具体实现
11、final关键字
final用来修饰类、方法和变量
1、 final修饰的类不能被继承,final类中的所有成员方法都会被隐式的指定为final方法 (但是final修饰的类中成员变量是可变的,如果想要final类的成员变量不可变,必须给成员变量增加final修饰)
2、final修饰的方法不能被重写
3、 final修饰的变量是常量 ;如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能让其指向另一个对象
12、static关键字
static关键字主要有以下4种用法:
1、修饰成员变量和成员方法
被 static 修饰的成员属于类,被类中所有对象共享,可通过 类名.成员变量 或 对象.成员变量的方式调用
static变量也称作静态变量,静态变量和非静态变量的区别是: 静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化 ;而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响;static成员变量的初始化顺序按照定义的顺序进行初始化
static方法也称作静态方法,静态方法不依赖于任何对象就可以进行访问,静态方法只能访问静态成员,但不能访问类的非静态成员,因为非静态成员必须依赖具体的对象才能够被调用(成员:成员方法与成员变量)
2.静态代码块
静态代码块定义在类中方法外,类中可以有多个static块
静态代码块在非静态代码块之前按照static块的顺序来执行每个static块(静态代码块–>非静态代码块–>构造方法)
一个类不管创建多少对象,静态代码块只执行一次
3.静态内部类
static修饰类的话只能修饰内部类;静态内部类与非静态内部类之间存在一个最大的区别: 非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围类,但是静态内部类却没有。没有这个引用就意味着:<1>它的创建是不需要依赖外围类的创建;<2>它不能使用任何外围类的非静态成员(成员:成员方法与成员变量)
4.静态导包
用来导入类中的静态资源,1.5之后的新特性;可以指定导入某个类中的指定静态资源,并且不需要使用类名调用类中的静态成员,可以直接使用类中静态成员变量和成员方法。
静态代码块的加载次序:
父类静态代码块–>子类静态代码块–>父类非静态代码块–>父类构造函数–>子类非静态代码块–>子类构造函数
13、深拷贝和浅拷贝
浅拷贝:对基本数据类型进行值传递;对引用数据类型只是进行引用的传递,并没有在内存中的创建一个新的对象,此为浅拷贝
深拷贝:对基本数据类型进行值传递;对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝
14、Java异常体系
Java中,所有的异常都有⼀个共同的祖先java.lang包中的Throwable类:Throwable类有两个重要的⼦类:Exception(异常) 和 Error(错误),⼆者都是Java异常体系的重要⼦类,各⾃都包含⼤量⼦类
Error(错误):程序⽆法处理的错误,表示运⾏应⽤程序中较严重问题;⼤多数错误与代码编写者执⾏的操作⽆关,⽽表示代码运⾏时JVM出现的问题;例如,Java 虚拟机运⾏错误(Virtual MachineError),当 JVM 不再有继续执⾏操作所需的内存资源时,将出现内存溢出(OutOfMemoryError);这些异常发⽣时,JVM⼀般会选择终⽌线程
Exception(异常):程序本身可以处理的异常;Exception 类有⼀个重要的⼦类RuntimeException;RuntimeException异常由JVM抛出;还有NullPointerException(要访问的变量没有引⽤任何对象时,抛出该异常);ArithmeticException(算术运算异常,⼀个整数除以0时,抛出该异常)以及 ArrayIndexOutOfBoundsException(数组下标越界异常)
Exception(异常)又分为两类:运行时异常和编译时异常
1、运行时异常(不受检异常):RuntimeException类及其子类表示JVM在运行期间可能出现的错误;比如说试图使用空值对象的引用(NulIPointerException)、数组下标越界(ArraylndexOutBoundException);此类异常属于不可查异常,一般是由程序逻辑错误引起的,在程序中可以选择捕获处理,也可以不处理
2、编译时异常(受检异常):Exception中除RuntimeException及其子类之外的异常;如果程序中出现此类异常,比如说IOException,必须对该异常进行处理,否则编译不通过;在程序中,通常不会自定义该类异常,而是直接使用系统提供的异常类
15、反射
1、什么是Java的反射
反射是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取信息以及动态调用对象的方法的功能称为 Java 语言的反射机制
2、反射的作用
运行时:判断对象所属的类;构造一个对象所属的类;判断一个对象的方法和属性;调用对象的方法和属性
16、Java泛型
Java的泛型即"参数化类型",允许程序在创建集合时指定集合元素的类型,表示该集合只能保存该类型的对象
为什么要使用泛型?
答: 如果不使用泛型,当把一个对象存入集合后,集合就会忘记这个对象的数据类型,再次取出该对象时,该对象的编译类型就变成了Object类型,还需要进行强制转换;当使用泛型后,集合中只能存入指定类型的对象,否则将报错,并且将对象从集合取出后无需对元素进行强制转换,就是原本的类型(指定的类型) ;
由此可见在集合中存储对象并在使用前进行类型转换是多么的不方便;泛型防止了那种情况的发生,提供了编译时的类型安全,确保只能把正确类型的对象放入集合中,避免了在运行时出现ClassCastException(类型转换异常)
扩展知识:
父子对象之间的转换分为了向上转型和向下转型;它们解释如下:
向上转型: 通俗地讲,就是将子类对象向上转为父类对象,或者说是父类引用指向子类对象 ,此处父类对象可以是接口
格式: 父类 变量名 = new 子类();
向上转型的好处?
向上转型后,父类引用可以调用子类重写过的父类方法,当需要新添功能时,可以新增一个(子)类即可,而不用更改原父类代码
向上转型后的对象不是新创建的父类对象,而是子类对象的"简化"状态,它不关心子类新增的功能,只关心子类继承和重写的功能;当一个类有很多子类时,并且这些子类都重写了父类中的某个方法,使用上转型对象调用这个方法时就可能具有多种形态,因为不同的子类在重写父类的方法时可能产生不同的行为;也就是说, 不同对象的上转型对象调用同一方法可能产生不同的行为
向下转型:与向上转型相反,即是把父类对象转为子类对象;一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制转换的格式
格式: 子类 变量名 = (父类类型)父类变量;
为什么要向下转型?
向下转型一般是为了重新获得因为向上转型而丢失的子类特性;因此,通常在向下转型前已经有向上转型,而向下转型通常也会结合instanceof一起使用;借由向下转型,可以在灵活应用多态的基础上,同时兼顾子类的独有特征(instanceof:用来测试一个对象是否为一个类的实例)
用法是: boolean result = obj instanceof Class
17、什么是泛型擦除
在代码中定义 List<Object>
和 List<String>
等类型,在编译后都会变成List,JVM看到的只是List,而由泛型附加的类型信息对JVM是看不到的
在如下例子中,定义了两个ArrayList数组;一个是ArrayList 泛型类型的,只能存储字符串;一个是ArrayList
泛型类型的,只能存储整数;通过list1对象和list2对象的getClass()方法获取他们的类的信息,最后发现结果为true
说明泛型类型String和Integer都被擦除掉了,只剩下原始类型
Java代码:
import java.util.*;
public class Test {
public static void main(String[] args) {
List l1 = new ArrayList();
List l2 = new ArrayList();
System.out.println(l1.getClass() == l2.getClass());
System.out.println(“l1.getClass():”+l1.getClass().getName());
System.out.println(“l1.getClass():”+l2.getClass().getName());
}
}
运行结果:
true
l1.getClass():java.util.ArrayList
l1.getClass():java.util.ArrayList
18、Java Object类中的方法
| 方法 | 含义 |
| — | — |
| getClass() | 返回一个对象的运行时类 |
| int hashCode() | 返回该对象的哈希码值 |
| boolean equals(Object obj) | 判断其他对象是否与此对象“相等” |
| String toString() | 返回该对象的字符串表示 |
| void notify() | 唤醒在此对象监视器上等待的单个线程 |
| void notifyAll() | 唤醒在此对象监视器上等待的所有线程 |
| void wait() | 导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法 |
| protected Object clone() | 创建并返回此对象的一个副本 |
| protected void finalize() | 当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法 |
19、Java String类中的方法
20、Java创建对象的5种方式?
①使用new关键字
②使用Class类的newInstance方法
③使用Constructor类的newInstance方法
④使用clone方法
⑤使用反序列化
21、Java访问修饰符的范围
22、Hash冲突的解决方式?
1、开放定址法
当发生冲突时,使用某种探查技术在散列表中形成一个探查序列,沿此序列逐个单元地查找,直到找到一个开放的地址(地址单元为空)或探查序列查找完为止;若探查到开放的地址,则可将待插入的新结点存人该地址单元;若探查序列查找完都没有找到开放的地址,则失败
按照形成探查序列的方法不同,可将开放定址法区分为线性探查法、二次探查法、随机探查法
①线性探查法
②二次探查法
③随机探查法
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
总结
我们总是喜欢瞻仰大厂的大神们,但实际上大神也不过凡人,与菜鸟程序员相比,也就多花了几分心思,如果你再不努力,差距也只会越来越大。实际上,作为程序员,丰富自己的知识储备,提升自己的知识深度和广度是很有必要的。
Mybatis源码解析
(img-8701S3NV-1712087164101)]
[外链图片转存中…(img-rQZGtcio-1712087164102)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-JhtCarww-1712087164102)]
总结
我们总是喜欢瞻仰大厂的大神们,但实际上大神也不过凡人,与菜鸟程序员相比,也就多花了几分心思,如果你再不努力,差距也只会越来越大。实际上,作为程序员,丰富自己的知识储备,提升自己的知识深度和广度是很有必要的。
Mybatis源码解析
[外链图片转存中…(img-Ko3KxVfL-1712087164102)]
[外链图片转存中…(img-NRuHazsZ-1712087164103)]