java遇到过的面试题

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: java、面试题。记录下自己之前面试复习,以及遇到过的面试题

基础面试题大全 :

1. 面向对象的特征 :

封装 、 继承 、抽象 、 多态

封装 : 面向对象的本质就是把世界万物封装成一系列的完全自治、自闭的对象,在JAVA当中的体现就是数据和操作数据的方法绑定起来。

封装就是隐藏。

继承 : 继承是从已有类得到继承信息创建新类的过程。 继承和抽象类2者区别。

抽象 : 抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象。

多态 : 多态性是指允许不同子类型的对象对同一消息作出不同的响应。

简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。

多态性分为编译时的多态性和运行时的多态性。

方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。

2. 几个访问修饰符的范围 ?

修饰符 当前类 同 包 子 类 其他包

public √ √ √ √

protected √ √ √ ×

default √ √ × ×

private √ × × ×

3. 基本类型 ?

8个:byte、short、int、long、float、double、char、boolean;

枚举类型也算是一种比较特殊的引用类型。

byte 8位 -128~127

short 16位 最小值是-32768(-2^15); 最大值是32767(2^15 - 1);

int 32位 最小值是-2,147,483,648(-2^31) 最大值是2,147,485,647(2^31 - 1)

long 64位

小数类型 :

float 单精度、32位 double 双精度、64位

char 16位Unicode字符

4. float f=3.4;是否正确?

不正确。3.4是双精度数,将双精度型(double)赋值给浮点型(float)属于下转型(down-casting,也称为窄化)会造成精度损失,

因此需要强制类型转换float f =(float)3.4; 或者写成float f =3.4F;。

在java里面,没小数点的默认是int,有小数点的默认是 double;

5. BigDecimal 会比较精度

BigDecimal a = new BigDecimal("2.00");

BigDecimal b = new BigDecimal("2.0");

System.out.println(a.equals(b)); // false

System.out.println(a.compareTo(b) == 0); // true

6. short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗?

s1 = s1 + 1 -》 1是int类型,要强转才能给s1 ; s1 += 1 是正确的。

7. JAVA 中有没有GOTO -》 有 ,保留字

8. int 和 integer 有什么区别 ?

int 的包装类型 是 integer 。

Java 为每个原始类型提供了包装类型:

- 原始类型: boolean,char,byte,short,int,long,float,double

- 包装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double

拆箱和装箱 :

Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150; 装箱就是说当我们给一个Integer对象赋一个int值的时候,会调用Integer类的静态方法valueOf

System.out.println(f1 == f2); // 虽然 == 比较的是引用,但是 -127~128 是有缓存的,这里是true

System.out.println(f3 == f4); // 这里是false

9. &和&&的区别

&运算符有两种用法:(1)按位与;(2)逻辑与。&&运算符是短路与运算。 &&和& 都是是左右2边都成立才成真,但是 && 是个短路的,只要第一个不成立就不会判断

第二个,所以很大可能不会出现NPE。

| 跟 || 也是这个差别。

10. 栈(stack)、堆(heap)和方法区(method area)的用法

栈 : 基本数据类型 、 引用 、函数调用的现场 ——》 空间不足的话,stackOverflowError

堆 : 对象的值基本都把保存在堆上,堆也是垃圾回收的主要场所 --> 空间不足的话, OOM

方法区和堆都是各个线程共享的内存区域,用于存储已经被JVM加载的类信息、常量、静态变量、JIT编译器编译后的代码等数据;

程序中的字面量(literal)如直接书写的100、"hello"和常量都是放在常量池中,常量池是方法区的一部分

String str = new String("hello"); -》 str放在栈上, new 的字符串变量放在堆上, hello 字面量放在方法区上

10、Math.round(11.5) 等于多少?Math.round(-11.5)等于多少?

答:Math.round(11.5)的返回值是12,Math.round(-11.5)的返回值是-11。四舍五入的原理是在参数上加0.5然后进行下取整。

