web前端面试题(必背面试题)

Posted Z_Xshan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了web前端面试题(必背面试题)相关的知识,希望对你有一定的参考价值。

必背面试题-手写题

前端面试(手写题)_Z_Xshan的博客-CSDN博客

css系列

面试官:说说你对盒子模型的理解

一、是什么

所有元素都可以有像盒子一样的平面空间和外形

一个盒子由四部分组成:context ,padding,margin,border

content:实际内容,显示文本和图像

padding:内边距,清除内容周边的区域,内边距是透明的,不能取负值,受盒子的background属性影响

margin:外边距,在元素外创建额外的空白,空白通常指不能放其他元素的区域

下面来段代码:

<style>
  .box 
    width: 200px;
    height: 100px;
    padding: 20px;
  
</style>
<div class="box">
  盒子模型
</div>

当我们在浏览器查看元素时,却发现元素的大小变成了240px

这是因为,在CSS中,盒子模型可以分成:

  • W3C 标准盒子模型
  • IE 怪异盒子模型

默认情况下,盒子模型为W3C 标准盒子模型

二、标准盒子模型

标准盒子模型,是浏览器默认的盒子模型

  • 盒子总宽度 = width + padding + border + margin;

  • 盒子总高度 = height + padding + border + margin

也就是,width/height 只是内容高度,不包含 padding 和 border

所以上面问题中,设置width为200px,但由于存在padding,但实际上盒子的宽度有240px

三、IE 怪异盒子模型

  • 盒子总宽度 = width + margin;

  • 盒子总高度 = height + margin;

也就是,width/height 包含了 padding和 border

Box-sizing

CSS 中的 box-sizing 属性定义了引擎应该如何计算一个元素的总宽度和总高度

box-sizing: content-box|border-box|inherit:

  • content-box 默认值,元素的 width/height 不包含padding,border,与标准盒子模型表现一致
  • border-box 元素的 width/height 包含 padding,border,与怪异盒子模型表现一致
  • inherit 指定 box-sizing 属性的值,应该从父元素继承

 回到上面的例子里,设置盒子为 border-box 模型

<style>
  .box 
    width: 200px;
    height: 100px;
    padding: 20px;
    box-sizing: border-box;
  
</style>
<div class="box">
  盒子模型
</div>

这时,盒子所占据的宽度为200px

面试官:css选择器有哪些?优先级?哪些属性可以继承?

一、选择器

CSS选择器是CSS规则的第一部分

它是元素和其他部分组合起来告诉浏览器哪个html元素应当是被选为应用规则中的CSS属性值的方式

选择器所选择的元素,叫做“选择器的对象”

