一、java基础
1.重载和重写的区别
重载: 发生在同一类中,函数名必须一样,参数类型、参数个数、参数顺序、返回值、修饰符可以不一样。
重写: 发生在父子类中,函数名、参数、返回值必须一样,访问修饰符必须大于等于父类,异常要小于等于父类,父类方法是private不能重写。
2.浅拷贝和深拷贝的区别
浅拷贝: 基础数据类型复制值,引用类型复制引用地址,修改一个对象的值,另一个对象也随之改变。
深拷贝: 基础数据类型复制值,引用类型在新的内存空间复制值,新老对象不共享内存,修改一个值,不影响另一个。
深拷贝相对浅拷贝速度慢,开销大。
3.并发和并行
并发: 一个处理器同时处理多个任务。(一个人同时吃两个苹果)
并行: 多个处理器同时处理多个任务。(两个人同时吃两个苹果)
3.同步和异步的区别
- 同步:发出一个调用之后,在没有得到结果之前, 该调用就不可以返回,一直等待。
- 异步:调用在发出之后,不用等待返回结果,该调用直接返回
4.throw 和 throws 的区别
throw:抛出一个异常。
throws:声明一个异常。
5.实例化对象有哪几种方式
① new
② clone()
③ 反射
④先序列化在反序列化
6.序列化和反序列化
- 序列化:序列化是将Java对象转换为字节序列的过程。这一过程使得对象状态能够被写入到磁盘文件中或通过网络传输,从而实现对象的持久化和远程通信。
- 反序列化:反序列化则是将字节序列恢复为Java对象的过程。通过这个过程,可以从文件中读取对象状态或通过网络接收对象状态,实现数据的重构和恢复。
注意:抽象类: abstract关键字修饰的类。
7.什么是自动拆装箱 int和Integer有什么区别
基本数据类型,如int,float,double,boolean,char,byte,不具备对象的特征,不能调用方法。
- 装箱:将基本类型转换成包装类对象
- 拆箱:将包装类对象转换成基本类型的值
java为什么要引入自动装箱和拆箱的功能?主要是用于java集合中,List<Inteter> list=new ArrayList<Integer>();
list集合如果要放整数的话,只能放对象,不能放基本类型,因此需要将整数自动装箱成对象。
8.==和equals区别
==: 基础类型比较的值,引用类型比较的是地址值。
equals: 没有重写比较地址值是否相等,重写比较的内容是否相对。
9.接口与抽象类的区别
-
构造器
- 接口:不能有构造器。
- 抽象类:可以有构造器,通常由子类调用。
-
方法实现
- 接口:在Java 8之前,所有的方法都不能有实现,只能声明。但现在可以包含默认方法。
- 抽象类:可以提供成员方法的实现细节
扩展:普通类是亲爹,手把手教你怎么学,抽象类(多个类具有相同的东西,拿出来放抽象类)是师傅,教你一部分秘籍,然后告诉你怎么学。接口(规范了某些行为)是干爹,只给你秘籍,怎么学全靠你。
10.get和post请求的区别
get相对不安全,数据放在url中(请求行),post放在body中(请求体),相对安全。
get传送的数据量小,post传送的数据量大。
get效率比post高,是form的默认提交方法。
11.sleep和wait区别
- sleep方法
属于Thread类中的方法
释放cpu给其它线程 不释放锁资源
sleep(1000) 等待超过1s被唤醒
- wait方法
属于Object类中的方法
释放cpu给其它线程,同时释放锁资源
wait(1000) 等待超过1s被唤醒
唤醒机制
sleep():自动苏醒,不需要其他线程唤醒。
wait():需要被notify()或notifyAll()方法唤醒。
12.Java中有几种类型的流
Java中有多种类型的流,主要包括字节流和字符流、输入流和输出流、节点流和处理流等分类方式。
- 字节流和字符流
- 字节流:用于处理8位字节的数据传输。主要类型包括
FileInputStream
、BufferedInputStream
和DataInputStream
用于读取数据;FileOutputStream
、BufferedOutputStream
和DataOutputStream
用于写出数据。字节流可以操作任何类型的数据,例如图片、音频或视频文件。 - 字符流:用于处理16位字符的数据传输,主要用来读写文本数据。字符流会自动处理字符编码问题,使得文本文件的处理更为方便。主要类型包括
FileReader
和FileWriter
等。
- 字节流:用于处理8位字节的数据传输。主要类型包括
- 输入流和输出流
- 输入流:数据从外部源流入程序,如从文件或网络读取数据。在Java中,所有继承自
InputStream
和Reader
的流都是输入流。 - 输出流:数据从程序流向外部目标,如写入文件或发送到网络。在Java中,所有继承自
OutputStream
和Writer
的流都是输出流。
- 输入流:数据从外部源流入程序,如从文件或网络读取数据。在Java中,所有继承自
序列化的优点
将对象转为字节流存储到硬盘上,当JVM噶了的话,字节流还会在硬盘上等待,等待下一次JVM的启动,把序列化的对象,通过反序列化为原来的对象,减少储存空间和方便网络传输(因为是二进制)。
13.线程的创建方式
- 继承Thread类创建线程
- 实现Runnable接口创建线程
- 使用Callable和Future创建线程 有返回值
- 使用线程池创建线程
14.泛型是什么?有什么好处?
本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
好处:
①类型安全
②消除强制类型转换
③提高性能
④提高代码的复用性
15.什么是反射
在运行过程中,对于任何一个类都能获取它的属性和方法,任何一个对象都能调用其方法,动态获取信息和动态调用,就是反射
16.为什么浮点数运算的时候会有精度丢失的风险?
这个和计算机保存浮点数的机制有很大关系。我们知道计算机是二进制的,而且计算机在表示一个数字时,宽度是有限的,无限循环的小数存储在计算机时,只能被截断,所以就会导致小数精度发生损失的情况。
BigDecimal
可以实现对浮点数的运算,不会造成精度丢失。通常情况下,大部分需要浮点数精确运算结果的业务场景(比如涉及到钱的场景)都是通过 BigDecimal
来做的。
17.cookie 和Session 的区别
- Cookie 是 web 服务器发送给浏览器的一块信息,浏览器会在本地一个文件中给每个 web 服务器存储 cookie。以后浏览器再给特定的 web 服务器发送请求时,同时会发送所有为该服务器存储的 cookie
- Session 是存储在 web 服务器端的一块信息。session 对象存储特定用户会话所需的属性及配置信息。当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去
- Cookie 和session 的不同点
无论客户端做怎样的设置,session 都能够正常工作。当客户端禁用 cookie 时将无法使用 cookie
在存储的数据量方面:session 能够存储任意的java 对象,cookie 只能存储 String 类型的对象
二、java集合
1.List、Set、Map的区别
List集合有序、可重复的单例集合。
Set集合无序、不可重复的单例集合。
Map集合无序、k不可重复,v可重复的双例集合。
2.集合为什么要用迭代器(Iterator)
更加安全,因为它可以确保,在当前遍历的集合元素被更改的时候,就会抛出 ConcurrentModificationException 异常。
如果不用迭代器,只能for循环,还必须知道集合的数据结构,复用性不强。
3.ArrarList和LinkedList区别
- ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
- 对于随机访问get和set,ArrayList效率优于LinkedList,因为LinkedList要移动指针。
-
对于新增和删除操作add和remove,LinkedList比较占优势,因为ArrayList要移动数据。 这一点要看实际情况的。若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。但若是批量随机的插入删除数据,LinkedList的速度大大优于ArrayList. 因为ArrayList每插入一条数据,要移动插入点及之后的所有数据。
三、多线程
1.start()和run()的区别
start()方法: 是启动线程,调用了之后线程会进入就绪状态,一旦拿到cpu使用权就开始执行run()方法,不能重复调用start(),否则会报异常。
run()方法: 就相当于一个普通的方法而已。直接调用run()方法就还只有一个主线程,还是会顺序执行,也可以重复调用run()方法。
2.什么是线程池,线程池有哪些(创建)
线程池就是事先将多个线程对象放到一个容器中,当使用的时候就不用 new 线程而是直接去池中拿线程即可,节省了开辟子线程的时间,提高的代码执行效率
3.线程池的好处
① 线程是稀缺资源,使用线程池可以减少线程的创建和销毁,每个线程都可重复使用。
② 可以根据系统的需求,调整线程池里面线程的个数,防止了因为消耗内存过多导致服务器崩溃。
4.了解volatile关键字不
- volatile是Java提供的最轻量级的同步机制,保证了共享变量的可见性,被volatile关键字修饰的变量,如果值发生了变化,其他线程立刻可见,避免出现脏读现象。
- volatile禁止了指令重排,可以保证程序执行的有序性,但是由于禁止了指令重排,所以JVM相关的优化没了,效率会偏弱
5.synchronized 是什么?有什么用?
synchronized 是 Java 中的一个关键字,翻译成中文是同步的意思,主要解决的是多个线程之间访问资源的同步性,可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程执行。
6.ThreadLocal 有什么用?
通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。如果想实现每一个线程都有自己的专属本地变量该如何解决呢?
JDK 中自带的ThreadLocal类正是为了解决这样的问题。 ThreadLocal类主要解决的就是让每个线程绑定自己的值,可以将ThreadLocal类形象的比喻成存放数据的盒子,盒子中可以存储每个线程的私有数据。
如果你创建了一个ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的本地副本,这也是ThreadLocal变量名的由来。他们可以使用 get() 和 set() 方法来获取默认值或将其值更改为当前线程所存的副本的值,从而避免了线程安全问题。
再举个简单的例子:两个人去宝屋收集宝物,这两个共用一个袋子的话肯定会产生争执,但是给他们两个人每个人分配一个袋子的话就不会出现这样的问题。如果把这两个人比作线程的话,那么 ThreadLocal 就是用来避免这两个线程竞争的。
7.Java 中 3 种常见 IO 模型
在Java中,三种常见的I/O模型分别是BIO、NIO和AIO
四、jvm
1.java文件的加载过程
.java -> .class -> 类加载器 -> jvm
2.类加载器的作用
将.class文件装载到jvm中,实质就是把文件从硬盘写到内存。
3.双亲委派机制
- 类加载器接收到一个加载请求时,他会委派给他的父加载器,实际上是去他父加载器的缓存中去查找是否有该类,如果有就加载返回,如果没有则继续委派给父类加载,直到顶层类加载器。
- 如果顶层类加载器也没有加载该类,则会依次向下查找子加载器的加载路径,如果有就加载返回,如果都没有,则会抛出异常。