11、switch 是否能作用在byte 上,是否能作用在long 上,是否能作用在String上?

答:在Java 5以前,switch(expr)中,expr只能是byte、short、char、int。从Java 5开始,Java中引入了枚举类型,expr也可以是enum类型,

从Java 7开始,expr还可以是字符串(String),但是长整型(long)在目前所有的版本中都是不可以的。

12、用最有效率的方法计算2乘以8?

答: 2 << 3(左移3位相当于乘以2的3次方,右移3位相当于除以2的3次方)。

13、数组有没有length()方法?String有没有length()方法?

答:数组没有length()方法,有length 的属性。String 有length()方法。JavaScript中,获得字符串的长度是通过length属性得到的,这一点容易和Java混淆。

15、构造器(constructor)是否可被重写(override)?

答:构造器不能被继承,因此不能被重写,但可以被重载。

16、两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?

不对,如果两个对象x和y满足x.equals(y) == true,它们的哈希码(hash code)应当相同。

(1)如果两个对象相同(equals方法返回true),那么它们的hashCode值一定要相同;(2)如果两个对象的hashCode相同,它们并不一定相同。

17、是否可以继承String类?

答:String 类是final类,不可以被继承。

18、当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?

答:是值传递。Java语言的方法调用只支持参数的值传递。 ——》 值传递

19、String和StringBuilder、StringBuffer的区别?

String引用的字符串内容是不能被改变的。而StringBuffer/StringBuilder类表示的字符串对象可以直接进行修改

StringBuilder是Java 5中引入的,它和StringBuffer的方法完全相同,区别在于它是在单线程环境下使用的,

因为它的所有方面都没有被synchronized修饰,因此它的效率也比StringBuffer要高。

20、 为什么不能根据返回类型来区分重载 -》 根据参数来区分的

同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载; 所以不能根据返回类型区分重载。

21、描述一下JVM加载class文件的原理机制?

JVM中类的装载是由类加载器(ClassLoader)和它的子类来实现的,Java中的类加载器是一个重要的Java运行时系统组件,它负责在运行时查找和装入类文件中的类。

由于Java的跨平台性,经过编译的Java源程序并不是一个可执行程序,而是一个或多个类文件。

当Java程序需要使用某个类时,JVM会确保这个类已经被加载、连接(验证、准备和解析)和初始化。

由于Java的跨平台性,经过编译的Java源程序并不是一个可执行程序,而是一个或多个类文件。

加载 ; 类的加载是指把类的.class文件中的数据读入到内存中,通常是创建一个字节数组读入.class文件,然后产生与所加载类对应的Class对象。

连接 : 加载完成后,Class对象还不完整,所以此时的类还不可用。当类被加载后就进入连接阶段,这一阶段包括验证、准备(为静态变量分配内存并设置默认的初始值)

和解析(将符号引用替换为直接引用)三个步骤。

初始化 : 1)如果类存在直接的父类并且这个类还没有被初始化,那么就先初始化父类;

2)如果类中存在初始化语句,就依次执行这些初始化语句。

类的加载是由类加载器完成的,类加载器包括:根加载器(BootStrap)、扩展加载器(Extension)、

系统加载器(System)和用户自定义类加载器(java.lang.ClassLoader的子类)。

22、char 型变量中能不能存贮一个中文汉字,为什么?

char -> 2个字节 16个比特 ,可以存一个汉字

23. 抽象类(abstract class)和接口(interface)有什么异同 ?

抽象类和接口都不能够实例化,但可以定义抽象类和接口类型的引用。

接口比抽象类更加抽象,因为抽象类中可以定义构造器,可以有抽象方法和具体方法,而接口中不能定义构造器而且其中的方法全部都是抽象方法。

抽象类中的成员可以是private、默认、protected、public的,而接口中的成员全都是public的。

抽象类中可以定义成员变量,而接口中定义的成员变量实际上都是常量。 接口只能定义final

