当前位置:网站首页 > Java基础 > 正文

java基础203



1. JDK 和 JRE 有什么区别?

JDK:Java Development Kit 的简称,java 开发工具包,提供了 java 的开发和运行环境,编译器、调试和分析工具等。jdk包含jre。

JRE:Java Runtime Environment 的简称,java 运行时环境,为 java 程序的运行提供了所需环境。jre包含jvm。

2. == 和 equals 的区别是什么?

==对于基本类型和引用类型 == 的作用效果是不同的,基本类型比较的是值是否相同,引用类型:比较的是引用是否相同。

equals是Object类的方法,默认实现就是 ==,只不过 String 和 Integer 等重写了 equals 方法,把它变成了值比较。

3. 两个对象的 hashCode()相同,则 equals()也一定为 true,对吗?

不对,如果,则相同,但如果相同,不需要保证。

但是,为对象生成不同的可能会提高哈希表的性能。

4. final 在 java 中有什么作用?

final 修饰的类不能被继承。

final 修饰的方法(包括静态方法)不能被重写。

final 修饰的变量叫常量,常量必须初始化且不能修改。

5. java 中的 Math.round(-1.5) 等于多少?

等于 -1,因为在数轴上取值时,中间值(0.5)向右取整,所以正 0.5 是往上取整,负 0.5 是直接舍弃。

6. String 属于基础的数据类型吗?

String继承Objcet属于引用类型,但可以直接使用双引号创建String对象而不用new,基础类型有 8 种:byte、boolean、char、short、int、float、long、double。

7. java 中操作字符串都有哪些类?它们之间有什么区别?

操作字符串的类有:String、StringBuffer、StringBuilder。

String 是不可变的字符串,无法对字符串内容进行修改, StringBuffer、StringBuilder 是可变字符串,可以对字符串内容进行修改。

StringBuffer 是线程安全的,StringBuilder 是非线程安全的,StringBuilder 的性能却高于 StringBuffer。

最简便的字符串拼接是使用加号,但性能最好的拼接是使用StringBuilder.append()。

8. String str="i"与 String str=new String("i")一样吗?

不一样,因为内存的分配方式不一样。String str="i"的方式,java 虚拟机会将其分配到常量池中;而 String str=new String("i") 则会被分到堆内存中。

9. 如何将字符串反转?

使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。

10. String 类的常用方法都有那些?

length,equals,indexOf,lastIndexOf,substring,replace,trim,split,getBytes,charAt,toLowerCase,toUpperCase。

11. 抽象类必须要有抽象方法吗?

不一定要有抽象方法。

12. 普通类和抽象类有哪些区别?

抽象类使用abstract修饰,可以包含抽象方法,不能直接实例化,普通类反之。

13. 抽象类能使用 final 修饰吗?

不能,语法错误编译不通过。

14. 接口和抽象类有什么区别?

使用 extends 来继承抽象类,使用 implements 来实现接口。

抽象类可以有构造函数,接口不能有。

抽象类可以有 main 方法,并且我们能运行它,接口不能有 main 方法。

抽象类只能单继承,接口可以多实现。

接口中的方法默认使用 public 修饰,抽象类中的方法可以是任意访问修饰符。

15. java 中 IO 流分为几种?

按功能来分:输入流(input)、输出流(output)。

按类型来分:字节流和字符流。

字节流和字符流的区别是:字节流以字节(8bit)为单位输入输出数据,字符流以字符(多少bit与指定的字符编码有关)为单位输入输出数据。

16. BIO、NIO、AIO 有什么区别?

BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。

NIO:New IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。

AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。

17. Files的常用方法都有哪些?

Files.exists():检测文件路径是否存在。

Files.createFile():创建文件。

Files.createDirectory():创建文件夹。

Files.delete():删除一个文件或目录。

Files.copy():复制文件。

Files.move():移动文件。

Files.size():查看文件个数。

Files.read():读取文件。

Files.write():写入文件。

18. java 容器都有哪些?

常用容器的图录:

java同义词库开源 java的近义词是什么_抽象类

19. Collection 和 Collections 有什么区别?

java.util.Collection 是一个顶级集合接口,它提供了对集合对象进行基本操作的通用接口方法,Java 类库中有很多具体的实现,直接继承接口有List与Set。

Collections则是集合类的一个工具类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作,与Collections对应的是操作数据的工具类Arrays。

20. List、Set、Map 之间的区别是什么?

list有序可重复,set无序不可重复(treeset是自动排序而不是有序),map是键值对,键不能重复。

21. HashMap 和 Hashtable 有什么区别?

最重要的两点:

Hashtable线程安全,HashMap非线程安全,但效率高。

HashMap允许空键值,而Hashtable不允许。

22. 如何决定使用 HashMap 还是 TreeMap?

HashMap使用哈希码增删改查都很快,TreeMap使用红黑二叉树比哈希码慢但会自己排序。

除非需要对map进行排序,否则一律使用HashMap。

23. 说一下 HashMap 的实现原理?

数组(桶)+链表实现。

根据key的哈希值折算成在数组中的下标,如果该下标没有存值,则直接放入该下标,如果该下标已经有值,则在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放入链尾。

JDK 1.8对HashMap的做了优化,当链表中的节点数据超过八个之后,该链表会转为红黑树来提高查询效率。

24. 说一下 HashSet 的实现原理?

HashSet底层由HashMap实现,HashSet的值存放于HashMap的key上,HashMap的value统一为一个常量值。

25. ArrayList 和 LinkedList 的区别是什么?

ArrayList底层的数据结构是数组, LinkedList 的底层数据结构是双向循环链表。

ArrayList 增删慢,查询快,LinkedList 反之。

26. 如何实现数组和 List 之间的转换?

List转换成为数组:调用ArrayList的toArray方法。

数组转换成为List:调用Arrays的asList方法。

27. ArrayList 和 Vector 的区别是什么?

Vector是线程安全的,ArrayList非线程安全但效率要快。

Vector是很古老的类,不建议使用Vector,因为我们可以使用Collections.synchronizedList获取同步列表。

28. 数组和 ArrayList 有何区别?

数组可以存储基本类型也可以存储对象,而ArrayList只能存储对象。

数组创建时必须指定长度,而ArrayList长度不需要指定,可以根据已有数据量自行增加长度。

数组没有ArrayList众多操作列表的方法。

29. 在 Queue 中 poll()和 remove()有什么区别?

poll() 和 remove() 都是从队列中取出一个元素,但是 poll() 在获取元素失败的时候会返回空,但是 remove() 失败的时候会抛出异常。

30. 哪些集合类是线程安全的?

hashtable,vector

31. 迭代器 Iterator 是什么?

迭代器是一种设计模式,用于遍历列表中的对象,开发人员不需要了解该列表的底层结构。

iterator是java里迭代器的一种实现,还有一个迭代器实现是enumeration。

32. Iterator 怎么使用?有什么特点?

Java中的iterator功能比较简单,并且只能单向移动:

(1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。

(2) 使用next()获得序列中的下一个元素。

(3) 使用hasNext()检查序列中是否还有元素。

(4) 使用remove()将迭代器新返回的元素删除。

Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。

33. Iterator 和 ListIterator 有什么区别?

Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。

Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。

ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。

35. 并行和并发有什么区别?

并发:不同代码块交替执行;并行:不同代码块同时执行。

并发编程的目标是充分的利用处理器的每一个核,以达到最高的处理性能。

36. 线程和进程的区别?

进程是操作系统中程序运行和资源分配的基本单位,线程是进程的执行分支,是比进程更小的cpu执行单位,一个进程至少有一个线程,多个线程共享进程的内存资源。

37. 守护线程是什么?

守护线程(daemon thread),是运行在后台服务于其他线程的线程,周期性地执行某种任务或等待处理某些发生的事件。

38. 创建线程有哪几种方式?

1. 继承Thread类重写run方法。

2. 实现Runnable接口实现run方法,并将Runnable接口实现类的实例作为Thread的构造参数。

3. 实现Callable接口实现run方法,并将Callable接口实现实现类的实例作为和FutureTask的构造参数创建FutureTask对象,然后将FutureTask对象作为Thread的构造参数。这种方式可以获取执行的返回值,获取返回值时会阻塞。

 

4.使用线程池。

39. 说一下 runnable 和 callable 有什么区别?

Runnable接口中的run()方法的返回值是void,它做的事情只是纯粹地去执行run()方法中的代码而已;

Callable接口中的call()方法是有返回值的,是一个泛型,和Future、FutureTask配合可以用来获取异步执行的结果。

40. 线程有哪些状态?

传统的线程状态分为五种:创建、就绪、运行、阻塞和死亡。

java线程有六种状态,在java.lang.Thread.State定义,分别是:

1.New/新生(创建),使用new Thread(r)创建一个新线程时,该线程处于新生状态,新生状态会为线程的运行做一些准备。

2.Runnable/可运行(就绪+运行),调用线程的start方法,使该线程处于可运行状态。可运行状态不代表该线程一定在运行,而是它具备运行的条件,它可能正在运行,也可能没有在运行,这完全取决于线程调度控制。

3.Blocked/被阻塞(阻塞),当线程试图获取一个内部的对象锁时,该对象锁被其他线程持有,则该线程进入阻塞状态。

4.Waiting/等待(阻塞),当在调用Object.wait方法、Thread.join方法、java.util.concurrent库中的Lock或Condition时,该线程进入等待状态。

5.Timed waiting/记时等待(阻塞),进入该状态的条件和进入等待状态的条件相同,不过此状态能在指定的时间之后苏醒,所以又有别于等待状态,Thread.sleep(long)和Object.wait(long)方法会使线程进入计时等待状态。

6.Terminated/被终止(死亡),Java没有可直接终止一个线程的方法(stop已经被申明过时不允许使用了,interrrupt方法只是请求中断,不是一定可以中断一个线程),所以只有在程序自然结束或抛出了一个没有捕获的异常时,线程才会进入被终止状态。

使用Thread类的getState()方法可以获取线程状态。

41. sleep() 和 wait() 有什么区别?

sleep():是Thread的静态方法,让调用线程进入休眠,让出执行机会给其他线程,等到休眠时间结束后,线程进入就绪状态和其他线程一起竞争cpu执行。它不能释放锁,当一个synchronized块中调用了sleep() 方法,线程虽然进入休眠,但是锁没有被释放,其他线程依然无法执行该synchronized块代码。调用Thread.sleep一定要捕获java.lang.InterruptedException异常(编译异常)。

wait():wait()本质是一个锁释放自己本身的操作方法,因为任何对象都能作为锁,所以放在了Object类中来。调用wait()一定要放到synchronized代码中,否则会报 IllegalMonitorStateException 异常(运行异常)。可以通过notify,notifyAll方法来唤醒等待的线程。

42. notify()和 notifyAll()有什么区别?

notify()和notifyAll()本质都是一个锁通知在等待自己的线程,notify是通知等待自己的其中一个线程,notifyAll是通知所有等待自己的线程。被通知的线程会进入这个锁的竞争池,优先级高的会优先持有这个锁。

43. 线程的 run()和 start()有什么区别?

start是启动线程的方法,启动线程必须显式调用start,run是具体运行线程代码的线程体,不需要显式调用。

44. 创建线程池有哪几种方式?

①. Executors.newFixedThreadPool(int nThreads)

创建一个固定长度的线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程规模将不再变化,当线程发生未预期的错误而结束时,线程池会补充一个新的线程。

②. Executors.newCachedThreadPool()

创建一个可缓存的线程池,如果线程池的规模超过了处理需求,将自动回收空闲线程,而当需求增加时,则可以自动添加新线程,线程池的规模不存在任何限制。

③. Executors.newSingleThreadExecutor()

这是一个单线程的Executor,它创建单个工作线程来执行任务,如果这个线程异常结束,会创建一个新的来替代它;它的特点是能确保依照任务在队列中的顺序来串行执行。

④. Executors.newScheduledThreadPool(int corePoolSize)

创建了一个固定长度的线程池,而且以延迟或定时的方式来执行任务,类似于Timer。

45. 线程池都有哪些状态?

线程池有5种状态:Running、ShutDown、Stop、Tidying、Terminated。

线程池各个状态切换框架图:

java同义词库开源 java的近义词是什么_抽象类_02

46. java基础203 线程池中 submit()和 execute()方法有什么区别?

submit里面其实就是调用的execute,只不过execute没有返回值,submit将run方法的返回值通过Future返回。

47. 在 java 程序中怎么保证多线程的运行安全?

线程安全在三个方面体现:

原子性:同一时刻只能由一个线程来运行某段代码或操作某个数据,代码原子性可以使用synchronized来保证,数据原子性可以使用atomic相关类来操作。

 

JMM只实现了基本的原子性,保证了对基本数据类型的读取和赋值操作是原子性操作,像上面那样的操作,必须借助于和来保证整块代码的原子性了。线程在释放锁之前,必然会把的值刷回到主存的。

可见性:一个线程对主内存的修改可以及时地被其他线程看到,当一个变量被volatile修饰时,那么对它的修改会立刻刷新到主存,当其它线程需要读取该变量时,会去内存中读取新值。而普通变量则不能保证这一点。其实通过synchronized和Lock也能够保证可见性,线程在释放锁之前,会把共享变量值都刷回主存,但是synchronized和Lock的开销都更大。

有序性

java遵循java内存模型的happens-before原则来保证有序性。

JMM是允许编译器和处理器对指令重排序的,但是规定了as-if-serial语义,即不管怎么重排序,程序的执行结果不能改变。比如下面的程序段:

 

上面的语句,可以按照执行,结果为3.14,但是也可以按照的顺序执行,因为A、B是两句独立的语句,而C则依赖于A、B,所以A、B可以重排序,但是C却不能排到A、B的前面。JMM保证了重排序不会影响到单线程的执行,但无法保证多线程执行结果的正确。

使用volatile可以禁止重排序,可以确保程序的“有序性”,也可以上重量级的synchronized和Lock来保证有序性,它们能保证那一块区域里的代码都是一次性执行完毕的。

48. 多线程锁的升级原理是什么?

在Java中,锁共有4种状态,级别从低到高依次为:无状态锁,偏向锁,轻量级锁和重量级锁状态,这几个状态会随着竞争情况逐渐升级。锁可以升级但不能降级。

锁升级的图示过程:

java同义词库开源 java的近义词是什么_java同义词库开源_03

49. 什么是死锁?

死锁是指两个或两个以上的线程互相持有对方所需要的资源,导致这些线程处于等待状态,都无法继续执行。

死锁不单单发生于多线程,多进程、软件系统甚至人类生活中都可能发生此种情况。

50. 怎么防止死锁?

加锁顺序(线程按照一定的顺序加锁)

当多个线程需要相同的一些锁,但是按照不同的顺序加锁,死锁就很容易发生。

如果能确保所有的线程都是按照相同的顺序获得锁,那么死锁就不会发生。

如果一个线程(比如线程3)需要一些锁,那么它必须按照确定的顺序获取锁。它只有获得了从顺序上排在前面的锁之后,才能获取后面的锁。

例如,线程2和线程3只有在获取了锁A之后才能尝试获取锁C(译者注:获取锁A是获取锁C的必要条件)。因为线程1已经拥有了锁A,所以线程2和3需要一直等到锁A被释放。然后在它们尝试对B或C加锁之前,必须成功地对A加了锁。

按照顺序加锁是一种有效的死锁预防机制。但是,这种方式需要你事先知道所有可能会用到的锁(译者注:并对这些锁做适当的排序),但总有些时候是无法预知的。

加锁时限(线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁)

另外一个可以避免死锁的方法是在尝试获取锁的时候加一个超时时间,这也就意味着在尝试获取锁的过程中若超过了这个时限该线程则放弃对该锁请求。若一个线程没有在给定的时限内成功获得所有需要的锁,则会进行回退并释放所有已经获得的锁,然后等待一段随机的时间再重试。这段随机的等待时间让其它线程有机会尝试获取相同的这些锁,并且让该应用在没有获得锁的时候可以继续运行(加锁超时后可以先继续运行干点其它事情,再回头来重复之前加锁的逻辑)。

ReentrantLock类

死锁检测

死锁检测是一个更好的死锁预防机制,它主要是针对那些不可能实现按序加锁并且锁超时也不可行的场景。

每当一个线程获得了锁,会在线程和锁相关的数据结构中(map、graph等等)将其记下。除此之外,每当有线程请求锁,也需要记录在这个数据结构中。

当一个线程请求锁失败时,这个线程可以遍历锁的关系图看看是否有死锁发生。例如,线程A请求锁7,但是锁7这个时候被线程B持有,这时线程A就可以检查一下线程B是否已经请求了线程A当前所持有的锁。如果线程B确实有这样的请求,那么就是发生了死锁(线程A拥有锁1,请求锁7;线程B拥有锁7,请求锁1)。

当然,死锁一般要比两个线程互相持有对方的锁这种情况要复杂的多。线程A等待线程B,线程B等待线程C,线程C等待线程D,线程D又在等待线程A。线程A为了检测死锁,它需要递进地检测所有被B请求的锁。从线程B所请求的锁开始,线程A找到了线程C,然后又找到了线程D,发现线程D请求的锁被线程A自己持有着。这是它就知道发生了死锁。

一个可行的做法是释放所有锁,回退,并且等待一段随机的时间后重试。这个和简单的加锁超时类似,不一样的是只有死锁已经发生了才回退,而不会是因为加锁的请求超时了。虽然有回退和等待,但是如果有大量的线程竞争同一批锁,它们还是会重复地死锁(原因同超时类似,不能从根本上减轻竞争)。

一个更好的方案是给这些线程设置优先级,让一个(或几个)线程回退,剩下的线程就像没发生死锁一样继续保持着它们需要的锁。如果赋予这些线程的优先级是固定不变的,同一批线程总是会拥有更高的优先级。为避免这个问题,可以在死锁发生的时候设置随机的优先级。

51. ThreadLocal 是什么?有哪些使用场景?

ThreadLocal和Synchronized都是为了解决多线程中相同变量的访问冲突问题,不同的点是

Synchronized是通过线程等待,牺牲时间来解决访问冲突。ThreadLocal是通过每个线程单独一份存储空间,牺牲空间来解决冲突,并且相比于Synchronized,ThreadLocal具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问到想要的值。

正因为ThreadLocal的线程隔离特性,使他的应用场景相对来说更为特殊一些。当某些数据是以线程为作用域并且不同线程具有不同的数据副本的时候,就可以考虑采用ThreadLocal。

但是在线程生命周期很长时使用ThreadLocal存在内存泄露的风险。

52.说一下 synchronized 底层实现原理?

synchronized可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到临界区,同时它还可以保证共享变量的内存可见性(释放锁时,对修改的变量立刻更新到共享内存)。普通同步方法,锁是当前实例对象,静态同步方法,锁是当前类的class对象,同步方法块,锁是括号里面指定的对象。

底层实现非常复杂,目前只了解java对象头里有保存锁相关信息的Mark Word。

任何一个对象都有一个Monitor与之关联,当且一个Monitor被持有后,它将处于锁定状态。Synchronized在JVM里的实现都是 基于进入和退出Monitor对象来实现方法同步和代码块同步,虽然具体实现细节不一样,但是都可以通过成对的MonitorEnter和MonitorExit指令来实现。

  1. MonitorEnter指令:插入在同步代码块的开始位置,当代码执行到该指令时,将会尝试获取该对象Monitor的所有权,即尝试获得该对象的锁;
  2. MonitorExit指令:插入在方法结束处和异常处,JVM保证每个MonitorEnter必须有对应的MonitorExit;

那什么是Monitor?可以把它理解为 一个同步工具,也可以描述为 一种同步机制,它通常被 描述为一个对象

与一切皆对象一样,所有的Java对象是天生的Monitor,每一个Java对象都有成为Monitor的潜质,因为在Java的设计中 ,每一个Java对象自打娘胎里出来就带了一把看不见的锁,它叫做内部锁或者Monitor锁

也就是通常说Synchronized的对象锁,MarkWord锁标识位为10,其中指针指向的是Monitor对象的起始地址。在Java虚拟机(HotSpot)中,Monitor是由ObjectMonitor实现的,其主要数据结构如下(位于HotSpot虚拟机源码ObjectMonitor.hpp文件,C++实现的)。

53. synchronized 和 volatile 的区别是什么?

volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取; synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。

volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的。

volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性。

volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。

volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化。

54. synchronized 和 Lock 有什么区别?

首先synchronized是java内置关键字,Lock是个java类;

synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁;

synchronized会自动释放锁(a 线程执行完同步代码会释放锁 ;b 线程执行过程中发生异常会释放锁),Lock需在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁;

用synchronized关键字的两个线程1和线程2,如果当前线程1获得锁,线程2线程等待。如果线程1阻塞,线程2则会一直等待下去,而Lock锁就不一定会等待下去,如果尝试获取不到锁,线程可以不用一直等待就结束了;

synchronized的锁可重入、不可中断、非公平,而Lock锁可重入、可判断、可公平(两者皆可);

Lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题。

55. synchronized 和 ReentrantLock 区别是什么?

synchronized是和if、else、for、while一样的关键字,ReentrantLock是类,这是二者的本质区别。既然ReentrantLock是类,那么它就提供了比synchronized更多更灵活的特性,可以被继承、可以有方法、可以有各种各样的类变量,ReentrantLock比synchronized的扩展性体现在几点上:

ReentrantLock可以对获取锁的等待时间进行设置,这样就避免了死锁

ReentrantLock可以获取各种锁的信息

ReentrantLock可以灵活地实现多路通知

另外,二者的锁机制其实也是不一样的:ReentrantLock底层调用的是Unsafe的park方法加锁,synchronized操作的应该是对象头中mark word。

56. 说一下 atomic 的原理?

在多线程或者并发环境中,我们常常会遇到这种情况 int i=0; i++ 但这种写法是线程不安全的。
为了达到线程安全的目的,我们通常会用synchronized来修饰对应的代码块,还有一种办法就是使用atomic类。
atomic类通过CAS自旋锁操作volatile变量实现数据操作的原子性。因为加锁或使用 synchronized 关键字带来的性能损耗较大,而用 CAS 可以实现乐观锁,它实际上是直接利用了 CPU 层面的指令,所以性能很高。

57. 什么是反射?

反射主要是指程序运行时可以访问、检测和修改它本身状态或行为的一种能力。

Java反射机制主要提供了以下功能:

在运行时判断任意一个对象所属的类。

在运行时构造任意一个类的对象。

在运行时判断任意一个类所具有的成员变量和方法。

在运行时调用任意一个对象的方法。

58. 什么是 java 序列化?什么情况下需要序列化?

Java序列化是永久保存对象的机制,一个对象被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。把对象变成字节序列叫序列化,把字节序列变成对象叫反序列化。

在一个平台上序列化的对象可以在另一个完全不同的平台上反序列化该对象。类 ObjectInputStream 和 ObjectOutputStream 是高层次的数据流,它们包含反序列化和序列化对象的方法。

要序列化的对象,必须实现Serializable接口。

序列化只能保存实例变量,静态变量无法序列化。

并建议设置版本号:

 

什么情况下需要序列化:

a)把的内存中的对象状态保存到一个文件中或者数据库中时候;
b)用套接字或使用RMI在网络上传输对象的时候;
c)深克隆;

