当前位置: 首页 > news >正文

Java面试常用,初级到高级(持续更新中....)

文章目录

  • 一、java基础
    • 1、基本类型
    • 2、String相关
    • 3、数组和list相互转换
    • 4、java中的锁
    • 5、常用的算法
  • 二、项目层面
    • 1、并发与并行的区别
  • 三、常见错误解决
    • 1、Java ConcurrentModificationException异常原因和解决方法
    • 2、 main中不能使用this
  • 四、底层的相关技术
    • 1、spring如何处理循环依赖
    • 2、jvm如何判断对象该回收
      • 2.1)jvm判断对象是否可以被回收的方式
        • 2.1.1 引用计数法
        • 2.1.2 可达性算法
        • 2.1.3 哪些对象可以作为GC Root呢?
    • 3、jdk1.8的接口优化,stream包集合优化
    • 4、线程池初始化方式有哪些?种类有哪些?参数有哪些?
      • 4.1)线程池初始化两种方式
      • 4.2)线程池五类
      • 4.2)线程池七个参数详解

面试保持一个探讨交流的心态,因为没有人什么都懂!
也就是说,互相平等,保持开发中,编写代码的状态
欢迎加入扣扣组织,783092701

一、java基础

1、基本类型

java语言中有8种基本数据类型,分类四大类型:

逻辑类型:boolean
整数类型:byte、short、int、long
浮点类型 :float、double
字符类型:char   

2、String相关

1)String是基本类型吗?
String不是基本类型,引用类型

2)String常用的方法?
split substring valueOf

3、数组和list相互转换

List list = new ArrayList();
list.add(1);
//toArray
Object[] array = list.toArray();
System.out.println("list转数组"+Arrays.toString(array));
//asList
List list2 = Arrays.asList(array);
System.out.println("数组转list2"+list2);

4、java中的锁

悲观锁与乐观锁
1)悲观锁:认为别人会修改
synchronized原始采用的是CPU悲观锁机制

2)乐观锁:认为别人不会修改
Lock 用的是乐观锁方式
实现方式:
在数据表中添加一个数据版本号version字段,表示数据被修改的次数,当数据被修改的时候,version值会加一;当线程A要重新更新数据值的时候,在读取数据的时候也会读取version值,在提交更新的时候,若刚才读取到的version值与当前数据库中的version值相等才更新,否则重新更新操作,直到更新成功

3)应用场景
乐观锁使用于写比较少(即读多)的场景,即冲突很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但是如果是写比较多的情况,一般会经常发生冲突,这就会导致上层应用会不断的进行充实,这样反倒是降低了性能,所以一般多写的场景下用悲观锁比较合适

5、常用的算法

二、项目层面

1、并发与并行的区别

并发是指一个处理器同时处理多个任务。
并行是指多个处理器或者是多核的处理器同时处理多个不同的任务。
并发是逻辑上的同时发生(simultaneous),而并行是物理上的同时发生。

三、常见错误解决

1、Java ConcurrentModificationException异常原因和解决方法

1)在使用iterator迭代的时候使用synchronized或者Lock进行同步;
2)使用并发容器CopyOnWriteArrayList代替ArrayListVector

2、 main中不能使用this

因为main方法是静态方法属于类,无法直接使用对象级别的变量和方法,也就是实例属性和实例方法。而关键字“ this”用作对实例的引用,因此不能在静态方法中使用“ this”引用。

原因(个人理解,勿喷):静态方法在类加载时就会被加载到方法区中,而此时,main函数还没有执行,没有new出对象th,所以无法使用对象级别的属性和方法。

四、底层的相关技术

1、spring如何处理循环依赖

【这个有点深度,暂时需要研究一下】转载 spring循环依赖探究

2、jvm如何判断对象该回收

2.1)jvm判断对象是否可以被回收的方式

要分辨一个对象是否可以被回收,有两种方式:引用计数法可达性算法

2.1.1 引用计数法

就是在对象被引用时,计数加1,引用断开时,计数减1。那么一个对象的引用计数为0时,说明这个对象可以被清除。

这个算法的问题在于,如果A对象引用B的同时,B对象也引用A,即循环引用,那么虽然双方的引用计数都不为0,但如果仅仅被对方引用实际上没有存在的价值,应该被GC掉。

2.1.2 可达性算法

通过引用计数法的缺陷可以看出,从被引用一方去判定其是否应该被清理过于片面,所以我们可以通过相反的方向去定位对象的存活价值:一个存活对象引用的所有对象都是不应该被清除的(Java中软引用或弱引用在GC时有不同判定表现,不在此深究)。这些查找起点被称为GC Root

