【前言】

参考文章


Java基础

抽象类和接口的区别,类可以继承多个类么,接口可以继承多个接口么?
抽象类要被子类继承,接口要被类实现。抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。接口只能做方法申明(没有大括号:abstract void abc();不能写成abstract void abc(){}),抽象类中可以做方法申明,也可以做方法实现。接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,实现一个接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。抽象类里可以没有抽象方法。如果一个类里有抽象方法,那么这个类只能是抽象类。抽象方法要被实现,所以不能是静态的,也不能是私有的。接口可继承接口,并可多继承接口,但类只能单根继承(为什么?类B继承类A1和A2,不知道继承的是属于谁的共有方法f())。

类的实例化顺序?
父类静态代变量、父类静态代码块、子类静态变量、子类静态代码块、父类非静态变量(父类实例成员变量)、父类构造函数、子类非静态变量(子类实例成员变量)、子类构造函数。

Java反射原理?
Java反射机制容许程序在运行时加载、探知、使用编译期间完全未知的classes。ClassLoader.loadClass()Class.forName()使用反射来构造类的方法。参考文章

Java浅拷贝和深拷贝?
浅拷贝(引用拷贝)是创建一个指向对象引用变量的拷贝,实际在内存中只一个对象;深拷贝(对象拷贝)是 在内存中将对象复制一份,并创建一个变量指向它,修改不会相互影响。

Java异常
2020Java面试题
在java.lang包下,Throwable是所有异常的根。CheckedException是可以被处理的异常,Java程序必须显示处理Checked异常,处理方法:第一种,当前方法知道如何处理的异常,使用try…catch语句块来处理。第二种,当前方法不知道如何处理的异常,则在定义该方法时声明抛出该异常throws Exception。自定义异常

Java泛型
其本质是参数化类型,也就是说所操作的数据类型被指定为一个参数(type parameter)这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。作用:泛化,类型安全,消除强制类型转换,向后兼容。

Java设计原则和设计模式