59. 动态代理是什么?有哪些应用?

动态代理是代理模式中一种实现,区别于静态代理。

代理模式由三种角色构成:

抽象角色:通过接口或抽象类声明真实角色实现的业务方法。

代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。

真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。

动态代理和静态代理的区别就在于,静态代理需要自己编写代理角色的代码,而动态代理的代理角色是在程序运行中通过反射自动生成的。

动态代理主要应用在AOP编程中,而AOP编程主要应用在统一的日志、事物、异常、权限等等的处理。

动态代理是AOP编程的实现方式。

60. 怎么实现动态代理?

 

Proxy.newInstance()的工作顺序是根据参数生成class字节码,然后利用加载器加载,并将其实例化产生代理对象,最后返回。

61. 为什么要使用克隆?

对一个对象的多个属性进行修改,需要保留原有的属性值,克隆是便捷的实现途径。

62. 如何实现对象克隆?

实现Cloneable接口并重写Object类中的clone()方法,方法声明可以改为public,克隆自己使用super.clone()。

实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。

63. 深克隆和浅克隆区别是什么?

浅克隆复制当前对象属性的基本类型,和引用类型的引用地址,引用的对象和原属性相同。

深克隆复制当前对象属性的基本类型,和引用类型,引用的对象和原属性不同。

