avatar

面试题汇总

以下内容参考了大量互联网博主、GPT人工智能以及本人亲自面试后累积的面试题目整理笔记,分享有缘人!

优质渠道推荐:

前端渡劫秘籍 前端面试题汇总 互联网大厂面试每日一题 前端内参

Java学习|面试指南 Java学习笔记 『Java八股文』


前端面试常见问题汇总

CSS问题

1.flex布局
2.css3的新特性
3.img中alt和title的区别
4.用纯CSS创建一个三角形
5.如何理解CSS的盒子模型?
6.如何让一个div水平居中
7.如何让一个div水平垂直居中
8.如何清除浮动?
9.css3实现三栏布局,左右固定,中间自适应
10.display:none 和 visibility: hidden的区别
11.CSS中 link 和@import 的区别是?
12.position的absolute与fixed共同点与不同点
13…transition和animation的区别
14.CSS优先级

雪碧图

雪碧图(Sprite Sheet)是将多个小图标或小图片合并到一张大图中的技术。通过使用雪碧图,可以减少网页加载的请求数量,提高网页的加载速度。

使用雪碧图的步骤如下:

  1. 将需要合并的小图标或小图片收集到一起。
  2. 使用图像编辑工具(如Photoshop)将这些小图标或小图片合并到一张大图中,保持它们之间有一定的间距。
  3. 在CSS中,为每个小图标或小图片创建对应的样式类,并设置背景图为合并后的大图。
  4. 使用 background-position属性来指定每个小图标或小图片在大图中的位置。
  5. 在HTML中,使用对应的样式类来应用雪碧图。

通过使用雪碧图,可以减少网页加载的请求数量,从而提高网页的加载速度。同时,还可以通过调整 background-position属性来显示不同的小图标或小图片,实现动画效果或状态切换。

JS问题

1.typeof和instance of 检测数据类型有什么区别?
2.使元素消失的方法
3.es6的新特性都有哪些?
4.和=区别是什么?
5.常见的设计模式有哪些?
6.call bind apply 的区别?
7.js继承方式有哪些?
8.你怎样看待闭包?
9.你是如何理解原型和原型链的?
10.浏览器渲染的主要流程是什么?
11.从输入url地址到页面相应都发生了什么?
12.session、cookie、localStorage的区别
13.js中跨域方法
14.前端有哪些页面优化方法?
15.Ajax的四个步骤
16.数组去重的方法
17.ajax中get和post请求的区别
18.ajax的状态码
19.移动端的兼容问题
20.JS中同步和异步,以及js的事件流
24.DOM diff原理
25.作用域、全局作用域
26.Promise处理异步
27.map和forEach的区别、相同点
28.async await函数
29.this指向
30.原型
31.异步回调

如何解决回调地狱问题?

使用 Promise 对象、async/await 语句或第三方库可以有效地解决 JavaScript 中的回调地狱问题。建议您根据自己的需求选择合适的方法。

32.前端事件流
33.事件如何先捕获后冒泡?
34.如何判断一个变量是对象还是数组(prototype.toString.call())。
35.setTimeout 和 setInterval的机制
36.splice和slice、map和forEach、 filter()、reduce()的区别

VUE问题

1.聊聊对vue的理解
2.V-model的原理是什么?
3.谈谈对生命周期的理解
4.VUE和REACT有什么区别?
5.vuex的流程
6.vuex有哪几种状态和属性
7.vue路由的两种模式
8.vue中 key 值的作用
9 r o u t e 和 route和 route和router的区别
10.vue-router守卫
11.axios是什么?怎么使用?描述使用它实现登录功能的流程?
12.vue修饰符
13.vue项目中的性能优化
14.vue.extend和vue.component

React问题

1.react和vue的区别
2.redux中的reducer(纯函数)
3.react的refs
4.react中的keys
5.React的生命周期
6.React子组件向父组件传值
7.为什么虚拟DOM会提高性能
8.diff算法
9.简述下flux的思想
10.reac性能优化是哪个周期函
11.react怎么划分业务组件和技术组件
12.setState

性能优化类

1.webpack打包文件体积过大?(最终打包为一个js文件)
2.如何优化webpack构建的性能
3.移动端的性能优化
4.Vue的SPA 如何优化加载速度
5.移动端300ms延迟
6.页面的重构

前端面试问题

