Java面试题总结(一)

在这里插入图片描述

1. int和Integer的区别

(1)int是基本数据类型,Integer是int的封装类型;
(2)int可以没有初始值,Integer必须设置初始值;
(3)int默认为0,Integer默认为null;

2. ==和equals的区别

答案:

  • 相同之处:都是对比2个数据是否相同;
  • 不同之处:== 符号可以对比所有数据,而equals()只能被对象调用;== 符号对比变量的值是否相同,所以,基本类型的变量只要字面量相同即返回true,引用类型的变量仅当引用地址相同时才返回true,equals()方法是Object定义的,默认使用 == 实现对比,所以,当该方法没有被重写时,执行效果与 == 相同,如果被重写,则取决于重写的代码,以String类为例,在执行equals()将逐一对比字符串中每个字符,所以,只要2个String对象的字符完全相同,2个String对象使用equals()对比将返回true。
  • 补充说明:由于Java会在编译期处理常量,并且,常量池中的每个常量都是唯一的,所以,当使用字符串常量直接对变量赋值,或使用[-128,127]区间值对Byte/Short/Integer/Long类型的对象赋值时,使用 == 对比的结果也是true。
  • 实际使用原则:在实际编写代码时,对于基本数据类型的变量,必须使用 == 进行对比,因为基本数据类型的变量不可以调用equals()方法;对于引用数据类型的变量,推荐使用equals()进行对比,并且,在有必要的情况下,重写equals()方法,使之返回结果的规则符合当前编写代码的需求,在重写时,至少保证同一个对象的对比结果为true(即:如果 == 对比为true时,则equals()对比返回true)。

3. ArrayList和LinkedList区别

答案:

  • 相同之处:
    • 都是List接口的实现类
      • 都是序列的,可存储相同元素
      • 绝大部分情况下,不关心特有方法
    • 都是线程不安全的
  • 不同之处:
    • ArrayList的底层实现是基于数组的,所以,查询效率高,但修改效率偏低
    • LinkedList的底层实现是基于双向链表的,所以,查询效率偏低,但修改效率高,另外,其内部本质上管理的是多个节点,每个节点需要记录指向前一个节点和后一个节点的引用,占用的存储空间更多
  • 实际使用原则:在使用简单的字符串作为集合元素时,在10万级别的元素数量时,ArrayList和LinkedList的性能差异并不明显(在绝大部分情况下,使用List时的元素数量都不超过100个,尽管元素数据更加复杂),并且,不可以单纯的只读不写,或只写不读,同时,基于ArrayList占用的存储空间更少,一般使用ArrayList即可,仅当需要极致的追求性能时,再根据读写频率来区分使用,但是,当需要考虑线程安全问题时,则使用CopyOnWriteArrayList。

4. HashMap和HashTable的区别

答案:
(1)线程安全性不同:
HashMap 是线程不安全的,HashTable 是线程安全的,其中的方法是 Synchronized 的,在多线程并发的情况下,可以直接使用 HashTable,但是使用 HashMap 时必须自己增加同步处理。
(2)是否提供 contains 方法:
HashMap 只有 containsValue 和 containsKey 方法;HashTable 有 contains、containsKey 和 containsValue 三个方法,其中 contains 和 containsValue 方法功能 相同。
(3)key 和 value 是否允许 null 值:
Hashtable 中,key 和 value 都不允许出现 null 值。HashMap 中,null 可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为 null。
(4)数组初始化和扩容机制:
HashMap 初始化大小是 16 ,扩容因子默认0.75,扩容后为2倍;HashTable默认初始容量为11,扩容后为2倍+1
(5)HashTable 继承自 Dictionary 类,而 HashMap 是Map 接口的一个实现
(6)HashTable 数据结构底层是数组+链表,HashMap数据结构底层是数组+链表+红黑树

5. TreeSet和HashSet的区别