64. jsp 和 servlet 有什么区别?

jsp是特殊的servlet,web容器最终会将jsp编译成servlet。

jsp直接提供jsp文件给web容器,支持运行时修改发布而不用重启web服务器,servlet需要先编译成class文件打包成jar或war,所以任何修改必须重新编译重启web服务器。

jsp专注于页面显示,servlet专注于逻辑控制。

Servlet中没有内置对象,Jsp中的内置对象都是必须通过HttpServletRequest对象,HttpServletResponse对象获取。

65. jsp 有哪些内置对象?作用分别是什么?

JSP有9个内置对象:

request:封装客户端的请求,其中包含来自GET或POST请求的参数;

response:封装服务器对客户端的响应;

pageContext:存储页面相关数据,四大作用域之一的page存取值对象;

session:封装用户会话的对象;

application:封装服务器运行环境的对象;

out:输出服务器响应的输出流对象;

config:Web应用的配置对象;

page:JSP页面本身(相当于Java程序中的this);

exception:封装页面抛出异常的对象。

66. 说一下 jsp 的 4 种作用域?

JSP中的四种作用域包括page、request、session和application,具体来说:

page,在当前页面有效,也就是用户请求的页面有效,当当前页面关闭或转到其他页面时,page对象将在响应回馈给客户端后释放。实际操作的时候是使用pageContext内置对象完成的。

request,在当前请求中有效,request可以通过setAttribute()方法实现页面中的信息传递,也可以通过forward()方法进行页面间的跳转。

session,在当前会话中有效。当一个台电脑上的同一浏览器对服务器进行多次访问时,在这多次访问之间传递的信息就是session作用域的范围。它从浏览器发出第一个HTTP请求即可认为会话开始,但是会话结束的时间是不确定的,因为在浏览器关闭时并不会通知服务器,一般Tomcat设置的默认时间为120分钟,也可以通过setMaxInactiveInterval(int)方法进行设置,或是通过invalidate()方法强制结束当前会话。

application,在所有的应用程序中都有效,也就是当服务器开始到服务器结束这段时间,application作用域中存储的数据都是有效的。

67. session 和 cookie 有什么区别?

session是为了标识访问服务器的用户,cookie是浏览器存储一些本地化数据,这些数据在每次请求时都会发送给服务器,服务器在响应时也可以对cookie进行设置。

session的实现使用到了cookie。

68. 说一下 session 的工作原理?

第一次访问一个网站,网站会返回一个名为sessionid的cookie,里面的值在服务器里是唯一的,浏览器保存这个cookie和它的值到本地,第二次访问这个网站,浏览器会将这个sessionid的cookie发送给服务器,服务器要去所有session池中找这个sessionid,如果找到了,并且时间没有超过设置的失效时间,那么就会认定这个请求和第一个请求是同一个会话。

69. 如果客户端禁止 cookie 能实现 session 还能用吗?

不能,不过可以自己写代码实现类似效果。

70. spring mvc 和 struts2 的区别是什么?

Struts2拦截器是Filter(StrutsPrepareAndExecuteFilter)实现的,SpringMVC核心控制器是Servlet(DispatcherServlet)实现的。

Struts2将请求的参数注入到Action实例的属性,SpringMVC将请求的参数注入到Controller方法的参数。

Struts2每次请求都会创建一个Action实例,SpringMVC的Controller默认是单例的。

SpringMVC和spring是无缝集成,可以直接使用Spring框架里的其他组件。

71. 如何避免 sql 注入?

PreparedStatement(简单又有效的方法)

使用正则等过滤传入的参数。

72. 什么是 XSS 攻击,如何避免?

XSS(Cross Site Script )中文全称叫跨站脚本攻击,类似于 SQL 注入攻击,通过插入恶意脚本,实现对用户游览器的控制,获取用户的一些信息。

拿csdn举例,假设一个用户发表一篇博文,文章内容夹杂有如下代码:

 

在文章发表成功后,其他用户浏览该文章,那么其他用户的用户名等所有cookie信息都将被窃取,除了cookie,xss还能窃取用户其他信息(得看网站把哪些数据放前端了)。

当然,csdn早就处理过xss问题了,上面代码对应的输出是:

 

XSS解决方式是:对输入(和URL参数)进行过滤和转义。

73. 什么是 CSRF 攻击,如何避免?

CSRF(Cross-site request forgery)中文全称叫跨站请求伪造,举例用户访问了网站a,然后访问网站b,网站b在用户不知情的情况,利用用户在网站a的session未过期,伪造成用户向网站a发送请求。常用于盗取账号、转账、发送虚假消息等。

CSRF与XSS非常不同,攻击方式几乎相左。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范。

和重复提交问题有点类似,解决方式也和重复提交一样,通过给关键操作页面设置一个随机码,这个随机码可以放在请求体也可以放在请求头也可以放在url,每次服务器收到关键操作请求,检查这个随机码是否和服务器的一致即可。

除此之外,还可以通过验证请求头的Referer字段判断请求源是否为合法网站,来避免csrf攻击,极端一点可以在关键操作设置图形验证码防止csrf攻击。

74. throw 和 throws 的区别?

throws是声明方法可能抛出的异常类型,throw是抛出的一个具体的异常对象。

75. final、finally、finalize 有什么区别?

final可以修饰类、变量、方法,修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、修饰变量表示该变量是一个常量不能被重新赋值。

finally是异常代码块关键字,用于无论是否异常都需要执行的代码。

finalize是Object类的方法,对象在被垃圾回收时会该方法被调用。

76. try-catch-finally 中哪个部分可以省略?

try必须要有,catch和finally可以省略其中一个。

77. try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?

答:会执行,并且是在catch所有代码执行之后再执行的。如果finally里也有return,那么以finally的return为准,try和catch的return的代码会执行但不会真正返回值,finally里的return才是最终的真正的返回值。

示例:

 

打印:

 

去掉finally里的return的注释:

 

打印:

 

78. 常见的异常类有哪些?

NullPointerException,ClassNotFoundException,ClassCastException,NoSuchMethodException,FileNotFoundException,IOException,NumberFormatException,ParseException,SQLException,ArrayIndexOutOfBoundsException。

79. http 响应码 301 和 302 代表的是什么?有什么区别?

301,302 都是重定向http状态码,区别在于301永久性转移,302暂时性转移。

附http状态码:

继续。客户端应继续其请求

80. forward 和 redirect 的区别?

