JAVA面试题

1、Integer i1 = 100;

integer i2 = 100;

i1 == i2是什么结果?

Integer i3 = 128;

Integer i4 = 128;

i3 == i4是什么结果? 

integer底层其实是定义一个Integer类型的数组cahe[]把-128到127的所有数字进行封装,当定义字面量后他会转化为Integer类型,调用底层valueOf方法,他会判断是否在-128到127范围内,如果在范围内,他就去cache数组中找到这个数字,下标就是当前数+128,因为数组总容量等于128+127=255.如果超过-128到127这个范围,他就会重新new一个integer。

所以 i1 == i2为true  i3 == i4为false

2、慢查询如何优化?

首先可以看一下是否有利用索引优化sql,再看看是不是最优解的索引,检查字段是否都是必须的查出多余的数据,单个表是不是数据过于庞大是否要分表,检查机器性能

3、string、stringbuffer、stringbuild区别

string被final修饰是无法修改的,修改后等于再次赋值,创建新的字符串常量

string不是每次都new,被存放在常量池中,如果下次赋值会直接调用

stringbuild和stringbuffer都可以改变字符串,但是stringbuild没有加锁线程不安全,不可以用于并发

4、arrylist和linkedlist区别

他们都实现了list接口,但是linkedlist额外实现了deque(双端队列)接口

arrylist底层是数组实现,需要连续的存储空间,linkedlist是链表实现,数组查询要快一些,链表查询慢但是删除修改要快。但是使用他们简单的尾部进行添加元素,效率相似都很快,如果涉及到扩容数组添加就比较慢,默认容量是10.但是如果指定下标去添加,下标很好找,但是添加以后后面的所有元素下标都要移动,如果容量不够还要扩容,所以比较慢。而linkedlist只需要修改指针,但是链表不像数组可以通过下标很快找到元素位置,如果要找到位置需要遍历,如果下标小速度很快,如果下标大速度就会变得很慢。linkedlist只能通过迭代器遍历

5、copyOnWriteArrayList底层原理

arrylist是线程不安全的,如果两个线程同时写入,两个线程同时判断最后一个位置为空,那么都开始写的操作,第一个写的就会被后来写的覆盖

copyOnWriteArrayList也是基于数组的,他的写操作是加锁的,防止数据写入数据丢失。然后把旧的数组复制一份并且容量加一,所以可以边写边读,适用于多读少写的应用场景。但是由于实时性不高,写的时候有可能读到的是旧的数组数据,所以不适用与实时性高的应用场景

6、hasmap扩容机制

 

7、arrylist的扩容机制

初始容量如果不设定那么就是10,超出去以后是10右移一位+10 ,因为位移运算快,右移相当于10/2所以每次扩容后容量都是旧容量+旧容量/2,扩容不能大也不能小,所以1.5倍可以利用之前的容量基础扩容。如果指定了容量初始化是不需要扩容直接初始化大小为指定的。

jdk1.6以前无参初始化容量默认是10

jdk1.7以后默认容量是0,直到添加第一个元素才正式分配容量

8、面向对象是什么思想

面向过程是把每一个步骤作为方法,比较注重步骤和顺序,面向对象会把事情变成需要哪些对象,每个对象需要哪些动作。更易于维护,复用扩展。

三大特性:封装、继承、多态

封装:的意义就是明确表示外部使用的和外部不需要使用的属性,内部细节对外部不透明,不需要关心实现,只要知道有什么用,setter getter方法来调用属性,属性赋值的内部逻辑一定要是javabean来确定,不能由外部随意修改。比如orm框架,mybatis只需要关注怎么去用,不需要关注怎么实现。

继承:继承父类的方法,子类和父类有共有的属性和方法就可以抽象,子类只需要继承父类就可以复用,子类再增加自己的独特的属性方法。

多态:基于对象所属类的不同,外部调用同一个方法实现,实现不同的逻辑。基于继承的。多态的弊端无法调用子类特有的,必须是父类定义过的

9、jdk、jre、jvm

jdk是程序员开发工具包

jre是运行java程序时的环境

jvm是虚拟机,用来编译class文件让操作系统执行,可以移植让java程序一次编译到处运行

jdk=jre+jvm

jre=jvm+lib

10、==和equals区别

==是判断两个对象在栈中的引用地址是否相等

string a = “hello”;

string b = “hello”;

a==b  true