有抽象方法的类必须被声明为抽象类,而抽象类未必要有抽象方法。

24. 通常的内部类需要在外部类实例化后才能实例化

25、Java 中会存在内存泄漏吗,请简单描述。

理论上Java因为有垃圾回收机制(GC)不会存在内存泄露问题(这也是Java被广泛使用于服务器端编程的一个重要原因);

然而在实际开发中,可能会存在无用但可达的对象,这些对象不能被GC回收,因此也会导致内存泄露的发生。

-》 无用不可达会被回收,但是无用却可达就是内存泄露

26、抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被synchronized修饰?

都不能。抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。本地方法是由本地代码(如C代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。

synchronized和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。

27、阐述静态变量和实例变量的区别。

答:静态变量是被static修饰符修饰的变量,也称为类变量,它属于类,不属于类的任何一个对象,一个类不管创建多少个对象,

静态变量在内存中有且仅有一个拷贝;实例变量必须依存于某一实例,需要先创建对象然后通过对象才能访问到它。静态变量可以实现让多个对象共享内存。

28、是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用?

不可以,静态方法只能访问静态成员,因为非静态方法的调用要先创建对象,在调用静态方法时可能对象并没有被初始化。

29. 如何实现对象克隆?

有两种方式:

1). 实现Cloneable接口并重写Object类中的clone()方法;

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

30、GC是什么?为什么要有GC?

GC是垃圾收集的意思,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。

要请求垃圾收集,可以调用下面的方法之一:System.gc() 或Runtime.getRuntime().gc() ,但JVM可以屏蔽掉显示的垃圾回收调用。

垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。

垃圾回收器通常是作为一个单独的低优先级的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,

程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。

31. 垃圾回收机制:

分代复制垃圾回收、标记垃圾回收、增量垃圾回收等方式。

Java平台对堆内存回收和再利用的基本算法被称为标记和清除。

在垃圾收集过程中,可能会将对象移动到不同区域:

- 伊甸园(Eden):这是对象最初诞生的区域,并且对大多数对象来说,这里是它们唯一存在过的区域。

- 幸存者乐园(Survivor):从伊甸园幸存下来的对象会被挪到这里。

- 终身颐养园(Tenured):这是足够老的幸存对象的归宿。年轻代收集(Minor-GC)过程是不会触及这个地方的。

当年轻代收集不能把对象放进终身颐养园时,就会触发一次完全收集(Major-GC),这里可能还会牵扯到压缩,以便为大对象腾出足够的空间。

JVM参数:

-Xms / -Xmx — 堆的初始大小 / 堆的最大大小

-Xmn — 堆中年轻代的大小

-XX:-DisableExplicitGC — 让System.gc()不产生任何作用

-XX:+PrintGCDetails — 打印GC的细节

-XX:+PrintGCDateStamps — 打印GC操作的时间戳

32. String s = new String("xyz");创建了几个字符串对象?

答:两个对象,一个是静态区的"xyz",一个是用new创建在堆上的对象。 所以这里创造了2个对象。

这个跟JAVA 当中的 String 机制有关,

ava中为了节省内存空间和运行时间(如比较字符串时,==比equals()快),在编译阶段就把所有的字符串文字放到一个文字池(pool of literal strings)中,

而运行时文字池成为常量池的一部分。文字池的好处,就是该池中所有相同的字符串常量被合并,只占用一个空间。

33. 接口是否可继承(extends)接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concrete class)?

答:接口可以继承接口,而且支持多重继承。抽象类可以实现(implements)接口,抽象类可继承具体类也可以继承抽象类。

33、一个".java"源文件中是否可以包含多个类(不是内部类)?有什么限制?

答:可以,但一个源文件中最多只能有一个公开类(public class)而且文件名必须和公开类的类名完全保持一致。

34、Anonymous Inner Class(匿名内部类)是否可以继承其它类?是否可以实现接口?

