刚刚参加完的 java开发面试题--整理复盘(2020.10.28)



被面试了三四十分钟,面试官问了我二三十个问题,问到后面几个的时候,感觉都快要哭了,原来我们平时用到的,不能只会实践,还是要对Java基础理论知识特别了解才行,而且要多刷面试题!!好了,我把今天面试被问到的题整理一下,希望有帮助



1、Java中String,StringBuffer和StringBuilder的区别

String:是字符串常量,对象不可变
StringBuffer:是字符串变量,对象可变,线程安全
StringBuilder:是字符串变量,对象可变,线程不安全

2、创建线程有哪几种方式

继承Thread类,创建子类对象,调用start()方法启动线程,重写run()方法。
实现Runnable接口,定义一个类实现runnable接口,实现run方法,创建runnable实现类对象,作为target传入Thread构造函数中,调用start启动线程。
实现Callable接口
通过线程池创建临时线程

线程池:
多线程处理,处理时将任务添加到队列,然后自动启动这些任务,使用默认的堆栈,以默认的优先级处理。

newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个调度型线程池,支持定时及周期性任务执行。
newSingleThreadExecutor创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

3、进程和线程的区别

进程

什么是进程呢?
进程是系统进行资源分配的调度的基本单位,是操作系统结构的基础。简单来讲:进程是指运行中的应用程序,进程是一个实体,每一个进程都有它自己的地址空间。例如我们点击了QQ,就启动了一个进程,操作系统就会为这个进程分配独立的地址空间,当我们又点击浏览器,这样又启动了一个进程,操作系统将为新的进程分配新的独立的地址空间。

线程

什么是线程呢?

线程是操作系统能够进行运算调度的最小单位,被包含在进程之中,是进程中的实际运作单位。一个进程至少有一个线程。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。注意:线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属于一个进程的其他线程共享进程所拥有的全部资源,线程有就绪,阻塞,运行三种基本状态。

4、线程安全是什么,怎样保证线程安全

线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。
线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据

如何保证线程安全:
互斥同步:synchronized关键字:Java中的每一个对象都可以作为锁
非阻塞同步

CAS是实现非阻塞同步的计算机指令,它有三个操作数:内存位置,旧的预期值,新值,在执行CAS操作时,当且仅当内存地址的值符合旧的预期值的时候,才会用新值来更新内存地址的值,否则就不执行更新。

无同步

线程本地存储:将共享数据的可见范围限制在一个线程中。这样无需同步也能保证线程之间不出现数据争用问题。
经常使用的就是ThreadLocal
ThreadLocal类 最常见的ThreadLocal使用场景为 用来解决数据库连接、Session管理等。

5、重写和重载分别是什么,有什么区别

方法重写:是存在子类与父类关系的两个类中,是子类继承的父类方法无法满足子类需求时进行的,重写的方法具有相同的名字,相同的参数列表,返回类型为同类或子类,方法的修饰权限不能缩小。

1、有继承关系的子类中
2、方法名相同,参数列表相同(参数顺序、个数、类型),方法返回值相同
3、访问修饰符,访问范围需要大于等于父类的访问范围
4、与方法的参数名无关

方法重载:指的是指一个类中多个方法具有相同的方法名,但是参数不同、返回值不同。是为了适用于在不同参数返回值类型时均能调用同一方法而出现的

1、同一个类中
2、方法名相同,参数列表不同(参数顺序、个数、类型)
3、方法返回值、访问修饰符任意
4、与方法的参数名无关

在这里插入图片描述

6、java中的访问修饰符有哪些

public: 用public修饰的类、类属变量及方法,包内及包外的任何类(包括子类和普通类)均可以访问;

protected: 用protected修饰的类、类属变量及方法,包内的任何类及包外那些继承了该类的子类才能访问,protected重点突出继承

default: 如果一个类、类属变量及方法没有用任何修饰符(即没有用public、protected及private中任何一种修饰),则其访问权限为default(默认访问权限)。默认访问权限的类、类属变量及方法,包内的任何类(包括继承了此类的子类)都可以访问它,而对于包外的任何类都不能访问它(包括包外继承了此类的子类)。default重点突出包;

private: 用private修饰的类、类属变量及方法,只有本类可以访问,而包内包外的任何类均不能访问它。

7、==和equals区别

1)对于==,比较的是值是否相等

如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;
如果作用于引用类型的变量,则比较的是所指向的对象的地址

2)对于equals方法,注意:equals方法不能作用于基本数据类型的变量,equals继承Object类,比较的是是否是同一个对象

如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;
诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容

8、mybatis标签都有哪些

在这里插入图片描述

9、Mybatis如何执行批量操作

使用foreach标签

foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合。foreach标签的属性主要有item,index,collection,open,separator,close。