Axios

axios 是什么

  • Axios 是一个基于 promiseHTTP 库,可以用在浏览器和 node.js 中。前端最流行的 ajax 请求库,
  • react/vue 官方都推荐使用 axiosajax 请求
  • 基于 XMLHttpRequest 服务来执行 HTTP 请求,支持丰富的配置,支持 Promise,支持浏览器端和 Node.js 端。自 Vue2.0起,尤大宣布取消对 vue-resource 的官方推荐,转而推荐 axios。现在 axios 已经成为大部分 Vue 开发者的首选。

axios 特点

  • 基于 promise 的异步 ajax 请求库,支持 promise所有的 API
  • 浏览器端/node 端都可以使用,浏览器中创建 XMLHttpRequests
  • 支持请求/响应拦截器
  • 支持请求取消
  • 可以转换请求数据和响应数据,并对响应回来的内容自动转换成 JSON类型的数据
  • 批量发送多个请求
  • 安全性更高,客户端支持防御 XSRF,就是让你的每个请求都带一个从 cookie中拿到的 key, 根据浏览器同源策略,假冒的网站是拿不到你 cookie中得 key的,这样,后台就可以轻松辨别出这个请求是否是用户在假冒网站上的误导输入,从而采取正确的策略

为什么要二次封装

axios 的 API 很友好,你完全可以很轻松地在项目中直接使用。

不过随着项目规模增大,如果每发起一次 HTTP请求,就要把这些比如设置超时时间、设置请求头、根据项目环境判断使用哪个请求地址、错误处理等等操作,都需要写一遍

这种重复劳动不仅浪费时间,而且让代码变得冗余不堪,难以维护。为了提高我们的代码质量,我们应该在项目中二次封装一下 axios 再使用。

Vue浅拷贝和深拷贝

浅拷贝

指的是创建新的数据,这个数据有着原始数据属性值的一份精确拷贝;

如果属性是基本类型,拷贝的就是基本类型的值。如果属性是引用类型,拷贝的就是内存地址;

即浅拷贝是拷贝一层,深层次的引用类型则共享内存地址。

存在浅拷贝的现象:

  • Object.assign
  • Array.prototype.slice(), Array.prototype.concat()
  • 使用拓展运算符实现的复制

深拷贝

深拷贝开辟一个新的栈,两个对象属完成相同,但是对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性

常见的深拷贝方式有:

  • _.cloneDeep()
  • jQuery.extend()
  • JSON.stringify():但是这种方式存在弊端,会忽略 undefinedsymbol函数
  • 手写循环递归

小结

前提为引用类型的情况下:

  • 浅拷贝是拷贝一层,属性为对象时,浅拷贝是复制,两个对象指向同一个地址
  • 深拷贝是递归拷贝深层次,属性为对象时,深拷贝是新开栈,两个对象指向不同的地址

防抖和节流

在Vue中,防抖(Debounce)和节流(Throttle)是常用的优化技术,用于控制事件的触发频率,提升性能和用户体验。

防抖和节流的区别在于触发事件的时机和执行次数:

  1. 防抖(Debounce):在事件触发后的一段时间内,如果事件再次被触发,则重新计时。只有在事件停止触发一段时间后,才会执行事件处理函数。防抖常用于处理频繁触发的事件,如窗口大小改变、输入框输入等。
  2. 节流(Throttle):在事件触发后的一段时间内,无论事件再次被触发多少次,都只会执行一次事件处理函数。节流常用于限制事件的触发频率,如滚动事件、鼠标移动事件等。

在Vue中,可以通过以下方式实现防抖和节流:

  1. 防抖(Debounce):
1
2
3
4
5
6
7
8
9
10
11
12
// 使用Lodash库的debounce函数
import { debounce } from 'lodash';

export default {
// ...
methods: {
// 使用防抖函数包装事件处理函数
handleInput: debounce(function() {
// 处理事件
}, 300), // 设置防抖的延迟时间
},
};
  1. 节流(Throttle):
1
2
3
4
5
6
7
8
9
10
11
12
// 使用Lodash库的throttle函数
import { throttle } from 'lodash';

export default {
// ...
methods: {
// 使用节流函数包装事件处理函数
handleScroll: throttle(function() {
// 处理事件
}, 300), // 设置节流的间隔时间
},
};