答:可以继承其他类或实现其他接口,在Swing编程和Android开发中常用此方式来实现事件监听和回调。

35、内部类可以引用它的包含类(外部类)的成员吗?有没有什么限制?

答:一个内部类对象可以访问创建它的外部类对象的成员,包括私有成员。

36、Java 中的final关键字有哪些用法?

答:(1)修饰类:表示该类不能被继承;(2)修饰方法:表示方法不能被重写;(3)修饰变量:表示变量只能一次赋值以后值不能被修改(常量)。

40、怎样将GB2312编码的字符串转换为ISO-8859-1编码的字符串?

String s2 = new String(s1.getBytes("GB2312"), "ISO-8859-1");

41. 获取当前时间

LocalDateTime dt = LocalDateTime.now();

System.out.println(dt.getYear());

System.out.println(dt.getMonthValue()); // 1 - 12

System.out.println(dt.getDayOfMonth());

System.out.println(dt.getHour());

System.out.println(dt.getMinute());

System.out.println(dt.getSecond());

42. 获取毫秒数

Calendar.getInstance().getTimeInMillis();

System.currentTimeMillis();

Clock.systemDefaultZone().millis(); // Java 8

44、什么时候用断言(assert)?

断言用于保证程序最基本、关键的正确性。断言检查通常在开发和测试时开启。

在执行这个语句时假定该表达式为true;如果表达式的值为false,那么系统会报告一个AssertionError。

45、Error和Exception有什么区别?

Error表示系统级的错误和程序不必处理的异常,是恢复不是不可能但很困难的情况下的一种严重问题;比如内存溢出,不可能指望程序能处理这样的情况;

Exception表示需要捕捉或者需要程序进行处理的异常,是一种设计或实现问题

46、try{}里有一个return语句,那么紧跟在这个try后的finally{}里的代码会不会被执行,什么时候被执行,在return前还是后?

答:会执行,在方法返回调用者前执行。

48、运行时异常与受检异常有何异同?

异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误,只要程序设计得没有问题通常就不会发生。

受检异常跟程序运行的上下文环境有关,即使程序设计无误,仍然可能因使用的问题而引发。比如File文件类的操作异常。

49、列出一些你常见的运行时异常?

答:

- ArithmeticException(算术异常)

- ClassCastException (类转换异常)

- IllegalArgumentException (非法参数异常)

- IndexOutOfBoundsException (下标越界异常)

- NullPointerException (空指针异常)

- SecurityException (安全异常)

50、阐述final、finally、finalize的区别。

final不多说,finally也不多说,

finalize:Object类中定义的方法,Java中允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。

这个方法是由垃圾收集器在销毁对象时调用的,通过重写finalize()方法可以整理系统资源或者执行其他清理工作。

52、List、Set、Map是否继承自Collection接口?

答:List、Set 是,Map 不是。Map是键值对映射容器,与List和Set有明显的区别,而Set存储的零散的元素且不允许有重复元素(数学中的集合也是如此),

List是线性结构的容器,适用于按数值索引访问元素的情形。

53、阐述ArrayList、Vector、LinkedList的存储性能和特性。

ArrayList 和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,

但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢。Vector中的方法由于添加了synchronized修饰,

因此Vector是线程安全的容器,但性能上较ArrayList差,因此已经是Java中的遗留容器

LinkedList使用双向链表实现存储(将内存中零散的内存单元通过附加的引用关联起来,形成一个可以按序号索引的线性结构,

这种链式存储方式与数组的连续存储方式相比,内存的利用率更高)

按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。

ArrayList和LinkedListed都是非线程安全的,如果遇到多个线程操作同一个容器的场景,

则可以通过工具类Collections中的synchronizedList方法将其转换成线程安全的容器后再使用(这是对装潢模式的应用,

将已有对象传入另一个类的构造器中创建新的对象来增强实现)。、