转发是服务器做出的处理,浏览器并不知情,浏览器地址栏未改变,实际只发送了一次请求;重定向是服务器和浏览器联合做出的处理,服务器将新地址发给浏览器,浏览器重写请求新地址,浏览器地址栏会发生改变,并实际发送了两次请求。

81. 简述 tcp 和 udp的区别?

tcp是基于一对一连接的协议(数据流协议),三次握手建立连接,四次挥手关闭连接,udp是基于无连接广播式的协议(数据报协议)。

tcp保证数据的正确性可靠性,udp不保证数据的正确性和可靠性。

tcp效率低,udp效率高。

82. tcp 为什么要三次握手,两次不行吗?为什么?

只有三次才能验证客户端接收数据的能力有没有问题。

第一次握手是为了验证客户端发送数据的能力,第二次握手是为了验证服务端接收数据和发送数据的能力,第三次握手是为了验证客户端接收数据的能力。在收到客户端发来的第三次握手,服务端才能确认客户端接收数据的能力有没有问题。

83. 说一下 tcp 粘包是怎么产生的?

接收方粘包问题是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。

发送方粘包是由TCP协议本身造成的,TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一个TCP段。若连续几次需要send的数据都很少,通常TCP会根据negal优化算法把这些数据合成一个TCP段后一次发送出去,这样接收方就收到了粘包数据。

附negal优化算法介绍:

会将数据量小的,且时间间隔较短的数据一次性发给对方。

84. OSI 的七层模型都有哪些?

应用层(http,ftp,smtp,pop),表示层。会话层,传输层(tcp,udp),网络层(ip),数据链路层,物理层。

附七层网络模型和四层网络模型对照表:

java同义词库开源 java的近义词是什么_抽象类_04

85. get 和 post 请求有哪些区别?

get参数只能拼接在url上,post可以放url也可以放请求体中。

url长度有限制,所以get参数有限制,post参数放请求体没有大小限制。

get参数放在url上显示在浏览器地址栏不友好不安全,post没有此问题。

get只能接受ASCII字符类型的参数,post不受限制。

get请求在浏览器回退时不会重复提交,post会重复提交。

86. 如何实现跨域?

方式一:

利用img、script、iframe标签的地址不受域名限制的原理,请求跨域的服务。jquery里的jsonp就是用的script标签,而且使用了jquery里的jsonp,那么async只能为true,method只能是get。

方式二:

修改服务器的cors设置,允许指定域名或所有域名访问。

方式三:

在浏览器能请求的服务器上请求跨域的服务,并将服务结果返回给浏览器,从而完成代理访问跨域服务。

其他:

WebSocket支持跨域请求。

修改document.domain跨子域。

window.postMessage(),本质还是利用iframe地址不受域名限制的原理。

88. 说一下你熟悉的设计模式?

单例模式

:类的实例只有一个的设计模式,实现方式是私有化构造方法,提供一个公有的静态方法获取唯一的实例化对象。

线程不安全的写法:

 
 

线程安全的写法:

 
 

观察者模式

对象间一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

观察者模式有两大角色,一个是主题(被观察者、主角),一个是观察者,然后,主题又派生出抽象主题,和实际主题,观察者又派生出抽象观察者和实际观察者。

我个人认为,抽象主题是可以省略。

观察者模式结构图:

java同义词库开源 java的近义词是什么_java面试题_05

观察者模式特别适合事件的通知,比如Swing的各种事件都使用到了观察者模式。

装饰者模式

对已有的业务逻辑进一步的封装,使其增加额外的功能。

与代理模式比较像,但区别在于代理模式是为了隐藏原对象,而装饰模式是为了给原对象增加功能,目的不一样。

代理模式调用方不需要知道原对象,而装饰模式调用方需要自己构造原对象并传入。

Java中的IO流就使用了装饰者模式。

适配器模式

将两种完全不同的事物联系到一起,就像现实生活中的变压器。

适配器模式既可以作为类结构型模式,也可以作为对象结构型模式

java8接口有默认实现,适配器模式作为类适配器已经不需要了。

工厂模式

简单工厂模式

抽象工厂模式:

代理模式

隐藏真实的对象,提供代理对象给调用方调用,代理类和真实对象实现同一个接口,并可以增加新的功能。

和装饰模式很像,但区别在于代理模式是为了隐藏原对象,而装饰模式是为了给原对象增加功能,目的不一样。

代理模式调用方不需要知道原对象,而装饰模式调用方需要自己构造原对象并传入。

89. 简单工厂和抽象工厂有什么区别?

90. 为什么要使用 spring?

spring使用依赖注入实现对调用方与被调用方的解耦,实现对业务对象的统一管理。

spring使用动态代理提供了面向切面编程的能力,事物,异常处理,权限控制,日志处理这些代码都可以与业务类脱离,统一由一个地方处理,避免了冗余代码的出现提升了开发效率。

相对ejb而言,spring是轻量的非侵入式的容器。

91. 解释一下什么是 aop?

AOP是面向切面编程,是面向对象编程的补充。

AOP是为了解决散布在系统中冗余代码,将这些散布的冗余代码统一提构出来,以横切的形式插入执行。

避免了代码的冗余,提升了开发效率,利于系统维护。

92. 解释一下什么是 ioc?

控制反转是影响广泛的设计模式,其主要目的就是为了管理对象之间的关系,为对象之间解除耦合,把对象生命周期的管理和关系的管理这些和对象个体无关的公共任务交给公共容器处理。

控制反转有的好处:每一个模块只专注于它自己的任务;每一个模块都假定自己与其它模块无关,无需操心其它模块是如何实现和做什么的;更换某个模块对其它模块无影响。

依赖注入是容器全权负责组件装配,它把对象传递给需要的对象,依赖注入DI(Dependency Injection)是控制反转IoC(Inversion of Control)的一种实现方式,另一种实现方式是依赖查找。

93. spring 有哪些主要模块?

Spring框架至今已集成了20多个模块。这些模块主要被分如下图所示的核心容器、数据访问/集成,、Web、AOP、工具、消息和测试模块。

java同义词库开源 java的近义词是什么_java同义词库开源_06

94. spring 常用的注入方式有哪些?

xml注入:构造方法注入,set方法注入,属性注入

注解注入:@Autowired、@Inject、@Resource。

附@Autowired、@Inject、@Resource区别:

@Autowired从容器查找时,先匹配类型,再匹配名称,如果匹配到多个则根据beanid来区分(也就是说需要使用@Qualifier),不然会报错。

@Inject和@Autowired查找顺序一致,只是@Inject不能设置required属性,并且@Inject不属于spring,而是jsr-330定义的规范,因此推荐使用@Inject代替@Autowired。

@Resource先查找名称,再查找类型,和@Autowired只是查找顺序不一样,其他都一样。

95. spring 中的 bean 是线程安全的吗?

Spring容器本身并没有提供Bean的线程安全策略,所以spring 中的 bean不是线程安全的。

96. spring 支持几种 bean 的作用域?

singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例

prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例,相当于new

request:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不同的Bean实例。只有在Web应用中使用Spring时,该作用域才有效

session:对于每次HTTP Session,使用session定义的Bean豆浆产生一个新实例。同样只有在Web应用中使用Spring时,该作用域才有效

globalsession:每个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。典型情况下,仅在使用portlet context的时候有效。同样只有在Web应用中使用Spring时,该作用域才有效

其中比较常用的是singleton和prototype两种作用域。对于singleton作用域的Bean,每次请求该Bean都将获得相同的实例。容器负责跟踪Bean实例的状态,负责维护Bean实例的生命周期行为;如果一个Bean被设置成prototype作用域,程序每次请求该id的Bean,Spring都会新建一个Bean实例,然后返回给程序。在这种情况下,Spring容器仅仅使用new 关键字创建Bean实例,一旦创建成功,容器不在跟踪实例,也不会维护Bean实例的状态。