答案:
HashSet 是采用 hash 表来实现的。其中的元素没有按顺序排列,add()、remove()以及 contains()等方法都是复杂度为 O(1)的方法。
TreeSet 是采用树结构实现(红黑树算法)。元素是按顺序进行排列,但是 add()、remove()以及 contains()等方法都是复杂度为 O(log (n))的方法。它还提供 了一些方法来处理排序的 set,如 first(), last(), headSet(), tailSet()等等。

6. String、StringBuffer和StringBuilder的区别

答案:

  • 相同之处:
    • 都是用于处理字符串数据的类
    • 都是管理内部的一个char[]实现的
    • 实现的接口大致相同,特别是CharSequence接口
    • 有许多相同的API,例如replace()、indexOf()等
  • 不同之处:
    • String的字符串操作效率低下,是因为它的“不可变”特性决定的
    • StringBuffer和StringBuilder会保证管理的char[]的长度始终高于实际存入的字符长度,在处理字符串操作时,效率远高于String
    • StringBuffer是线程安全的,而StringBuilder不是
  • 实际使用原则:尽管StringBuffer和StringBuilder在处理字符串时的效率远高于String,但并不是每个String都需要频繁的改变,相比之下,使用String的语法更加简洁、直观,实际占用的存储空间更小,所以,当字符串不需要频繁的改变时,优先使用String。如果字符串需要频繁改变,原则上来说,仅当单线程运行时,或已经采取措施保障线程安全时,优先使用StringBuilder,因为它的执行效率高于StringBuffer,事实上,尽管StringBuilder的执行效率比StringBuffer高,但差距并不大,为了避免后续调整带来的安全隐患,当字符串可能频繁改变时,一般使用StringBuffer

7. 什么是面向对象

面向对象是将现实问题构建关系,然后抽象成类class,给类定义属性和方法后,再将类实例化成实例instance,通过访问实例的属性和调用方法来进行使用。
在不同的语言中,对象的定义范围不同。在Java等静态语言中 一般把类的实例称为对象。

面向对象思想是什么?
java是一门纯粹的面向对象语言,将现实世界的一切事物都看作是对象。一个人是一个对象,汽车、飞机、小鸟都是对象,强调从对象出发

面向对象三大特征:封装、继承、多态

封装就是将对象的属性和行为特征包装到一个类中,封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。要访问该类的代码和数据,必须通过严格的接口控制。

继承:对原有类的扩展,指从已有的类中派生新的类

多态:是在继承的基础上。是指允许不同类的对象对同一消息做出响应,根据对象创建实例的不同调用不同的方法,本质是编译时和运行时才决定对象的行为。例如,子类类型的对象可以赋值给父类类型的引用变量,但运行时仍表现子类的行为特征(在内存中运行的,new的实例)。也就是说,同一种类型的对象执行同一个方法时可以表现出不同的行为特征。

8. Final、Finally、Finalize区别

(1)final可以修饰类、变量、方法

  • 修饰类时,这个类不能被继承。
  • 修饰变量时,这个变量必须赋值,在引用中只能读取不可修改,即为常量;
  • 修饰方法时,这个方法不能被子类重写;

(2)finally:通常放在 try…catch 的后面构造最终执行代码块,这就意味着程序无论正常执行还是发生异常,这里的代码只要 JVM 不关闭都能执行,可以将 释放外部资源的代码写在 finally 块中。
(3)finalize() Object 类中定义的方法,Java 中允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集 器在销毁对象时调用的,通过重写 finalize() 方法可以整理系统资源或者执行其他清理工作。

9. 什么是Java序列化,如何实现Java序列化