54、Collection和Collections的区别?

答:Collection是一个接口,它是Set、List等容器的父接口;Collections是个一个工具类,提供了一系列的静态方法来辅助容器操作,

这些方法包括对容器的搜索、排序、线程安全化等等。

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

答:List以特定索引来存取元素,可以有重复元素。Set不能存放重复元素(用对象的equals()方法来区分元素是否重复)。

Map保存键值对(key-value pair)映射,映射关系可以是一对一或多对一。Set和Map容器都有基于哈希存储和排序树的两种实现版本,

基于哈希存储的版本理论存取时间复杂度为O(1),而基于排序树版本的实现在插入或删除元素时会按照元素或元素的键(key)构成排序树从而达到排序和去重的效果。

56 、TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?

答:TreeSet要求存放的对象所属的类必须实现Comparable接口,该接口提供了比较元素的compareTo()方法,当插入元素时会回调该方法比较元素的大小。TreeMap要求存放的键值对映射的键必须实现Comparable接口从而根据键对元素进行排序。Collections工具类的sort方法有两种重载的形式,第一种要求传入的待排序容器中存放的对象比较实现Comparable接口以实现元素的比较;第二种不强制性的要求容器中的元素必须可比较,但是要求传入第二个参数,参数是Comparator接口的子类型(需要重写compare方法实现元素的比较),相当于一个临时定义的排序规则,其实就是通过接口注入比较元素大小的算法,也是对回调模式的应用(Java中对函数式编程的支持)。

57、Thread类的sleep()方法和对象的wait()方法都可以让线程暂停执行,它们有什么区别?

答:sleep()方法(休眠)是线程类(Thread)的静态方法,调用此方法会让当前线程暂停执行指定的时间,将执行机会(CPU)让给其他线程,

但是对象的锁依然保持,因此休眠时间结束后会自动恢复(线程回到就绪状态,请参考第66题中的线程状态转换图)。wait()是Object类的方法,

调用对象的wait()方法导致当前线程放弃对象的锁(线程暂停执行),进入对象的等待池(wait pool),

只有调用对象的notify()方法(或notifyAll()方法)时才能唤醒等待池中的线程进入等锁池(lock pool),如果线程重新获得对象的锁就可以进入就绪状态。

58、线程的sleep()方法和yield()方法有什么区别?

① sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会;

② 线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态;

③ sleep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常;

④ sleep()方法比yield()方法(跟操作系统CPU调度相关)具有更好的可移植性。

59、当一个线程进入一个对象的synchronized方法A之后,其它线程是否可进入此对象的synchronized方法B?

答:不能。其它线程只能访问该对象的非同步方法,同步方法则不能进入。 -》 没上锁的方法可以 对象锁

因为非静态方法上的synchronized修饰符要求执行方法时要获得对象的锁,如果已经进入A方法说明对象锁已经被取走,

那么试图进入B方法的线程就只能在等锁池(注意不是等待池哦)中等待对象的锁。

60、请说出与线程同步以及线程调度相关的方法。

wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁;

sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要处理InterruptedException异常;

notify():唤醒一个处于等待状态的线程

- notityAll():唤醒所有处于等待状态的线程,该方法并不是将对象的锁给所有线程,而是让它们竞争,只有获得锁的线程才能进入就绪状态;

61、编写多线程程序有几种实现方式?

1. 继承thread类,

2. 实现runnable 接口

3. 实现callable接口 -》 这个可以回调 接口,通过 FutureTask 的 select 方法。

62、synchronized关键字的用法?

实现对对象和方法的互斥访问,可以用synchronized(对象) { … }定义同步代码块,或者在声明方法时将synchronized作为方法的修饰符

63. 同步和异步 ?

同步就是指阻塞式操作,而异步就是非阻塞式操作。

64. 启动一个线程是调用run()还是start()方法?

启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM 调度并执行,这并不意味着线程就会立即运行。