关于css属性选择器常用的有:

  • id选择器(#box),选择id为box的元素

  • 类选择器(.one),选择类名为one的所有元素

  • 标签选择器(div),选择标签为div的所有元素

  • 后代选择器(#box div),选择id为box元素内部所有的div元素

  • 子选择器(.one>one_1),选择父元素为.one的所有.one_1的元素

  • 相邻同胞选择器(.one+.two),选择紧接在.one之后的所有.two元素

  • 群组选择器(div,p),选择div、p的所有元素

 还有一些使用频率相对没那么多的选择器:

  • 伪类选择器
:link :选择未被访问的链接              
:visited:选取已被访问的链接            
:active:选择活动链接                   
:hover :鼠标指针浮动在上面的元素        
:focus :选择具有焦点的                 
:first-child:父元素的首个子元素
  • 伪元素选择器
:first-letter :用于选取指定选择器的首字母
:first-line :选取指定选择器的首行
:before : 选择器在被选元素的内容前面插入内容
:after : 选择器在被选元素的内容后面插入内容
  • 属性选择器
[attribute] 选择带有attribute属性的元素
[attribute=value] 选择所有使用attribute=value的元素
[attribute~=value] 选择attribute属性包含value的元素
[attribute|=value]:选择attribute属性以value开头的元素

CSS3中新增的选择器有如下:

  • 层次选择器(p~ul),选择前面有p元素的每个ul元素
  • 伪类选择器
:first-of-type 表示一组同级元素中其类型的第一个元素
:last-of-type 表示一组同级元素中其类型的最后一个元素
:only-of-type 表示没有同类型兄弟元素的元素
:only-child 表示没有任何兄弟的元素
:nth-child(n) 根据元素在一组同级中的位置匹配元素
:nth-last-of-type(n) 匹配给定类型的元素,基于它们在一组兄弟元素中的位置,从末尾开始计数
:last-child 表示一组兄弟元素中的最后一个元素
:root 设置HTML文档
:empty 指定空的元素
:enabled 选择可用元素
:disabled 选择被禁用元素
:checked 选择选中的元素
:not(selector) 选择与 <selector> 不匹配的所有元素
  • 属性选择器
[attribute*=value]:选择attribute属性值包含value的所有元素
[attribute^=value]:选择attribute属性开头为value的所有元素
[attribute$=value]:选择attribute属性结尾为value的所有元素

二、优先级

!important >内联 > ID选择器 > 类选择器 > 标签选择器

三、继承属性

css中,继承是指的是给父元素设置一些属性,后代元素会自动拥有这些属性

关于继承属性,可以分成:

  • 字体系列属性
font:组合字体
font-family:规定元素的字体系列
font-weight:设置字体的粗细
font-size:设置字体的尺寸
font-style:定义字体的风格
font-variant:偏大或偏小的字体
  • 文本系列属性
text-indent:文本缩进
text-align:文本水平对刘
line-height:行高
word-spacing:增加或减少单词间的空白
letter-spacing:增加或减少字符间的空白
text-transform:控制文本大小写
direction:规定文本的书写方向
color:文本颜色
  • 元素可见性
visibility
  • 表格布局属性
caption-side:定位表格标题位置
border-collapse:合并表格边框
border-spacing:设置相邻单元格的边框间的距离
empty-cells:单元格的边框的出现与消失
table-layout:表格的宽度由什么决定
  • 列表属性
list-style-type:文字前面的小点点样式
list-style-position:小点点位置
list-style:以上的属性可通过这属性集合
  • 引用
quotes:设置嵌套引用的引号类型
  • 光标属性
cursor:箭头可以变成需要的形状

继承中比较特殊的几点:

  • a 标签的字体颜色不能被继承

  • h1-h6标签字体的大下也是不能被继承的

无继承的属性

  • display

  • 文本属性:vertical-align、text-decoration

  • 盒子模型的属性:宽度、高度、内外边距、边框等

  • 背景属性:背景图片、颜色、位置等

  • 定位属性:浮动、清除浮动、定位position等

  • 生成内容属性:content、counter-reset、counter-increment

  • 轮廓样式属性:outline-style、outline-width、outline-color、outline

  • 页面样式属性:size、page-break-before、page-break-after

面试官:元素水平垂直居中的方法有哪些?如果元素不定宽高呢?

一、背景

在开发中经常遇到这个问题,即让某个元素的内容在水平和垂直方向上都居中,内容不仅限于文字,可能是图片或其他元素

居中是一个非常基础但又是非常重要的应用场景,实现居中的方法存在很多,可以将这些方法分成两个大类:

  • 居中元素(子元素)的宽高已知
  • 居中元素宽高未知

二、实现方式

实现元素水平垂直居中的方式:

  • 利用定位+margin:auto

  • 利用定位+margin:负值

  • 利用定位+transform

  • table布局

  • flex布局

  • grid布局

利用定位+margin:auto

先上代码:

<style>
    .father
        width:500px;
        height:300px;
        border:1px solid #0a3b98;
        position: relative;
    
    .son
        width:100px;
        height:40px;
        background: #f0a238;
        position: absolute;
        top:0;
        left:0;
        right:0;
        bottom:0;
        margin:auto;
    
</style>
<div class="father">
    <div class="son"></div>
</div>

父级设置为相对定位,子级绝对定位 ,并且四个定位属性的值都设置了0,那么这时候如果子级没有设置宽高,则会被拉开到和父级一样宽高

这里子元素设置了宽高,所以宽高会按照我们的设置来显示,但是实际上子级的虚拟占位已经撑满了整个父级,这时候再给它一个margin:auto它就可以上下左右都居中了

利用定位+margin:负值

绝大多数情况下,设置父元素为相对定位, 子元素移动自身50%实现水平垂直居中

<style>
    .father 
        position: relative;
        width: 200px;
        height: 200px;
        background: skyblue;
    
    .son 
        position: absolute;
        top: 50%;
        left: 50%;
        margin-left:-50px;
        margin-top:-50px;
        width: 100px;
        height: 100px;
        background: red;
    
</style>
<div class="father">
    <div class="son"></div>
</div>

  • 初始位置为方块1的位置
  • 当设置left、top为50%的时候,内部子元素为方块2的位置
  • 设置margin为负数时,使内部子元素到方块3的位置,即中间位置

这种方案不要求父元素的高度,也就是即使父元素的高度变化了,仍然可以保持在父元素的垂直居中位置,水平方向上是一样的操作

但是该方案需要知道子元素自身的宽高,但是我们可以通过下面transform属性进行移动

利用定位+transform

实现代码如下:

<style>
    .father 
        position: relative;
        width: 200px;
        height: 200px;
        background: skyblue;
    
    .son 
        position: absolute;
        top: 50%;
        left: 50%;
  transform: translate(-50%,-50%);
        width: 100px;
        height: 100px;
        background: red;
    
</style>
<div class="father">
    <div class="son"></div>
</div>

translate(-50%, -50%)将会将元素位移自己宽度和高度的-50%

这种方法其实和最上面被否定掉的margin负值用法一样,可以说是margin负值的替代方案,并不需要知道自身元素的宽高

table布局

设置父元素为display:table-cell,子元素设置 display: inline-block。利用verticaltext-align可以让所有的行内块级元素水平垂直居中

<style>
    .father 
        display: table-cell;
        width: 200px;
        height: 200px;
        background: skyblue;
        vertical-align: middle;
        text-align: center;
    
    .son 
        display: inline-block;
        width: 100px;
        height: 100px;
        background: red;
    
</style>
<div class="father">
    <div class="son"></div>
</div>

flex弹性布局

还是看看实现的整体代码:

<style>
    .father 
        display: flex;
        justify-content: center;
        align-items: center;
        width: 200px;
        height: 200px;
        background: skyblue;
    
    .son 
        width: 100px;
        height: 100px;
        background: red;
    
</style>
<div class="father">
    <div class="son"></div>
</div>

css3中了flex布局,可以非常简单实现垂直水平居中

这里可以简单看看flex布局的关键属性作用:

  • display: flex时,表示该容器内部的元素将按照flex进行布局

  • align-items: center表示这些元素将相对于本容器水平居中

  • justify-content: center也是同样的道理垂直居中

grid网格布局

<style>
    .father 
            display: grid;
            align-items:center;
            justify-content: center;
            width: 200px;
            height: 200px;
            background: skyblue;

        
        .son 
            width: 10px;
            height: 10px;
            border: 1px solid red
        
</style>
<div class="father">
    <div class="son"></div>
</div>

这里看到,gird网格布局和flex弹性布局都简单粗暴

面试官:怎么理解回流跟重绘?什么场景下会触发?

一、是什么

HTML中,每个元素都可以理解成一个盒子,在浏览器解析过程中,会涉及到回流与重绘:

  • 回流:布局引擎会根据各种样式计算每个盒子在页面上的大小与位置

  • 重绘:当计算好盒模型的位置、大小及其他属性后,浏览器根据每个盒子特性进行绘制

在页面初始渲染阶段,回流不可避免的触发,可以理解成页面一开始是空白的元素,后面添加了新的元素使页面布局发生改变

当我们对 DOM 的修改引发了 DOM几何尺寸的变化(比如修改元素的宽、高或隐藏元素等)时,浏览器需要重新计算元素的几何属性,然后再将计算的结果绘制出来

当我们对 DOM的修改导致了样式的变化(colorbackground-color),却并未影响其几何属性时,浏览器不需重新计算元素的几何属性、直接为该元素绘制新的样式,这里就仅仅触发了回流

二、如何触发

回流触发时机

回流这一阶段主要是计算节点的位置和几何信息,那么当页面布局和几何信息发生变化的时候,就需要回流,如下面情况:

  • 添加或删除可见的DOM元素
  • 元素的位置发生变化
  • 元素的尺寸发生变化(包括外边距、内边框、边框大小、高度和宽度等)
  • 内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代
  • 页面一开始渲染的时候(这避免不了)
  • 浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的)

还有一些容易被忽略的操作:获取一些特定属性的值

offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight

这些属性有一个共性,就是需要通过即时计算得到。因此浏览器为了获取这些值,也会进行回流

除此还包括getComputedStyle方法,原理是一样的

重绘触发时机

触发回流一定会触发重绘

可以把页面理解为一个黑板,黑板上有一朵画好的小花。现在我们要把这朵从左边移到了右边,那我们要先确定好右边的具体位置,画好形状(回流),再画上它原有的颜色(重绘)

除此之外还有一些其他引起重绘行为:

  • 颜色的修改

  • 文本方向的修改

  • 阴影的修改

浏览器优化机制

由于每次重排都会造成额外的计算消耗,因此大多数浏览器都会通过队列化修改并批量执行来优化重排过程。浏览器会将修改操作放入到队列里,直到过了一段时间或者操作达到了一个阈值,才清空队列

当你获取布局信息的操作的时候,会强制队列刷新,包括前面讲到的offsetTop等方法都会返回最新的数据

因此浏览器不得不清空队列,触发回流重绘来返回正确的值

三、如何减少

我们了解了如何触发回流和重绘的场景,下面给出避免回流的经验:

  • 如果想设定元素的样式,通过改变元素的 class 类名 (尽可能在 DOM 树的最里层)
  • 避免设置多项内联样式
  • 应用元素的动画,使用 position 属性的 fixed 值或 absolute 值(如前文示例所提)
  • 避免使用 table 布局,table 中每个元素的大小以及内容的改动,都会导致整个 table 的重新计算
  • 对于那些复杂的动画,对其设置 position: fixed/absolute,尽可能地使元素脱离文档流,从而减少对其他元素的影响
  • 使用css3硬件加速,可以让transformopacityfilters这些动画不会引起回流重绘
  • 避免使用 CSS 的 javascript 表达式

在使用 JavaScript 动态插入多个节点时, 可以使用DocumentFragment. 创建后一次插入. 就能避免多次的渲染性能

但有时候,我们会无可避免地进行回流或者重绘,我们可以更好使用它们

例如,多次修改一个把元素布局的时候,我们很可能会如下操作

const el = document.getElementById('el')
for(let i=0;i<10;i++) 
    el.style.top  = el.offsetTop  + 10 + "px";
    el.style.left = el.offsetLeft + 10 + "px";

每次循环都需要获取多次offset属性,比较糟糕,可以使用变量的形式缓存起来,待计算完毕再提交给浏览器发出重计算请求

// 缓存offsetLeft与offsetTop的值
const el = document.getElementById('el')
let offLeft = el.offsetLeft, offTop = el.offsetTop

// 在JS层面进行计算
for(let i=0;i<10;i++) 
  offLeft += 10
  offTop  += 10


// 一次性将计算结果应用到DOM上
el.style.left = offLeft + "px"
el.style.top = offTop  + "px"

我们还可避免改变样式,使用类名去合并样式

const container = document.getElementById('container')
container.style.width = '100px'
container.style.height = '200px'
container.style.border = '10px solid red'
container.style.color = 'red'

使用类名去合并样式

<style>
    .basic_style 
        width: 100px;
        height: 200px;
        border: 10px solid red;
        color: red;
    
</style>
<script>
    const container = document.getElementById('container')
    container.classList.add('basic_style')
</script>

前者每次单独操作,都去触发一次渲染树更改(新浏览器不会),

都去触发一次渲染树更改,从而导致相应的回流与重绘过程

合并之后,等于我们将所有的更改一次性发出

我们还可以通过通过设置元素属性display: none,将其从页面上去掉,然后再进行后续操作,这些后续操作也不会触发回流与重绘,这个过程称为离线操作

const container = document.getElementById('container')
container.style.width = '100px'
container.style.height = '200px'
container.style.border = '10px solid red'
container.style.color = 'red'

离线操作后

let container = document.getElementById('container')
container.style.display = 'none'
container.style.width = '100px'
container.style.height = '200px'
container.style.border = '10px solid red'
container.style.color = 'red'
...(省略了许多类似的后续操作)
container.style.display = 'block'

面试官:什么是响应式设计?响应式设计的基本原理是什么?如何做?

一、是什么

响应式网站设计(Responsive Web design)是一种网络页面设计布局,页面的设计与开发应当根据用户行为以及设备环境(系统平台、屏幕尺寸、屏幕定向等)进行相应的响应和调整

描述响应式界面最著名的一句话就是“Content is like water”

大白话便是“如果将屏幕看作容器,那么内容就像水一样”

响应式网站常见特点:

  • 同时适配PC + 平板 + 手机等

  • 标签导航在接近手持终端设备时改变为经典的抽屉式导航

  • 网站的布局会根据视口来调整模块的大小和位置

 二、实现方式

响应式设计的基本原理是通过媒体查询检测不同的设备屏幕尺寸做处理,为了处理移动端,页面头部必须有meta声明viewport

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no”>

属性对应如下:

  • width=device-width: 是自适应手机屏幕的尺寸宽度

  • maximum-scale:是缩放比例的最大值

  • inital-scale:是缩放的初始化

  • user-scalable:是用户的可以缩放的操作

实现响应式布局的方式有如下:

  • 媒体查询
  • 百分比
  • vw/vh
  • rem

媒体查询

CSS3中的增加了更多的媒体查询,就像if条件表达式一样,我们可以设置不同类型的媒体条件,并根据对应的条件,给相应符合条件的媒体调用相对应的样式表

使用@Media查询,可以针对不同的媒体类型定义不同的样式,如:

@media screen and (max-width: 1920px)  ... 

当视口在375px - 600px之间,设置特定字体大小18px

@media screen (min-width: 375px) and (max-width: 600px) 
  body 
    font-size: 18px;
  

通过媒体查询,可以通过给不同分辨率的设备编写不同的样式来实现响应式的布局,比如我们为不同分辨率的屏幕,设置不同的背景图片

比如给小屏幕手机设置@2x图,为大屏幕手机设置@3x图,通过媒体查询就能很方便的实现

百分比

通过百分比单位 " % " 来实现响应式的效果

比如当浏览器的宽度或者高度发生变化时,通过百分比单位,可以使得浏览器中的组件的宽和高随着浏览器的变化而变化,从而实现响应式的效果

heightwidth属性的百分比依托于父标签的宽高,但是其他盒子属性则不完全依赖父元素:

  • 子元素的top/left和bottom/right如果设置百分比,则相对于直接非static定位(默认定位)的父元素的高度/宽度

  • 子元素的padding如果设置百分比,不论是垂直方向或者是水平方向,都相对于直接父亲元素的width,而与父元素的height无关。

  • 子元素的margin如果设置成百分比,不论是垂直方向还是水平方向,都相对于直接父元素的width

  • border-radius不一样,如果设置border-radius为百分比,则是相对于自身的宽度

可以看到每个属性都使用百分比,会照成布局的复杂度,所以不建议使用百分比来实现响应式

vw/vh

vw表示相对于视图窗口的宽度,vh表示相对于视图窗口高度。 任意层级元素,在使用vw单位的情况下,1vw都等于视图宽度的百分之一

与百分比布局很相似,在以前文章提过与%的区别,这里就不再展开述说

rem

在以前也讲到,rem是相对于根元素htmlfont-size属性,默认情况下浏览器字体大小为16px,此时1rem = 16px

可以利用前面提到的媒体查询,针对不同设备分辨率改变font-size的值,如下:

@media screen and (max-width: 414px) 
  html 
    font-size: 18px
  


@media screen and (max-width: 375px) 
  html 
    font-size: 16px
  


@media screen and (max-width: 320px) 
  html 
    font-size: 12px
  

为了更准确监听设备可视窗口变化,我们可以在css之前插入script标签,内容如下:

//动态为根元素设置字体大小
function init () 
    // 获取屏幕宽度
    var width = document.documentElement.clientWidth
    // 设置根元素字体大小。此时为宽的10等分
    document.documentElement.style.fontSize = width / 10 + 'px'


//首次加载应用,设置一次
init()
// 监听手机旋转的事件的时机,重新设置
window.addEventListener('orientationchange', init)
// 监听手机窗口变化,重新设置
window.addEventListener('resize', init)

无论设备可视窗口如何变化,始终设置remwidth的1/10,实现了百分比布局

除此之外,我们还可以利用主流UI框架,如:element uiantd提供的栅格布局实现响应式

 三、总结

响应式布局优点可以看到:

  • 面对不同分辨率设备灵活性强
  • 能够快捷解决多设备显示适应问题

缺点:

  • 仅适用布局、信息、框架并不复杂的部门类型网站
  • 兼容各种设备工作量大,效率低下
  • 代码累赘,会出现隐藏无用的元素,加载时间加长
  • 其实这是一种折中性质的设计解决方案,多方面因素影响而达不到最佳效果
  • 一定程度上改变了网站原有的布局结构,会出现用户混淆的情况

面试官:如果要做优化,CSS提高性能的方法有哪些?

一、前言

css主要是用来完成页面布局的,像一些细节或者优化,

减少css嵌套,最好不要套三层以上。

不要在ID选择器前面进行嵌套,ID本来就是唯一的而且人家权值那么大,嵌套完全是浪费性能。

建立公共样式类,把相同样式提取出来作为公共类使用,比如我们常用的清除浮动等。

不用css表达式,css表达式对性能的浪费可能是超乎你的想象的

二、实现方式

实现方式有很多种,主要有如下:

  • 内联首屏关键CSS
  • 异步加载CSS
  • 资源压缩
  • 合理使用选择器
  • 减少使用昂贵的属性
  • 不要使用@import

内联首屏关键CSS

在打开一个页面,页面首要内容出现在屏幕的时间影响着用户的体验,而通过内联css关键代码能够使浏览器在下载完html后就能立刻渲染

而如果外部引用css代码,在解析html结构过程中遇到外部css文件,才会开始下载css代码,再渲染

所以,CSS内联使用使渲染时间提前

注意:但是较大的css代码并不合适内联(初始拥塞窗口、没有缓存),而其余代码则采取外部引用方式

异步加载CSS

CSS文件请求、下载、解析完成之前,CSS会阻塞渲染,浏览器将不会渲染任何已处理的内容

前面加载内联代码后,后面的外部引用css则没必要阻塞浏览器渲染。这时候就可以采取异步加载的方案,主要有如下:

// 创建link标签
const myCSS = document.createElement( "link" );
myCSS.rel = "stylesheet";
myCSS.href = "mystyles.css";
// 插入到header的最后位置
document.head.insertBefore( myCSS, document.head.childNodes[ document.head.childNodes.length - 1 ].nextSibling );

  • 设置link标签media属性为noexis,浏览器会认为当前样式表不适用当前类型,会在不阻塞页面渲染的情况下再进行下载。加载完成后,将media的值设为screenall,从而让浏览器开始解析CSS
<link rel="stylesheet" href="mystyles.css" media="noexist" onload="this.media='all'">
  • 通过rel属性将link元素标记为alternate可选样式表,也能实现浏览器异步加载。同样别忘了加载完成之后,将rel设回stylesheet
<link rel="alternate stylesheet" href="mystyles.css" onload="this.rel='stylesheet'">

资源压缩

利用webpackgulp/gruntrollup等模块化工具,将css代码进行压缩,使文件变小,大大降低了浏览器的加载时间

合理使用选择器

css匹配的规则是从右往左开始匹配,例如#markdown .content h3匹配规则如下:

  • 先找到h3标签元素
  • 然后去除祖先不是.content的元素
  • 最后去除祖先不是#markdown的元素

如果嵌套的层级更多,页面中的元素更多,那么匹配所要花费的时间代价自然更高

所以我们在编写选择器的时候,可以遵循以下规则:

  • 不要嵌套使用过多复杂选择器,最好不要三层以上
  • 使用id选择器就没必要再进行嵌套
  • 通配符和属性选择器效率最低,避免使用

减少使用昂贵的属性

在页面发生重绘的时候,昂贵属性如box-shadow/border-radius/filter/透明度/:nth-child等,会降低浏览器的渲染性能

不要使用@import

css样式文件有两种引入方式,一种是link元素,另一种是@import

@import会影响浏览器的并行下载,使得页面在加载时增加额外的延迟,增添了额外的往返耗时

而且多个@import可能会导致下载顺序紊乱

比如一个css文件index.css包含了以下内容:@import url("reset.css")

那么浏览器就必须先把index.css下载、解析和执行后,才下载、解析和执行第二个文件reset.css

面试官:说说JavaScript中的数据类型?存储上的差别?

js的数据类型分为两类,一个是基本数据类型,一个是引用数据类型

基本数据类型有undefinednullbooleannumberstringsymbol

引用数据类型有 object

在js的执行过程中,主要有三种数据类型内存空间,分别是代码空间,栈空间,堆空间,其中的代码空间主要是存储可执行代码的,原始类型的数据值都是直接保存在栈中的,引用数据类型的值是存放在堆空间中的, 原始数据类型存储的是变量的值,而引用数据类型存储的是其在堆空间中的地址

JavaScript系列 

面试官:typeof 与 instanceof 区别

一、typeof

typeof 对于原始数据类型来说,除了null都可以正确的显示类型

使用方法如下:

typeof operand
typeof(operand)

operand表示对象或原始值的表达式,其类型将被返回

举个例子

typeof 1 // 'number'
typeof '1' // 'string'
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
typeof null // 'object'
typeof [] // 'object'
typeof  // 'object'
typeof console // 'object'
typeof console.log // 'function'

从上面例子,前6个都是基础数据类型。虽然typeof nullobject,但这只是JavaScript 存在的一个悠久 Bug,不代表null就是引用数据类型,并且null本身也不是对象

所以,null在 typeof之后返回的是有问题的结果,不能作为判断null的方法。如果你需要在 if 语句中判断是否为 null,直接通过===null来判断就好

同时,可以发现引用类型数据,用typeof来判断的话,除了function会被识别出来之外,其余的都输出object

如果我们想要判断一个变量是否存在,可以使用typeof:(不能使用if(a), 若a未声明,则报错)

if(typeof a != 'undefined')
    //变量存在

 二、instanceof

 instanceof 可以正确显示数据类型, 因为它是通过对象的原型链来进行判断的,

使用如下:

object instanceof constructor

object为实例对象,constructor为构造函数

构造函数通过new可以实例对象,instanceof能判断这个对象是否是之前那个构造函数生成的对象

// 定义构建函数
let Car = function() 
let benz = new Car()
benz instanceof Car // true
let car = new String('xxx')
car instanceof String // true
let str = 'xxx'
str instanceof String // false

 关于instanceof的实现原理,可以参考下面:

function myInstanceof(left, right) 
    // 这里先用typeof来判断基础数据类型,如果是,直接返回false
    if(typeof left !== 'object' || left === null) return false;
    // getProtypeOf是Object对象自带的API,能够拿到参数的原型对象
    let proto = Object.getPrototypeOf(left);
    while(true)                   
        if(proto === null) return false;
        if(proto === right.prototype) return true;//找到相同原型对象,返回true
        proto = Object.getPrototypeof(proto);
    

 也就是顺着原型链去找,直到找到相同的原型对象,返回true,否则为false 

三、区别 

typeofinstanceof都是判断数据类型的方法,区别如下:

  • typeof会返回一个变量的基本类型,instanceof返回的是一个布尔值

  • instanceof 可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型

  • typeof 也存在弊端,它虽然可以判断基础数据类型(null 除外),但是引用数据类型中,除了function 类型以外,其他的也无法判断

可以看到,上述两种方法都有弊端,并不能满足所有场景的需求

如果需要通用检测数据类型,可以采用Object.prototype.toString,调用该方法,统一返回格式“[object Xxx]”的字符串

如下

Object.prototype.toString()       // "[object Object]"
Object.prototype.toString.call()  // 同上结果,加上call也ok
Object.prototype.toString.call(1)    // "[object Number]"
Object.prototype.toString.call('1')  // "[object String]"
Object.prototype.toString.call(true)  // "[object Boolean]"
Object.prototype.toString.call(function())  // "[object Function]"
Object.prototype.toString.call(null)   //"[object Null]"
Object.prototype.toString.call(undefined) //"[object Undefined]"
Object.prototype.toString.call(/123/g)    //"[object RegExp]"
Object.prototype.toString.call(new Date()) //"[object Date]"
Object.prototype.toString.call([])       //"[object Array]"
Object.prototype.toString.call(document)  //"[object HTMLDocument]"
Object.prototype.toString.call(window)   //"[object Window]"

了解了toString的基本用法,下面就实现一个全局通用的数据类型判断方法

function getType(obj)
  let type  = typeof obj;
  if (type !== "object")     // 先进行typeof判断,如果是基础数据类型,直接返回
    return type;
  
  // 对于typeof返回结果是object的,再进行如下的判断,正则返回结果
  return Object.prototype.toString.call(obj).replace(/^\\[object (\\S+)\\]$/, '$1'); 

使用如下

getType([])     // "Array" typeof []是object,因此toString返回
getType('123')  // "string" typeof 直接返回
getType(window) // "Window" toString返回
getType(null)   // "Null"首字母大写,typeof null是object,需toString来判断
getType(undefined)   // "undefined" typeof 直接返回
getType()            // "undefined" typeof 直接返回
getType(function()) // "function" typeof能判断,因此首字母小写
getType(/123/g)      //"RegExp" toString返回

面试官:说说你对闭包的理解?闭包使用场景

闭包就是可以访问其他函数内部变量的函数,我们通常用它来定义私有化的变量和方法,创建一个闭包最简单的方法就是在一个函数内创建一个函数,它有三个特性是 函数内可以再嵌套函数,内部函数可以访问外部的方法和变量,方法和变量不会被垃圾回收机制回收,

一、是什么

闭包最简单的方法就是在一个函数内创建一个函数,闭包让你可以在一个内层函数中访问到其外层函数的作用域

二、使用场景

任何闭包的使用场景都离不开这两点:

  • 创建私有变量
  • 延长变量的生命周期

一般函数的词法环境在函数返回后就被销毁,但是闭包会保存对创建时所在词法环境的引用,即便创建时所在的执行上下文被销毁,但创建时所在词法环境依然存在,以达到延长变量的生命周期的目的

创建私有变量:好比vue里的data 每个data都是一个闭包所以他们互不干扰

三、优缺点

它的优点就是可以实现封装和缓存,缺点就是可能会造成内存泄漏的问题

面试官:bind、call、apply 区别?如何实现一个bind?

关于call、apply、bind函数,它们主要用来改变this指向的

call的用法

fn.call(thisArg, arg1, arg2, arg3, ...)

调用fn.call时会将fn中的this指向修改为传入的第一个参数thisArg;将后面的参数传入给fn,并立即执行函数fn。

let obj = 
        name: "xiaoming",
        age: 24,
        sayHello: function (job, hobby) 
            console.log(`我叫$this.name,今年$this.age岁。我的工作是: $job,我的爱好是: $hobby。`);
        
    
    obj.sayHello('程序员', '看美女'); // 我叫xiaoming,今年24岁。我的工作是: 程序员,我的爱好是: 看美女。


    let obj1 = 
        name: "lihua",
        age: 30
    
    // obj1.sayHello(); // Uncaught TypeError: obj1.sayHello is not a function
    obj.sayHello.call(obj1, '设计师', '画画'); // 我叫lihua,今年30岁。我的工作是: 设计师,我的爱好是: 画画。

apply的用法

apply(thisArg, [argsArr])

fn.apply的作用和call相同:修改this指向,并立即执行fn。区别在于传参形式不同,apply接受两个参数,第一个参数是要指向的this对象,第二个参数是一个数组,数组里面的元素会被展开传入fn,作为fn的参数。

bind的用法

bind(thisArg, arg1, arg2, arg3, ...)

fn.bind的作用是只修改this指向,但不会立即执行fn;会返回一个修改了this指向后的fn。需要调用才会执行:bind(thisArg, arg1, arg2, arg3, ...)()bind的传参和call相同。

obj.sayHello.bind(obj1, '设计师', '画画'); // 无输出结果

obj.sayHello.bind(obj1, '设计师', '画画')(); // 我叫lihua,今年30岁。我的工作是: 设计师,我的爱好是: 画画。

bind、call、apply的区别

1、相同点
三个都是用于改变this指向;
接收的第一个参数都是this要指向的对象;
都可以利用后续参数传参。
2、不同点
call和bind传参相同,多个参数依次传入的;
apply只有两个参数,第二个参数为数组;
call和apply都是对函数进行直接调用,而bind方法不会立即调用函数,而是返回一个修改this后的函数。 

面试官:说说你对事件循环的理解

一、是什么

JavaScript是一门单线程的语言,在JavaScript中,所有的任务都可以分为

  • 同步任务:立即执行的任务,同步任务一般会直接进入到主线程中执行

  • 异步任务:异步执行的任务,比如ajax网络请求,setTimeout定时函数等

同步任务与异步任务的运行流程图如下:

 从上面我们可以看到,同步任务进入主线程,即主执行栈,异步任务进入任务队列,主线程内的任务执行完毕为空,会去任务队列读取对应的任务,推入主线程执行。上述过程的不断重复就事件循环

二、宏任务与微任务

微任务

一个需要异步执行的函数,执行时机是在主函数执行结束之后、当前宏任务结束之前

常见的微任务有:

  • Promise.then

  • MutaionObserver

  • Object.observe(已废弃;Proxy 对象替代)

  • process.nextTick(Node.js)

宏任务

宏任务的时间粒度比较大,执行的时间间隔是不能精确控制的,对一些高实时性的需求就不太符合

常见的宏任务有:

  • script (可以理解为外层同步代码)
  • setTimeout/setInterval
  • UI rendering/UI事件
  • postMessage、MessageChannel
  • setImmediate、I/O(Node.js)

这时候,事件循环,宏任务,微任务的关系如图所示

 三、async与await

async

async 是异步的意思,await则可以理解为 async wait。所以可以理解async就是用来声明一个异步方法,而 await是用来等待异步方法执行

async函数返回一个promise对象,下面两种方法是等效的

function f() 
    return Promise.resolve('TEST');


// asyncF is equivalent to f!
async function asyncF() 
    return 'TEST';

await

正常情况下,await命令后面是一个 Promise对象,返回该对象的结果。如果不是 Promise对象,就直接返回对应的值

async function f()
    // 等同于
    // return 123
    return await 123

f().then(v => console.log(v)) // 123

不管await后面跟着的是什么,await都会阻塞后面的代码 

async function fn1 ()
    console.log(1)
    await fn2()
    console.log(2) // 阻塞


async function fn2 ()
    console.log('fn2')


fn1()
console.log(3)

上面的例子中,await 会阻塞下面的代码(即加入微任务队列),先执行 async外面的同步代码,同步代码执行完,再回到 async 函数中,再执行之前阻塞的代码

所以上述输出结果为:1fn232

面试官:DOM常见的操作有哪些?

一、DOM

任何 HTMLXML文档都可以用 DOM表示为一个由节点构成的层级结构

<div>
    <p title="title">
        content
    </p >
</div

上述结构中,divp就是元素节点,content就是文本节点,title就是属性节点

二、操作

DOM操作才能有助于我们理解框架深层的内容

下面就来分析DOM常见的操作,主要分为:

  • 创建节点
  • 查询节点
  • 更新节点
  • 添加节点
  • 删除节点

创建节点

createEleme

创建新元素,接受一个参数,即要创建元素的标签名

const divEl = document.createElement("div");

createTextNode

创建一个文本节点

const textEl = document.createTextNode("content");

获取节点

querySelector

传入任何有效的css 选择器,即可选中单个 DOM元素(首个):

document.querySelector('.element')
document.querySelector('#element')
document.querySelector('div')
document.querySelector('[name="username"]')
document.querySelector('div + p > span')

如果页面上没有指定的元素时,返回 null

关于获取DOM元素的方法还有如下,就不一一述说

document.getElementById('id属性值');返回拥有指定id的对象的引用
document.getElementsByClassName('class属性值');返回拥有指定class的对象集合
document.getElementsByTagName('标签名');返回拥有指定标签名的对象集合
document.getElementsByName('name属性值'); 返回拥有指定名称的对象结合
document/element.querySelector('CSS选择器');  仅返回第一个匹配的元素
document/element.querySelectorAll('CSS选择器');   返回所有匹配的元素
document.documentElement;  获取页面中的HTML标签
document.body; 获取页面中的BODY标签
document.all[''];  获取页面中的所有元素节点的对象集合型

更新节点

innerHTML

不但可以修改一个DOM节点的文本内容,还可以直接通过HTML片段修改DOM节点内部的子树

// 获取<p id="p">...</p >
var p = document.getElementById('p');
// 设置文本为abc:
p.innerHTML = 'ABC'; // <p id="p">ABC</p >
// 设置HTML:
p.innerHTML = 'ABC <span style="color:red">RED</span> XYZ';
// <p>...</p >的内部结构已修改

innerText、textContent

两者的区别在于读取属性时,innerText不返回隐藏元素的文本,而textContent返回所有文本

 添加节点

innerHTML

如果这个DOM节点是空的,例如,<div></div>,那么,直接使用innerHTML = '<span>child</span>'就可以修改DOM节点的内容,相当于添加了新的DOM节点

如果这个DOM节点不是空的,那就不能这么做,因为innerHTML会直接替换掉原来的所有子节点

appendChild

把一个子节点添加到父节点的最后一个子节点

举个例子

<!-- HTML结构 -->
    <p id="js">JavaScript</p>
    <div id="list">
        <p id="java">Java</p>
        <p id="python">Python</p>
        <p id="scheme">Scheme</p>
    </div>
    <!--添加一个p元素-->
    <script>

        const js = document.getElementById('js')
        js.innerHTML = "JavaScript"
        const list = document.getElementById('list');
        list.appendChild(js);

    </script>

 现在HTML结构变成了下面

<!-- HTML结构 -->
<div id="list">
    <p id="java">Java</p >
    <p id="python">Python</p >
    <p id="scheme">Scheme</p >
    <p id="js">JavaScript</p >  <!-- 添加元素 -->
</div>

上述代码中,我们是获取DOM元素后再进行添加操作,这个js节点是已经存在当前文档树中,因此这个节点首先会从原先的位置删除,再插入到新的位置

如果动态添加新的节点,则先创建一个新的节点,然后插入到指定的位置

const list = document.getElementById('list'),
const haskell = document.createElement('p');
haskell.id = 'haskell';
haskell.innerText = 'Haskell';
list.appendChild(haskell);

insertBefore

把子节点插入到指定的位置,使用方法如下:

parentElement.insertBefore(newElement, referenceElement)

子节点会插入到referenceElement之前

删除节点

删除一个节点,首先要获得该节点本身以及它的父节点,然后,调用父节点的removeChild把自己删掉

// 拿到待删除节点:
const self = document.getElementById('to-be-removed');
// 拿到父节点:
const parent = self.parentElement;
// 删除:
const removed = parent.removeChild(self);
removed === self; // true

删除后的节点虽然不在文档树中了,但其实它还在内存中,可以随时再次被添加到别的位置

面试官:说说你对BOM的理解,常见的BOM对象你了解哪些?

一、是什么 

BOM (Browser Object Model),浏览器对象模型,提供了内容与浏览器窗口进行交互的对象

 其作用就是跟浏览器做一些交互效果,比如如何进行页面的后退,前进,刷新

 二、window

Bom的核心对象是window,它表示浏览器的一个实例

在浏览器中 即是浏览器窗口的一个接口,又是全局对象

三、location

window对象给我们提供了一个location属性用于获取或设置窗体的URL,并且可以用于解析URL。

四、navigator 

navigator 对象主要用来获取浏览器的属性,区分浏览器类型。属性较多,且兼容性比较复杂

 五、screen

保存的是浏览器窗口外面的客户端显示器的信息,比如像素宽度和像素高度

六、history

history对象主要用来操作浏览器URL的历史记录,可以通过参数向前,向后,或者向指定URL跳转

面试官:Javascript本地存储的方式有哪些?区别及应用场景?

javaScript本地缓存的方法我们主要讲述以下四种:

  • cookie
  • sessionStorage
  • localStorage
  • indexedDB

Cookie,用户发送请求时会携带cookie到服务端,服务端会判断cookie来识别用户,cookie存储一般不超过 4KB 的小型文本数据,但是cookie在每次请求中都会被发送,如果不使用 HTTPS并对其加密,其保存的信息很容易被窃取,

localStorage

HTML5新方法,IE8及以上浏览器都兼容

特点

  • 生命周期:持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的
  • 存储的信息在同一域中是共享的
  • 当本页操作(新增、修改、删除)了localStorage的时候,本页面不会触发storage事件,但是别的页面会触发storage事件。
  • 大小:5M(跟浏览器厂商有关系)
  • localStorage本质上是对字符串的读取,如果存储内容多的话会消耗内存空间,会导致页面变卡
  • 受同源策略的限制

sessionStorage

sessionStorage和 localStorage使用方法基本一致,唯一不同的是生命周期,一旦页面(会话)关闭,sessionStorage 将会删除数据

扩展的前端存储方式 

indexedDB是一种低级API,用于客户端存储大量结构化数据(包括, 文件/ blobs)。

面试官:什么是防抖和节流?有什么区别?如何实现?

一、是什么

本质上是优化高频率执行代码的一种手段

为了优化体验,需要对这类事件进行调用次数的限制,对此我们就可以采用 防抖(debounce) 和 节流(throttle) 的方式来减少调用频率

定义

  • 节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效
  • 防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时

一个经典的比喻:

电梯第一个人进来后,15秒后准时运送一次,这是节流

电梯第一个人进来后,等待15秒。如果过程中又有人进来,15秒等待重新计时,直到15秒后开始运送,这是防抖

二、区别

相同点:

  • 都可以通过使用 setTimeout 实现
  • 目的都是,降低回

    JAVA必背面试题和项目面试通关要点

    一 数据库 

    1.常问数据库查询、修改(SQL查询包含筛选查询、聚合查询和链接查询和优化问题,手写SQL语句,例如四个球队比赛,用SQL显示所有比赛组合;举例2:选择重复项,然后去掉重复项;) 数据库里的密码如何加密(md5);

    (1)数据库的密码加密:单向加密,insert into users (username,password) values (‘mike’,MD5(‘guessme’));

    (2)双向加密:insert into users (username ,password) values (‘mike’,ENCODE(‘guessme’,’abanaafn’));

    (3)SQL筛选查询:select * from user where user_id in (select user_id from user group by user_id having count(user_id)>1) order by user_id desc;

    (4)SQL聚合查询:select user_id from user group by user_id;

    (5)SQL衔接查询:内连接.select s.name,m.mess from student s inner join mark m on s.id=m.studentid;左外连接:select s.name, m.mess from student s left join mark m on s.id=m.studentid;右外连接:select s.name, m.mess from student s right join mark m on s.id=m.studentid;全外连接:select s.name ,m.mess from student s full join mark m on s.id=m.studentid;

    (6)球队比赛组合:select count(*) from department as a ,department as b a.name<>b.name;

    (7)SQL选择重复语句:select id ,name from user where id in (select id from user group by id having count(1)>2);去除重复语句:select id from user group by id having count(*)>1;

    (8)数据库优化:prepareStatement比Statement性能高,一个sql发给服务器去执行.涉及步骤:语法检查,语义定义,编译和缓存.有外检约束会影响插入和删除功能,如果程序能保证数据的完整性,那么设计数据库的时候就去掉外键.sql语句全部大写,特别是列名和表名.

    2. 如何实现数据库分页功能? SQL语句复杂的关联表查询,累计求和。

    在不使用框架情况下,如何连接数据库?

    数据库连接完之后,需要关闭的两个接口是什么?

    关闭数据库过程中最容易抛出的异常是什么?

    (1)分页:”select * from user limit “+(pageNo-1)*pageSize+”,”+pageSize;

    (2)求和:select * from user1 union select * from user2;

    (3)手动连接数据库:Connection cn=null;PreparedStatement pst=null;Result rs=null;try{Class.forname(driverClassName);cn=DriverManager.getConnection(url,username,password);pst=cn.prepareStatement(“sql”);pst.setString(1,studentName);Result rs=pst.executeQuery();while(rs.next()){system.out.println();}catch(Exception e){e.printStackTrace();}finally{if(rs!=null){rs.close();}if(pst!=null){pst.close()}if(cn!=null){cn.close();}}}

    (4)Result prepareStatement 结果集和sql传输

    (5)Exception

    3. Oracle索引的优缺点、视图和存储过程、连接符是什么?默认端口是什么?MySQL什么是左链接、右链接和内链接?数据库中查询左链接、右链接和内链接结果是什么?

    数据库的存储原理,讲一讲?

    (1)端口:1521;

    (2)内连接就是左表和右表相同的数据.

    外连接分为:左外连接、右外连接、全外连接

    左外连接就是以左表为准,去匹配右表,左表有多少条数据,结果就是多少条数据

    右外连接就是与左外连接反之,以右表为准,去匹配左表,右表有多少条数据,结果就是多少条数据。

    全外连接数据条数不一定,相当与是左外连接 和右外连接 的综合。

    (3)oracle索引分为:聚集索引,非聚集索引,唯一索引;优点:方便查询,在数据量大时排序更宜查询;缺点:查询时需要进行重新排序,减少了效率。物理索引缺点 建立索引效率低,只能建一个更有说服力的;

    (4)连接符为”||”或CONCAT();

    (5)视图:其实就是一条查询sql语句,用于显示一个或多个表或其他视图中的相关数据。视图将一个查询的结果作为一个表来使用,因此视图可以被看作是存储的查询 或一个虚拟表。视图来源于表,所有对视图数据的修改最终都会被反映到视图的基表中,这些修改必须服从基表的完整性约束,并同样会触发定义在基表上的触发器

    (6)存储过程:oracle有系统存储过程和自定义存储过程,为了完成特定功能的sql语句集,经编译后存储在数据库中,用户通过特定的存储过程名来执行

    (7)存储原理:当用户创建索引时,oracle会自动的在表空间里创建索引段来存储索引的数据;

    4. Char里面可以存放汉字吗?

    (1)char型变量就是用来存储Unicode编码字符的,Unicode编码字符集中包含了汉字,所以可以存储汉字,如果某个特殊的汉字没有包含在Unicode编码字符集中,那么char型变量就不能存储,Unicode占用两个字节,所以char型的变量也是占用两个字节.

    二 Java基础 

    1. 说一下多态的表现形式?

    (1)重载,重写,重载Overload表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同

    (2)重写Override表示子类中的方法可以与父类中的某个方法的名称和参数完全相同,通过子类创建的实例对象调用这个方法时,将调用子类中的定义方法,这相当于把父类中定义的那个完全相同的方法给覆盖了,这也是面向对象编程的多态性的一种表现,只能比父类抛出更少的异常,或者是抛出父类抛出的异常的子异常,子类方法的访问权限只能比父类的更大,不能更小。如果父类的方法是private类型,那么,子类则不存在覆盖的限制,相当于子类中增加了一个全新的方法

    2. 数据的加密模式?加密模式的顺序?

    (1)对称式和非对称式,顺序:传输加密,数据存储加密,数据完整型的鉴别,密钥管理;

    3. 问到hasshmap底层数据结构,arraylist-linklist区别和为什么有这样的区别;数组的比较方法;基本类型和引用数据类型的区别;问接口和抽象类的区别;

    (1)HashMap是线程序不安全的,不是同步的

    HashMap可以让你将空值作为一个表的条目的key或value

    Hashmap实际上是一个数组和链表的结合体,在java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,hashmap也不例外。Hashmap实际上是一个数组和链表的结合体.

    (2)区别:ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构,对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针,.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据,若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。但若是批 量随机的插入删除数据,LinkedList的速度大大优于ArrayList. 因为ArrayList每插入一条数据,要移动插入点及之后的所有数据。  这一点我做了实验。在分别有200000条“记录”的ArrayList和LinkedList的首位插入20000条数据,LinkedList耗时约 是ArrayList的20分之1。

    4. 如何配置安装jdk?如何判断其配置成功?

    (1)首先安装JDK要看你电脑的位数,选择32位或64位的jdk版本,建议使用1.6版本以上,1.7版本一下;

    (2)从Oracle官网下载JDK安装包。

    (3)安装包下载完成后,双击安装包进行安装,安装路径可以使用默认路径。

    (4)安装完成后,还需要进行环境变量的配置,在系统环境变量的用户变量里面添加一个变量名为 JAVA_HOME环境变量,然后在变量值处填写上JDK安装目录的bin文件夹的路径,如:C:\ProgramFiles\Java \jdk1.7.0_79,然后再添加一个变量名为Path的变量,变量值填写为%JAVA_HOME%\bin;即可。

    (5)可以写一个简单的java程序来测试JDK是否已安装成功:public class Test{public static void main(String args[]){System.out.println("This is a test program.");}}将上面的这段程序保存为文件名为Test.java的文件。(注意Test是程序的公共类,必须和文件名一致,包括大小写)然后打开命令提示符窗口,cd到你的Test.java所在目录,然后键入下面的命令 :javac Test.java (回车)java Test 此时如果看到打印出来This is a test program.的话说明安装成功了,如果没有打印出这句话,你需要仔细检查一下你的配置情况。

    5. 手写单例模式(饿汉和饱汉模式)和工厂模式?

    (1)单例饿汉模式://饿汉式单例类.在类初始化时,已经自行实例化 
     2 public class Singleton1 {
     3     //私有的默认构造子
     4     private Singleton1() {}
     5     //已经自行实例化 
     6     private static final Singleton1 single = new Singleton1();
     7     //静态工厂方法 
     8     public static Singleton1 getInstance() {
     9         return single;
    10     }
    11 }

    (2)懒汉模式://懒汉式单例类.在第一次调用的时候实例化 
     2 public class Singleton2 {
     3     //私有的默认构造子
     4     private Singleton2() {}
     5     //注意,这里没有final    
     6     private static Singleton2 single=null;
     7     //静态工厂方法 
     8     public synchronized  static Singleton2 getInstance() {
     9          if (single == null) {  
    10              single = new Singleton2();
    11          }  
    12         return single;
    13     }
    14 }

    (3)工厂模式:

    interface IFactory{

    public IProduct createProduct();}

    Class Factory implements IFactory{

    public IProduct createProduct(){return new Product();}}

    Public class client{

    Public Static void main (String [] args){IFactory factory=new Factory();

    IProduct product=factory.createProduct();

    product.ProductMethod();}}

    6. 手写创建list,定义list,泛型?

    (1)List list=new ArrayList();

    (2)List<Student> list=new ArrayList<Student>();

    (3)Student s=new Student();

    (4)List.add(s);

    7. 安全:hassmap和hasstable的区别?那个不安全?为什么?怎么便利hashmap?线程方面:线程有几种状态?谈谈多线程的安全问题;问到线程和同步?写一个生产者和消费者模式; 考虑高并发的问题。

    (1):区别:一.历史原因:Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现;

    (2)二.同步性:Hashtable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的

    (3)三.值:只有HashMap可以让你将空值作为一个表的条目的key或value

    (4)为什么?最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。 

    Hashtable和HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差异

    (5)遍历hashmap:两种方式,Map map=new HashMap();

    Iterator iter=map.entrySet().iterator();s

    Iterator iter=map.keySet().iterator();

    (6)线程通常有五种状态,创建,就绪,运行,阻塞,和死亡;

    第一是创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态手写字符串反转和冒泡排序;

    第二是就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。

    第三是运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。

    第四是阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。sleep,suspend,wait等方法都可以导致线程阻塞。

    第五是死亡状态。如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪

    (7)多线程的安全问题:总结来说,多个线程在执行同一段代码的时候,每次的执行结果和单线程执行的结果都是一样的,不存在执行结果的二义性,就可以称作是线程安全的。线程安全问 题多是由全局变量和静态变量引起的,当多个线程对共享数据只执行读操作,不执行写操作时,一般是线程安全的;当多个线程都执行写操作时,需要考虑线程同步 来解决线程安全问题。

    (8)线程和同步:说明Java线程的两个特性,可见性和有序性。多个线程之间是不能直接传递数据交互的,它们之间的交互只能通过共享变量来实现.

    java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查), 

        将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他线程的调用, 

    从而保证了该变量的唯一性和准确性

    (9)生产者和消费者模式:存储空间已满,而生产者占用着它,消费者等着生产者让出空间从而去除产品,生产者等着消费者消费产品,从而向空间中添加产品。互相等待,从而发生死锁。

    (10)模式:1.wait()和notify();2.await()和signal(),即线程锁的方式;3.阻塞队列的方式;

    (11)高并发:手段无非是切割(纵向,横向)和负载均衡。纵向分隔主要是按业务(功能)来分,也就是所谓面向服务架构,横向分隔方式比较多,主要依赖于所处理的对象属性负载均衡则可以是镜像(部署)分布(同样的功能部署几份)和计算分布(一个问题分几个子问题在不同的机器上运行,然后合并结果)。当然,这些手段是可以综合利用的,最终可以做成多流水线分布式计算模式;

    8. list、map和set什时候用?彼此间的区别和联系?

    (1)list列表是顺序存放对象的,可以有相同的对象,通过索引存取;一般在能直接使用数组的时候,就有使用列表

    (2)set集合:集合是无序存放对象的,其中不能有重复的对象(唯一的,回忆高中时候数学中学习的集合特性),集合没有索引,只能遍历次存取;一般用于存放无序的(指顺序不重要)不能重复的对象

    (3)Map映射:映射,存放的是键与值的映射,其中键是唯一的(不能有重复对象),而值可以有重复的对象,存的时候,需要指定键和对应的值,取的时候可以根据键名取到值,也可以遍历;一般在用于存放具有对应关系的键值对的时候用;

    (4)三者的区别和联系:三者都是接口,List与Set具有相似性,它们都是单列元素的集合,list,set是继承自collection,而map不是,list里可以有重复元素,有先后顺手,Set里面不允许有重复的元素,而且无序,Map 保存key-value值,value可多值。

    9. java常见的数据类型是什么和对应的包装类是什么?java的隐式类型?assert什么时候使用?

    (1)int, double, float, long, short, boolean, byte, char

    (2)Integer.Double,Float,Long,Short,Boolean,Byte,Characher.

    (3)java的隐式类型是int,byte,short,char都可以隐含转换为int ,

    (4)一般来说,assertion用于保证程序最基本、关键的正确性。assertion检查通常在开发和测试时开启。为了提高性能,在软件发布后,assertion检查通常是关闭的;

    10. object类型中有哪些方法?

    (1)equals()、hashCode()、wait()、toString(),finalize(),notify(),notifyAll(),wait(),

    11. final、finallly和finalize的区别?

    (1)final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。 

    内部类要访问局部变量,局部变量必须定义成final类型,例如,一段代码……

    finally是异常处理语句结构的一部分,表示总是执行。

    finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法

    12. LinkedList和ArrayList的区别?继承的接口?

    (1)ArrayList是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢

    LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。

    LinkedList也是线程不安全的,LinkedList提供了一些方法,使得LinkedList可以被当作堆栈和队列来使用

    (2)list接口;ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问; Vector与ArrayList一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,访问它比访问ArrayList慢。LinkedList是用链表结构存储数据的,很适合数据的动态插入和删除,随机访问和遍历速度比较慢。另外,接口中没有定义的方法 get,remove,insertList,专门用于操作表头和表尾元素,可以当作堆栈、队列和双向队列使用。LinkedList没有同步方法。如果 多个线程同时访问一个List,则必须自己实现访问同步。一种解决方法是在创建 List时构造一个同步的List:

    13. int和string是如何转化的?

    (1)int i = Integer.parseInt([String]);i = Integer.parseInt([String],[int radix]);或者int i = Integer.valueOf(my_str).intValue();int转StringString s = String.valueOf(i);String s = Integer.toString(i);String s = "" + i;

    15. 谈谈你对面向对象编程的理解?

    (1)Java语言是纯粹的面向对象的程序设计语言,这主要表现为Java完全支持面向对象的三种基本特征:继承、封装和多态。Java语言完全以对象为中心,Java程序的最小程序单位是类,整个Java程序由一个一个的类组成;Java完全支持使用对象、类、继承、封装、消息等基本概念来进行程序设计,允许从现实世界中客观存在的事物(即对象)出发来构造软件系统,在系统构造中 尽可能运用人类的自然思维方式。实际上,这些优势是所有面向对象编程语言的共同特征。而面向对象的方式实际上由OOA(面向对象分析)、OOD(面向对象 设计)和OOP(面向对象编程)三个部分有机组成,其中,OOA和OOD的结构需要使用一种方式来描述并记录,目前业界统一采用UML(统一建模语言)来 描述并记录OOA和OOD的结果。目前UML的最新版是2.0它一共包括13种类型的图形,使用这13种图形中的某些就可以很好地描述并记录软件分析、设 计的结果

    16. 重写和重载的区别?

    (1)重载Overload表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同(即参数个数或类型不同);

    (2)重写Override表示子类中的方法可以与父类中的某个方法的名称和参数完全相同,通过子类创建的实例对象调用这个方法时,将调用子类中的定义方法,这相当于把父类中定义的那个完全相同的方法给覆盖了,这也是面向对象编程的多态性的一种表现;只能比父类抛出更少的异常,或者是抛出父类抛出的异常的子异常;子类方法的访问权限只能比父类的更大,不能更小。如果父类的方法是private类型,那么,子类则不存在覆盖的限制,相当于子类中增加了一个全新的方法;

    17. sleep&wait区别和联系?

    (1)这两个方法来自不同的类分别是,sleep来自Thread类,和wait来自Object类;sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在a线程里调用了b的sleep方法,实际上还是a去睡觉,要让b线程睡觉要在b的代码中调用sleep。

    (2)最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。sleep不出让系统资源;wait是进入线程等待池等待,出让系统资源,其他线程可以占用CPU。一般wait不会加时间限制,因为如果wait线程的 运行资源不够,再出来也没用,要等待其他线程调用notify/notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待OS分配系统资源。 sleep(milliseconds)可以用时间指定使它自动唤醒过来,如果时间不到只能调用interrupt()强行打断;

    18. string、stringbuffer和stringbuilder的区别?哪个更安全?为什么?hashmap为什么查询的比较快?

    (1)JAVA平台提供了两个类:String和StringBuffer,它们可以储存和操作字符串,即包含多个字符的字符数据。这个String类提供了数值不可改变的字符串。而这个StringBuffer类提供的字符串进行修改。当你知道字符数据要改变的时候你就可以使用StringBuffer。典型地,你可以使用StringBuffers来动态构造字符数据。另外,String实现了equals方法;而StringBuffer没有实现equals方法,所以,new StringBuffer(“abc”).equals(new StringBuffer(“abc”)的结果为false。

    (2)StringBuffer线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改;通过某些方法调用可以改变该序列的长度和内容,可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致;

    (3)StringBuilder一个可变的字符序列。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。(如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。但将 StringBuilder 的实例用于多个线程是不安全的。如果需要这样的同步,则建议使用 StringBuffer。);

    (4)HashMap是Hashtable的轻量级实现(非同步非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),由于非线程安全,在只有一个线程访问的情况下,效率要高于Hashtable。

    19. hashmap的数组是hashcode定位的,有很多key得到的hashcode是相同的,这时候如何定位?

    (1)Java采用了哈希表的原理。哈希算法也称为散列算法,就是集合首先会调用该对象的hashcode方法;是将数据依特定算法直接指定到一个地址上。关于哈希算法,这里就不详细介绍。可以这样简单理解,hashCode方法实际上返回的就是对象存储位置的映像;hashcode相同但是对象并不同,所有存储位置也不同;对于List集合、数组而言,他就是一个累赘,不重要;但是对于HashMap、HashSet、HashTable而言,它变得异常重要。

    20. string是否是基本数据类型?int和string是如何转化的?

    (1)基本数据类型包括byte、int、char、long、float、double、boolean和short;java.lang.String类是final类型的,因此不可以继承这个类、不能修改这个类。为了提高效率节省空间,我们应该用StringBuffer类;

    (2)int i = Integer.parseInt([String]);i = Integer.parseInt([String],[int radix]);或者int i = Integer.valueOf(my_str).intValue();int转StringString s = String.valueOf(i);String s = Integer.toString(i);String s = "" + i;

    三 Java Web

    1. Jsp页面便利集合?

    (1)List<String> names = new LinkedList<String>();

    (2)Set<String> set = new TreeSet<String>();

    (3)Map<String, String> map = new HashMap<String, String>();

    2. tomcat核心项目:tomacate出现乱码如何解决?如何增加tomcat和jdk的内存?jdk的版本?

    (1)Java的内核和class文件是基于unicode的,这使Java程序具有良好的跨平台性,但也带来了一些中文乱码问题的麻烦。原因主要有两方面,Java和JSP文件本身编译时产生的乱码问题和Java程序于其他媒介交互产生的乱码问题。

    (2)更改 D:\Tomcat\conf\server.xml,指定浏览器的编码格式为“简体中文;方法是找到 server.xml 中的:<Connector port="8080" maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
        enableLookups="false" redirectPort="8443" acceptCount="100"
        connectionTimeout="20000" disableUploadTimeout="true" URIEncoding=‘GBK‘ />

    (3)另一种方法:更该 Java 程序,我的程序是这样的:public class ThreeParams extends HttpServlet {
      public void doGet(HttpServletRequest request, HttpServletResponse response)
       throws ServletException, IOException {
          response.setContentType("text/html; charset=GBK");

    (4)增加tomcat内存的方法:linux下,在文件{tomcat_home}/bin/catalina.sh的前面,增加如下设置:SET JAVA_OPTS=-Xms512m -Xmx1024m;表示初始化内存为512MB,可以使用的最大内存为1024MB;windows下,在tomcat_home}/bin/catalina.bat的前面,增加如下设置:SET JAVA_OPTS=-Xms512m -Xmx1024m;

    (5)Jdk的版本:JDK分为三种不同的版本 JAVA SE(标准版)Java EE(企业版)Java ME(微型版)。

    Java SE 以前称为J2SE。它允许开发和部署在桌面、服务器、嵌入式环境和实时环境中使用的 Java 应用程序。Java SE是基础包,但是也包含了支持 Java Web 服务开发的类,并为 Java Platform,Enterprise Edition(Java EE)提供基础。

    JavaEE:这个版本以前称为 J2EE。企业版本帮助开发和部署可移植、健壮、可伸缩且安全的服务器端 Java 应用程序。Java EE 是在 Java SE 的基础上构建的,它提供 Web 服务、组件模型、管理和通信 API,可以用来实现企业级的面向服务体系结构(service-oriented architecture,SOA)和 Web 2.0 应用程序。

    JavaME:这个版本以前称为 J2ME。Java ME 为在移动设备和嵌入式设备(比如手机、PDA、电视机顶盒和打印机)上运行的应用程序提供一个健壮且灵活的环境。Java ME 包括灵活的用户界面、健壮的安全模型、许多内置的网络协议以及对可以动态下载的连网和离线应用程序的丰富支持。基于 Java ME 规范的应用程序只需编写一次,就可以用于许多设备,而且可以利用每个设备的本机功能。

    3. 谈谈对MVC的理解以及它的工作流程;

    (1)MVC是一个设计模式,它强制性的使应用程序的输入、处理和输出分开。使用MVC应用程序被分成三个核心部件:模型、视图、控制器。它们各自处理自己的任务;

    jsp+Servlet+JavaBean 就是一种基础的基于mvc的开发模式;在MVC结构中,模型(Model)代表应用程序的数据(data)和用于控制访问和修改这些数据的业务规则(business rule)。通常模型被用来作为对现实世界中一个处理过程的软件近似,当定义一个模型时,可以采用一般的简单的建模技术。

    当模型发生改变时,它会通知视(View),并且为视提供查询模型相关状态的能力。同时,它也为控制器(Controller)提供访问封装在模型内部的应用程序功能的能力。

    一个视(View)用来组织模型的内容。它从模型那里获得数据并指定这些数据如何表现。当模型变化时,视负责维持数据表现的一致性。视同时将用户要求告知控制器(Controller)。

    控制器(Controller)定义了应用程序的行为;它负责对来自视的用户要求进行解释,并把这些要求映射成相应的行为,这些行为由模型负责实现。在独立运行的GUI客户端,用户要求可能是一些鼠标单击或是菜单选择操作。在一个Web应用程序中,它们的表现形式可能是一些来自客户端的GET或POST的HTTP请求。模型所实现的行为包括处理业务和修改模型的状态。根据用户要求和模型行为的结果,控制器选择一个视作为对用户请求的应答。通常一组相关功能集对应一个控制器。

    工作流程:一个请求发送到action(作用:MVC中的C),action控制它发送到哪个biz处理,如果用到数据库,那么biz在连接dao,然后返回要的数据,最后action在返回响应的页面(比如jsp),因为是面向对象,所以实体domain在中间传递数据。

    4. post和get以及get和load的区别?使用get应注意什么?

    (1)Get 方法通过 URL 请求来传递用户的数据,将表单内各字段名称与其内容,以成对的字符串连接,以URL字串本身传递数据参数,在服务器端可以从‘QUERY_STRING‘这个变量中直接读取,效率较高,但缺乏安全性,也无法来处理复杂的数据(只能是字符串,比如在servlet/jsp中就无法处理发挥java的比如vector之类的功能,输的数据量非常小,一般限制在 2 KB 左右);

    Post 方法通过 HTTP post 机制,将表单内各字段名称与其内容放置在 HTML 表头(header)内一起传送给服务器端交由 action 属性能所指的程序处理,该程序会通过标准输入(stdin)方式,将表单的数据读出并加以处理post方式:就传输方式讲参数会被打包在数据报中传输,从CONTENT_LENGTH这个环境变量中读取,便于传送较大一些的数据,同时因为不暴露数据在浏览器的地址栏中,安全性相对较高,但这样的处理效率会受到影响。接收的最大数据有限制,IIS 4 中为 80 KB 字节,IIS 5 中为 100 KB 字节

    (1)建议:除非你肯定你提交的数据可以一次性提交,否则请尽量用 Post 方法;Get 方式提交数据,会带来安全问题;通过 Get 方式提交数据时,用户名和密码将出现在 URL 上;所以表单提交建议使用 Post 方法;Post 方法提交的表单页面常见的问题是,该页面如果刷新的时候,会弹出一个对话框;

    (2)Get与load的区别:总之对于get和load的根本区别,一句话,hibernate对于load方法认为该数据在数据库中一定存在,可以放心的使用代理来延迟加载,如果在使用过程中发现了问题,只能抛异常;而对于get方法,hibernate一定要获取到真实的数据,否则返回null;

    5. java的九大内置对象和四大作用域;

    (1)request 用户端请求,一次请求.此请求会包含来自GET/POST请求的参数

        response 网页传回用户端的回应

        pageContext 网页的属性是在这里管理

    session 与请求有关的会话期 

    application servlet 正在执行的内容

    out 用来传送回应的输出 

    config servlet的构架部件

    page JSP网页本身 

    exception 针对错误网页,未捕捉的例外

    四大作用域:page对象表示当前一个JSP页面,可以理解为一个对象本身,是代表与一个页面相关的对象和属性;一个页面由一个编译好的 Java servlet 类表示,

    request是代表与 Web 客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个 Web 组件(由于 forward 指令和 include 动作的关系);用户端请求

    session是代表与用于某个 Web 客户机的一个用户体验相关的对象和属性。一个 Web 会话可以也经常会跨越多个客户机请求 与请求有关的会话期 

    application是代表与整个 Web 应用程序相关的对象和属性。这实质上是跨越整个 Web 应用程序,包括多个页面、请求和会话的一个全局作用域 正在执行的内容

    四 Ajax

    1. js里面的button方法,提交的时候,如何将数据传递到数据库?

    (1)单击button的时候,先执行客户端的javascript代码,将JavaScript里面的值赋值到form表单里,然后通过表单提交的方式将数据提交到后台,交给java方法处理,然后调用业务层和数据库交互;

    2. Ajax与jquery区别?ajax和servelet生命周期?

    (1)区别:Ajax是一门技术,它提供了异步更新的机制,使用客户端与服务器间交换数据而非整个页面文档,实现页面的局部更新。jQuery是一个框架,它对JS(JS是一门前端语言。)进行了封装,使其更方便使用。jQuery使得JS与Ajax的使用更方便

    jsp负责客户端显示

    servlet负责控制,转向等

    (2)生命周期:Servlet 生命周期:Servlet 加载--->实例化--->服务--->销毁;

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

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

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

    Ajax:ajax负责客户端与服务器直接联系,而不用jsp提交表单。一般ajax与servlet联系,也可直接与javabean联系

    3. Jquery的常用标签,常用选择器。

    (1)标签: jquery常用标签 $(document) //选择整个文档对象; $(‘#myId‘) //选择ID为myId的网页元素; $(‘div.myClass‘) // 选择class为myClass的div元素;$(‘input[name=first]‘) // 选择name属性等于first的input元素;

    (2)常用函数:val() 用来获得value属性的值;html() 获得元素标签内的所有信息;包裹标签和文本,相当于DOM中的innerHTML;size()获得集合/数组的长度;

    (2)常用选择器: 基本选择器; 层次选择器; 过滤选择器; 表单选择器;

    (2)#id : 根据给定的id匹配一个元素,返回单个匹配的元素:

    (3).class:根据给定的类名匹配元素,返回集合元素

    (4)*:匹配所有的元素,返回集合元素

    (5)elements:根据给定的元素名匹配元素,返回集合元素

    (6)Selector1选择器匹配:将每一个选择器匹配到的元素合并后一起返回

    4. JQ(封装ajax;异步通讯;从前台传过去jason,后台如何解析?

    (1)method:请求方式(GET/POST)

    *  url:目标URL

    *  content:用POST方式发出请求时想传给服务器的数据,

    *         数据以查询字串的方式列出,如:name=value&anothername=othervalue。

    *      若用GET方式:请传null

    *  responseType:响应内容的格式(text/xml)

    *  callback:要回调的函数

    (2)异步通讯:  

    I:初始化对象并发送XMLHttpRequest请求(针对IE7.0、8.0、firefox、mozillar、opera、safari浏览器;var xmlhr=new XMLHttpRequest;针对IE5.0、5.5、6.0,var xmlhr=new ActiveXObject( );)

    II:指定响应处理函数(onreadystatechange)

    III:发出HTTP请求(send)

    IIII:处理服务器返回的数据(responseXML)

    (3)解析:首先,我们要在前台引入json的脚本,以便于把js对象序列化

    <script type="text/javascript" src="/js/jquery.json-2.4.min.js"></script>

    然后我们在前台声明一个类,将你要保存的值放到类里面,最后序列化

    然后我们在后台,进行反序列化,并使用值.因为我们使用ajax所以要在后台的方法上加上[Ajax.AjaxMethod]特性,并且在你前台所在页面的cs里面也要加上Ajax的注册;

    五 框架

    1. 三大框架使用的版本?三大框架各核心组件及作用;如果不用三大框架,jdbc能不能下出来?

    (1)三大框架的版本:struts 2; spring 3; hibernate 3.3;

    (2)组件及作用:Java三大框架主要用来做WEb应用; Struts主要负责表示层的显示;Spring利用它的IOC和AOP来处理控制业务(负责对数据库的操作);Hibernate主要是数据持久化到数据库;

    (3)Struts的组件:Struts对Model,View和Controller都提供了对应的组件;

    Model部分:由JavaBean组成,ActionForm用于封装用户的请求参数,封装成ActionForm对象,该对象被ActionServlet转发给Action,Action根据ActionFrom里面的请求参数处理用户的请求。JavaBean则封装了底层的业务逻辑,包括数据库访问等。

    View部分:该部分采用JSP实现。Struts提供了丰富的标签库,通过标签库可以减少脚本的使用,自定义的标签库可以实现与Model的有效交互,并增加了现实功能。对应上图的JSP部分。

    Controller组件:Controller组件有两个部分组成——系统核心控制器,业务逻辑控制器。   系统核心控制器,对应上图的ActionServlet。该控制器由Struts框架提供,继承HttpServlet类,因此可以配置成标注的Servlet。该控制器负责拦截所有的HTTP请求,然后根据用户请求决定是否要转给业务逻辑控制器。业务逻辑控制器,负责处理用户请求,本身不具备处理能力,而是调用Model来完成处理。对应Action部分。

    (4)Spring的组件:工厂类BeanFactory;反转控制IOC;面向切面编程AOP

    Spring实现了工厂模式的工厂类BeanFactory,在程序中通常BeanFactory的子类ApplicationContext。Spring相当于一个大的工厂类,在其配置文件中通过<bean>元素配置用于创建实例对象的类名和实例对象的属性。

    Spring提供了对IOC良好支持,IOC是一种编程思想,是一种架构艺术,利用这种思想可以很好地实现模块之间的解耦

    Spring提供了对AOP技术的良好封装, AOP称为面向切面编程,就是系统中有很多各不相干的类的方法,在这些众多方法中要加入某种系统功能的代码;例如,加入日志,加入权限判断,加入异常处理,这种应用称为AOP;

    (5)Hibernate的组件:五个核心接口:session接口,sessionFactory接口,configuration接口,transaction接口,query和criteria接口;

    Session接口:负责执行被持久化对象的CRUD操作(CRUD的任务是完成与数据库的交流,包含了很多常见的SQL语句。)。但需要注意的是Session对象是非线程安全的。同时,Hibernate的session不同于JSP应用中的HttpSession。这里当使用session这个术语时,其实指的是Hibernate中的session,而以后会将HttpSession对象称为用户session。

    SessionFactory接口:负责初始化Hibernate。它充当数据存储源的代理,并负责创建Session对象。这里用到了工厂模式。

    Configuration接口:负责配置并启动Hibernate,创建SessionFactory对象。在Hibernate的启动的过程中,Configuration类的实例首先定位映射文档位置、读取配置,然后创建SessionFactory对象。

    Transaction接口:负责事务相关的操作。它是可选的,开发人员也可以设计编写自己的底层事务处理代码。

    Query和Criteria接口:负责执行各种数据库查询。它可以使用HQL语言或SQL语句两种表达方式.

    JDBC:

    Connection cn=null;

    PreparedStatement pst=null;

    ResultSet rs=null;

    Try{Class.forname(driverClassName);

    cn=DriverManager.getStatement(“sql”);

    pst.setString(1,statementName);

    rs=pst.executeQuery();

    While(rs.next()){

    System.out.println();}

    }catch(Exception e){

    e.printStackTrace();

    }finally{

    If(rs!=null){rs.close()};

    If(pst!=null){pst.close()};

    If(cn!=null){cn.close()};

    }

    2. hql语句是如何查询的?hql语句中内切和外切的区别?

    (1):hql是面向对象的类名,属性区分大小写;from+你的实体类;

    (2)内切:利用内连接可获取两表的公共部分的记录;采用左外连接查询返回的结果集中包含的是对象数组,对象数组中的每个元素存放了一对相互关联的Customer对象和Order对象,而迫切左外连接会返 回Customer对象,与Customer对象相关联的Order对象存放在Customer对象的集合元素对象中,这就是迫切左外连接和左外连接查询 的其中一个区别;另一个区别是当使用左外连接时,对关联对象的检索会依照实体映射配置文件所指定的策略,而不会像迫切左外连接那样忽略它,比如此时对Customer对象关联的Order对象采用延迟加载,那么左外连接检索也会使用延迟加载机制检索 Order对象。

    (3)采用迫切内连接检索,对集合元素的检索策略以及返回结果集中的对象类型都采用与迫切左外连接一样的方式,QBC查询不支持迫切内连接检索.

    3. 多表关联什么情况下用hashmap?

    (1)Map用于保存具有映射关系的数据,Map里保存着两组数据:key和value,它们都可以使任何引用类型的数据(class,interface,array ),但key不能重复。所以通过指定的key就可以取出对应的value。HashMap可以让你将空值作为一个表的条目的key或value,HashMap最多只有一个key值为null,但可以有无数多个value值为null。

    spring mvc工作机制?MVC里面视图的好处?

    工作机制:客户端请求提交到DispatcherServlet

    由DispatcherServlet控制器查询一个或多个HandlerMapping,找到处理请求的Controller

    DispatcherServlet将请求提交到Controller

    Controller调用业务逻辑处理后,返回ModelAndView

    DispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图

    视图负责将结果显示到客户端

    视图的好处:视图对象的定义比实体定义还要简单,不需要注解,不需要映射,但是唯一不同的是我们需要额外构造一个带有字段初始化的构造函数

    4. hibernat和mybaitis的优势和区别?haibernate的缓存机制有没有了解过?如何使用hibernate将数据永久保存到数据库中?mybaitates是如何实现查询的?hibernate有很多数据操作时候如何优化?

       (1)hibernate的优势:·  MyBatis可以进行更为细致的SQL优化,可以减少查询字段。·  MyBatis容易掌握,而Hibernate门槛较高。

       (2)mybaitis 的优势:·  Hibernate的DAO层开发比MyBatis简单,Mybatis需要维护SQL和结果映射;·  Hibernate对对象的维护和缓存要比MyBatis好,对增删改查的对象的维护要方便;·  Hibernate数据库移植性很好,MyBatis的数据库移植性不好,不同的数据库需要写不同SQL。·  Hibernate有更好的二级缓存机制,可以使用第三方缓存。MyBatis本身提供的缓存机制不佳。

       (3)区别:Hibernate功能强大,数据库无关性好,O/R映射能力强,如果你对Hibernate相当精通,而且对Hibernate进行了适当的封装,那么你的项目整个持久层代码会相当简单,需要写的代码很少,开发速度很快,非常爽。·  iBATIS入门简单,即学即用,提供了数据库查询的自动对象绑定功能,而且延续了很好的SQL使用经验,对于没有那么高的对象模型要求的项目来说,相当完美。

      (4)Hibernate一级缓存是Session缓存,利用好一级缓存就需要对Session的生命周期进行管理好。建议在一个Action操作中使用一个Session。一级缓存需要对Session进行严格管理。Hibernate二级缓存是SessionFactory级的缓存。 SessionFactory的缓存分为内置缓存和外置缓存。内置缓存中存放的是SessionFactory对象的一些集合属性包含的数据(映射元素据及预定SQL语句等),对于应用程序来说,它是只读的。外置缓存中存放的是数据库数据的副本,其作用和一级缓存类似.二级缓存除了以内存作为存储介质外,还可以选用硬盘等外部存储设备。二级缓存称为进程级缓存或SessionFactory级缓存,它可以被所有session共享,它的生命周期伴随着SessionFactory的生命周期存在和消亡。

      (5)mybatitis的查询:Mybatis的SQL是手动编写的,所以可以按需求指定查询的字段。mybatis是数据映射器(数据映射器层:用于在对象和数据库之间搬运数据,同时保证对象、数据库和数据映射器层本身相对独立。Martin Fowler 《企业应用架构模式》)把sql语句的参数与结果(即输入与输出)映射为类。为如何在类和数据库间建立映射带来了更大的灵活性。同时也更好的隔离了数据库设计和应用程序中使用的对象模型。

      (6)hibernate 的持久化:Hibernate采用了更自然的面向对象的视角来持久化 Java 应用中的数据。使用 Hibernate 的开发者应该总是关注对象的状态(state),不必考虑 SQL 语句的执行。这部分细节已经由 Hibernate 掌管妥当,只有开发者在进行系统性能调优的时候才需要进行了解。

       (6)mybatis的调优:MyBatis在Session方面和Hibernate的Session生命周期是一致的,同样需要合理的Session管理机制。MyBatis同样具有二级缓存机制。 MyBatis可以进行详细的SQL优化设计。

      (7)hibernate如何实现优化:·  制定合理的缓存策略;

    ·  尽量使用延迟加载特性;·  采用合理的Session管理机制;·  使用批量抓取,设定合理的批处理参数(batch_size);·  进行合理的O/R映射设计

    5. spring、hibernate、Struts的工作原理,为什么使用这些框架?简单说下struts2中数据传递情况? hibernate的三种状态和彼此的区别?使用hibernate如何分页?spring的事务隔离级别?ssh如何整合(spring核心流程)?

    (1)spring的工作原理:

    ISpring内部最核心的就是IOC了,动态注入,让一个对象的创建不用new了,可以自动的生产,这其实就是利用java里的反射,反射其实就是在运行 时动态的区创建、调用对象,Spring就是在运行时,跟xmlSpring的配置文件来动态的创建对象,和调用对象里的方法。

    II.Spring工作原理还有一个核心就是Aop这个就是面向切面的编程,可以为某一类对象进行监督和控制(也就是在调用这类对象的具体方法的前后去调用你指定的模块)从而达到对一个模块扩充的功能这些都是通过配置类达到的。

    III.Spring目的:就是让对象与对象(模块与模块)之间的关系没有通过代码来关联,都是通过配置类说明管理的(主要是通过反射机制)。

    (2)hibernate的工作原理:

    I.读取并解析hibernate.cfg.xml配置文件

    II.读取并解析映射信息

    III.创建SessionFactory

    IV.负责被持久化对象CRUD操作,打开Sesssion

    V.创建并启动事务Transation

    VI.操作数据,持久化操作

    VII.提交事务,关闭Session,关闭SesstionFactory;

    (3)struts的工作原理同下:

    I.客户端浏览器发出HTTP请求。II.根据web.xml配置,该请求被FilterDispatcher接收。III.根据struts.xml配置,找到需要调用的Action类和方法, 并通过IoC方式,将值注入给Aciton。IV.Action调用业务逻辑组件处理业务逻辑,这一步包含表单验证。V.Action执行完毕,根据struts.xml中的配置找到对应的返回结果result,并跳转到相应页面。VI.返回HTTP响应到客户端浏览器。

    (4)使用原因:

    struts是开源软件。使用Struts的目的是为了帮助我们减少在运用MVC设计模型来开发Web应用的时间。如果我们想混合使用Servlets和JSP的优点来建立可扩展的应用,struts是一个不错的选择。

    Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任;

    Spring:Spring是一个开源框架,它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益.

    (5)struts数据传递:可以直接基于应用程序域对象转移,验证数据,数据绑定,动作把从请求接收到的所有数据放在简单的JavaBean上。除了单独接受每个数 据,struts2最优雅的地方时可以创建一个对象来放置这些琐碎的数据,我们可以把复杂对象本身提供给平台的数据转移机制。这不但节省时间,而且也能节 省工作量。

    (6)hibernate的三种状态和区别:

    瞬时(transient):也叫自由状态.数据库中没有数据与之对应,超过作用域会被JVM垃圾回收器回收,一般是new出来且与session没有关联的对象。

    持久(persistent):数据库中可能有数据与之对应(save),当前与session有关联,并且相关联的session没有关闭,事务没有提交;持久对象状态发生改变,在事务提交时会影响到数据库(hibernate能检测到)。

    脱管(detached):也叫游离状态.数据库中可能有数据与之对应,但当前没有session与之关联,但是有oid;托管对象状态发生改变,hibernate不能检测到。

    区别:Transient状态的实体缺乏与数据库表记录之间的联系,而Detached状态的实体恰恰相反.只不过是脱离了session这个数据库操作平台而已.

    (7)hibernate分页:1.HQL查询:Query query=session.createQuery(from 实体类);2.从第几条开始:query.setFirstResult(mini);3.每次最多提取多少条数据:query.setMaxResults(max);接收返回的结果集:List<实体类> HousesList=query.list();

    代码如下(Query query = session.createQuery(hql);  

    query.setParameter(0, userId);  

    query.setMaxResults(maxCount);  

    query.setFirstResult(firstResult);  

    return query.list();

    )

    (8)ssh整合步骤:

    1.导入struts2的jar包以及struts2-spring-plugin-2.0.11.2.jar; 

    2.在web.xml中分别配置struts2与spring相关信息;

    3.struts中原有的Action需要继承ActionSupport;

    4.在Spring配置Action Bean;

    5.在Struts2的配置文件中,调用Spring中配置的Bean;

    6.Spring与Hibernate整合,只需要在Spring配置文件配置SessionFactory即可

    (9)Spring的隔离级别:Default默认的事务隔离级别

    READ_UNCOMMITTED读未提交,一个事务可以操作另外一个未提交的事务,不能避免脏读,不可重复读,幻读,隔离级别最低,并发性 能最高

    READ_COMMITTED读已提交,一个事务不可以操作另外一个未提交的事务, 能防止脏读,不能避免不可重复读,幻读。

    repeatable_read能够避免脏读,不可重复读,不能避免幻读

    SERIALIZABLE隔离级别最高,消耗资源最低,代价最高,能够防止脏读, 不可重复读,幻读。

    6. Struts的工作流程;

    工作流程:

    (1)客户端提交一个HttpServletRequest请求(action或JSP页面)。

       (2)请求被提交到一系列Filter过滤器,如ActionCleanUp和FilterDispatcher等。

       (3)FilterDispatcher是Struts2控制器的核心,它通常是过滤器链中的最后一个过滤器.

       (4)请求被发送到FilterDispatcher后,FilterDispatcher询问ActionMapper时候需要调用某个action来处理这个Request。

       (5)如果ActionMapper决定需要调用某个action,FilterDispatcher则把请求交给ActionProxy进行处理.

       (6)ActionProxy通过Configuration Manager询问框架的配置文件struts.xml,找到调用的action类。

       (7)ActionProxy创建一个ActionInvocation实例,通过代理模式调用Action。

       (8)action执行完毕后,返回一个result字符串,此时再按相反的顺序通过Intercepter拦截器。

       (9)最后ActionInvocation实例,负责根据struts.xml中配置result元素,找到与之相对应的result,决定进一步输出。

    基本简要流程:

    I.客户端浏览器发出HTTP请求。

    II.根据web.xml配置,该请求被FilterDispatcher接收。

    III.根据struts.xml配置,找到需要调用的Action类和方法, 并通过IoC方式,将值注入给Aciton。

    IV.Action调用业务逻辑组件处理业务逻辑,这一步包含表单验证。  

        VI.Action执行完毕,根据struts.xml中的配置找到对应的返回结果result,并跳转到相应页面。VI.返回HTTP响应到客户端浏览器。 

    7. 简述SSH工作流程;

    (1)JSP页面发出请求,Struts接收页面请求,Struts的action调用业务逻辑,业务逻辑调用业务组件(其中使用到Spring的依赖注入 IOC,或者AOP等);业务组件根据Hibernate的对象/关系数据库的映射关系查询数据库。Struts根据结果返回页面。

    8. 谈谈Spring和Spring MVC的流程和事务;spring配置文件都写什么?

    (1)spring提供两种管理事务的方式:一种是声明式事务,一种是编程式事务。

    Spring的声明式事务管理,基于Spring的AOP,基于Spring AOP实现,几乎就是xml文件的配置,不再需要不停地写commit,rollback,(但Spring仍然没有放弃编程式的事务管理策略)。

    Spring的编程式事务管理,统一的事务编码风格,几乎是一个模板化的。

    为我们提供了一个TransactionTemplate,使用回调机制,将应用代码从样板式的资源获取和释放代码中解放出来,不再有大量的try/catch/finally/try/catch代码块。

    (2)springMVC的流程和事务:动态注入,让一个对象的创建不用new了,可以自动的生产,这其实就是利用java里的反射 ,反射其实就是在运行时动态的去创建、调用对象,Spring就是在运行时,跟xml Spring的配置 
    文件来动态的创建对象,和调用对象里的方法的 。

    Spring还有一个核心就是AOP这个就是面向切面编程,可以为某一类对象 进行监督和控制(也就是在调用这类对象的具体方法的前后去调用你指定的 模块)从而达到对一个模块扩充的功能。这些都是通过 配置类达到的。Spring目的:就是让对象与对象(模块与模块)之间的关系没有通过代码来关联,都是通过配置类说明管理的(Spring根据这些配置 内部通过反射去动态的组装对象) 
    要记住:Spring是一个容器,凡是在容器里的对象才会有Spring所提供的这些服务和功能。

    (3)spring的配置文件:一、引用外部属性文件;二、常用数据源的配置;三、配置事务管理器;四、context:component-scan<!-- 对包中的所有类进行扫描,以完成Bean创建和自动依赖注入的功能 -->;五、aop注解支持;六、缓存配置;七、<!-- Spring、MyBatis的整合,需要在 Spring 应用上下文中定义至少两样东西:一个SqlSessionFactory和至少一个数据映射器类(UserMapper->iocContext.xml)。 -->;

    9. ssm和ssh的区别?

    (1)基于MVC三层架构,使用ssh框架 or ssm框架 or ssi框架,采用面向接口的方式编程。
    共同点是struts、spring,不同点是nibernate和mybatis、ibatis。

    (2)相对Hibernate“O/R”而言,iBATIS 是一种“Sql Mapping”的ORM实现。

    (3)由于hibernate是完全面向对象的编程,在实现dao中就非常的方便,而且不重复;当mybatis在.java代码中也是可以做到不重复,麻烦一点的是,每个映射文件都必须编写几乎相同的配置,除了resultType不一样。

    (4)hibernate在实际编程中可以把基础的CRUD封装,比如BaseDao类。其它类只要去继承BaseDao就能执行所有的基础的CRUD。这样就非常方便。这个带来的好处还有,可以建立BaseService和BaseAction。 

    由于mybatis的映射文件中,虽然SQL语句中的表名可以通过parameterType指定,但是resultType必须定死,不能以参数 的形式给予指定。导致的结果就是所有的DAO类的每个CRUD都必须和指定的映射文件绑定在一起,以至于不可能存在BaseDao类。当然也就不能建立 BaseService和BaseAction。

    10. spring核心:aop和ioc的解释?隔离范围? 3种注入方法?

    (1)aop:Spring提供了对AOP技术的良好封装, AOP称为面向切面编程,就是系统中有很多各不相干的类的方法,在这些众多方法中要加入某种系统功能的代码;例如,加入日志,加入权限判断,加入异常处理,这种应用称为AOP。实现AOP功能采用的是代理技术,客户端程序不再调用目标,而调用代理类,代理类与目标类对外具有相同的方法声明,有两种方式可以实现相同的方法声明,一是实现相同的接口,二是作为目标的子类在,JDK中采用Proxy类产生动态代理的方式为某个接口生成实现类,spring提供了这种支持,只需要在spring配置文件中配置这两个元素即可实现代理和aop功能;

    (2)Ioc:Spring提供了对IOC良好支持,IOC是一种编程思想,是一种架构艺术,利用这种思想可以很好地实现模块之间的解耦。IOC也称为DI(Depency Injection);IOC可以理解为‘面向接口编程思想’的一种实现方法,通过IOC实现了强制的‘面向接口编程’。

    (3)隔离范围: Spring支持JDBC规范定义的四种隔离级别

    Default默认的事务隔离级别

    READ_UNCOMMITTED读未提交,一个事务可以操作另外一个未提交的事务,不能避免脏读,不可重复读,幻读,隔离级别最低,并发性 能最高

    READ_COMMITTED读已提交,一个事务不可以操作另外一个未提交的事务, 能防止脏读,不能避免不可重复读,幻读。

    repeatable_read能够避免脏读,不可重复读,不能避免幻读

    SERIALIZABLE隔离级别最高,消耗资源最低,代价最高,能够防止脏读, 不可重复读,幻读。

    (4)Spring的注入和IoC反转控制是一回事;关于getter和setter方式的注入;

    Autowire=”defualt”;autowire=”byName”;autowire=”byType”;

    11. 两亿条数据如何同时删除

    (1)·  public boolean delUsers(String[] userIds){  

    ·          boolean flag = false;  

    ·          Connection conn = null;  

    ·          PreparedStatement pstmt = null;    

    ·          String sql = "delete from t_user where user_id=?";  

    ·          try {  

    ·              conn = DbUtil.getConnection();  

    ·              conn.setAutoCommit(false);  

    ·              pstmt = conn.prepareStatement(sql);  

    ·              for(int i =0 ;i<userIds.length;i++){   

    ·                  pstmt.setString(1,userIds[i].trim());  

    ·                  pstmt.addBatch();                 

    ·              }   

    ·              pstmt.executeBatch(); //批量执行   

    ·              conn.commit();//提交事务  

    ·              flag = true;  

    ·          } catch (SQLException e) {  

    ·              try {  

    ·                  conn.rollback(); //进行事务回滚  

    ·              } catch (SQLException ex) {   

    ·              }   

    ·          }finally {  

    ·              DbUtil.close(pstmt);  

    ·              DbUtil.close(conn);  

    ·          }   

    ·          return flag;  

    ·      }  

    12. 如何将1个g的数据最快速度放进C盘中?

    (1)public class Test01 {

         

        public static void main(String[] args) throws Exception{

            getInputStream("C:\\setup.log","D:\\a.txt");

        }

        private static void getInputStream(String pathName,String copyName)throws Exception{

            File file = new File(pathName);

            if(!file.exists())

                throw new RuntimeException("文件不存在呀,你Copy个屁!");

            else{

                getCopy(copyName,new BufferedInputStream(new FileInputStream(file)));

            }

        }

        private static void getCopy(String copyName,BufferedInputStream bis)throws Exception{

            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(copyName));

            BufferedInputStream biss = bis;

            byte[] b = new byte[biss.available()];

            int len = 0;

            while((len = biss.read(b))!=-1){

                bos.write(b, 0, len);

            }

            bos.close();

            biss.close();

            System.out.println(copyName+"复制成功!");

        }

    冒泡排序:

    public static void bubbleSort(int[] numbers) {   
        int temp; // 记录临时中间值   
        int size = numbers.length; // 数组大小   
        for (int i = 0; i < size - 1; i++) {   
            for (int j = i + 1; j < size; j++) {   
                if (numbers[i] < numbers[j]) { // 交换两数的位置   
                    temp = numbers[i];   
                    numbers[i] = numbers[j];   
                    numbers[j] = temp;   
                }   
            }   
        }   
    }  

    选择排序:

    public static void selectSort(int[] numbers) {   
        int size = numbers.length, temp;   
        for (int i = 0; i < size; i++) {   
            int k = i;   
            for (int j = size - 1; j >i; j--)  {   
                if (numbers[j] < numbers[k])  k = j;   
            }   
            temp = numbers[i];   
            numbers[i] = numbers[k];   
            numbers[k] = temp;   
        }   
    }  

    项目面试通关必懂

    项目通用问题:

    1.介绍下整个项目流程,谈谈你自己负责的模块?别人的模块是否了解?

    2.讲解下自己负责的模块,这个模块如何实现的?做这个项目时候遇到怎样的问题?

    3.你在项目组中的角色和优势?

    4.做项目的时间,项目组几个人,多长时间完成?

    5. 介绍下算法和项目的思路?

    6. 问session和cooie的区别?

        (1)具体来说cookie机制采用的是在客户端保持状态的方案,而session 机制采用的是在服务器端保持状态的方案。由于才服务器端保持状态的方案在客户端也需要保存一个标识,所以session机制可能需要借助于cookie机制来达到保存标识的目的,但实际上还有其他选择。

    7. 问登陆页;

    8. Spring事务;

    9. 同步锁;

    10.往关联两个表中添加数据,如果没有添加成功,会怎样?如何处理?

    11.说下使用的项目ssm框架和使用的技术Json和ajax。

    12.大数据如何处理?数据库如何批量删除和批量插入?

    具体项目还要清楚

    一:好买网商城项目

    1:商城项目的需求,介绍整个项目流程;

    二:你我贷金融P2P项目

    1.项目利息问题;

    2.身份如何验证的问题?

    3.项目的逻辑关系?

    4.第三方接口怎么写?

    5.违约如何提醒的问题?

    6.金额除不尽的问题?

    三 进销存项目:

    1.介绍下进销存项目?

    介绍项目时先说项目需求,然后从开始的进销存进货说到最后,进销存的模块:进货、销售、库存、财务报表、用户管理、信用冻结、全局资源,然后按照销售流程把项目贯穿一下。

    2.进销存项目负责的模块是什么?

    3.权限:权限分配;做权限控制,数据库关系映射介绍下?

    4.数据库资金类型设置成bigdecimal还是double?

    5.报表用的是什么?

    6.一个项目数据库牵扯几个表?

    7.进销存多少个表?用户管理方面多少个模块?用户管理模块多少个表?

    9. 如何判断是自己的采购、给哪家公司做的、好多人买东西发生了错误如何解决(事物&多线程)

    以上是关于web前端面试题(必背面试题)的主要内容,如果未能解决你的问题,请参考以下文章

    前端面试题汇总

    面试集合(更)web前端经典面试题试题及答案html/css

    面试集合(更)web前端经典面试题试题及答案JavaScript

    新手小白必知的5道Web前端经典面试题

    web前端开发程序员面试题集锦

    WEB前端面试题