答案:
序列化就是一种用来处理对象流的机制,所谓对象流就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可以将流化后的对象传输于网络之间。
序列化的实现:
实现serializable接口,该接口没有需要实现的方法;然后使用一个输出流(FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,然后使用writeObject(Obejct obj)方法就可以将obj写出(即保存其状态),要恢复的话则用输入流。

10. Object中有哪些方法

  • getcode()
  • getClass()
  • toString()
  • equals()
  • finalize()
  • wait()
  • notify()
  • notifyAll()
  • clone()

11. JDK、JRE和JVM的区别和联系

11.1 JDK

JDK(Java Development Kit):

jdk是Java的开发工具包,是整个java开发的核心。
其中主要包含了三方面的内容:

  • Java程序的运行环境-JRE
  • Java的基础类库(Java API)
    Java API是Java的应用程序接口,里面有很多已经写好的Java class,包含一些重要的语法结构和基本的线程、图形和IO等。我们可以直接拿来使用。
  • Java的一些工具包(其中包含了javac源码编译器,还有一些其他的命令:jdb,javah,jmp等)。

在jdk中有很多的文件,其中最主要的就是四个文件:bin、include、jre、lib。

bin:bin目录下有大量的可运行exe文件,其中最主要的就是javac.exe文件,源码编译器。
include:包含一些头文件,用于java和JVM进行交互。
lib:类库。
jre:java程序运行环境。

11.2 JRE

JRE(Java Runtime Environment—java运行环境):

jre是java程序的运行环境,所有的Java程序必须依赖jre才能运行。jre中包含jvm,但是只有jvm是不能完全解释字节码文件的,还需要一些核心的类库。这些类库都存放在jre目录底下的lib文件中。所以jre就包括了两部分:解释字节码的jvm+一些核心类库(存放于lib文件中)

11.3 JVM

JVM(Java Virtual Machine–java虚拟机):

jvm是jre的一部分,jvm是虚拟出的一台计算机,这台计算机不关心java源代码如何写的,它只关心java源程序编译出的字节码文件,jvm是java程序能实现跨平台的核心,它不关心真实计算机,也不关心操作系统等等,就像一个中间平台,只负责将字节码文件转换成当前计算机能理解的CPU指令集或系统调用。jvm有自己完善的硬件架构,如处理器、栈区、寄存器等。
总结:jvm是一个虚拟的中间平台,只负责将编译后的字节码文件转换成当前计算机能理解并执行的指令。jvm是java“一次编译,到处执行”的原因。

11.4 关系图

在这里插入图片描述

11.5 一个Java程序的执行过程

  • 我们利用JDK(通过调用一些Java API)写出java源程序,然后储存在.java文件中。
  • JDK中的源码编译器javac将源代码编译成java字节码,储存在.class文件中。
  • JRE加载、验证、执行Java字节码。
  • JVM将字节码文件解析为机器码映射到CPU指令集或者供系统调用。

12. 普通类和抽象类的区别

抽象类不能被实例化;
抽象类可以有抽象方法,只需申明,无须实现;
有抽象方法的类一定是抽象类;
抽象类的子类必须实现抽象类中的所有抽象方法,否则子类仍然是抽象类;
抽象方法不能声明为静态、不能被static、final修饰。

13. 接口和抽象类的区别

(1)接口
接口使用interface修饰;
接口不能实例化;
类可以实现多个接口;
①java8之前,接口中的方法都是抽象方法,省略了public abstract。②java8之后;接口中可以定义静态方法,静态方法必须有方法体,普通方法没有方法体,需要被实现;
(2)抽象类
抽象类使用abstract修饰;
抽象类不能被实例化;
抽象类只能单继承;
抽象类中可以包含抽象方法和非抽象方法,非抽象方法需要有方法体;
如果一个类继承了抽象类,①如果实现了所有的抽象方法,子类可以不是抽象类;②如果没有实现所有的抽象方法,子类仍然是抽象类。

14. BIO、NIO、AIO 的区别

(1)同步阻塞BIO
一个连接一个线程。
JDK1.4之前,建立网络连接的时候采用BIO模式,先在启动服务端socket,然后启动客户端socket,对服务端通信,客户端发送请求后,先判断服务端是否有线程响应,如果没有则会一直等待或者遭到拒绝请求,如果有的话会等待请求结束后才继续执行。
(2)同步非阻塞NIO
一个请求一个线程。
NIO主要是想解决BIO的大并发问题,BIO是每一个请求分配一个线程,当请求过多时,每个线程占用一定的内存空间,服务器瘫痪了。
JDK1.4开始支持NIO,适用于连接数目多且连接比较短的架构,比如聊天服务器,并发局限于应用中。
(3)异步非阻塞AIO
一个有效请求一个线程。
JDK1.7开始支持AIO,适用于连接数目多且连接比较长的结构,比如相册服务器,充分调用OS参与并发操作。

15. throw 和 throws 的区别

(1)throw
作用在方法内,表示抛出具体异常,由方法体内的语句处理;一定抛出了异常;
(2)throws
作用在方法的声明上,表示抛出异常,由调用者来进行异常处理;可能出现异常,不一定会发生异常;

16. 重载和重写的区别

  • 重载发生在本类,重写发生在父类与子类之间;
  • 重载的方法名必须相同,重写的方法名相同;
  • 重载的参数列表不同,重写的参数列表必须相同。

重载发生在本类,方法名相同,参数列表不同,与返回值无关,只和方法名,参数列表,参数的类型有关。
重载(Overload):首先是位于一个类之中或者其子类中,具有相同的方法名,但是方法的参数不同,返回值类型可以相同也可以不同。
(1):方法名必须相同
(2):方法的参数列表一定不一样
(3):访问修饰符和返回值类型可以相同也可以不同
简单而言:重载就是对于不同的情况写不同的方法。 比如,同一个类中,写不同的构造函数用于初始化不同的参数。

重写发生在父类子类之间,比如所有类都是继承与Object类的,Object类中本身就有equals, hashcode,toString方法等.在任意子类中定义了重名和同样的参数列表就构成方法重写.
重写(override):一般都是表示子类和父类之间的关系,其主要的特征是:方法名相同,参数相同,但是具体的实现不同。

重写的特征:
(1):方法名必须相同
(2):参数列表必须相同
(3):子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为private和final的方法
(4):构造方法不能被重写
(5):派生类方法的访问权限大于或等于超类方法的
(6):派生类方法抛出的异常小于或等于超类方法的
(7):派生类方法的返回值类型小于或等于超类方法的

  • void和基本类型时,必须相等
  • 引用类型时,小于或等于

17. HashSet和HashMap的区别

答案:
1.HashMap实现了Map接口,而HashSet实现了Set接口。
2.HashMap用于存储键值对,而HashSet用于存储对象。
3.HashMap不允许有重复的键,可以允许有重复的值。HashSet不允许有重复元素。
4.HashMap允许有一个键为空,多个值为空,HashSet允许有一个空值。
5.HashMap中使用put()将元素加入map中,而HashSet使用add()将元素放入set中。
6.HashMap比较快,因为其使用唯一的键来获取对象。
在这里插入图片描述

18. List、Map、Set三个接口,存取元素时,各有什么特点?

答案:
1.List特点:元素有顺序,元素可重复
2.Set特点:元素无顺序,元素不可重复(注意:元素虽然无顺序,但是元素在set中的位置是由该元素的HashCode决定的,其位置其实是固定的)
3.Map特点:元素按键值对存储,无顺序,其中key不可重复,value可以重复

19. 队列和栈是什么,列出它们的区别?

答案:
1.队列(Queue)是限定只能在表的一端进行插入和在另一端进行删除操作的线性表。
2.栈(Stack)是限定只能在表的一端进行插入和删除操作的线性表。
队列先进先出(FIFO),栈先进后出(FILO)。

20. 数组和集合的区别

1.数组定义后类型确定,长度固定。集合类型可以不固定,大小是可变的。
2.数组可以存储基本类型和引用类型的数据。集合只能存储引用类型的数据。
3.数组适合做数据个数和类型确定的场景。集合适合做数据个数不确定,且要做增删元素的场景。

21. 线程的run()和start()的区别

  • 关于start()方法:
    • 是用于启动线程的方法
    • 其内部会(自动的)调用run()方法
    • 通常,每个线程对象只能调用1次该方法
  • 关于run()方法:
    • 是在线程启动后(自动的)被调用的方法
    • 用于编写子线程执行的代码
    • 默认的run()方法会尝试调用Runnable对象(如果存在的话)的run()方法,否则,什么都不执行,也不返回任何值
      • 使用Runnable接口时,应该实现run()方法
      • 使用Thread子类时,应该重写run()方法

22. sleep()和wait()的区别

  • sleep()是Thread类中的方法,而wait()则是Object类中的方法。
  • sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
  • 使用范围:wait、notify和notifyAll只能在同步控制方法或者同步控制块里面使用,一旦一个对象调用了wait方法,必须要采用notify()和notifyAll()方法唤醒该进程;而sleep可以在任何地方使用。
  • sleep必须捕获异常,wait,notify和notifyAll不需要捕获异常
  • sleep()方法导致了程序暂停(线程进入睡眠状态),但是它的监控状态依然保持着,当指定的时间到了又会自动恢复到 可运行状态。在调用sleep()方法的过程中,线程不会释放对象锁。
  • wait()方法会导致线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入可运行状态。即wait() 方法被调用后,线程不会自动苏醒,需要别的线程调用同一个对象上的 notify() 或者 notifyAll() 方法。

23. 字节流和字符流的区别

  • 字节流操作的基本单元为字节;字符流操作的基本单元为Unicode码元。
  • 字节流默认不使用缓冲区;字符流使用缓冲区。
  • 字节流在操作的时候本身是不会用到缓冲区的,是与文件本身直接操作的,所以字节流在操作文件时,即使不关闭资源,文件也能输出;字符流在操作的时候是使用到缓冲区的。如果字符流不调用close或flush方法,则不会输出任何内容。
  • 字节流通常用于处理二进制数据,实际上它可以处理任意类型的数据,但它不支持直接写入或读取Unicode码元;字符流通常处理文本数据,它支持写入和读取Unicode码元。
  • 字节流可用于任何类型的对象,包括二进制对象,而字符流只能处理字符或者字符串; 字节流提供了处理任何类型的IO操作的功能,但它不能直接处理Unicode字符,而字符流可以。

24. UNION和UNION ALL的区别

  • union: 对两个结果集进行并集操作, 不包括重复行,相当于distinct, 同时进行默认规则的排序;
    union all: 对两个结果集进行并集操作, 包括重复行, 即所有的结果全部显示;
  • union: 会对获取的结果进行排序操作
    union all: 不会对获取的结果进行排序操作

25. 正向代理和反向代理

正向代理:
当用户想访问某一网址时,用户先访问代理服务器,然后由代理服务器向目标网址发送请求最终将数据返回代理服务器,最后代理服务器将数据返回给用户这一过程我们称之为正向代理。在这里插入图片描述
正向代理它代理了客户端,相当于代理服务器去访问目标网址。

反向代理:
基本流程是与正向代理是相同的,都是通过用户发送请求 -->代理服务器–>目标服务器。但是二者的区别在于正向代理时用户知道自己访问的是代理服务器,而反向代理是无感知的,用户本质上是不知道自己访问的是代理服务器。
在这里插入图片描述
反向代理它代理了目标服务器,让客户感觉自己实际上是在和目标服务器本身进行交互

正向和反向代理的区别:
1、正向代理实际代理的是客户端。反向代理代理的是目标服务器。
2、正向代理是客户端架构,而反向代理是服务器架构。
3、正向代理中,服务器不知道真正的用户是谁。反向代理中,用户不知道真正的服务器是谁。
4、正向代理主要用来解决访问问题。反向代理主要用于解决负载均衡、安全防护,但二者都能提高访问速度。

26. get和post请求的区别

  1. get请求参数是连接在url后面的,而post请求参数是存放在requestbody内的;
  2. get请求因为浏览器对url长度有限制,所以参数个数有限制,而post请求参数个数没有限制;
  3. 因为get请求参数暴露在url上,所以安全方面post比get更加安全;
  4. get请求只能进行url编码,而post请求可以支持多种编码方式;
  5. get请求参数会保存在浏览器历史记录内,post请求并不会;
  6. get请求浏览器会主动cache,post并不会,除非主动设置;
  7. get请求产生1个tcp数据包,post请求产生2个tcp数据包;
  8. 在浏览器进行回退操作时,get请求是无害的,而post请求则会重新请求一次;
  9. 浏览器在发送get请求时会将header和data一起发送给服务器,服务器返回200状态码,而在发送post请求时,会先将header发送给服务器,服务器返回100,之后再将data发送给服务器,服务器返回200 OK;

27. Runnable和Callable的区别

相同点
1、两者都是接口;
2、两者都可用来编写多线程程序;
3、两者都需要调用Thread.start()启动线程;
不同点
1、两者最大的不同点是:实现Callable接口的任务线程能返回执行结果;而实现Runnable接口的任务线程不能返回结果;
2、Callable接口的call()方法允许抛出异常;而Runnable接口的run()方法的异常只能在内部处理,不能继续上抛;

28. Dubbo和Feign的区别

相同点
Dubbo 与 Feign 都依赖注册中心、负载均衡。

区别
1、协议
Dubbo:
支持多传输协议(Dubbo、Rmi、http、redis等等),可以根据业务场景选择最佳的方式。非常灵活。
默认的Dubbo协议:利用Netty,TCP传输,单一、异步、长连接,适合数据量小、高并发和服务提供者远远少于消费者的场景。
Feign:
基于Http传输协议,短连接,不适合高并发的访问。
2、负载均衡
Dubbo:
支持4种算法(随机、轮询、活跃度、Hash一致性),而且算法里面引入权重的概念。
配置的形式不仅支持代码配置,还支持Dubbo控制台灵活动态配置。
负载均衡的算法可以精准到某个服务接口的某个方法。
Feign:
只支持N种策略:轮询、随机、ResponseTime加权。
负载均衡算法是Client级别的。
3、容错策略
Dubbo:
支持多种容错策略:failover、failfast、brodecast、forking等,也引入了retry次数、timeout等配置参数。
Feign:
利用熔断机制来实现容错的,处理的方式不一样。

29. Iterator 和 ListIterator 的区别

(1)ListIterator 继承 Iterator
(2)ListIterator 比 Iterator多方法

  1. add(E e) 将指定的元素插入列表,插入位置为迭代器当前位置之前
  2. set(E e) 迭代器返回的最后一个元素替换参数e
  3. hasPrevious() 迭代器当前位置,反向遍历集合是否含有元素
  4. previous() 迭代器当前位置,反向遍历集合,下一个元素
  5. previousIndex() 迭代器当前位置,反向遍历集合,返回下一个元素的下标
  6. nextIndex() 迭代器当前位置,返回下一个元素的下标

(3)使用范围不同,Iterator可以迭代所有集合;ListIterator 只能用于List及其子类

  1. ListIterator 有 add 方法,可以向 List 中添加对象;Iterator 不能
  2. ListIterator 有 hasPrevious() 和 previous() 方法,可以实现逆向遍历;Iterator不可以
  3. ListIterator 有 nextIndex() 和previousIndex() 方法,可定位当前索引的位置;Iterator不可以
  4. ListIterator 有 set()方法,可以实现对 List 的修改;Iterator 仅能遍历,不能修改。

30. jsp 和 servlet 的区别

(1)servlet是服务器端的Java程序,它担当客户端和服务端的中间层。
(2)jsp全名为Java server pages,中文名叫Java服务器页面,其本质是一个简化的servlet设计。JSP是一种动态页面设计,它的主要目的是将表示逻辑从servlet中分离出来。
(3)JVM只能识别Java代码,不能识别JSP,JSP编译后变成了servlet,web容器将JSP的代码编译成JVM能够识别的Java类(servlet)。
(4)JSP有内置对象、servlet没有内置对象。

31. session 和 cookie 的区别

(1)存储位置不同

  • cookie在客户端浏览器;
  • session在服务器;

(2)存储容量不同

  • cookie<=4K,一个站点最多保留20个cookie;
  • session没有上线,出于对服务器的保护,session内不可存过多东西,并且要设置session删除机制;

(3)存储方式不同

  • cookie只能保存ASCII字符串,并需要通过编码方式存储为Unicode字符或者二进制数据;
  • session中能存储任何类型的数据,包括并不局限于String、integer、list、map等;

(4)隐私策略不同

  • cookie对客户端是可见的,不安全;
  • session存储在服务器上,安全;

(5)有效期不同

  • 开发可以通过设置cookie的属性,达到使cookie长期有效的效果;
  • session依赖于名为JESSIONID的cookie,而cookie JSESSIONID的过期时间默认为-1,只需关闭窗口该session就会失效,因而session达不到长期有效的效果;

(6)跨域支持上不同

  • cookie支持跨域;
  • session不支持跨域;

32. 重定向和请求转发的区别

重定向:客户端重新发送新的请求,无法request携带数据。地址栏会发生改变。
请求转发: 地址栏不会发生改变,在服务器端完成,效率高 使用request携带数据。

1.请求转发是服务器行为、重定向是客户端浏览器行为
2.请求转发是request对象调用方法、重定向是response对象调用方法
3.请求转发只有一次请求所以可以实现request域对象中的数据共享,而重定向是多次请求、多次响应
4.请求转发的效率要高于重定向
5.请求转发url地址栏不变,而重定向会发生变化
6.既然请求转发是服务器内部的行为,所以只能访问服务器内部资源!而重定向既然是浏览器行为,地址栏会变,所以可以访问服务器外部资源!
7.请求转发两次跳转之间传输的信息不会丢失,重定向两次跳转之间传输的信息会丢失(request范围);

如果既想要实现路径跳转,又需要实现数据共享,使用请求转发!
如果只是纯粹的想要实现路径跳转,我们可以使用重定向!

33. TCP 和 UDP 的区别

1.TCP是传输控制协议,UDP是用户数据表协议;
2.TCP长连接,UDP无连接;
3.UDP程序结构较简单,只需发送,无须接收;
4.TCP可靠,保证数据正确性、顺序性;UDP不可靠,可能丢数据;
5.TCP适用于少量数据,UDP适用于大量数据传输;
6.TCP速度慢,UDP速度快;

34. Dubbo 和 Spring Cloud区别

1、通信方式不同:Dubbo 使用的是 RPC 通信,而Spring Cloud 使用的是HTTP RESTFul方式。
2、组成不一样:

  • dubbo的服务注册中心为Zookeerper,服务监控中心为dubbo-monitor,无消息总线、服务跟踪、批量任务等组件;
  • Spring Cloud的服务注册中心为spring-cloud netflix enruka,服务监控中心为spring-boot admin,有消息总线、数据流、服务跟踪、批量任务等组件;

35. continue和 break有什么区别?

答案:
break和continue都是用来控制循环结构的。
1.break:提前终止循环可以使用break来完成。break完全结束一个循环,跳出循环体执行循环后面的语句。
2.continue:理解为continue是跳过当次循环中剩下的语句,执行下一次循环。
3.区别:continue只终止本次循环,break则完全终止循环

36. i++和++i的区别?

1.i++ 理解为:先用i值后加1, 比如int j=i++; 如果i的初值是1,那么表达式i++的整体值就是1,然后,i的值就变成了2,最后执行赋值运算,将i++整体的值1,赋值给j,j为1。
2.++i 理解为:先加1后用i值,比如int j=++i;如果i的初值是1,首先i增加1为2,然后用i的值2作为++i整体表达式的值,最后进行赋值运算,将++i表达式的值2赋值给j,j为2。
注意:这两个表达式在计算时,=号赋值计算,都是最后发生的,是非常常见的考点。

37. java的8种基本数据类型是什么?(简述java的8种基本数据类型)

答:八种基本数据类型包括:byte,short,int,long,float,double,boolean,char
1)byte:字节型,用于存储整数,占用1个字节,范围-128到127
2)short:短整型,用于存储整数,占用2个字节,范围-32768到32767
3)int:整型,用于存储整数,占用4个字节,范围-2^31~ 2^31 -1
4)long:长整型,用于存储整数,占用8个字节,范围-2^63~ 2^63 -1
5)float:单精度浮点型,用于存储小数,占用4个字节,不能表示精确的值
6)double:双精度浮点型,用于存储小数,占用8个字节,不能表示精确的值
7)boolean:布尔型,用于存储true或false,占用1个字节
8)char:字符型,采用Unicode编码格式,用于存储单个字符,占用2个字节