在上述代码中,我们使用了Lodash库的 debouncethrottle函数来实现防抖和节流。这两个函数接受两个参数:要包装的函数和延迟时间(对于防抖)或间隔时间(对于节流)。通过将事件处理函数传递给这些函数,可以实现防抖和节流的效果。

需要注意的是,防抖和节流函数的使用需要安装Lodash库。可以通过npm或yarn安装Lodash库,并在代码中导入相应的函数。

总结起来,防抖和节流是Vue中常用的优化技术,用于控制事件的触发频率。通过使用Lodash库的 debouncethrottle函数,可以方便地实现防抖和节流效果,提升性能和用户体验。

应用场景

防抖:

实时搜索:当用户在搜索框中输入关键字时,防抖可以用来延迟发送搜索请求。只有在用户停止输入一段时间后,才会触发实际的搜索操作,避免频繁的请求。
窗口调整:当窗口大小调整时,防抖可以用来确保只有在用户停止调整窗口大小后,才会触发相应的重新布局或重绘操作。
按钮点击:当用户点击一个按钮时,防抖可以用来防止用户多次点击造成的重复操作。只有在用户点击后等待一段时间后,才会执行按钮的逻辑操作。

节流:

页面滚动:当用户滚动页面时,节流可以用来限制触发滚动事件的频率,从而减少滚动事件处理的次数,提高页面的流畅度。
鼠标移动:当用户在页面上移动鼠标时,节流可以用来控制鼠标移动事件的触发频率,以避免过多的事件处理操作。
实时定位:当需要获取用户的实时位置信息时,节流可以用来限制位置更新事件的触发频率,避免过多的位置更新操作。

组件之间的传值方式

Vue常用的三种传值方式有:

  • 父传子
  • 子传父
  • 非父子传值

父子组件传值

父传子的关键:父组件在标签上传递,子组件通过 props接收。

1.父组件中(传递)

1
2
3
4
5
6
7
8
9
10
11
12
//1引入子组件
import zizujian from '@/components/login.vue'

//2注册子组件
export default {
components: {
zizujian
},
}

//3在template中以标签的形式载入,通过数据绑定的形式进行传值
<zizujian :userinfo="userinfo"></zizujian >

2.子组件中(接收)

1
2
3
4
5
//1通过props接收父组件传过来的值
props:['userinfo']

//2在标签中直接使用
<view>{{userinfo}}</view>

子父组件传值

子传父的关键:子组件通过 事件 this.$emit来向父组件传值。

1.子组件中:(传递)

1
2
3
4
5
6
7
8
9
10
11
12
//1通过事件传值
<view @click="sonlick">点击按钮</view>
<script>
export default{
methods:{
//2点击事件-向父组件传值
sonlick(){
this.$emit("sendData",this.userinfo)
},
}
}
</script>

2.父组件中:(接收)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//1引入子组件
<script>
import zizujian from '@/components/login.vue'

export default {
//2注册子组件
components: {
zizujian
},

methods:{
//3通过事件接收
getSonData(res){
console.log('子组件的内容',res)
this.avatarUrl = res.avatarUrl
this.nickName = res.nickName
},
}
}
</script>

//4在template中以标签的形式载入
<zizujian @sendData="getSonData"></zizujian >

兄弟组件传值

组件之间的传值,完全可以通过自定义事件中心,避免多个组件参与传递数据的复杂度!

1.定义事件中心 src/utils/events.js,在两个兄弟组件中同时导入(主要用于数据传递)

1
2
3
4
5
6
7
8
9
**
* 自定义事件中心
* events.js
*/
import Vue from "vue"

const vm = new Vue()

export default vm

2.组件A发送数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<template>
<button @click="sendData2">
发送数据给其他组件
</button>
</template>

<script>
// 导入事件中心
import vm from "../utils/event"

export default {
data() {
return {
msg: "子组件数据"
}
},
methods : {
sendData2() {
// 事件中心 触发自定义事件
vm.$emit("customEvent", this.msg)
}
}
}
</script>

3.组件B接收数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<template>
<p>
等待接受数据:{{ }}
</p>
</template>

<script>
// 导入事件中心
import vm from "../utils/event"

export default {

created() {
// 组件加载的时候执行函数,监听自定义事件
this.getData();
},
data() {
return {
dataFromOther: "等待接受"
}
},
methods: {
getData() {
vm.$on("customEvent", value => {
// 接受自定义事件传递的数据
this.dataFromOther = value
})
}
}
}
</script>