run()方法是线程启动后要进行回调(callback)的方法。

65、什么是线程池(thread pool)?

创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源,这就是”池化资源”技术产生的原因。

线程池顾名思义就是事先创建若干个可执行的线程放入一个池(容器)中,需要的时候从池中获取线程不用自行创建,

使用完毕不需要销毁线程而是放回池中,从而减少创建和销毁线程对象的开销。

Executor - newSingleThreadExecutor:创建一个单线程的线程池。

- newFixedThreadPool:创建固定大小的线程池。

- newCachedThreadPool:创建一个可缓存的线程池。

- newScheduledThreadPool:创建一个大小无限的线程池,通常是任务队列使用,可以定义多少秒后执行。

66. synchronized VS Lock

Lock 能完成synchronized所实现的所有功能;主要不同点:Lock有比synchronized更精确的线程语义和更好的性能,而且不强制性的要求一定要获得锁。

lock可以先尝试去获得锁。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且最好在finally 块中释放!!!

67. 序列化 的意义 :

1. 深克隆

2. 持久化对象

68. 几种类型的流?

字节流继承于InputStream、OutputStream,字符流继承于Reader、Writer。

一是两种对称性(输入和输出的对称性,字节和字符的对称性);二是两种设计模式(适配器模式和装潢模式)。

69. XML文档定义有几种形式?它们之间有何本质区别?

XML文档定义分为DTD和Schema两种形式,二者都是对XML语法的约束,其本质区别在于Schema本身也是一个XML文件,

可以被XML解析器解析,而且可以为XML承载的数据定义类型,约束能力较之DTD更强大。

对XML的解析主要有DOM(文档对象模型,Document Object Model)、SAX(Simple API for XML)和StAX.

75、阐述JDBC操作数据库的步骤。

加载驱动 -> 创建连接 -> 创建语句 -> 执行语句 -> 处理结果 -> 关闭资源。

76、Statement和PreparedStatement有什么区别?哪个性能更好?

PreparedStatement接口代表预编译的语句,它主要的优势在于可以减少SQL的编译错误并增加SQL的安全性(减少SQL注射攻击的可能性)

77、使用JDBC操作数据库时,如何提升读取数据的性能?如何提升更新数据的性能?

setFetchSize()方法指定每次抓取的记录数(典型的空间换时间策略);要提升更新数据的性能可以使用PreparedStatement语句构建批处理,

将若干SQL语句置于一个批处理中执行。

80、事务的ACID是指什么?

答:

- 原子性(Atomic):事务中各项操作,要么全做要么全不做,任何一项操作的失败都会导致整个事务的失败;

- 一致性(Consistent):事务结束后系统状态是一致的;

- 隔离性(Isolated):并发执行的事务彼此无法看到对方的中间状态;

- 持久性(Durable):事务完成后所做的改动都会被持久化,即使发生灾难性的失败。通过日志和同步备份可以在故障发生后重建数据。

久性(Durable):事务完成后所做的改动都会被持久化,即使发生灾难性的失败。通过日志和同步备份可以在故障发生后重建数据。

脏读(Dirty Read):(针对未提交的数据)A事务读取B事务尚未提交的数据并在此基础上操作,而B事务执行回滚,那么A读取到的数据就是脏数据。 -》 B要是回滚了,那A不就撒B了

不可重复读(Unrepeatable Read): 读取数据本身的对比) 事务A重新读取前面读取过的数据,发现该数据已经被另一个已提交的事务B修改过了。 -> 同一个用户可能感觉奇怪 -》 主要是 update

幻读(Phantom Read):(读取结果集条数的对比) 事务A重新执行一个查询,返回一系列符合查询条件的行,发现其中插入了被事务B提交的行。 -》 B已经提交了。

-》 主要是 insert 操作delete 操作

第1类丢失更新:事务A撤销时,把已经提交的事务B的更新数据覆盖了。

