昨天去了一家公司面试 Java 开发岗位,这篇文章主要是作一个面试的记录以及总结。html
这家公司的规模大概100-200人,环境还能够,在一栋大厦租了两层办公室(31层和32层)。一同搭电梯上去的还有一位去应聘测试岗位的妹纸🙂java
这里要吐槽一下该公司的前台,因为跟HR约好了是在31楼面试,我和测试妹纸都去了31楼的前台,31楼的前台直接让咱们去楼上找32楼的前台,32楼的前台找了楼下31楼的面试官,结果又把咱们带回楼下31楼面试。mysql
首先填了一份我的信息表,而后直接进入面试环节(没有笔试 🙃)。linux
如下是面试时一些问题的记录:git
答:封装、继承、多态。github
答:
一、解析方式面试
缺点:必须读取整个XML文档,才能构建DOM模型,若是XML文档过大,形成资源的浪费。
优势:适合对XML中的数据进行操做(CRUD)。spring
二、解析工具sql
DOM或SAX方式进行解析XML。API在JDK之中。数据库
是开源组织推出的解析开发包。(牛,你们都在用,包括SUN公司的一些技术的实现都在用)
答:当咱们的程序在运行时,须要动态的加载一些类,这些类可能以前用不到因此不用加载到jvm,而是在运行时根据须要才加载,这样的好处对于服务器来讲不言而喻。
举个例子,咱们的项目底层有时是用mysql,有时用oracle,须要动态地根据实际状况加载驱动类,这个时候反射就有用了,假设 com.java.dbtest.myqlConnection,com.java.dbtest.oracleConnection这两个类咱们要用,这时候咱们的程序就写得比较动态化,经过Class tc = Class.forName("com.java.dbtest.TestConnection");经过类的全类名让jvm在服务器中找到并加载这个类,而若是是oracle则传入的参数就变成另外一个了。这时候就能够看到反射的好处了,这个动态性就体现出java的特性了!
举多个例子,你们若是接触过spring,会发现当你配置各类各样的bean时,是以配置文件的形式配置的,你须要用到哪些bean就配哪些,spring容器就会根据你的需求去动态加载,你的程序就能健壮地运行。
Lambda 表达式:Lambda容许把函数做为一个方法的参数(函数做为参数传递进方法中)。
方法引用:方法引用提供了很是有用的语法,能够直接引用Java的类方法、对象方法或者构造器。
Lambda 表达式咱们能够理解为对于函数式接口和其中的抽象方法的具体实现。
Lambda 表达式能够认为是一种特殊的匿名内部类,Lambda只能用于函数式接口。
lambda语法以下: ([形参列表,不带数据类型]) -> { //执行语句 [return..;] }
代码演示以下:
public class TestLambda { public static void main(String[] args) { TestLambdaInterface1 t1 = new TestLambdaInterface1() { @Override public void test() { System.out.println("使用匿名内部类"); } }; //与上面的匿名内部类执行效果同样 //右边的类型会自动根据左边的类型进行判断 TestLambdaInterface1 t2 = () -> { System.out.println("使用lambda"); }; t1.test(); t2.test(); } } @FunctionalInterface interface TestLambdaInterface1 { //不带参数的抽象方法 void test(); }
单例模式:确保一个类只有一个实例,并提供了一个全局访问点。
实现:
使用一个私有静态变量、一个私有构造函数以及一个公有静态函数来实现。
私有构造函数保证了不能经过构造函数来建立对象实例,只能经过公有静态函数返回惟一的私有静态变量。
public class Singleton { private static Singleton instance; private Singleton() { } public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
Session 的缓存被称为 Hibernate 的第一级缓存。SessionFactory 的外置缓存称为 Hibernate 的二级缓存。这两个缓存都位于持久层,它们存放的都是数据库数据的拷贝。SessionFactory 的 内置缓存 存放元数据和预约义 SQL,SessionFactory 的内置缓存是只读缓存。
缓存的做用:
减小数据库的访问频率,提升访问性能。
保证缓存中的对象与数据库同步,位于缓存中的对象称为持久化对象。
HashMap 能够容许插入 null key 和 null value
HashTable 和 ConcurrentHashMap 都不能够插入 null key 和 null value
1、建立线程的时候没有传入名字
ThreadPoolManager.potatoPool.execute(new MyThread());
在这种状况下,线程池会给线程自动命名,若是想改变线程的名称,那么须要在线程中的run方法中给线程setName。以下:
public class MyThread extends Thread{ public String threadName; public MyThread (String threadName){ this.threadName=threadName; } @Override public void run() { Thread.currentThread().setName(threadName); } }
2、建立线程的时候直接传入名字
ThreadPoolManager.potatoPool.execute(new MyThread("aa"));
一、权限问题,修改权限
二、防火墙的缘由,修改防火墙配置
当全部的核心线程(core) 都在干活时,新添加的任务会被添加到队列中等待处理,若是队列满了,则新建非核心线程执行任务。
public class CaptureUncaughtException { public static void main(String[] args) { Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler()); ExecutorService exec = Executors.newCachedThreadPool(); exec.execute(new ExceptionThread2()); // ExceptionThread2 为任务对象 } } /** * MyUncaughtExceptionHandler:捕获线程异常处理的类,须要实现 UncaughtExceptionHandler 接口 * @author nnngu */ class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler { @Override public void uncaughtException(Thread t, Throwable e) { System.out.println(t+"捕获到了异常,异常处理的对象为:"+e); // e:抛出的对象 } }
参考:
Servlet 的生命周期:init、service(doGet、doPost)、destory
内置对象名 | 类型 |
---|---|
request | HttpServletRequest |
response | HttpServletResponse |
config | ServletConfig |
application | ServletContext |
session | HttpSession |
exception | Throwable |
page | Object(this) |
out | JspWriter |
pageContext | PageContext |
对象 | 域 |
---|---|
ServletContext | context域 |
HttpServletRequet | request域 |
HttpSession | session域 |
PageContext | page域 |
参考:
参考:
答:List、Set、Map
List 是有序的,能够有重复元素
Set 是无序的,不容许有重复元素
Map 是键值对
IO 和 NIO 的本质就是阻塞和非阻塞的区别。
阻塞概念:应用程序在获取网络数据的时候,若是网络传输数据很慢,那么程序就一直等着,直到传输完毕为止。
非阻塞概念:应用程序直接能够获取已经准备就绪的数据,无需等待。
参考:
Java NIO 系列教程
最后,我发现面试官也有一些错误,在此也把它记录下来:
先写到这里,之后有什么补充再更新。