Vue可以操作下标的方式修改数组的值吗?

Vue使用了一些特殊的技巧来追踪数组的变化,以便在数据变化时更新视图。这些技巧包括劫持数组的方法,例如 pushpopshiftunshiftsplicesortreverse。当使用这些方法修改数组时,Vue能够检测到数组的变化并更新视图。

然而,直接通过修改数组的下标来改变数组的值,Vue无法追踪这种变化,因为它无法劫持这种操作。这意味着,如果直接修改数组的下标,视图不会自动更新。

为了解决这个问题,Vue提供了一个特殊的方法 Vue.set(或 this.$set)来修改数组的值。这个方法接受三个参数:数组、下标和新的值。通过使用 Vue.set方法,Vue能够追踪数组的变化并更新视图。

Vue箭头函数和普通函数的区别

  • 箭头函数没有自己的 this,它会继承外层作用域的 this。而普通函数的 this是在运行时确定的,根据函数的调用方式决定。
  • 箭头函数不能作为构造函数使用,不能使用 new关键字实例化对象。
  • 箭头函数没有 arguments对象,可以使用剩余参数(rest parameters)来获取函数的参数。
  • 箭头函数不能使用 yield关键字,不能用作生成器函数。

v-model双向绑定原理

  • v-model指令是Vue提供的语法糖,用于实现表单元素的双向数据绑定。
  • 在组件中使用 v-model时,实际上是将 value属性和 input事件绑定到了组件的属性和方法上。
  • 当用户在表单元素中输入内容时,会触发 input事件,组件会更新内部的数据,并通过 value属性将新的值传递给父组件。
  • 当父组件更新了传递给子组件的值时,子组件会通过 props接收到新的值,并将其赋值给内部的数据,从而更新表单元素的值。

重排和重绘的区别

  • 重排(reflow)是指浏览器重新计算元素的位置和几何属性,然后重新构建渲染树的过程。重排会导致页面的布局发生改变,需要重新计算元素的位置和大小,性能开销较大。
  • 重绘(repaint)是指浏览器重新绘制元素的外观,但不会改变元素的布局。重绘不会改变元素的位置和大小,只会改变元素的样式,性能开销较小。
  • 重排和重绘通常是由于DOM的改变或者浏览器窗口的改变引起的。

Vue2和Vue3底层的区别

  • Vue2使用的是基于Object.defineProperty的响应式系统,而Vue3使用的是基于Proxy的响应式系统。Proxy相比Object.defineProperty具有更强大的功能和更好的性能。
  • Vue3对编译器进行了重写,使用了更快的编译算法,生成更小的代码包。
  • Vue3引入了Composition API,提供了更灵活和可组合的组件逻辑复用方式。
  • Vue3对虚拟DOM进行了优化,提升了渲染性能。
  • Vue3对TypeScript的支持更好,提供了更好的类型推断和类型检查。

Webpack打包的使用

  • 配置webpack.config.js文件,定义入口文件、输出文件、加载器、插件等。
  • 运行 webpack命令进行打包,或者使用 webpack-dev-server进行开发环境的实时打包和热更新。
  • 可以使用各种加载器(loader)来处理不同类型的文件,例如babel-loader处理ES6语法、css-loader处理CSS文件、file-loader处理图片文件等。
  • 可以使用各种插件(plugin)来扩展webpack的功能,例如HtmlWebpackPlugin生成HTML文件、MiniCssExtractPlugin提取CSS文件等。

Gulp和Webpack工具

Gulp和Webpack都是流行的前端构建工具,但它们的功能和用途有所不同。

Gulp是一个任务运行器,用于自动化重复性任务,例如:

  • 编译 Sass 或 Less 代码为 CSS
  • 压缩和混淆 JavaScript 代码
  • 复制文件和文件夹
  • 启动 Web 服务器
  • 运行测试

Gulp 的使用非常简单,只需要编写一些 JavaScript 代码即可。Gulp 提供了大量的插件,可以扩展其功能。

Webpack 是一個模块捆绑器,它可以将你的项目中的所有 JavaScript 模块打包成一个文件。Webpack 还提供了许多其他功能,例如:

  • 代码拆分(code splitting):将代码拆分成多个文件,以便在需要时加载
  • 懒加载(lazy loading):仅在需要时加载模块
  • 树形摇晃(tree shaking):删除未使用的代码
  • 支持各种预处理器