第2类丢失更新:事务A覆盖事务B已经提交的数据,造成事务B所做的操作丢失。

通常会通过锁机制来解决数据并发访问问题,按锁定对象不同可以分为表级锁和行级锁;按并发事务锁定关系可以分为共享锁和独占锁,具体的内容大家可以自行查阅资料进行了解。 -》 更新丢失 , 对语句加锁即可。

事务隔离级别

解决方案 :

脏读 : 可以去快照里面读取之前的未提交的数据。

不可重复读重点在于update和delete,而幻读的重点在于insert。

如果使用锁机制来实现这两种隔离级别,在可重复读中,该sql第一次读取到数据后,就将这些数据加锁,其它事务无法修改这些数据,就可以实现可重复 读了。但这种方法却无法锁住insert的数据,所以当事务A先前读取了数据,或者修改了全部数据,事务B还是可以insert数据提交,这时事务A就会 发现莫名其妙多了一条之前没有的数据,这就是幻读,不能通过行锁来避免。需要Serializable隔离级别 ,读用读锁,写用写锁,读锁和写锁互斥,这么做可以有效的避免幻读、不可重复读、脏读等问题,但会极大的降低数据库的并发能力。

所以说不可重复读和幻读最大的区别,就在于如何通过锁机制来解决他们产生的问题。

MySQL、ORACLE、PostgreSQL等成熟的数据库,出于性能考虑,都是使用了以乐观锁为理论基础的MVCC(多版本并发控制)来避免这两种问题。

在悲观锁的情况下,为了保证事务的隔离性,就需要一致性锁定读。读取数据时给加锁,其它事务无法修改这些数据。修改删除数据时也要加锁,其它事务无法读取这些数据。

而乐观锁机制在一定程度上解决了这个问题。乐观锁,大多是基于数据版本( Version )记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如 果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。

要说明的是,MVCC的实现没有固定的规范,每个数据库都会有不同的实现方式,这里讨论的是InnoDB的MVCC。

85、获得一个类的类对象有哪些方式?

答:

- 方法1:类型.class,例如:String.class

- 方法2:对象.getClass(),例如:"hello".getClass()

- 方法3:Class.forName(),例如:Class.forName("java.lang.String")

86、如何通过反射创建对象?

答:

- 方法1:通过类对象调用newInstance()方法,例如:String.class.newInstance()

- 方法2:通过类对象的getConstructor()或getDeclaredConstructor()方法获得构造器(Constructor)对象并调用其newInstance()方法创建对象,

例如:String.class.getConstructor(String.class).newInstance("Hello");

88、如何通过反射调用对象的方法?

String str = "hello";

Method m = str.getClass().getMethod("toUpperCase");

System.out.println(m.invoke(str)); // HELLO

89、简述一下面向对象的"六原则一法则"。

单一职责原则:一个类只做它该做的事情 ,也就是高内聚

开闭原则:软件实体应当对扩展开放,对修改关闭。

依赖倒转原则:面向接口编程。

里氏替换原则:任何时候都可以用子类型替换掉父类型。

接口隔离原则:接口要小而专,绝不能大而全。

90、简述一下你了解的设计模式。

Abstract Factory(抽象工厂模式),Builder(建造者模式),Factory Method(工厂方法模式)

- 工厂模式:工厂类可以根据条件生成不同的子类实例,这些子类有一个公共的抽象父类并且实现了相同的方法,

但是这些方法针对不同的数据进行了不同的操作(多态方法)。当得到子类的实例后,

开发人员可以调用基类中的方法而不必考虑到底返回的是哪一个子类的实例。

- 代理模式:给一个对象提供一个代理对象,并由代理对象控制原对象的引用。实际开发中,按照使用目的的不同,

代理可以分为:远程代理、虚拟代理、保护代理、Cache代理、防火墙代理、同步化代理、智能引用代理。

- 适配器模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起使用的类能够一起工作。