38. @Autowired和@Resource的区别

  • 相同之处:
    • 都可以实现自动装配
    • 都可以用于属性或Setter方法,以实现装配
  • 不同之处:
    • @Autowired是Spring框架中定义的注解,@Resource是javax包中的注解
    • @Autowired可用于构造方法,@Resource不可以
    • 当Spring容器中存在多个相同类型的对象,在自动注入时,需要根据名称匹配,使用@Autowired必须结合@Qualifer注解以指定Bean id/name,用于属性时,在属性的声明之前同时添加这2个注解,用于方法时,在方法的声明之前添加@Autowired,在方法的参数之前添加@Qualifier注解,而使用@Resource时则是配置该注解的name属性
    • @Autowired是先尝试根据类型装配,在尝试根据名称进行装配
    • 先查找匹配类型的对象的数量
      • 1个:直接装配
      • 0个:判断@Autowired的required属性
        • true:抛出异常
        • false:不装配,即属性值为null
      • 超过1个:尝试根据名称装配
        • 存在符合的对象:装配
        • 不存在符合的对象:抛出异常
    • @Resource是先尝试根据名称装配,再尝试根据类型装配
      • 能装配,则装配,最后仍装配不了,则抛出异常
  • 实际使用原则:
    • 由于自动装配是Spring的机制,@Autowired也是Spring的注解,所以,优先使用@Autowired实现装配,而@Resource注解是javax包中的,则不优先考虑
    • 应该为类添加带参数的构造方法,用于为各个需要注入值的属性赋值,并且保证这是类中唯一的构造方法,或在构造方法的声明之前添加@Autowired注解,则Spring会自动调用它,这样做客以避免单元测试时出现NPE(NullPointerException)问题
    • 如果在Spring容器中存在多个与需要装配的属性的类型相同的对象,应该结合@Qualifier注解一起使用,以显式的指定Bean id/name
    • 在追求编写代码的便利性时,可能会在属性声明之前使用@Autowired注解,以实现自动装配,如果要装配的是持久层(存储层)接口类型的对象,并且该接口对象是框架自动生成的,应该在接口的声明之前添加@Repository注解,以避免某些版本的IntelliJ IDEA报错