Webpack 的使用相对复杂一些,需要编写配置文件。但是,Webpack 可以为你提供更强大的功能和更好的性能。

Gulp和Webpack的区别

特性 Gulp Webpack
主要功能 任务运行器 模块捆绑器
用途 自动化重复性任务 将多个JavaScript模块组合成单个文件
配置 使用JavaScript代码 使用JSON或JavaScript配置文件
优势 简单易用、灵活 功能强大、性能优异
劣势 不擅长处理复杂的模块依赖关系 配置相对复杂

Gulp和Webpack的选择

  • 如果您的项目需要自动化大量重复性任务,那么Gulp是一个很好的选择。
  • 如果您的项目需要将多个JavaScript模块组合成单个文件,那么Webpack是一个很好的选择。
  • 您也可以将Gulp和Webpack结合使用。例如,您可以使用Gulp来自动化任务,例如编译Sass或Less和压缩图像,然后使用Webpack来将多个JavaScript模块组合成单个文件。

Promise的原理

  • Promise是一种用于处理异步操作的对象,它可以将异步操作的结果以同步的方式进行处理。
  • Promise有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。
  • Promise通过 then方法来注册回调函数,当异步操作完成时,会调用相应的回调函数。
  • Promise的构造函数接受一个执行器函数,该函数有两个参数:resolvereject。当异步操作成功时,调用 resolve函数;当异步操作失败时,调用 reject函数。
  • Promise可以通过 then方法链式调用,可以在 then方法中返回一个新的Promise对象,实现串行的异步操作。
  • Promise还提供了 catch方法用于捕获错误,以及 finally方法用于在Promise结束时执行一些操作。

async/await异步处理方式和原理

在 ES7 中引入的 async/await 是用于简化异步 JavaScript 编程的语法糖,它建立在 Promise 的基础上。让我们逐步解释 async/await 的工作原理以及 Promise 的作用:

  1. Promise 的作用:
    • Promise 是 JavaScript 中用于处理异步操作的对象。它代表了一个异步操作的最终完成(或失败)及其结果的承诺。
    • Promise 对象有三种状态:Pending(等待态)、Fulfilled(完成态)和Rejected(拒绝态)。当异步操作完成时,Promise 会从 Pending 转变为 Fulfilled;当异步操作失败时,Promise 会从 Pending 转变为 Rejected。
    • Promise 提供了 then() 方法来处理异步操作的结果,通过链式调用 then() 方法可以实现异步操作的串行执行,也可以通过 catch() 方法来捕获异步操作的错误。
  2. async/await 的异步处理方式和原理:
    • async 函数是一个返回 Promise 对象的函数,使用 async 关键字声明的函数会自动将返回值封装成 Promise 对象。
    • await 关键字只能在 async 函数内部使用,用于等待 Promise 对象的解决(resolve)或拒绝(reject),并返回异步操作的结果。
    • 使用 async/await 可以让异步代码看起来更像同步代码,提高了代码的可读性和可维护性。async/await 的工作原理是基于 Promise 对象,它实际上是 Promise 的语法糖。
    • 在 async 函数内部使用 await 关键字等待异步操作的结果时,该 async 函数会暂停执行,直到异步操作完成并返回结果,然后再继续执行下一条语句。
    • 如果异步操作成功解决(resolve),await 表达式会返回解决的值;如果异步操作失败(reject),await 表达式会抛出异常,可以通过 try/catch 来捕获异常。

简而言之,async/await 是一种更加直观、清晰的异步处理方式,它建立在 Promise 的基础上,通过使用 async/await 可以让异步代码更加易读、易写。Promise 则是实际处理异步操作的机制,提供了一种可靠的异步处理方式。

var与let的区别

  • var声明的变量存在变量提升,可以在声明之前使用,而let声明的变量不存在变量提升,必须在声明之后使用。
  • var声明的变量作用域是函数作用域,而let声明的变量作用域是块级作用域。
  • var声明的变量可以被重复声明,而let声明的变量不能被重复声明。
  • var声明的变量会被提升到函数作用域的顶部,而let声明的变量不会被提升。
  • 在全局作用域中,使用var声明的变量会成为全局对象的属性,而使用let声明的变量不会成为全局对象的属性。