六大设计原则:(参考文章
单一职责原则(一个类、接口或方法只负责一项职责,职责越多变化几率越大稳定性越低)、接口隔离原则(类A通过接口I1,I2去依赖类B,类C通过接口I1,I3去依赖类D)、依赖倒转原则(依赖于抽象而不是具体)、里氏替换原则(子类尽量不要重写或重载父类的方法)、开闭原则(对扩展开放对修改关闭)、迪米特原则(最少知道原则,陌生的类不要作为局部变量出现在类的内部)

二十三个设计模式:(10)(参考文章
单例模式(内存中只存在该类的一个对象实例,不允许new,构造方法私有化,内部创建对象并向外暴露一个公共的方法。使用场景:频繁创建和销毁对象。懒汉式单例,饿汉式单例,双重检查)、工厂模式(将实例化对象的代码提取出来统一放到放在工厂类中)、原型模式()、建造者模式适配器模式(类、对象和接口适配器)

Java集合类

Java集合主要有4个部分:List列表、Set集合、Map映射、Queue 队列
2020Java面试题
2020Java面试题
ArrayList 和 LinkedList 有什么区别?
ArrayList和LinkedList都实现了List接口,有以下的不同点:
1、ArrayList是基于索引的数据接口,它的底层是数组。它可以以O(1)时间复杂度对元素进行随机访问。与此对应,LinkedList是以元素列表的形式存储它的数据,每一个元素都和它的前一个和后一个元素链接在一起,查找某个元素的时间复杂度是O(n)。
2、相对于ArrayList,LinkedList的插入,添加,删除操作速度更快,因为当元素被添加到集合任意位置的时候,不需要像数组那样重新计算大小或者是更新索引。
3、LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素。

Java并发

参考文章
进程:程序的一次执行过程,系统运行程序的基本单位,进程是动态的。
线程:轻量级进程,一个进程里的多个线程共享堆和方法区资源,但每个线程有自己的程序计数器、虚拟机栈和本地方法栈。线程切换开销小得多,多线程提高并发能力和性能。

为什么堆和方法区线程共享
堆和方法区是所有线程共享的资源,其中堆是进程中最大的一块内存,主要用于存放新创建的对象 (所有对象都在这里分配内存),方法区主要用于存放已被加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

为什么程序计数器为什么是私有的?
为了线程切换后能恢复到正确的执行位置。

为什么虚拟机栈和本地方法栈为什么是私有的
为了保证线程中的局部变量不被别的线程访问到。

并发与并行的区别?
并发是同一时间段有多个任务在执行,但某一单位时间内只有一个任务在执行。并行是单位时间内有多个任务在执行,多CPU。

线程生命周期和状态
2020Java面试题
参考文章

上下文切换?
当前任务在执行完 CPU 时间片切换到另一个任务之前会先保存自己的状态,以便下次再切换回这个任务时,可以再加载这个任务的状态。任务从保存到再加载的过程就是一次上下文切换。

死锁
产生死锁4条件:互斥、请求与保持、不可剥夺和循环等待。

如何避免死锁?
(破坏四条件之一)破坏互斥条件:这个条件我们没有办法破坏,因为我们用锁本来就是想让他们互斥的(临界资源需要互斥访问)。破坏请求与保持条件:一次性申请所有的资源。破坏不剥夺条件:占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源。破坏循环等待条件:靠按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。破坏循环等待条件。

sleep() 方法和 wait() 方法区别和共同点?
• 两者都可以暂停线程的执行。
• 两者最主要的区别在于:sleep 方法没有释放锁,而 wait 方法释放了锁 。
• Wait 通常被用于线程间交互/通信,sleep 通常被用于暂停执行。
• wait() 方法被调用后,线程不会自动苏醒,需要别的线程调用同一个对象上的 notify()或者 notifyAll() 方法。sleep() 方法执行完成后,线程会自动苏醒。

为什么我们调用 start() 方法时会执行 run() 方法,不能直接调用 run() 方法?
new 一个 Thread,线程进入了新建状态;调用 start() 方法,会启动一个线程并使线程进入了就绪状态,当分配到时间片后就可以开始运行了。 start() 会执行线程的相应准备工作,然后自动执行 run() 方法的内容,这是真正的多线程工作。 而直接执行 run() 方法,会把 run 方法当成一个 main 线程下的普通方法去执行,并不会在某个线程中执行它,所以这并不是多线程工作。
总结: 调用 start 方法方可启动线程并使线程进入就绪状态,而 run 方法只是 thread 的一个普通方法调用,还是在主线程里执行。

Java数据结构和算法


栈后进先出,递归是借助栈来实现的。(注:凡是可以用递归来实现的算法,都可以用循环来迭代。凡是递归定义的数据结构都可以用 递归算法来实现)

如何借助栈来实现递归?
函数一层一层不停入栈,到最后一层后,再一层一层不停出栈运算,栈空后递归结束。

如何对递归做优化?
尾递归:在函数返回的时候,调用自身本身,并且return语句不能包含表达式。这样使递归本身无论调用多少次,都只占用一个栈帧,不会出现溢出的情况。

Java虚拟机

Java框架-Tomcat

Java框架-SpringBoot

SpringBoot用了哪些注解 @SpringBootApplication:复合注解,包含了@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan这三个注解。@Controller:表明这个类是一个控制类。@RestController:用于标注控制层组件,包含@Controller和 @ResponseBody(将java对象转为json格式的数据,返回值写入 HTTP response body 中,在异步获取数据时使用)。@Autowired:自动装配,可以用到构造器,变量域,方法,注解类型上。@GetMapping:标注在controller层的方法上,处理get类型的特定请求。@Data:lombok插件中的,帮我们自动在DTO(数据传输对象)中生成set/get/toString等方法。@Repository:用于标注数据访问组件,即DAO组件。@Service:用于标注业务层组件。@Component:泛指组件,当组件不好归类(@Service, @Controller, @Repository)的时候,我们可以使用这个注解进行标注。@Bean:标注在方法的上面,产生一个bean,并交给spring管理。@ExceptionHandler:异常处理。@Transactional: 通过这个注解可以声明事务,可以添加在类上或者方法上。@Self4j:lombok插件中的,为类提供一个 属性名为log 的 log4j 日志对象。

项目管理工具Maven

Maven:是一个项目管理工具,通过项目对象模型(pom)来进行:项目构建;依赖管理;版本管理;软件项目持续集成等。

Maven的生命周期: 项目的清理、验证初始化、编译、测试、打包、集成测试、验证、安装,站点生成和部署。Maven有三套相互独立的生命周期,分别是clean、default和site。每个生命周期包含一些阶段(phase),阶段是有顺序的,后面的阶段依赖于前面的阶段。
1、clean生命周期:清理项目,包含三个phase。
1)pre-clean:执行清理前需要完成的工作
2)clean:清理上一次构建生成的文件
3)post-clean:执行清理后需要完成的工作
2、default生命周期:构建项目,重要的phase如下。
1)validate:验证工程是否正确,所有需要的资源是否可用。
2)compile:编译项目的源代码。
3)test:使用合适的单元测试框架来测试已编译的源代码。这些测试不需要已打包和布署。
4)Package:把已编译的代码打包成可发布的格式,比如jar。
5)integration-test:如有需要,将包处理和发布到一个能够进行集成测试的环境。
6)verify:运行所有检查,验证包是否有效且达到质量标准。
7)install:把包安装到maven本地仓库,可以被其他工程作为依赖来使用。
8)Deploy:在集成或者发布环境下执行,将最终版本的包拷贝到远程的repository,使得其他的开发者或者工程可以共享。
3、site生命周期:建立和发布项目站点,phase如下
1)pre-site:生成项目站点之前需要完成的工作
2)site:生成项目站点文档
3)post-site:生成项目站点之后需要完成的工作
4)site-deploy:将项目站点发布到服务器

Maven常用命令:

命令 功能
mvn clean 清除项目目录中的生成结果
mvn archetype:create 创建
mvn compile 编译源代码
mvn test 运行应用程序中的单元测试
mvn test-compile 编译测试源代码
mvn package 根据项目生成的jar
mvn install 在本地Repository中安装jar
mvn deploy 发布项目
mvn site 生成项目相关信息的网站
mvn idea:idea 生成idea项目
mvn tomcat:run 启动tomcat服务

相关文章: