面试知识java基础(查漏补缺笔记)

设计模式
http://c.biancheng.net/design_pattern/

https://blog.csdn.net/u012844098/article/details/88621337

基本类型比较规则

int和int之间,用==比较,肯定为true。基本数据类型没有equals方法
int和Integer比较,Integer会自动拆箱,== 和 equals都肯定为true
int和new Integer比较,Integer会自动拆箱,调用intValue方法, 所以 == 和 equals都肯定为true
Integer和Integer比较的时候,由于直接赋值的话会进行自动的装箱。所以当值在[-128,127]中的时候,由于值缓存在IntegerCache中,那么当赋值在这个区间的时候,不会创建新的Integer对象,而是直接从缓存中获取已经创建好的Integer对象。而当大于这个区间的时候,会直接new Integer。
当Integer和Integer进行==比较的时候,在[-128,127]区间的时候,为true。不在这个区间,则为false
当Integer和Integer进行equals比较的时候,由于Integer的equals方法进行了重写,比较的是内容,所以为true

Integer和new Integer : new Integer会创建对象,存储在堆中。而Integer在[-128,127]中,从缓存中取,否则会new Integer.
所以 Integer和new Integer 进行==比较的话,肯定为false ; Integer和new Integer 进行equals比较的话,肯定为true

new Integer和new Integer进行==比较的时候,肯定为false ; 进行equals比较的时候,肯定为true
原因是new的时候,会在堆中创建对象,分配的地址不同,==比较的是内存地址,所以肯定不同

装箱过程是通过调用包装器的valueOf方法实现的
拆箱过程是通过调用包装器的xxxValue方法实现的(xxx表示对应的基本数据类型)

总结:Byte、Short、Integer、Long这几个类的valueOf方法实现类似的。所以在[-128,127]区间内,==比较的时候,值总是相等的(指向的是同一对象),在这个区间外是不等的。
而Float和Double则不相等, Boolean的值总是相等的

创建对象的5种方式
 ①、通过 new 关键字

这是最常用的一种方式,通过 new 关键字调用类的有参或无参构造方法来创建对象。比如 Object obj = new Object();

②、通过 Class 类的 newInstance() 方法

这种默认是调用类的无参构造方法创建对象。比如 Person p2 = (Person) Class.forName(“com.ys.test.Person”).newInstance();

③、通过 Constructor 类的 newInstance 方法

这和第二种方法类时,都是通过反射来实现。通过 java.lang.relect.Constructor 类的 newInstance() 方法指定某个构造器来创建对象。

Person p3 = (Person) Person.class.getConstructors()[0].newInstance();

实际上第二种方法利用 Class 的 newInstance() 方法创建对象,其内部调用还是 Constructor 的 newInstance() 方法。

④、利用 Clone 方法

Clone 是 Object 类中的一个方法,通过 对象A.clone() 方法会创建一个内容和对象 A 一模一样的对象 B,clone 克隆,顾名思义就是创建一个一模一样的对象出来。

Person p4 = (Person) p3.clone();

⑤、反序列化

序列化是把堆内存中的 Java 对象数据,通过某种方式把对象存储到磁盘文件中或者传递给其他网络节点(在网络上传输)。而反序列化则是把磁盘文件中的对象数据或者把网络节点上的对象数据,恢复成Java对象模型的过程。

多线程
java中创建线程的四种方法以及区别
https://www.jianshu.com/p/732a8858b0d4
Java使用Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例。Java可以用四种方式来创建线程,如下所示:

1)继承Thread类创建线程

2)实现Runnable接口创建线程

3)使用Callable和Future创建线程
创建Callable实现类的实例,创建一个线程池,调用线程池的submit方法,如果需要返回值就调用Future的get方法获取。

4)使用线程池例如用Executor框架

线程池系列知识

在这里插入图片描述

常用线程池

CachedThreadPool
corePoolSize = 0,maximumPoolSize = Integer.MAX_VALUE,即线程数量几乎无限制;
keepAliveTime = 60s,线程空闲60s后自动结束。
workQueue 为 SynchronousQueue 同步队列,这个队列类似于一个接力棒,入队出队必须同时传递,因为CachedThreadPool线程创建无限制,不会有队列等待,所以使用SynchronousQueue;
适用场景:快速处理大量耗时较短的任务,如Netty的NIO接受请求时,可使用CachedThreadPool。
FixedThreadPool
corePoolSize与maximumPoolSize相等,即其线程全为核心线程,是一个固定大小的线程池,是其优势;
keepAliveTime = 0 该参数默认对核心线程无效,而FixedThreadPool全部为核心线程;
workQueue 为LinkedBlockingQueue(无界阻塞队列),队列最大值为Integer.MAX_VALUE。如果任务提交速度持续大余任务处理速度,会造成队列大量阻塞。因为队列很大,很有可能在拒绝策略前,内存溢出。是其劣势;
FixedThreadPool的任务执行是无序的;

SingleThreadExecutor

创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。如果这个线程异常结束,会有另一个取代它,保证顺序执行。单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。

ScheduleThreadPool

创建一个定长的线程池,而且支持定时的以及周期性的任务执行,支持定时及周期性任务执行。

阿里开发手册要求不通过executor去创建线程池,而是通过ThreadPoolExecutor(形参)手动创建常量池

线程池的拒绝策略
https://www.jianshu.com/p/9fec2424de54

java1.8Stream api
https://blog.csdn.net/y_k_y/article/details/84633001
https://blog.csdn.net/mu_wind/article/details/109516995
1.8断言接口 (Predicate)接口
https://www.cnblogs.com/LeeScofiled/p/7096702.html

lambda用法
https://www.cnblogs.com/haixiang/p/11029639.html
https://www.cnblogs.com/gu-bin/p/11225749.html

Java面试常考的 BIO,NIO,AIO 总结
https://blog.csdn.net/m0_38109046/article/details/89449305

select、poll、epoll之间的区别(搜狗面试)
https://www.cnblogs.com/aspirant/p/9166944.html
https://zhuanlan.zhihu.com/p/63179839

collection 和 array 的方法
https://huangjiachen.com.cn/article/1587006860

深拷贝和浅拷贝
https://www.cnblogs.com/ysocean/p/8482979.html

HashMap初始容量为什么是2的n次幂及扩容为什么是2倍的形式
https://blog.csdn.net/Apeopl/article/details/88935422

谈谈 HashMap(int initialCapacity) 构造方法中阈值初始化过程
https://blog.csdn.net/woshiyizhiyu0/article/details/107017333

jdk1.7hashmap在多线程下,扩容时,链表成环问题
https://coolshell.cn/articles/9606.html

jvm内存模型简介
介绍下 Java 内存区域(运行时数据区)
Java 对象的创建过程(五步,建议能默写出来并且要知道每一步虚拟机做了什么)
对象的访问定位的两种方式(句柄和直接指针两种方式)

https://github.com/Snailclimb/JavaGuide/blob/3965c02cc0f294b0bd3580df4868d5e396959e2e/Java%E7%9B%B8%E5%85%B3/%E5%8F%AF%E8%83%BD%E6%98%AF%E6%8A%8AJava%E5%86%85%E5%AD%98%E5%8C%BA%E5%9F%9F%E8%AE%B2%E7%9A%84%E6%9C%80%E6%B8%85%E6%A5%9A%E7%9A%84%E4%B8%80%E7%AF%87%E6%96%87%E7%AB%A0.md
jvm直接内存
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

死锁条件和解决方法
学过操作系统的朋友都知道产⽣死锁必须具备以下四个条件:

  1. 互斥条件:该资源任意⼀个时刻只由⼀个线程占⽤。
  2. 请求与保持条件:⼀个进程因请求资源⽽阻塞时,对已获得的资源保持不放。
  3. 不剥夺条件:线程已获得的资源在末使⽤完之前不能被其他线程强⾏剥夺,只有⾃⼰使⽤完毕后
    才释放资源。
  4. 循环等待条件:若⼲进程之间形成⼀种头尾相接的循环等待资源关系。
    如何避免线程死锁?
    我上⾯说了产⽣死锁的四个必要条件,为了避免死锁,我们只要破坏产⽣死锁的四个条件中的其中⼀个
    就可以了。现在我们来挨个分析⼀下:
  5. 破坏互斥条件 :这个条件我们没有办法破坏,因为我们⽤锁本来就是想让他们互斥的(临界资
    源需要互斥访问)。
  6. 破坏请求与保持条件 :⼀次性申请所有的资源。
  7. 破坏不剥夺条件 :占⽤部分资源的线程进⼀步申请其他资源时,如果申请不到,可以主动释放
    它占有的资源。
  8. 破坏循环等待条件 :靠按序申请资源来预防。按某⼀顺序申请资源,释放资源则反序释放。破
    坏循环等待条件。

类锁和对象锁的区别
修饰实例⽅法: 作⽤于当前对象实例加锁,进⼊同步代码前要获得当前对象实例的锁
修饰静态⽅法: 也就是给当前类加锁,会作⽤于类的所有对象实例,因为静态成员不属于任何⼀
个实例对象,是类成员( static 表明这是该类的⼀个静态资源,不管new了多少个对象,只有
⼀份)。所以如果⼀个线程A调⽤⼀个实例对象的⾮静态 synchronized ⽅法,⽽线程B需要调⽤
这个实例对象所属类的静态 synchronized ⽅法,是允许的,不会发⽣互斥现象,因为访问静态
synchronized ⽅法占⽤的锁是当前类的锁,⽽访问⾮静态 synchronized ⽅法占⽤的锁是当前
实例对象锁。
修饰代码块: 指定加锁对象,对给定对象加锁,进⼊同步代码库前要获得给定对象的锁。
总结: synchronized 关键字加到 static 静态⽅法和 synchronized(class)代码块上都是是给 Class
类上锁。synchronized 关键字加到实例⽅法上是给对象实例上锁。尽量不要使⽤
synchronized(String a) 因为JVM中,字符串常量池具有缓存功能!
https://www.cnblogs.com/wpf-7/p/9639671.html

Synchronized关键字使用、底层原理、底层优化、ReenTrantLock的对比
https://blog.csdn.net/l18848956739/article/details/88846194

锁升级过程和锁状态,看完这篇你就懂了!
https://www.cnblogs.com/lwh1019/p/13093581.html

java 锁 Lock接口详解
https://www.cnblogs.com/myseries/p/10784076.html

读写锁
https://www.jianshu.com/p/9cd5212c8841

抢红包算法
https://blog.csdn.net/weixin_43232955/article/details/108916572

红黑树和平衡二叉树的一些区别
https://blog.csdn.net/canot/article/details/80045057
平衡二叉搜索树的形式多样,且各具特色。比如,伸展树实现简便、无需修改节点 结构、分摊复杂度低,但可惜最坏情况下的单次操作需要n时间,故难以适用于对可靠性和稳定性要求极高的场合。
反之,AVL树尽管可以保证最坏情况下的单次操作速度,但需在节点中嵌入平衡因子等标识;更重要的是,删除操作之后的重平衡可能需做多达logn次旋转,从而频繁地导致全树整体拓扑结构的大幅度变化。

红黑树即是针对后一不足的改进。通过为节点指定颜色,并巧妙地动态调整,红黑树可保证: 在每次插入或删除操作之后的重平衡过程中,全树拓扑结构的更新仅涉及常数个节点。尽管最坏情况下需对多达logn个节点重染色,但就分摊意义而言仅为O(1)个

当然,为此首先需在AVL树“适度平衡”标准的基础上,进一步放宽条件。实际上,红黑树所采用的“适度平衡”标准,可大致表述为:任一节点左、右子树的高度,相差不得超过两倍。

mysql索引种类
MySQL索引使⽤的数据结构主要有BTree索引 和 哈希索引
https://www.cnblogs.com/luyucheng/p/6289714.html

springmvc工作原理
https://www.cnblogs.com/fengquan-blog/p/11161084.html
.

、扩容的时候为什么1.8不用重新hash就可以直接定位到源节点再新数组的位置
这是因为扩容的时候数组变为原来的2倍,用于计算数组位置的掩码仅仅是比高位多了个1,比如扩容前数组长度为16,(n - 1)&hash中 n-1 = 0b 0000 1111,扩容后的长度是32,此时n-1 = 0b 0001 1111。&运算符的特点是有0则0,所以对于扩容前(n - 1)&e.hash和扩容后(n - 1)&e.hash的结果就只有两种情况,hash的倒数第五位是0还是1,如果是0,那么扩容后元素在新数组的位置与扩容前元素在新数组中的位置相同。如果为1,扩容后元素在新数组中的位置=扩容前元素在旧数组中的位置+旧数组的长度,所以,我们就不需要重新计算元素的位置,判断一下就可以了,jdk1.8采用的**(e.hash)&原数组长度**的结果来判断的。这种方式非常巧妙,原数组的长度的二进制编码的首位和扩容后数组长度对应的位置上的数是相同的,结果为0,以上面的例子来说,e.hash = ob xxx0 xxxx,扩容前后位置一样。结果不为0,e.hash = ob xxx1 xxxx,扩容后的位置= 扩容前位置+原数组长度。

在这里插入图片描述

Java表达式转型规则由低到高转换:
1、所有的byte,short,char型的值将被提升为int型;
2、如果有一个操作数是long型,计算结果是long型;

3、如果有一个操作数是float型,计算结果是float型;

4、如果有一个操作数是double型,计算结果是double型;
5、被fianl修饰的变量不会自动改变类型,当2个final修饰相操作时,结果会根据左边变量的类型而转化。
--------------解析--------------
语句1错误:b3=(b1+b2);自动转为int,所以正确写法为b3=(byte)(b1+b2);或者将b3定义为int;
语句2正确:b6=b4+b5;b4、b5为final类型,不会自动提升,所以和的类型视左边变量类型而定,即b6可以是任意数值类型;
语句3错误:b8=(b1+b4);虽然b4不会自动提升,但b1仍会自动提升,所以结果需要强转,b8=(byte)(b1+b4);
语句4错误:b7=(b2+b5); 同上。同时注意b7是final修饰,即只可赋值一次,便不可再改变。

Java中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。Java 支持 4 种不同的访问权限。

default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。

private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)

public : 对所有类可见。使用对象:类、接口、变量、方法

protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值