- 模板方法模式:提供一个抽象类,将部分逻辑以具体方法或构造器的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。

不同的子类可以以不同的方式实现这些抽象方法(多态实现),从而实现不同的业务逻辑。

除此之外,还可以讲讲上面提到的门面模式、桥梁模式、单例模式、装潢模式(Collections工具类和I/O系统中都使用装潢模式)等,

反正基本原则就是拣自己最熟悉的、用得最多的作答,以免言多必失。

91 。单例模式

TODO: 补充单例模式代码

饿汉式 :

publicclassSingleton {
privateSingleton(){}
//直接上来就newprivatestaticSingletoninstance=newSingleton();
publicstaticSingletongetInstance(){
returninstance;
    }
}

懒汉式单例:

publicclassSingleton {
privatestaticSingletoninstance=null;
privateSingleton() {}
//加锁避免多线程问题publicstaticsynchronizedSingletongetInstance(){
if (instance==null)
instancenewSingleton();
returninstance;
        }
}


相关文章
|
19天前
|
缓存 Java 关系型数据库
【Java面试题汇总】ElasticSearch篇(2023版)
倒排索引、MySQL和ES一致性、ES近实时、ES集群的节点、分片、搭建、脑裂、调优。
【Java面试题汇总】ElasticSearch篇(2023版)
|
19天前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
174 37
|
19天前
|
设计模式 安全 算法
【Java面试题汇总】设计模式篇(2023版)
谈谈你对设计模式的理解、七大原则、单例模式、工厂模式、代理模式、模板模式、观察者模式、JDK中用到的设计模式、Spring中用到的设计模式
【Java面试题汇总】设计模式篇(2023版)
|
19天前
|
存储 关系型数据库 MySQL
【Java面试题汇总】MySQL数据库篇(2023版)
聚簇索引和非聚簇索引、索引的底层数据结构、B树和B+树、MySQL为什么不用红黑树而用B+树、数据库引擎有哪些、InnoDB的MVCC、乐观锁和悲观锁、ACID、事务隔离级别、MySQL主从同步、MySQL调优
【Java面试题汇总】MySQL数据库篇(2023版)
|
19天前
|
存储 缓存 NoSQL
【Java面试题汇总】Redis篇(2023版)
Redis的数据类型、zset底层实现、持久化策略、分布式锁、缓存穿透、击穿、雪崩的区别、双写一致性、主从同步机制、单线程架构、高可用、缓存淘汰策略、Redis事务是否满足ACID、如何排查Redis中的慢查询
【Java面试题汇总】Redis篇(2023版)
|
19天前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
|
19天前
|
缓存 Java 数据库
【Java面试题汇总】Spring篇(2023版)
IoC、DI、aop、事务、为什么不建议@Transactional、事务传播级别、@Autowired和@Resource注解的区别、BeanFactory和FactoryBean的区别、Bean的作用域,以及默认的作用域、Bean的生命周期、循环依赖、三级缓存、
【Java面试题汇总】Spring篇(2023版)
|
19天前
|
存储 缓存 监控
【Java面试题汇总】JVM篇(2023版)
JVM内存模型、双亲委派模型、类加载机制、内存溢出、垃圾回收机制、内存泄漏、垃圾回收流程、垃圾回收器、G1、CMS、JVM调优
【Java面试题汇总】JVM篇(2023版)
|
19天前
|
存储 缓存 安全
【Java面试题汇总】多线程、JUC、锁篇(2023版)
线程和进程的区别、CAS的ABA问题、AQS、哪些地方使用了CAS、怎么保证线程安全、线程同步方式、synchronized的用法及原理、Lock、volatile、线程的六个状态、ThreadLocal、线程通信方式、创建方式、两种创建线程池的方法、线程池设置合适的线程数、线程安全的集合?ConcurrentHashMap、JUC
【Java面试题汇总】多线程、JUC、锁篇(2023版)
|
19天前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
下一篇
无影云桌面