39. 什么是hashCode?

  • hashCode()是Object定义的方法,它将返回一个整型值,它并不代表对象在内存中的地址,它存在的价值是为Hash容器处理数据时提供支持,Hash容器可以根据hashCode定位需要使用的对象,也可以根据hashCode来排除2个不相同的对象,即:hashCode不同,则视为2个对象不同。
  • 在重写hashCode()时,应遵循Java SE的官方指导:
    • 如果2个对象使用equals()对比的结果为true,则这2个对象的hashCode()返回的结果应该相同
    • 如果2个对象使用hashCode()对比的结果为false,则这2个对象的hashCode()返回的结果应该不同
    • 通常,你不必关心如何重写equals()方法和hashCode()方法,而是使用IDE生成,例如Eclipse、IntelliJ IDEA,它们生成的方法是符合以上指导意见的。

40. 什么是volatile?

  • 关于volatile:
    • 它是一个关键字,用于修饰类的成员
    • 它的主要作用有:
      • 禁止指令重排
      • 确保多线程时属性的可见性
  • synchronized和volatile均不可替代彼此,虽然两者都是用于解决多线程相关问题的,但问题的情景并不相同,通常,使用synchronized解决的问题大多是“多个线程执行相同的代码”的情景,而使用volatile解决的问题大多是“多个线程执行的代码不同,但使用到了相同的共享变量”的情景
  • 实际使用原则:当某个属性出现在多个方法中,至少有1个方法会改变改属性的值,且这些方法可能同时被不同的线程执行,则应该为属性添加volatile关键字。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值