如果不指定Bean的作用域,Spring默认使用singleton作用域。Java在创建Java实例时,需要进行内存申请;销毁实例时,需要完成垃圾回收,这些工作都会导致系统开销的增加。因此,prototype作用域Bean的创建、销毁代价比较大。

97. spring 自动装配 bean 有哪些方式?

spring中可以设置default-autowire属性来控制自动装配的方式,可以设置为byName、byType、constructor和autodetect;

java同义词库开源 java的近义词是什么_java面试题_07

98. spring 事务实现方式有哪些?

spring支持编程式事务和声明式事务两种方式。

编程式事务使用TransactionTemplate或者直接使用底层的PlatformTransactionManager,spring推荐使用TransactionTemplate。

声明式事务建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。

声明式事务管理也有两种常用的方式,一种是基于tx和aop名字空间的xml配置文件,另一种就是基于@Transactional注解。

99. 说一下 spring 的事务隔离?

隔离级别是指若干个并发的事务之间的隔离程度。TransactionDefinition 接口中定义了五个表示隔离级别的常量:

TransactionDefinition.ISOLATION_DEFAULT:这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是TransactionDefinition.ISOLATION_READ_COMMITTED。

TransactionDefinition.ISOLATION_READ_UNCOMMITTED:该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读,不可重复读和幻读,因此很少使用该隔离级别。比如PostgreSQL实际上并没有此级别。

TransactionDefinition.ISOLATION_READ_COMMITTED:该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。

TransactionDefinition.ISOLATION_REPEATABLE_READ:该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。该级别可以防止脏读和不可重复读。

TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

附数据库事物隔离级别:

(1)read uncommitted 读未提交


最低的隔离级别,一个事务可以读到另一个事务未提交的结果,该级别下所有的并发事务问题都会发生。

(2)read committed 读已提交


任何事务只可以读取其他事务已提交的数据,可以解决脏读问题。

(3)repeatable read 可重复读


在一个事务中,对于同一份数据的读取结果总是相同的,无论是否有其他事务对这份数据进行操作,以及这个事务是否提交。该级别可以解决脏读、不可重复读,但存在可能将未提交的记录查询出来,而出现幻读问题。

(4)serializable 可串行化


事务串行化执行(强制排序后按顺序执行),隔离级别最高,该级别下所有的并发事务问题都不会发生,但会导致大量超时现象和锁竞争。

附事务不同隔离级别引发事务并发问题:

br> 如,事务A修改了一个数据,但未提交,事务B读到了事务A未提交的更新结果,如果事务A提交失败,事务B读到的就是脏数据。

br> 如,事务A中执行了两个查询,但在事务A的执行过程中,事务B对要查询的数据进行了修改并提交,此时会造成事务A前面的查询是事务B修改之前的数据,事务A后面的查询是事务B修改之后的数据。

br> 不可重复读出现的原因就是事务并发修改记录,要避免这种情况,最简单的方法就是对要修改的数据加行锁,这会导致锁竞争加剧,影响性能。另一种方法是通过MVCC可以在无锁的情况下,避免不可重复读。

br> 和不可重复度类似,区别在于幻读的关注的是整个表(增删数据),不可重复度关注的是具体的数据(修改数据)。

br> 幻读是由于并发事务增删数据导致的,这个不能像不可重复读通过加行锁解决,因为对于新增的数据根本无法加行锁。需要将事务串行化,或锁表,才能避免幻读。

br>

100. 说一下 spring mvc 运行流程?

img src='https://s2.51cto.com/images/blog//_652fdff6160ae28305.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184' alt='java同义词库开源 java的近义词是什么_java同义词库开源_08' style="width: 796px; visibility: visible;">

101. spring mvc 有哪些组件?

102. @RequestMapping 的作用是什么?

103. @Autowired 的作用是什么?

104. 什么是 spring boot?

105. 为什么要用 spring boot?

br> public class App {

br>        SpringApplication.run(App.class, args);

br>    }

br> }

106. spring boot 核心配置文件是什么?

107. spring boot 配置文件有哪几种类型?它们有什么区别?

108. spring boot 有哪些方式可以实现热部署?

spring-boot-devtools

 

spring loaded

109. jpa 和 hibernate 有什么区别?

110. 什么是 spring cloud?

111. spring cloud 断路器的作用是什么?

112. spring cloud 的核心组件有哪些?

①. 服务发现——Netflix Eureka

②. 客服端负载均衡——Netflix Ribbon

③. 断路器——Netflix Hystrix

④. 服务网关——Netflix Zuul

⑤. 分布式配置——Spring Cloud Config

113. 为什么要使用 hibernate?

114. 什么是 ORM 框架?

115. hibernate 中如何在控制台查看打印的 sql 语句?

 

 

 

116. hibernate 有几种查询方式?

117. hibernate 实体类可以被定义为 final 吗?

118. 在 hibernate 中使用 Integer 和 int 做映射有什么区别?

119. hibernate 是如何工作的?

120. get()和 load()的区别?

121. 说一下 hibernate 的缓存机制?

122. hibernate 对象有哪些状态?

img src='https://s2.51cto.com/images/blog//_652fdff6675c.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184' alt='java同义词库开源 java的近义词是什么_线程池_09' style="width: 675px; visibility: visible;">

123. 在 hibernate 中 getCurrentSession 和 openSession 的区别是什么?

124. hibernate 实体类必须要有无参构造函数吗?为什么?

125. mybatis 中 #{}和 ${}的区别是什么?

126. mybatis 有几种分页方式?

sql分页

RowBounds分页

拦截器分页

128. mybatis 逻辑分页和物理分页的区别是什么?

129. mybatis 是否支持延迟加载?延迟加载的原理是什么?

130. 说一下 mybatis 的一级缓存和二级缓存?

img src='https://s2.51cto.com/images/blog//_652fdff.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184' alt='java同义词库开源 java的近义词是什么_线程池_10' style="width: 796px; visibility: visible;">

img src='https://s2.51cto.com/images/blog//_652fdff6bc.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184' alt='java同义词库开源 java的近义词是什么_java_11' style="width: 635px; visibility: visible;">

131. mybatis 和 hibernate 的区别有哪些?

132. mybatis 有哪些执行器(Executor)?

SimpleExecutor

:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。

ReuseExecutor

:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map内,供下一次使用。简言之,就是重复使用Statement对象。

BatchExecutor

:执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。

133. mybatis 分页插件的实现原理是什么?

134. mybatis 如何编写一个自定义插件?

 

intercept方法:拦截器具体处理逻辑方法

plugin方法:根据签名signatureMap生成动态代理对象

setProperties方法:设置Properties属性

 

135. rabbitmq 的使用场景有哪些?