服务端常见面试问题汇总

数据库

  1. 建立分区表的步骤:

    • 首先,选择适合分区的列作为分区键,例如日期、地区等。
    • 创建分区函数,定义如何将数据分布到不同的分区中。
    • 创建分区方案,指定分区函数和分区键,确定分区的数量和范围。
    • 创建分区表,使用 CREATE TABLE语句创建表时,通过 PARTITION BY子句指定分区方案。
  2. 提高SQL查询效率的方法:

    • 创建合适的索引,索引可以加快查询的速度。根据查询的字段和条件,创建适当的索引。
    • 编写高效的查询语句,避免使用不必要的子查询和复杂的连接操作。
    • 使用合适的数据类型,选择合适的数据类型可以减少存储空间和提高查询效率。
    • 对大表进行分区,将大表分成多个小表,可以提高查询的效率。
    • 使用合适的缓存策略,例如使用缓存数据库或缓存中间件来缓存查询结果。
    • 对频繁查询的字段进行冗余存储,避免多表关联查询。
  3. 防止SQL注入的方法:

    • 使用参数化查询或预编译语句,将用户输入的数据作为参数传递给SQL语句,而不是直接拼接到SQL语句中。
    • 对用户输入的数据进行合法性验证,例如检查输入是否符合预期的格式和范围。
    • 对用户输入的数据进行转义处理,将特殊字符转义为安全的字符,防止恶意注入。
    • 限制数据库用户的权限,避免给予过高的权限,以防止恶意操作。
    • 定期更新和升级数据库软件,以修复已知的安全漏洞。
    • 使用防火墙和安全策略来限制对数据库的访问,只允许受信任的主机和用户访问数据库。

应用

  • 报错怎么排查
  • 有没有写过公函
  • 后端服务怎么开发
  • springboot注解有没有使用过,怎么使用,怎么新增注解
  • SpringIOC的原理
  • 实时同步和强实时同步
  • 如何做超时任务处理本系统内处理
  • MySQL内生僻字用什么类型
  • Java字符集编码区别

springboot常用组件

spring的Ioc和AOP,反射机制

springMVC的理解

cookie和session

考查会话跟踪技术

多线程的创建实现方法

使用过radius数据库吗

研发公司面试后端题

  1. 数据结构和算法有多了解?
  2. 多线程的实现
  3. JVM和GC缓存机制
  4. SQL的优化
  5. long类型的理解,比如数据量大的话会发生什么变化
  6. 工作中常用的Linux命令
  7. Spring,SpringMVC,Springboot的区别
  8. 对Vue的生命周期的理解
  9. BootStrap框架的使用
  10. Springboot data Jpa和mybatis的差别

公司使用技术:Springboot、 Vue、mybatisPlus、Radius、MySQL和网关等一系列最新技术进行架构整合。

面试感受:公司主要是做APP产品研发的,没有APP经验不会让你去上手,只是想招后台系统的Java开发进行项目迭代优化。果然做研发的技术官给外包出来的程序员多少都是歧视的。说银行外包使用的技术都是老掉牙的技术,这个确实没毛病,个人觉得还是得打好扎实的Java基础,和学习最新的进阶的流行技术,才能有机会进入创业研发的公司。

简述索引存取的方法的作用和建立索引的原则?

建立索引的作用:加快查询速度
建立索引的原则
1.如果某属性经常出现在查询条件中,考虑为该属性建立索引。
2.如果某属性常作为最大值和最小值等聚集函数的参数考虑为该属性建立索引。
3.如果属性经常出现在连接操作的连接条件中,考虑为该属性建立索引。

、在java异常体系结构中,error与exception的区别是什么?
error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。
exception 表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况。
2、说出ArrayList,Vector, LinkedList的区别?
ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快
3、final, finally, finalize的区别?
final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。finally是异常处理语句结构的一部分,表示总是执行。finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。
4、HashMap和Hashtable的区别。
(1)HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key)。
(2)由于非线程安全,效率上可能高于Hashtable。
(3)HashMap允许将null作为一个entry的key或者value,而Hashtable不允许。
HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。
(4)Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现。
(5)最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。

String 类是否可以被继承?