string c = new string("hello);

string d = new string("hello);

c==b  false

c.equals(b)  true

equals实际上也是利用==判断,用的时候要重写,如果是字符串对象他就会判断每一个字符是否相等,相等返回true

equals不重写对比Object时,用的就是默认的==对比栈中对象引用地址

11、final的作用?为啥局部内部类和匿名内部类只能访问final修饰的变量?

final修饰类:不可以被继承

final修饰方法:不可以被重写,但是可以重载

final修饰变量:变量一但赋值不可被修改

内部类和外部类是同一个级别的,外部类执行后销毁而内部类有可能要继续执行,但是如果外部类中修改了变量,那么内部类和外部类就不一致,所以必须给变量加上final才可以被内部类访问

12、重载和重写的区别?

重载是方法名相同,参数列表不相同,类型、个数、顺序、方法返回值类型、访问修饰符可以不同。但是重载不能只是返回值不同,会造成歧义

重写是方法名相同,参数列表也相同,访问修饰符大于等于父类如果小于父类就破坏了继承性,不能通过父类访问到,抛出异常应该小于父类,返回值范围小于父类

13、抽象类和接口的区别

jdk8以前抽象类中可以有普通成员方法接口中只能存在public abstract方法

jdk以后抽象类中可以有静态方法和默认方法,好处就是接口中的抽象方法实现类必须去实现,而有时候并不需要实现,默认方法就可以自动继承不需要任何实现。接口默认方法可以被实现类重写。接口静态方法和默认方法类似,只是接口静态方法不可以被接口实现类重写。接口静态方法只可以直接通过静态方法所在的 接口名.静态方法名 来调用。

抽象类单继承,接口可以多实现,接口成员变量public static final修饰,用final是因为接口是最高层次的抽象,这样修饰就可以符合ocp原则,不会被随意修改。static是因为接口可以多实现,但是如果两个接口具有同一个变量,那么就很难区分,有static就可以用接口名直接调用属性区分开

接口目的是对类的行为约束,抽象是对代码复用

接口是like a的关系 小鸟像飞行器

抽象是is a的关系 宝马是车

关注事物本质用抽象,关注操作用接口

14、list和set区别

list是有序的,根据对象进入的顺序保存,可以重复,可以通过get获取下标的值,也可以用迭代器

set是无序的,不可以重复,不能通过下边get访问,只能通过迭代器

15、hashcode和equals

hashcode是每一个类都有的属性,作用就是帮助我们从hash表中快速找到位置,hash表中是键值对存储,通过散列码hashcode可以找出对应的值

为什么要有hashcode,举个例子hashset如何确定里面的值没有重复?就是利用了hashcode判断对象加入的位置是否有值,假如没有就说明没有重复,如果有值就是hash冲突,两个不一样的值有可能算出相同的散列码,会再次用equals判断值是否相同,如果相同不允许插入,如果不相同重新散列到其他位置,减少了equals的次数,提高了效率

16、hashmap和hashtable区别

hashmap没有synchronize所以线程不安全,会丢失数据

hashtable每一个线程加锁线程安全

hashmap允许一个key为null,value为null,hashtable都不行

hashmap底层原理数组、链表、红黑树。当hash冲突时,判断value是否相等,相同的话覆盖之前的。不同就放入链表。当链表高度大于8且数组长度大于64就产生红黑树存放链表。

阈值为8是因为超过8的概率非常的小,接近于0,几乎不可能,是经过大数据得出的

hashmap扩容时是当键值对超过数组大小*负载因子 新建一个hashmap容量为原来的两倍,然后把旧的hashmap中数据rehash到新的里面

负载因子默认0.75  太小会频繁扩容,rehash浪费资源  太大很有可能会让桶中的链表很长,影响效率

rehash到新hashmap是因为,如果直接复制会有一半连续的空数组数据不分散,hash碰撞概率增高

hashmap线程不安全,一方面是多线程put时会导致数据可能丢失,第二方面是jdk7以前扩容可能会造成死锁

17、死锁是怎么造成的?

四要素缺一条不构成死锁:

(1)互斥条件:一段时间内某资源只能被一个进程占用

(2)请求保持:进程阻塞后对已获得的资源保持不放

(3)不可剥夺:在未使用完资源前不可被其他进程抢占

(4)循环链路:互相等待

18、线程的生命周期

创建、就绪、运行、阻塞、死亡

阻塞:等待阻塞、其他(sleep、join阻塞)、同步阻塞

19、java中异常体系

object下有父类throwable 父类细分是exception和error   error是无法处理的错误(比如内存溢出)

exception分为runtimeexception(运行中异常)和checkedexception (检查异常)

检查异常在编译时不通过,会提示处理

运行时异常可以在编码时处理也可以不处理,只会导致当前线程执行失败

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值