item  表示集合中每一个元素进行迭代时的别名,随便起的变量名;
index  指定一个名字,用于表示在迭代过程中,每次迭代到的位置,不常用;
open  表示该语句以什么开始,常用“(”;
separator表示在每次进行迭代之间以什么符号作为分隔符,常用“,”;
close  表示以什么结束,常用“)”。
在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况下,该属性的值是不一样的,主要有一下3种情况:

如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map,实际上如果你在传入参数的时候,在MyBatis里面也是会把它封装成一个Map的,
map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key
具体用法如下:

<!-- 批量保存(foreach插入多条数据两种方法)
       int addEmpsBatch(@Param("emps") List<Employee> emps); -->
<!-- MySQL下批量保存,可以foreach遍历 mysql支持values(),(),()语法 --> //推荐使用
<insert id="addEmpsBatch">
    INSERT INTO emp(ename,gender,email,did)
    VALUES
    <foreach collection="emps" item="emp" separator=",">
        (#{emp.eName},#{emp.gender},#{emp.email},#{emp.dept.id})
    </foreach>
</insert>

具体参见博客

10、java集合有哪些

List接口有三个实现类:

1.1 LinkedList
基于链表实现,链表内存是散列的,增删快,查找慢;
1.2 ArrayList
基于数组实现,非线程安全,效率高,增删慢,查找快;
1.3 Vector
基于数组实现,线程安全,效率低,增删慢,查找慢;

Map接口有四个实现类:

2.1HashMap
基于 hash 表的 Map 接口实现,非线程安全,高效,支持 null 值和 null
键;
2.2HashTable
线程安全,低效,不支持 null 值和 null 键;
2.3 LinkedHashMap
是 HashMap 的一个子类,保存了记录的插入顺序;
2.4 SortMap 接口
TreeMap,能够把它保存的记录根据键排序,默认是键值的升序排序

Set接口有两个实现类:

3.1 HashSet
底层是由 Hash Map 实现,不允许集合中有重复的值,使用该方式时需要重写 equals()和 hash Code()方法;
3.2LinkedHashSet
继承于 HashSet,同时又基于 LinkedHashMap 来进行实现,底层使用的是 LinkedHashMap

11、list和数组的区别

①数据是大小固定的,而list的大小可以变化;

②数组可以存储基本类型数据和引用类型数据(基本类型/引用类型),而list只能存储引用类型变量;

③数组只能存储类型一样的数据,而list不做要求;

④list按放入的顺序来给数据排序,而数据按照下标排序;

数组转 List:使用 JDK 中 java.util.Arrays 工具类的 asList 方法

public static void testArray2List() {
	String[] strs = new String[] {"aaa", "bbb", "ccc"};
	List<String> list = Arrays.asList(strs);
	for (String s : list) {
		System.out.println(s);
	}
}

List 转数组:使用 List 的toArray方法。无参toArray方法返回Object数组,传入初始化长度的数组对象,返回该对象

public static void testList2Array() {
	List<String> list = Arrays.asList("aaa", "bbb", "ccc");
	String[] array = list.toArray(new String[list.size()]);
	for (String s : array) {
		System.out.println(s);
	}

12、HashMap怎样实现

数组加链表 key(键)和value(值)都可以存储null,key不允许重复,因此只能有一个键为null,另外HashMap不能保证放入元素的顺序,它是无序的,和放入的顺序并不能相同。线程不安全,但效率极高。

13、HashMap和Hashtable的区别有哪些

线程安全:Hashtable线程安全:Hashtable的实现方法里面都添加了synchronized关键字来确保线程同步。HashMap不安全。
null不同:HashMap可以使用null作为key,而Hashtable则不允许null作为key
继承结构:HashMap是对Map接口的实现,HashTable实现了Map接口和Dictionary抽象类
初始容量与扩容:

HashMap的初始容量为16,Hashtable初始容量为11,两者的填充因子默认都是0.75。
HashMap扩容时是当前容量翻倍即:capacity2,Hashtable扩容时是容量翻倍+1即:capacity2+1。

两者计算hash的方法不同:

Hashtable计算hash是直接使用key的hashcode对table数组的长度直接进行取模
HashMap计算hash对key的hashcode进行了二次hash,以获得更好的散列值,然后对table数组长度取模。

14、接口和抽象类的区别

抽象类表示的是,这个对象是什么。接口表示的是,这个对象能做什么。
①接口是抽象类的变体,接口中所有的方法都是抽象的。而抽象类是声明方法的存在而不去实现它的类
②接口可以多继承,抽象类不行
③接口定义方法,不能实现,而抽象类可以实现部分方法。
④接口中基本数据类型为static 而抽类象不是的。

15、java创建对象的几种方法

构造器:

①使用New关键字
②使用Class类的newInstance方法,newInstance方法调用无参构造器创建对象(反射)sClass.forName.newInstance();

无构造器:

③使用clone方法
反序列化

在这里插入图片描述

16、javaBean四大作用域

page 仅在当前页面有效

request 请求范围,可以通过HttpRequest.getAttribute()方法获取JavaBean对象

session 会话范围,可以通过HttpSession.getAttribute()方法获取JavaBean对象

application 全局范围, 可以通过application.getAttribute()方法获取JavaBean对象

17、javaWeb连接数据库的四大信息是什么

IP、port、username、password

<!--    四大信息 -->
       <property name="driver" value="com.mysql.jdbc.Driver"/>
       <property name="url" value="jdbc:mysql://localhost:3306/mybatis02?characterEncoding=utf-8"/>
       <property name="username" value="root"/>
       <property name="password" value="123456"/>

18、加载驱动的方法有哪些

Class.forName(“com.microsoft.sqlserver.jdbc.SQLServerDriver”);
DriverManager.registerDriver(newcom.mysql.jdbc.Driver());
System.setProperty(“jdbc.drivers”,”com.mysql.jdbc.Driver”);

19、java有哪些数据类型,对应的包装类是什么

数值型:
①整数类型(byte,short,int,long)
②浮点类型(float,double)
字符型(char)
布尔型(boolean)
在这里插入图片描述

20、请列举一些String的方法

①length() 查看长度
②hashCode() 查看哈希码
③equals() 判断内容是否相等
④split() 根据字符进行分割
⑤idnexOf() 查看字符第一次出现的位置
⑥concat() 拼接字符串到尾部
⑦charAt() 返回字符出现的位置
⑧replace() 替换字符
⑨compareTo() 按数据字典的顺序进行比较
在这里插入图片描述
在这里插入图片描述

21、git常用命令有哪些

参考博文

ls   //查看
cd    //切换路径

git init // 初始化 在工作路径上创建主分支
git clone 地址 // 克隆远程仓库
git clone -b 分支名 地址 // 克隆分支的代码到本地
git status // 查看状态
git add 文件名 // 将某个文件存入暂存区
git add b c //把b和c存入暂存区
git add . // 将所有文件提交到暂存区
git add -p 文件名 // 一个文件分多次提交
git stash -u -k // 提交部分文件内容 到仓库 例如本地有3个文件 a b c 只想提交a b到远程仓库 git add a b 然后 git stash -u -k 再然后git commit -m "备注信息" 然后再push push之后 git stash pop 把之前放入堆栈的c拿出来 继续下一波操作
git commit -m "提交的备注信息"  // 提交到仓库
若已经有若干文件放入仓库,再次提交可以不用git add和git commit -m "备注信息"2步, 直接用
git commit -am "备注信息" // 将内容放至仓库 也可用git commit -a -m "备注信息"
* git commit中的备注信息尽量完善 养成良好提交习惯 例如 git commit -m "变更(范围):变更的内容"


git config --list // 获取config信息
git config --global core.safecrlf false // 去掉git add 命令后 出现的一堆CR LF提示信息
其中CR是回车的意思 LF是换行
git config --global credential.helper wincred // 存储凭证 (可用于输入一次用户密码后,不再输入 有时我们已经用SSH key 绑定关联好了 但是每次git提交的时候 还是需要你输入用户名密码 在这个时候 敲入这个命令 将凭证存储起来 用户名密码就不需要再次输入了)
git config --global alias.ci commit // 将commit命令设置别名ci git commit命令将由git ci来代替

git push  XXXmaster

22、Linux常用命令你知道哪些

pwd # 查看你当前所在的目录
cd # 切换目录
ls # 查看显示目录的内容
du # 统计目录和文件空间的占用情况
mkdir # 创建新目录
rmdir # 删除空目录
touch # 创建文件
rm # 删除文件
ln # 创建硬链接
ln -s # 创建软链接
cp # 复制文件或目录
mv # 移动文件或目录
which # 查看linux命令所在的目录
v  #进入编译器

23、索引

索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。相当于图书的目录,可以根据目录中的页码快速找到所需的内容。
②常见的索引类型有:主键索引、唯一索引、普通索引、全文索引、组合索引

1、主键索引:即主索引,根据主键pk_clolum(length)建立索引,不允许重复,不允许空值;
ALTER TABLE ‘table_name’ ADD PRIMARY KEY pk_index(‘col’);

2、唯一索引:用来建立索引的列的值必须是唯一的,允许空值
ALTER TABLE ‘table_name’ ADD UNIQUE index_name(‘col’);

3、普通索引:用表中的普通列构建的索引,没有任何限制
ALTER TABLE ‘table_name’ ADD INDEX index_name(‘col’);

4、全文索引:用大文本对象的列构建的索引(下一部分会讲解)
ALTER TABLE ‘table_name’ ADD FULLTEXT INDEX ft_index(‘col’);

5、组合索引:用多个列组合构建的索引,这多个列中的值不允许有空值
ALTER TABLE ‘table_name’ ADD INDEX index_name(‘col1’,‘col2’,‘col3’);

③什么时候要使用索引?

①主键自动建立唯一索引;
②经常作为查询条件在WHERE或者ORDER BY 语句中出现的列要建立索引;
③作为排序的列要建立索引;
④查询中与其他表关联的字段,外键关系建立索引
⑤高并发条件下倾向组合索引;
⑥用于聚合函数的列可以建立索引,例如使用了max(column_1)或者count(column_1)时的column_1就需要建立索引

24、Servlet的生命周期是什么

Servlet 加载—>实例化—>服务—>销毁。

init():
在Servlet的生命周期中,仅执行一次init()方法。它是在服务器装入Servlet时执行的,负责初始化Servlet对象。可以配置服务器,以在启动服务器或客户机首次访问Servlet时装入Servlet。无论有多少客户机访问Servlet,都不会重复执行init()。

service():
它是Servlet的核心,负责响应客户的请求。每当一个客户请求一个HttpServlet对象,该对象的Service()方法就要调用,而且传递给这个方法一个“请求”(ServletRequest)对象和一个“响应”(ServletResponse)对象作为参数。在HttpServlet中已存在Service()方法。默认的服务功能是调用与HTTP请求的方法相应的do功能。

destroy():
仅执行一次,在服务器端停止且卸载Servlet时执行该方法。当Servlet对象退出生命周期时,负责释放占用的资源。一个Servlet在运行service()方法时可能会产生其他的线程,因此需要确认在调用destroy()方法时,这些线程已经终止或完成。

25、如果不使用eclipse、idea等工具,我要直接运行一个项目,此时,我想修改tomcat的端口为80xx,怎么改?

①在Tomcat的根(安装)目录下,有一个conf文件夹,双击进入conf文件夹,在里面找到Server.xml文件,打开该文件。
其次:在文件中找到如下文本:
< Connector port=“8080” protocol=“HTTP/1.1” maxThreads=“150” connectionTimeout=“20000” redirectPort=“8443” />
也有可能是这样的:
< Connector port=“8080” maxThreads=“150” minSpareThreads=“25” maxSpareThreads=“75” enableLookups=“false” redirectPort=“8443” acceptCount=“100” debug=“0” connectionTimeout=“20000” disableUploadTimeout=“true” />等等;

最后:将port="8080"改为其它的就可以了。如port="8081"等。
保存server.xml文件,重新启动Tomcat服务器,Tomcat就可以使用8081端口了。
注意,有的时候要使用两个tomcat,那么就需要修改其中的一个的端口号才能使得两个同时工作。
修改了上面的以后,还要修改两处:
(1)将 < Connector port=“8009” enableLookups=“false” redirectPort=“8443” debug=“0”
protocol=“AJP/1.3” />的8009改为其它的端口。
(2) 继续将< Server port=“8005” shutdown=“SHUTDOWN” debug=“0”>的8005改为其它的端口。
经过以上3个修改,应该就可以了。
在这里插入图片描述

Eclipse修改tomcat端口号:
在这里插入图片描述



昨天面试实在是太紧张了,以至于忘了一些题目,后面我会继续补充,有错误的地方,麻烦指正。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
java面经-百度准入职老哥整理.pdf》是一份关于百度准入职面试Java面经整理。这份面经是由百度准入职的老哥整理而成,其中记录了一些面试时可能会遇到的问题以及解答方法。 这份面经对于准备参加百度准入职面试的人来说非常有价值。首先,它列出了一些常见的面试问题,涵盖了Java语言的各个方面,包括基础知识、数据结构与算法、设计模式、多线程、网络编程等等。通过仔细研究和复习这些问题的答案,可以帮助面试者全面了解Java语言的特性和应用。 其次,这份面经还提供了问题的解答思路和方法,帮助面试者理清思路,正确回答问题。这对于很多面试者来说特别有帮助,因为在面试时有时会遇到一些棘手的问题,有了这份面经的指导,面试者可以更好地掌握应对策略。 不过需要注意的是,面经作为一份参考资料,不能全依赖于它来准备面试面试官可能会问一些不在面经中列出的问题,因此考生还是需要自己对Java语言有充分的了解,并能够熟练运用。同时,面试官还会关注考生的沟通能力、解决问题的能力以及对新技术的学习和掌握能力。 总体来说,《java面经-百度准入职老哥整理.pdf》是一份非常宝贵的资料,可以帮助面试者对Java面试中可能会遇到的问题有更深入的了解,提供了解答思路和方法。但记住,面试准备还需要多方面的知识积累和实践经验的积累,才能在面试中展现自己的优势。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值