被final 关键字修饰的类是不可以被继承的,没有被final 关键字修饰的类则可以被继承,可以派生新的子类,而String 类是使用final 关键字修饰的类,所以它不能被继承。

Java 创建线程池的四种方法

Java通过Executors提供四种线程池,分别为:

newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。

newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

线程池的作用:

线程池作用就是限制系统中执行线程的数量。
根 据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果;少了浪费了系统资源,多了造成系统拥挤效率不高。用线程池控制线程数量,其他线程排 队等候。一个任务执行完毕,再从队列的中取最前面的任务开始执行。若队列中没有等待进程,线程池的这一资源处于等待。当一个新任务需要运行时,如果线程池 中有等待的工作线程,就可以开始运行了;否则进入等待队列。

为什么要用线程池:

1.减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。

2.可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。

后端面试问题

以下内容是面试过程中常见的问题,根据自己的理解和总结进行简要描述。

详细参考链接:https://www.cnblogs.com/bailing80/p/11443409.html

‘==’,equals与compareTo区别

  • 基本类型:比较的就是值是否相同
  • 引用类型:比较的就是地址值是否相同
  • 对于第二种类型,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。因为每new一次,都会重新开辟堆内存空间。

==是对对象地址的比较,而equals是对对象内容的比较。对于基本数据类型,一般用==,而对于字符串的比较,一般用equals

compareTo(): 这个函数的作用就是对两个字符串按字典排序的方式进行比较,返回两个字符串中第一个不同的字符的ascII码差值。

springBoot和SpringMVC的区别

两者联系

spring在刚开始的时候使用工厂模式(DI)和代理模式(AOP)解耦应用组件,进而开发出适用于Web开发的SpringMVC,在实际开发过程当中会使用到很多样板代码,就开发出了懒人版的SpringBoot;

区别

1、springMVC是Spring的一个模式,是一个Web框架,提供了一个轻度耦合的方式来开发Web应用;

2、SpringBoot是习惯优于配置,降低了项目搭建的难度;

3、springMVC需要使用到Tomcat服务器,SpringBoot的话是内嵌了Tomcat服务器的;

String,StringBuffer与StringBuilder的区别

操作字符串的区别

Java中操作字符串的类有String,StringBuffer,StringBuilder。
运行速度快慢为:StringBuilder > StringBuffer > String

String是字符串常量,声明的是不可变的对象,每次执行都会生成新的string对象,是一个不断创建和回收的过程,因此导致执行速度很慢。
StringBuilder和StringBuffer都是字符串变量,所以对象是可变的。
在经常改变字符串内容的情况下最好不要使用 String。

String:适用于少量的字符串操作的情况
StringBuffer:线程安全,适合多线程环境使用,性能比StringBuilder低。
StringBuilder:非线程安全,适合单线程使用,性能高于StringBuffer。

对于三者使用的总结:
1.如果要操作少量的数据用 = String
2.单线程操作字符串缓冲区 下操作大量数据 = StringBuilder
3.多线程操作字符串缓冲区 下操作大量数据 = StringBuffer

如何将字符串反转

使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。

示例代码:

1
2
3
4
5
6
7
8
9
// StringBuffer
StringBuffer stringBuffer = new StringBuffer();
stringBuffer. append("abcdefg");
System. out. println(stringBuffer. reverse()); // gfedcba

// StringBuilder
StringBuilder stringBuilder = new StringBuilder();
stringBuilder. append("abcdefg");
System. out. println(stringBuilder. reverse()); // gfedcba

String 类的常用方法都有那些

indexOf():返回指定字符的索引。
charAt():返回指定索引处的字符。
replace():字符串替换。
trim():去除字符串两端空白。
split():分割字符串,返回一个分割后的字符串数组。
getBytes():返回字符串的 byte 类型数组。
length():返回字符串长度。
toLowerCase():将字符串转成小写字母。
toUpperCase():将字符串转成大写字符。
substring():截取字符串。
equals():字符串比较。

值传递和引用传递有什么区别

值传递:指的是在方法调用时,传递的参数是按值的拷贝传递,传递的是值的拷贝,也就是说传递后就互不相关了。

引用传递:指的是在方法调用时,传递的参数是按引用进行传递,其实传递的引用的地址,也就是变量所对应的内存空间的地址。传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)。

集合框架Collection

定义概述