2.1.3 哪些对象可以作为GC Root呢?

JAVA虚拟机栈中的本地变量引用对象

方法区中静态变量引用的对象

方法区中常量引用的对象

本地方法栈中JNI引用的对象

3、jdk1.8的接口优化,stream包集合优化

问题1:接口方法必须实现,jdk1.8如何做到可以不实现?
问题2:假设一个父接口被超级多子类继承,并且子类还会被子类的子类继承……,当父接口需要添加一个方法时,因为该方法一定会在超多个子类中被覆写的,所以工作量难以想象。
回答可以使用default来定义普通方法

interface INew{
	public default void fun() {//普通方法,有方法体
		System.out.println("world!");
	}
	public void print();//抽象方法
}
class Person implements INew{
	@Override
	public void print() {
		System.out.println("hello!");
	}
}
public class TestDemo {
	public static void main(String[] args) {
		INew p=new Person();
		p.print();
		p.fun();//实例化对象是可以调用fun()方法的
	}
}

另外一个特性:可以使用static来定义静态方法,通过接口名就可以调用

interface INew{
	public default void fun() {//普通方法,有方法体
		System.out.println("world!");
	}
	public static INew getInstance() {//定义静态方法
		return new Person();
	}
	public void print();//抽象方法
}
class Person implements INew{
	@Override
	public void print() {
		System.out.println("hello!");
	}
}
public class TestDemo {
	public static void main(String[] args) {
		INew p=INew.getInstance();//静态方法可以由类名称直接调用了
		p.print();
		p.fun();//实例化对象是可以调用fun()方法的
	}
}

4、线程池初始化方式有哪些?种类有哪些?参数有哪些?

误区:cpu过高,是单个线程请求过高问题。而不是线程过多造成的。

4.1)线程池初始化两种方式

在这里插入图片描述

4.2)线程池五类

  • 固定数量的线程池——newFixedThreadPool
    作用:这是一个线程数固定的,线程可以重用的线程池,用共享的无界队列方式运行这些线程。
  • 缓存线程池——newCachedThreadPool
    作用:它是根据需要,创建线程,没有核心线程,当60s内这个线程没接收到任务时,它就会被从池中收走。60s内这个线程又接收到新任务时,它就又被重用了。
  • 只有一个线程的线程池——newSingleThreadPool
    作用:这个线程池中只有1个线程,用无界队列的方式运行。如果这个线程突然挂掉了,线程池会新建一个新的线程顶替它,继续完成任务。
  • 延时线程池——newScheduleThreadPool
    作用:创建一个线程池,可以让它里面的线程延迟执行,或在规定的时间后执行。
  • 并行线程池——newWorkStealingPool
    作用:jdk1.8提供的线程池,底层使用ForkJoinPool实现,池中有多个任务队列。适用于任务多,可以并发执行的场景。

4.2)线程池七个参数详解

在这里插入图片描述

  1. corePoolSize 线程池核心线程大小
  2. maximumPoolSize 线程池最大线程数量
  3. keepAliveTime 空闲线程存活时间
  4. unit 空闲线程存活时间单位
  5. workQueue 工作队列
  6. threadFactory 线程工厂
  7. handler 拒绝策略
    如何真正理解记忆:找一台服务器,跑一下代码就行!

相关文章:

  • 北京建筑培训网/谷歌搜索引擎优化
  • 免费制作企业微商城/上海网络营销seo
  • 侦探公司做网站的资料/优化大师优化项目有
  • 深圳设计网页制作公司/兰州搜索引擎优化
  • html旅游网站页面设计模板/google官网入口手机版
  • 弹幕网站是什么技术做的/微信搜索seo优化
  • 面临项目失控?四个维度应对项目进度优化【洞见2】
  • 一致性哈希
  • 艾美捷内皮血管生成检测试剂盒的多种特点
  • 【JavaEE】Tomcat
  • 【QScrollBar | QSlider | QDial | QProgressBar | QLCDNumber】
  • HSF 实现原理
  • CF1324F Maximum White Subtree
  • LeetCode 96. 不同的二叉搜索树
  • 冬至已至,你的在职读研2023能在社科院与杜兰大学金融管理硕士项目实现吗
  • 数据结构C语言版——链式二叉树的基本操作实现
  • 关联规则挖掘算法: Aprior算法和Fpgrowth算法
  • 加载速度提升 15%,关于 Python 启动加速探索与实践的解析 | 龙蜥技术