136. rabbitmq 有哪些重要的角色?

  • 生产者:消息的创建者,负责创建和推送数据到消息服务器;

  • 消费者:消息的接收方,用于处理数据和确认消息;

  • 代理:就是 RabbitMQ 本身,用于扮演“快递”的角色,本身不生产消息,只是扮演“快递”的角色。

  • 137. rabbitmq 有哪些重要的组件?

  • ConnectionFactory(连接管理器):应用程序与Rabbit之间建立连接的管理器,程序代码中使用。

  • Channel(信道):消息推送使用的通道。

  • Exchange(交换器):用于接受、分配消息。

  • Queue(队列):用于存储生产者的消息。

  • RoutingKey(路由键):用于把生成者的数据分配到交换器上。

  • BindingKey(绑定键):用于把交换器的消息绑定到队列上。

  • 138. rabbitmq 中 vhost 的作用是什么?

    139. rabbitmq 的消息是怎么发送的?

    140. rabbitmq 怎么保证消息的稳定性?

  • 提供了事务的功能。

  • 通过将 channel 设置为 confirm(确认)模式。

  • 141. rabbitmq 怎么避免消息丢失?

  • 消息持久化

  • ACK确认机制

  • 设置集群镜像模式

  • 消息补偿机制

  • 142. 要保证消息持久化成功的条件有哪些?

  • 声明队列必须设置持久化 durable 设置为 true.

  • 消息推送投递模式必须设置持久化,deliveryMode 设置为 2(持久)。

  • 消息已经到达持久化交换器。

  • 消息已经到达持久化队列。

  • 143. rabbitmq 持久化有什么缺点?

    144. rabbitmq 有几种广播类型?

  • fanout: 所有bind到此exchange的queue都可以接收消息(纯广播,绑定到RabbitMQ的接受者都能收到消息);

  • direct: 通过routingKey和exchange决定的那个唯一的queue可以接收消息;

  • topic:所有符合routingKey(此时可以是一个表达式)的routingKey所bind的queue可以接收消息;

  • 145. rabbitmq 怎么实现延迟消息队列?

  • 通过消息过期后进入死信交换器,再由交换器转发到延迟消费队列,实现延迟功能;

  • 使用 RabbitMQ-delayed-message-exchange 插件实现延迟功能。

  • 146. rabbitmq 集群有什么用?

  • 高可用:某个服务器出现问题,整个 RabbitMQ 还可以继续使用;

  • 高容量:集群可以承载更多的消息量。

  • 147. rabbitmq 节点的类型有哪些?

  • 磁盘节点:消息会存储到磁盘。

  • 内存节点:消息都存储在内存中,重启服务器消息丢失,性能高于磁盘类型。

  • 148. rabbitmq 集群搭建需要注意哪些问题?

  • 各节点之间使用“--link”连接,此属性不能忽略。

  • 各节点使用的 erlang cookie 值必须相同,此值相当于“秘钥”的功能,用于各节点的认证。

  • 整个集群中必须包含一个磁盘节点。

  • 149. rabbitmq 每个节点是其他节点的完整拷贝吗?为什么?

  • 存储空间的考虑:如果每个节点都拥有所有队列的完全拷贝,这样新增节点不但没有新增存储空间,反而增加了更多的冗余数据;

  • 性能的考虑:如果每条消息都需要完整拷贝到每一个集群节点,那新增节点并没有提升处理消息的能力,最多是保持和单节点相同的性能甚至是更糟。

  • 150. rabbitmq 集群中唯一一个磁盘节点崩溃了会发生什么情况?

  • 不能创建队列

  • 不能创建交换器

  • 不能创建绑定

  • 不能添加用户

  • 不能更改权限

  • 不能添加和删除集群节点

  • 151. rabbitmq 对集群节点停止顺序有要求吗?

    152. kafka 可以脱离 zookeeper 单独使用吗?为什么?

    153. kafka 有几种数据保留的策略?

    154. kafka 同时设置了 7 天和 10G 清除数据,到第五天的时候消息达到了 10G,这个时候 kafka 将如何处理?

    155. 什么情况会导致 kafka 运行变慢?

  • cpu 性能瓶颈

  • 磁盘读写瓶颈

  • 网络瓶颈

  • 156. 使用 kafka 集群需要注意什么?

  • 集群的数量不是越多越好,最好不要超过 7 个,因为节点越多,消息复制需要的时间就越长,整个群组的吞吐量就越低。

  • 集群数量最好是单数,因为超过一半故障集群就不能用了,设置为单数容错率更高。

  • 157. zookeeper 是什么?

    158. zookeeper 都有哪些功能?

  • 集群管理:监控节点存活状态、运行请求等。

  • 主节点选举:主节点挂掉了之后可以从备用的节点开始新一轮选主,主节点选举说的就是这个选举的过程,使用 zookeeper 可以协助完成这个过程。

  • 分布式锁:zookeeper 提供两种锁:独占锁、共享锁。独占锁即一次只能有一个线程使用资源,共享锁是读锁共享,读写互斥,即可以有多线线程同时读同一个资源,如果要使用写锁也只能有一个线程使用。zookeeper可以对分布式锁进行控制。

  • 命名服务:在分布式系统中,通过使用命名服务,客户端应用能够根据指定名字来获取资源或服务的地址,提供者等信息。

  • 159. zookeeper 有几种部署模式?

  • 单机部署:一台集群上运行;

  • 集群部署:多台集群运行;

  • 伪集群部署:一台集群启动多个 zookeeper 实例运行。

  • 160. zookeeper 怎么保证主从节点的状态同步?

    161. 集群中为什么要有主节点?

    162. 集群中有 3 台服务器,其中一个节点宕机,这个时候 zookeeper 还可以使用吗?

    163. 说一下 zookeeper 的通知机制?

    164. 数据库的三范式是什么?

    完全

    依赖主键。

    直接

    依赖主键,不能间接依赖主键。

    id

    ,name,age,dept_id,dept_name,dept_detail)

    165. 一张自增表里面总共有 17 条数据,删除了最后 2 条数据,重启 mysql 数据库,又插入了一条数据,此时 id 是几?

    166. mysql如何获取当前数据库版本?

    167. 说一下 ACID 是什么?

    br> 一个事务包含多个操作,这些操作要么全部执行,要么全都不执行。实现事务的原子性,要支持回滚操作,在某个操作失败后,回滚到事务执行之前的状态。

    br> 事务的一致性指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态(正确的状态)。这种特性称为事务的一致性。假如数据库的状态满足所有的完整性约束,就说该数据库是一致的。

    br> 什么叫正确的状态呢?就是当前的数据满足预定的约束条件就叫做正确的状态。实际上它依赖于应用层来实现,也就是依赖于开发者来实现。数据库是利用AID(特别是A)来支持一致性的,所以说一致性与原子性紧密相关。

    br> 事务可以不同程度的一致性:

    br> 强一致性:读操作可以立即读到提交的更新操作。

    br> 弱一致性:提交的更新操作,不一定立即会被读操作读到,此种情况会存在一个不一致窗口,指的是读操作可以读到最新值的一段时间。

    br> 最终一致性:是弱一致性的特例。事务更新一份数据,最终一致性保证在没有其他事务更新同样的值的话,最终所有的事务都会读到之前事务更新的最新值。如果没有错误发生,不一致窗口的大小依赖于:通信延迟,系统负载等。

    br> 单调一致性:如果一个进程已经读到一个值,那么后续不会读到更早的值。

    br> 会话一致性:保证客户端和服务器交互的会话过程中,读操作可以读到更新操作后的最新值。

    br> 由并发事务所作的修改必须与任何其它并发事务所作的修改隔离。事务查看数据时数据所处的状态,到底是另一个事务执行之前的状态还是中间某个状态,相互之间存在什么影响,是可以通过隔离级别的设置来控制的。

    br> 事务可以不同程度的隔离性(隔离级别):

    br> 读未提交、读已提交、可重复读、可串行化。

    br> 事务结束后,事务处理的结果必须能够得到固化,不可回滚,即写入数据库文件中即使机器宕机数据也不会丢失,它对于系统的影响是永久性的。

    br>

    168. mysql的char 和 varchar 的区别是什么?

    169.mysql的 float 和 double 的区别是什么?

    170. 内连接、左连接、右连接有什么区别?

    171. mysql 索引是怎么实现的?

    172. 怎么验证 mysql 的索引是否满足需求?

    173. 说一下数据库的事务隔离?

    br> 最低的隔离级别,一个事务可以读到另一个事务未提交的结果,该级别下所有的并发事务问题都会发生。

    br> 任何事务只可以读取其他事务已提交的数据,可以解决脏读问题。

    br> 在一个事务中,对于同一份数据的读取结果总是相同的,无论是否有其他事务对这份数据进行操作,以及这个事务是否提交。该级别可以解决脏读、不可重复读,但存在可能将未提交的记录查询出来,而出现幻读问题。

    br> 事务串行化执行(强制排序后按顺序执行),隔离级别最高,该级别下所有的并发事务问题都不会发生,但会导致大量超时现象和锁竞争。

    br> MySQL 支持四种事务隔离级别:read uncommitted、read committed、repeatable read、serializable。

     

    174. 说一下 mysql 常用的引擎?

    175. 说一下 mysql 的行锁和表锁?

    176. 说一下乐观锁和悲观锁?

    177. mysql 问题排查都有哪些手段?

    178. 如何做 mysql 的性能优化?

     

    179. redis 是什么?都有哪些使用场景?

    180. redis 有哪些功能?

  • 数据缓存功能

  • 分布式锁的功能

  • 支持数据持久化

  • 支持事务

  • 支持消息队列

  • 181. redis 和 memecache 有什么区别?

  • memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型

  • redis的速度比memcached快很多

  • redis可以持久化其数据

  • 182. redis 为什么是单线程的?

    183. 什么是缓存穿透?怎么解决?

    184. redis 支持的数据类型有哪些?

    185. redis 支持的 java 客户端都有哪些?

    186. jedis 和 redisson 有哪些区别?

    187. 怎么保证缓存和数据库数据的一致性?

    188. redis 持久化有几种方式?

    189. redis 怎么实现分布式锁?

    190. redis 分布式锁有什么缺陷?

    191. redis 如何做内存优化?

    192. redis 淘汰策略有哪些?

  • volatile-lru:从已设置过期时间的数据集(server. db[i]. expires)中挑选最近最少使用的数据淘汰。

  • volatile-ttl:从已设置过期时间的数据集(server. db[i]. expires)中挑选将要过期的数据淘汰。

  • volatile-random:从已设置过期时间的数据集(server. db[i]. expires)中任意选择数据淘汰。

  • allkeys-lru:从数据集(server. db[i]. dict)中挑选最近最少使用的数据淘汰。

  • allkeys-random:从数据集(server. db[i]. dict)中任意选择数据淘汰。

  • no-enviction(驱逐):禁止驱逐数据。

  • 193. redis 常见的性能问题有哪些?该如何解决?

  • 主服务器写内存快照,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务,所以主服务器最好不要写内存快照。

  • Redis 主从复制的性能问题,为了主从复制的速度和连接的稳定性,主从库最好在同一个局域网内。

  • 194. 说一下 jvm 的主要组成部分?及其作用?

    195. 说一下 jvm 运行时数据区?

    img src='https://s2.51cto.com/images/blog//_652fdff71071c59.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184' alt='java同义词库开源 java的近义词是什么_java面试题_12' style="width: 475px; visibility: visible;">

    196. 说一下堆栈的区别?

    197. 队列和栈是什么?有什么区别?

    198. 什么是双亲委派模型?

  • 启动类加载器(Bootstrap ClassLoader),是虚拟机自身的一部分,用来加载Java_HOME/lib/目录中的,或者被 -Xbootclasspath 参数所指定的路径中并且被虚拟机识别的类库;

  • 其他类加载器:

  • 扩展类加载器(Extension ClassLoader):负责加载<java_home style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; text-size-adjust: none; -webkit-font-smoothing: antialiased; outline: 0px !important;">libext目录或Java. ext. dirs系统变量指定的路径中的所有类库;</java_home>

  • 应用程序类加载器(Application ClassLoader)。负责加载用户类路径(classpath)上的指定类库,我们可以直接使用这个类加载器。一般情况,如果我们没有自定义类加载器默认就是用这个加载器。

  • 199. 说一下类加载的执行过程?

  • 加载:根据查找路径找到相应的 class 文件然后导入;

  • 检查:检查加载的 class 文件的正确性;

  • 准备:给类中的静态变量分配内存空间;

  • 解析:虚拟机将常量池中的符号引用替换成直接引用的过程。符号引用就理解为一个标示,而在直接引用直接指向内存中的地址;

  • 初始化:对静态变量和静态代码块执行初始化工作。

  • 200. 怎么判断对象是否可以被回收?

  • 引用计数器:为每个对象创建一个引用计数,有对象引用时计数器 +1,引用被释放时计数 -1,当计数器为 0 时就可以被回收。它有一个缺点不能解决循环引用的问题;

  • 可达性分析:从 GC Roots 开始向下搜索,搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是可以被回收的。

  • 201. java 中都有哪些引用类型?

  • 强引用

  • 软引用

  • 弱引用

  • 虚引用(幽灵引用/幻影引用)

  • 202. 说一下 jvm 有哪些垃圾回收算法?

  • 标记-清除算法

  • 标记-整理算法

  • 复制算法

  • 分代算法

  • 203. 说一下 jvm 有哪些垃圾回收器?

  • Serial:最早的单线程串行垃圾回收器。

  • Serial Old:Serial 垃圾回收器的老年版本,同样也是单线程的,可以作为 CMS 垃圾回收器的备选预案。

  • ParNew:是 Serial 的多线程版本。

  • Parallel 和 ParNew 收集器类似是多线程的,但 Parallel 是吞吐量优先的收集器,可以牺牲等待时间换取系统的吞吐量。

  • Parallel Old 是 Parallel 老生代版本,Parallel 使用的是复制的内存回收算法,Parallel Old 使用的是标记-整理的内存回收算法。

  • CMS:一种以获得最短停顿时间为目标的收集器,非常适用 B/S 系统。

  • G1:一种兼顾吞吐量和停顿时间的 GC 实现,是 JDK 9 以后的默认 GC 选项。

  • 204. 详细介绍一下 CMS 垃圾回收器?

    205.新生代垃圾回收器和老生代垃圾回收器都有哪些?有什么区别?

  • 新生代回收器:Serial、ParNew、Parallel Scavenge

  • 老年代回收器:Serial Old、Parallel Old、CMS

  • 整堆回收器:G1

  • 206. 简述分代垃圾回收器是怎么工作的?

  • 把 Eden + From Survivor 存活的对象放入 To Survivor 区;

  • 清空 Eden 和 From Survivor 分区;

  • From Survivor 和 To Survivor 分区交换,From Survivor 变 To Survivor,To Survivor 变 From Survivor。

  • 207. 说一下 jvm 调优的工具?

  • jconsole:用于对 JVM 中的内存、线程和类等进行监控;

  • jvisualvm:JDK 自带的全能分析工具,可以分析:内存快照、线程快照、程序死锁、监控内存的变化、gc 变化等。

  • 208. 常用的 jvm 调优的参数都有哪些?

  • -Xms2g:初始化推大小为 2g;

  • -Xmx2g:堆最大内存为 2g;

  • -XX:NewRatio=4:设置年轻的和老年代的内存比例为 1:4;

  • -XX:SurvivorRatio=8:设置新生代 Eden 和 Survivor 比例为 8:2;

  • –XX:+UseParNewGC:指定使用 ParNew + Serial Old 垃圾回收器组合;

  • -XX:+UseParallelOldGC:指定使用 ParNew + ParNew Old 垃圾回收器组合;

  • -XX:+UseConcMarkSweepGC:指定使用 CMS + Serial Old 垃圾回收器组合;

  • -XX:+PrintGC:开启打印 gc 信息;

  • -XX:+PrintGCDetails:打印 gc 详细信息。

  • 上一篇: 基础java后台
  • 下一篇: java基础chm
  • 版权声明


    相关文章:

  • 基础java后台2025-04-22 23:18:06
  • java基础知识总结2025-04-22 23:18:06
  • java基础java标识符2025-04-22 23:18:06
  • java基础学多久2025-04-22 23:18:06
  • java基础课件ppt2025-04-22 23:18:06
  • java基础chm2025-04-22 23:18:06
  • java基础系列详解2025-04-22 23:18:06
  • java基础代码解读2025-04-22 23:18:06
  • java基础小练习2025-04-22 23:18:06
  • java基础语言讲座2025-04-22 23:18:06