定义:集合是存储元素个数不受限制、元素类型不受限制的数据存储结构。
概述:
List , Set, Map都是接口,前两个继承至Collection接口,Map为独立接口
Set下有HashSet,LinkedHashSet,TreeSet
List下有ArrayList,Vector,LinkedList
Map下有Hashtable,LinkedHashMap,HashMap,TreeMap
Collection接口下还有个Queue(队列)接口,与List、Set同级。

接口总结

  1. List接口:有序,有索引,可重复。

    ArrayList:优点:底层数据结构是数组,查询快。缺点:线程不安全,增删慢。Vector:优点:底层数据结构是数组,查询快,线程安全缺点:增删慢,效率低LinkedList:优点:底层数据结构是链表,增删快,效率高缺点:查询慢,线程不安全

  2. Set接口:无序,无索引,不可重复(唯一)

    HashSet底层数据结构是哈希表。(无序,唯一)如何来保证元素唯一性?1.依赖两个方法:hashCode()和equals()

    LinkedHashSet底层数据结构是链表和哈希表。(FIFO插入有序,唯一)1.由链表保证元素有序2.由哈希表保证元素唯一

    TreeSet底层数据结构是红黑树。(唯一,有序)1.如何保证元素排序的呢?自然排序比较器排序2.如何保证元素唯一性的呢?根据比较的返回值是否是0来决定

  3. Map接口:存储一组键值对象,提供key到value的映射(key不能重复)Map接口有三个比较重要的实现类,分别是HashMap、TreeMap和HashTable。
    TreeMap是有序的,HashMap和HashTable是无序的。
    Hashtable是同步的,线程安全的,效率低,不允许null值。
    HashMap是不同步的,非线程安全的,效率高,允许null值。
    HashMap:适用于Map中插入、删除和定位元素。
    Treemap:适用于按自然顺序或自定义顺序遍历键(key)。

  4. ArrayList和HashMap的区别

    4.1 ArrayList是有序,不同步,非线程安全,底层是数组
    4.2 HashMap是无序的,不同步,非线程安全,底层是Hash算法存储数据。

    使用场景:
    如果需要快速随机访问元素,应该使用ArrayList。需要键值对形式的数据时,应该使用HashMap。

什么时候使用序列化

对象、文件、数据,有许多不同的格式,很难统一传输和保存
序列化以后就都是字节流了,无论原来是什么东西,都能变成一样的东西,就可以进行通用的格式传输或保存,传输结束以后,要再次使用,就进行反序列化还原,这样对象还是对象,文件还是文件

多线程的理解和应用

并行和并发有什么区别

并行:多个处理器或多核处理器同时处理多个任务。
并发:多个任务在同一个 CPU 核上,按细分的时间片交替执行,从逻辑上来看那些任务是同时执行。

线程和进程的区别

  1. 进程是系统进行资源调度和分配的基本单位,实现了操作系统的并发性。
  2. 线程是进程的子任务,是CPU调度和分派的基本单位,用于保证程序的实时性,实现进程内部的并发。
  3. 一个程序至少有一个进程,一个进程至少有一个线程,线程依赖于进程而存在。

守护线程是什么

守护线程是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。在 Java 中垃圾回收线程就是特殊的守护线程。

创建线程有哪几种方式

创建线程有三种方式:

继承 Thread 重写 run 方法;
实现 Runnable 接口;
实现 Callable 接口。

runnable 和 callable 有什么区别?
runnable 没有返回值
callable 有返回值 可以看作是 runnable 的补充。

如何保证多线程的运行安全

方法一:使用安全类,比如 Java. util. concurrent 下的类。
方法二:使用自动锁 synchronized。
方法三:使用手动锁 Lock。

手动锁 Java 示例代码如下:

1
2
3
4
5
6
7
8
9
10
Lock lock = new ReentrantLock();
lock. lock();
try {
System. out. println("获得锁");
} catch (Exception e) {
// TODO: handle exception
} finally {
System. out. println("释放锁");
lock. unlock();
}

IO流

参考:https://blog.csdn.net/CSDN_Terence/article/details/89513420

文章作者: PanXiaoKang
文章链接: http://example.com/2020/07/11/%E9%9D%A2%E8%AF%95%E9%A2%98%E6%B1%87%E6%80%BB/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 向阳榆木
打赏
  • 微信
    微信
  • 支付宝
    支付宝

评论