全国咨询热线:400-009-1906

第一篇:面试题汇总

Java基础、语法
1.Java跨平台原理(字节码文件、虚拟机) 2.Java的安全性 3.Java三大版本 4.什么是JVM?什么是JDK? 什么是JRE? 5.Java三种注释类型 6.8种基本数据类型及其字节数 7.i++和++i的异同之处 8.&和&&的区别和联系,|和||的区别和联系 9.用最有效率的方法算出2乘以8等于多少 10.基本数据类型的类型转换规则 11.if多分支语句和switch多分支语句的异同之处 12.while和do-while循环的区别 13.break和continue的作用 14.请使用递归算法计算n! 15.递归的定义和优缺点 16.数组的特征 17.请写出冒泡排序代码 18.请写出选择排序的代码 19.请写出插入排序的代码 20.可变参数的作用和特点 21.类和对象的关系 22.面向过程和面向对象的区别 23.this和super关键字的作用 24.static关键字的作用 25.final和abstract关键字的作用 26.final、finally、finalize的区别 27.写出java.lang.Object类的六个常用方法 28.private/默认/protected/public权限修饰符的区别 29.继承条件下构造方法的执行过程 30.==和equals的区别和联系 31.谈谈Java的多态 32.简述Java的垃圾回收机制 33.基本数据类型和包装类 34.Integer与int的区别 35.java.sql.Date和java.util.Date的联系和区别 36.使用递归算法输出某个目录下所有文件和子目录列表 37.关于Java编译,下面哪一个正确()(选择一项) 38.下列说法正确的有()(选择一项) 39.Java中接口的修饰符可以为()(选择一项) 40.给定以下代码,程序将输出 ()(选择一项) 41.下列关于关键字的使用说法错误的是()(选择一项) 42.下列哪些语句关于内存回收的说法是正确的()(选择一项) 43.选出合理的标识符()(选择两项) 44.下列说法正确的是()(选择多项) 45.定义一个类名为”MyClass.java”的类,并且该类可被一个工程中的所有类访问,那么该类的正确声明为()(选择两项) 46.面向对象的特征有哪些方面?请用生活中的例子来描述。 47.说明内存泄漏和内存溢出的区别和联系,结合项目经验描述Java程序中如何检测?如何解决? 48.什么是Java的序列化,如何实现Java的序列化?列举在哪些程序中见过Java序列化? 49.不通过构造函数也能创建对象吗? 50.匿名内部类可不可以继承或实现接口。为什么? 在Java中,为什么基本类型不能做为HashMap的键值,而只能是引用类型,把引用类型做为HashMap的健值,需要注意哪些地方。 52.简述Java中如何实现多态 53.以下对继承的描述锚误的是 () 54.Java 中 Math.random()/Math.random()值为? 55.Java中,如果Manager是Employee的子类,那么Pair< Manager>是Pair< Employee>的子类吗? 56.接口和抽象类的区别 57.同步代码块和同步方法有什么区别 58.静态内部类和内部类有什么区别 59.反射的概念与作用 60.提供Java存取数据库能力的包是() 61.下列运算符合法的是()(多选) 62.执行如下程序代码,c的值打印出来是() 63.下列哪一种叙述是正确的() 64.下列语句正确的是() 65.下列哪种说法是正确的() 66.Java程序的种类有()(多选) 67.下列说法正确的有()(多选) 68.下列标识符不合法的有()(多选) 69.下列说法错误的有()(多选) 70.不能用来修饰interface的有()(多选) 71.下列正确的有()(多选) 72.下列说法错误的有()(多选) 73.下列说法错误的有()(多选) 74.下列说法错误的有()(多选) 75.请问0.3332的数据类型是() 76.Java接口的修饰符可以为() 77.不通过构造函数也能创建对象么() 78.存在使i+1< i的数么? 79.接口可否继承接口?抽象类是否可实现接口?抽象类是否可继承实体类? 80.int与Integer有什么区别? 81.可序列化对象为什么要定义serialversionUID值? 82.写一个Java正则,能过滤出html中的 < a href=”url” >title< /a>形式中的链接地址和标题. 83.十进制数72转换成八进制数是多少? 84.Java程序中创建新的类对象,使用关键字new,回收无用的类对象使用关键字free正确么? 85.Class类的getDeclaredFields()方法与getFields()的区别? 86.在switch和if-else语句之间进行选取,当控制选择的条件不仅仅依赖于一个x时,应该使用switch结构;正确么? 88.使用final关键字修饰符一个变量时,是引用不能变,还是引用的对象不能变? 88.使用final关键字修饰符一个变量时,是引用不能变,还是引用的对象不能变? 89.请解释以下常用正则含义:\d,\D,\s,.,*,?,|,[0-9]{6},\d+ 90.已知表达式int m[] = {0,1,2,3,4,5,6}; 下面那个表达式的值与数组的长度相等() 91.下面那些声明是合法的?() 92.以下选项中选择正确的java表达式() 93.下列代码的输出结果是 94.以下哪些运算符是含有短路运算机制的?请选择:() 95.下面哪个函数是public void example(){....}的重载函数?() 96.给定某java程序片段,该程序运行后,j的输出结果为() 97.在java中,无论测试条件是什么,下列()循环将至少执行一次。 98.打印结果: 99.指出下列程序的运行结果 100.解释继承、重载、覆盖。 101.什么是编译型语言,什么是解释型语言?java可以归类到那种? 102.简述操作符(&,|)与操作符(&&,||)的区别 &和&&的联系(共同点) 103.try{}里面有一个return语句,那么紧跟在这个try后的finally, 里面的语句在异常出现后,都会执行么?为什么? 104.有一段java应用程序,它的主类名是al,那么保存它的源文件可以是?() 105.Java类可以作为() 106.在调用方法时,若要使方法改变实参的值,可以?() 107.Java语言具有许多优点和特点,哪个反映了java程序并行机制的() 108.下关于构造函数的描述错误是() 109.若需要定义一个类域或类方法,应使用哪种修饰符?() 110.下面代码执行后的输出是什么() 111.给出如下代码,如何使成员变量m被函数fun()直接访问() 112.下面哪几个函数是public void example(){….}的重载函数() 113.请问以下代码执行会打印出什么? 114.如果有两个类A、B(注意不是接口),你想同时使用这两个类的功能,那么你会如何编写这个C类呢? 115.一个类的构造方法是否可以被重载(overloading),是否可以被子类重写(overrding)? 116.Java中byte表示的数值范围是什么? 117.如何将日期类型格式化为:2013-02-18 10:53:10? 118.不通过构造函数也能创建对象吗() 119.下面哪些是对称加密算法() 120.下面的代码段,当输入为2的时候返回值是() 121.以下Java代码段会产生几个对象 122.Math.round(-11.2)的运行结果是。 123.十进制数278的对应十六进制数 124.Java中int.long占用的字节数分别是 125.System.out.println(‘a’+1);的结果是 126.下列语句那一个正确() 127.下列说法正确的有() 128.执行如下程序代码() 129.下列哪一种叙述是正确的() 130.下列语句正确的是() 131.成员变量用static修饰和不用static修饰有什么区别? 132.如果变量用final修饰,则怎样?如果方法final修饰,则怎样? 133.在二进制数据中,小数点向右移一位,则数据() 134.面向对象的特征有哪些方面? 135.float f=3.4;是否正确? 136.short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗? 137.Java 有没有goto? 138.int 和Integer 有什么区别? 139.&和&&的区别? 140.Math.round(11.5) 等于多少? Math.round(-11.5)等于多少? 141.swtich 是否能作用在byte 上,是否能作用在long 上,是否能作用在String上? 142.用最有效率的方法计算2乘以8? 143.在Java 中,如何跳出当前的多重嵌套循环? 144.构造器(constructor)是否可被重写(override)? 145.两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对? 146.当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递? 147.重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分? 148.华为的面试题中曾经问过这样一个问题:为什么不能根据返回类型来区分重载,为什么? 149.静态嵌套类(Static Nested Class)和内部类(Inner Class)的不同? 150.抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被synchronized修饰? 151.静态变量和实例变量的区别? 152.是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用? 153.如何实现对象克隆? 154.接口是否可继承(extends)接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承具体类(concrete class)? 155.一个“.java”源文件中是否可以包含多个类(不是内部类)?有什么限制? 156.Anonymous Inner Class(匿名内部类)是否可以继承其它类?是否可以实现接口? 157.内部类可以引用它的包含类(外部类)的成员吗?有没有什么限制? 158.Java 中的final关键字有哪些用法? 159.指出下面程序的运行结果: 160.说说数据类型之间的转换: 161.如何实现字符串的反转及替换? 162.怎样将GB2312编码的字符串转换为ISO-8859-1编码的字符串? 163.Java中的日期和时间: 164.打印昨天的当前时刻。 165.Java反射技术主要实现类有哪些,作用分别是什么? 166.Class类的作用?生成Class对象的方法有哪些? 167.反射的使用场合和作用、及其优缺点 168.面向对象设计原则有哪些
集合
193.Java集合体系结构(List、Set、Collection、Map的区别和联系) 194.Vector和ArrayList的区别和联系 195.ArrayList和LinkedList的区别和联系 196.HashMap和Hashtable的区别和联系 197.HashSet的使用和原理(hashCode()和equals()) 198.TreeSet的原理和使用(Comparable和comparator) 199.集合和数组的比较(为什么引入集合) 200.Collection和Collections的区别 201.下列说法正确的有()(选择一项) 202.Java的HashMap和Hashtable有什么区别HashSet和HashMap有什么区别?使用这些结构保存的数需要重载的方法是哪些? 203.列出Java中的集合类层次结构? 204.List,Set,Map各有什么特点 205.ArrayList list=new ArrayList(20);中的list扩充几次() 206.List、Set、Map哪个继承自Collection接口,一下说法正确的是() 207.合并两个有序的链表 208.用递归方式实现链表的转置。 209.给定一个不包含相同元素的整数集合,nums,返回所有可能的子集集合。解答中集合不能包含重复的子集。 210.以下结构中,哪个具有同步功能() 211.以下结构中,插入性能最高的是() 212.以下结构中,哪个最适合当作stack使用() 213.Map的实现类中,哪些是有序的,哪些是无序的,有序的是如何保证其有序性,你觉得哪个有序性性能更高,你有没有更好或者更高效的实现方式? 214.下面的代码在绝大部分时间内都运行得很正常,请问什么情况下会出现问题?根源在哪里? 215.TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素? 216.List里面如何剔除相同的对象?请简单用代码实现一种方法 217.Java.util.Map的实现类有 218.下列叙述中正确的是() 219.List、Set、Map 是否继承自Collection 接口? 220.说出ArrayList、Vector、LinkedList 的存储性能和特性? 221.List、Map、Set 三个接口,存取元素时,各有什么特点? 222.TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?
多线程
223.下面程序的运行结果()(选择一项) 224.下列哪个方法可用于创建一个可运行的类() 225.说明类java.lang.ThreadLocal的作用和原理。列举在哪些程序中见过ThreadLocal的使用? 226.说说乐观锁与悲观锁 227.在Java中怎么实现多线程?描述线程状态的变化过程。 228.请写出多线程代码使用Thread或者Runnable,并说出两种的区别。 229.在多线程编程里,wait方法的调用方式是怎样的? 230.Java线程的几种状态 231.在Java多线程中,请用下面哪种方式不会使线程进入阻塞状态() 232.volatile关键字是否能保证线程安全? 233.请写出常用的Java多线程启动方式,Executors线程池有几种常用类型? 234.关于sleep()和wait(),以下描述错误的一项是() 235.进程和线程的区别是什么? 236.以下锁机机制中,不能保证线程安全的是() 237.创建n多个线程,如何保证这些线程同时启动?看清,是“同时”。 238.同步和异步有何异同,在什么情况下分别使用它们? 239.Java线程中,sleep()和wait()区别 240.下面所述步骤中,是创建进程做必须的步骤是() 241.无锁化编程有哪些常见方法?() 242.sleep()和yield()有什么区别? 243.当一个线程进入一个对象的synchronized方法A之后,其它线程是否可进入此对象的synchronized方法? 244.请说出与线程同步相关的方法。 245.编写多线程程序有几种实现方式? 246.synchronized关键字的用法? 247.启动一个线程是用run()还是start()方法? 248.什么是线程池(thread pool)? 249.线程的基本状态以及状态之间的关系? 250.简述synchronized 和java.util.concurrent.locks.Lock的异同? 251.创建线程的两种方式分别是什么,优缺点是什么? 252.Java创建线程后,调用start()方法和run()的区别 253.线程的生命周期 254.如何实现线程同步? 255.说说关于同步锁的更多细节 256.Java中实现线程通信的三个方法的作用是什么?
Web方面相关
291.WEB应用中如果有.class和.jar类型的文件一般分别应该放在什么位置? 292.元素中有一个输入框(< input type=‘text’ name=’username‘id=’username”value=‘’"/>,请用JavaScript语言写一行代码,取得这个输入框中的值。 293.简单描述一下Servlet与JSP的的相同点和区别点。 294.请简单描述下几个您熟悉JavaScript库,它们有哪些作用和特点? 295.简单描述HTML,CSS,Javascript在Web开发中分别起什么作用? 296.当DOM加载完成后要执行的函数,下面哪个是正确的() 297.举例说明JAVA中如何解析xml,不同方式有和优缺点? 298.char型变量中能不能存储一个中文汉字? 299.一个类可以实现多个接口,但只能继承一个抽象类。 300.比较一下Java 和JavaSciprt 301.什么时候用assert? 302.UML是什么?UML中有哪些图? 303.XML 文档定义有几种形式?它们之间有何本质区别?解析XML 文档有哪几种方式? 304.你在项目中哪些地方用到了XML? 305.用JavaScript实现用正则表达式验证,某个字符串是合法的6位数字的邮编的函数 306.请使用JQuery将页面上的所有元素边框设置为2pix宽的虚线? 307.如何设定JQuery异步调用还是同步调用? 308.说出3条以上firefox和IE的浏览器兼容问题? 309.请用Jquery语言写出ajax请求或者post请求代码 310.body中的onload ()函数和jQuery中document.ready()有什么区别? 311.jQuery中有哪几种类型的选择器? 312.EasyUI中datagrid刷新当前数据的方法? 313.分别写出一个div居中和其中的内容居中的css属性设置 314.概述一下session与cookie的区别 315.JavaScript 中 null和 undefined 是否有区别?有哪些区别? 316.Servlet中的doPost和doGet方法有什么区别?它们在传递和获取参数上有什么区别? 317.请写出一段jQuery代码,实现把当前页面中所有的a元索中class 属性为“view-link”的链接都改为在新窗口中打开 318.如下JavaScript代码的输出为: 319.Jquery中’.get()’与’.eq()’的区别 320.如何给weblogic定内存的大小? 321.TCP为何采用三次握手来建立连接,若釆用二次握手可以吗,请说明理由? 322.以下HTTP相应状态码的含义描述正确的是() 323.JSP页面包括哪些元素?() 324.Ajax有四种技术组成:DOM,CSS,JavaScript,XmlHttpRequest,其中控制文档结构的是() 325.下面关于session的用法哪些是错误的?() 326.Jsp九大内置对象 327.如何配置一个servlet? 328.JavaScript,如何定义含有数值1至8的数组? 329.以下JavaScipt语句会产生运行错误的是_() 330.在JSP中,下面__()__块中可以定义一个新类: 331.HTML含义和版本变化 332.什么是锚链接 333.HTML字符实体的作用及其常用字符实体 334.HTML表单的作用和常用表单项类型 335.表格、框架、div三种HTML布局方式的特点 336.form中input设置为readonly和disabled的区别 337.CSS的定义和作用 338.CSS2常用选择器类型及其含义 339.引入样式的三种方式及其优先级别 340.盒子模型 341.JavaScript语言及其特点 342.JavaScript常用数据类型有哪些 343.html语法中哪条命令用于使一行文本折行,而不是插入一个新的段落? (B) 344.Ajax的优点和缺点 345.怎样防止表单刷新重复提交问题?(说出思路即可) 346.JQuery.get()和JQuery.ajax()方法之间的区别是什么? 347.Jquery里的缓存问题如何解决?例如($.ajax()以及$.get()) 348.Javascript是面向对象的,怎么体现Javascript的继承关系? 349.Javascript的有几种种变量。变量范围有什么不同? 350.Js如何获取页面的dom对象 351.Servlet API中forward() 与redirect()的区别? 352.Session域和request域什么区别? 353.页面中有一个命名为bankNo的下拉列表,写js脚本获取当前选项的索引值,如果用jquery如何获取 354.写出要求11位数字的正则表达式 355.分别获取指定name、Id的javascript对象,如果用jquey如何获取 356.一个页面有两个form,如何获取第一个form 357.如何设置一个层的可见/隐藏 358.描述JSP中动态INCLUDE与静态INCLUDE的区别? 359.列举JSP的内置对象及方法 360.列举jsp的四大作用域 361.html和xhtml的区别是什么? 362.你做的页面用哪些浏览器测试过?这些测试的内核分别是什么? 363.你遇到了哪些浏览器的兼容性问题?怎么解决的? 364.你知道的常用的js库有哪些? 365.Js中的三种弹出式消息提醒(警告窗口、确认窗口、信息输入窗口)的命令是什么? 366.谈谈js的闭包 367.写一段js,遍历所有的li,将每个li的内容逐个alert出来 368.页面上如何用JavaScript对多个checkbox全选 369.写一个简单的JQuery的ajax 370.Js截取字符串abcdefg的efg 371.http的请求头信息包含了什么? 372.http的响应码200,404,302,500表示的含义分别是? 373.Servlet中request对象的方法有? 374.Javascript的常用对象有哪些 375.DOM和BOM及其关系 376.JavaScript中获取某个元素的三种方式JavaScript中的三种弹出式消息提醒命令是什么? 377.JavaScript操作CSS的两种方式 378.静态网页和动态网页的联系和区别 379.JSP/ASP/PHP的比较 380.CGI/Servlet/JSP的比较 381.HTTP协议工作原理及其特点 382.get和post的区别 383.如何解决表单提交的中文乱码问题 384.绝对路径、根路径、相对路径的含义及其区别 385.如实现servlet的单线程模式 386.Servlet的生命周期 387.转发和重定向的区别 388.JSP的执行过程 389.JSP动作有哪些,简述作用? 390.page/request/session/application作用域区别 391.JSP和Servlet的区别和联系 392.谈谈过滤器原理及其作用? 393.jQuery相比JavaScript的优势在哪里 394.DOM对象和jQuery对象的区别及其转换 395.jQuery中$的作用主要有哪些 396.Ajax含义及其主要技术 397.Ajax的工作原理 398.JSON及其作用 399.文件上传组件Common-fileUpload的常用类及其作用? 400.说出Servlet的生命周期,并说出Servlet和CGI的区别? 401.JSP 和Servlet 有有什么关系? 402.JSP中的四种作用域? 403.如何实现JSP或Servlet的单线程模式? 404.实现会话跟踪的技术有哪些? 405.过滤器有哪些作用和用法? 406.监听器有哪些作用和用法? 407.你的项目中使用过哪些JSTL标签? 408.使用标签库有什么好处?如何自定义JSP标签? 409.表达式语言(EL)的隐式对象及其作用? 410.表达式语言(EL)支持哪些运算符? 411.Servlet 3中的异步处理指的是什么? 412.如何在基于Java的Web项目中实现文件上传和下载? 413.简述值栈(Value-Stack)的原理和生命周期 414.阐述Session加载实体对象的过程。 415.怎么防止重复提交 416.$(document).ready(function(){}) jQuery(document).ready(function(){}); 有什么区别? 417.写出输出结果 418.web项目从浏览器发起交易响应缓慢,请简述从哪些方面如数分析
高级框架
431.什么是Maven? 432.Maven和ANT的区别 433.Maven仓库是什么 434.Maven的工程类型有哪些? 435.Maven常用命令有哪些? 436.ZooKeeper的作用是什么? 437.什么是Znode? 438.Znode节点类型有哪些? 439.什么是Dubbo? 440.什么是RPC远程过程调用? 441.Dubbo中有哪些角色? 442.Dubbo执行流程什么是? 443.说说Dubbo支持的协议有哪些? 444.Dubbo支持的注册中心有哪些? 445.SessionFactory是线程安全的吗?Session是线程安全的吗,两个线程能够共享同一个Session吗? 446.Session的load和get方法的区别是什么? 447.Session的save()、update()、merge()、lock()、saveOrUpdate()和persist()方法有什么区别? 448.什么是VSFTPD? 449.什么是Nginx? 450.Nginx有哪些作用? 451.什么是正向代理? 452.什么是反向代理? 453.什么是Redis? 454.Redis的特点什么是? 455.Redis数据类型有哪些? 456.Redis中的常用命令哪些? 457.Redis的配置以及持久化方案有几种? 458.什么是RDB方式? 459.什么是AOF方式? 460.什么是全文检索? 461.什么是Lucene? 462.什么是Solr? 463.Solr是由哪两个部分构成? 464.什么是正排索引? 465.什么是倒排索引? 466.什么是ActiveMQ? 467.消息服务的应用场景有哪些? 468.什么是JMS? 469.JMS有哪些模型? 470.什么是JsonP? 471.什么是跨域? 472.什么是同源策略? 473.什么是MyCat? 474.什么是纵向切分/垂直切分? 475.简述Tomcat,Apache,JBoss和WebLogic的区别和联系 476.以下可以实现负载均衡的是() 477.Tomcat/ WebSphere/WebLogic的作用和特点 478.B/S和C/S的含义及其区别 479.说说你对容器的理解 480.为什么要使用连接池? 481.数据库连接池的原理 482.MVC模式及其优缺点 483.MVC模式完成分页功能的基本思路是什么? 484.常用的Web容器 485.Java Web开发的Model 1和Model 2分别指的是什么? 486.说说什么是框架: 487.简单说一下MVC框架? 488.简单讲一下struts2的执行流程 489.Struts2中的拦截器,你都用它干什么? 490.简单讲一下SpringMVC的执行流程? 491.简单说一下struts2和springMVC有什么不同 492.说一下Spring中的两大核心 493.讲一下Spring的事务的传播特性 494.什么是ORM 495.Hibernate对象的状态 496.介绍一下Hibernate的缓存 497.简单讲一下webservice使用的场景 498.简单介绍一下activity? 499.什么是MyBatis? 500.Mybatis是如何进行分页的?分页插件的原理是什么? 501.MyBatis与Hibernate有哪些不同? 502.简述Mybatis的Xml映射文件和Mybatis内部数据结构之间的映射关系? 503.什么是MyBatis的接口绑定,有什么好处? 504.Mybatis能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别? 505.MyBatis里面的动态Sql是怎么设定的?用什么语法? 506.使用MyBatis的mapper接口调用时有哪些要求? 507.Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式? 508.MyBatis接口绑定有几种实现方式,分别是怎么实现的? 509.MyBatis实现一对一有几种方式?具体怎么操作的? 510.什么情况下用注解绑定,什么情况下用xml绑定? 511.MyBatis的好处是什么?
数据库
538.下列属于关系型数据库的是()(选择两项) 539.请列出Java常见的开源数据连接池,并对参数做出简单的说明 540.储蓄所有多个储户,储户在多个储户所存取款,储蓄所与储户之间是() 541.视图是一个“虚表”,视图的构造基于() 542.设有关系R(A,B,C,D)及其上的函数相关性集合F={B→A,BC→D},那么关系R最高是() 543.什么是DAO模式? 544.数据库MySQL,Oracle,SqlServer分页时用的语句 545.Oracle完成分页功能的三层子查询语句及其含义? 546.问SQL怎么优化执行效率更高 547.谈谈数据库去空格的情况 548.根据你以往的经验简单叙述一下MYSQL的优化 549.以Oracle11R为例简述数据库集群部署 550.说一下数据库的存储过程? 551.数据库创建索引的缺点? 552.有两张表;请用SQL查询,所有的客户订单日期最新的前五条订单记录。(分别注明MySQL. Oracle写法) 553.关于HQL与SQL,以下哪些说法正确?() 554.下面是学生表(student)的结构说明 555.为管理岗位业务培训信息,有如下3个表: 556.用Java怎么实现有每天有1亿条记录的DB储存?MySQL上亿记录数据量的数据库如何设计? 557.Mysql的引擎有哪些?支持事物么?DB储存引擎有哪些? 558.以下是学生考试结果表 559.库中已经存在雇用表表名: 560.如下表1中的数据,表名为:t_test,记录某场比赛的结果。 561.请将如下数据库语句进行优化,使其执行效率更高(提示:…不需要更改) 562.请简述如何将Oracle中的数据库转至DB2中,需要保证表结构和数据不变 563.学生成绩表 564.Oracl数据库中有两张表Stu(学生表)和Grade(分数表),如下图所示: 565.下面是学生表(Student)的结构说明: 566.取出sql表中低31到40的记录(以自动增长ID为主键) 567.下列两个表,需要用一条sql语句把b表中的ID和NAME 字段的数值复制到A表中 568.什么是基本表,什么是视图,两者的区别和联系是什么? 569.什么是事务?什么是锁? 570.Student学生表(学号,姓名、性别、年龄、组织部门),Course 课程表(编号,课程名称),Sc选课表(学号,课程编号,成绩) 571.sql查询
Linux操作
580.请写出常用的linux指令不低于10个,请写出linux tomcat启动。 581.当使用RMI技术实现远程方法调用时,能为远程对象生成Sub和Skeleton命令的是() 582.以下哪个是服务() 583.下面的网络协议中,面向连接的的协议是: () 584.在/etc/fstab 文件中指定的文件系统加载参数中, () 参数一般用于CD-ROM 等移动设备。 585.Linux 文件权限一共10 位长度,分成四段,第三段表示的内容是 () 586.终止一个前台进程可能用到的命令和操作 () 587.在使用mkdir 命令创建新的目录时,在其父目录不存在时先创建父目录的选项是 () 588.下面关于i 节点描述错误的是 () 589.一个文件名字为rr.Z,可以用来解压缩的命令是: () 590.具有很多C 语言的功能,又称过滤器的是 () 591.一台主机要实现通过局域网与另一个局域网通信,需要做的工作是 () 592.建立动态路由需要用到的文件有 () 593.局域网的网络地址192.168.1.0/24,局域网络连接其它网络的网关地址是192.168.1.1。主机192.168.1.20 访问172.16.1.0/24 网络时,其路由设置正确的是 () 594.下列提法中,不属于ifconfig 命令作用范围的是 () 595.下列关于链接描述,错误的是() 596.在局域网络内的某台主机用ping 命令测试网络连接时发现网络内部的主机都可以连同,而不能与公网连通,问题可能是() 597.下列文件中,包含了主机名到IP 地址的映射关系的文件是: 598.不需要编译内核的情况是() 599.在shell 中变量的赋值有四种方法,其中,采用name=12 的方法称 () 600.()命令可以从文本文件的每一行中截取指定内容的数据。 601.下列不是Linux 系统进程类型的是() 602.在日常管理中,通常CPU 会影响系统性能的情况是: () 603.若一台计算机的内存为128MB,则交换分区的大小通常是 604.在安装Linux 的过程中的第五步是让用户选择安装方式,如果用户希望安装部分组件(软件程序),并在选择好后让系统自动安装,应该选择的选项是() 605.Linux 有三个查看文件的命令,若希望在查看文件内容过程中可以用光标上下移动来查看文件内容,应使用()命令 606.下列信息是某系统用ps –ef 命令列出的正在运行的进程 ()进程是运行Internet 超级服务器,它负责监听Internet sockets 上的连接,并调用合适的服务器来处理接收的信息。 607.在TCP/IP 模型中,应用层包含了所有的高层协议,在下列的一些应用协议中, ()是能够实现本地与远程主机之间的文件传输工作 608.当我们与某远程网络连接不上时,就需要跟踪路由查看,以便了解在网络的什么位置出现了问题,满足该目的的命令是() 609.对名为fido 的文件用chmod 551 fido 进行了修改,则它的许可权是() 610.用ls –al 命令列出下面的文件列表,()文件是符号连接文件 611.DNS 域名系统主要负责主机名和()之间的解析。 612.WWW 服务器是在Internet 上使用最为广泛,它采用的是()结构 613.Linux 系统通过()命令给其他用户发消息。 614.NFS 是()系统。 615.()命令可以在Linux 的安全系统中完成文件向磁带备份的工作 616.Linux 文件系统的文件都按其作用分门别类地放在相关的目录中,对于外部设备文件,一般应将其放在()目录中 617.在重新启动Linux 系统的同时把内存中的信息写入硬盘,应使用()命令实现 618.网络管理具备以下几大功能:配置管理、()、性能管理、安全管理和计费管理等 619.关闭linux 系统(不重新启动)可使用命令() 620.实现从IP 地址到以太网MAC 地址转换的命令为: () 621.在vi 编辑器中的命令模式下,键入()可在光标当前所在行下添加一新行 622.在vi 编辑器中的命令模式下,删除当前光标处的字符使用()命令 623.在vi 编辑器中的命令模式下,重复上一次对编辑的文本进行的操作,可使用()命令 624.删除文件命令为: () 625.退出交互模式的shell,应键入()
算法分析及手写代码
626.判断身份证:要么是15位,要么是18位,最后一位可以为字母,并写出程序提出其中年月日。要求: 627.对于一个字符串,请设计一个高效算法,找到第一次重复出现的字符保证字符串中有重复的字符,字符串的长度小于等于500. 628.写一个完整函数,实现拷贝数组 629.写一排序算法,输入10个数字,以逗号分开,可根据参数选择升序或者降序排序,须注明是何种排序算法。 630.判断字符串是否是这样的组成的,第一个字母,后面可以是字母、数字、下划线、总长度为5-20。 631.已排好序的数组A,一般来说可用二分查找可以很快找到,现有一特殊数组A,它是循环递增的,如a[]={17, 19 ,20, 25, 1, 4, 7, 9},在这样的数组中找一元素,看看是否存在。请写出你的算法,必要时可写伪代码,并分析其空间,时间复杂度。 632.请编写一个完整的程序,实现如下功能:从键盘输入数字n,程序自动计算n!并输出。(注1:n!=1*2*3...*n, 注2:请使用递归实现) 633.请用递归的方法计算斐波那契数列的同项F(n),已知F0=0,F1=1,F(n)=F(n-1)+F(n-2)(n>=2,n∈N*). 634.现在有整数数组{11,66,22,0,55,32},请任意选择一种排序算法,用Java程序实现 635.请根据注释,编码实现下面类的方法 636.二分法查询(递归实现) 637.编写一段Java程序,把一句英语中的每个单词中的字母次序倒转,单词次序保持不变,例入输入为“There is a dog.”,输出结果应该是“erehT si a god.”要求不使用Java的库函数,例如String类的split,reverse方法。 638.手写9x9乘法表,冒泡排序 639.题目: 给定一个整数数组,找到是否该数组包含任何重复数字。你的函数应该返回true只要有任何数字 在该数组中重复出现,否则返回false。 640.给定一个数组nums, 写一个函数来移动所有0元素到数组末尾,同时维持数组中非0元素的相对顺序不变。要求不能申请额外的内存空间,并且最小化操作次数。 641.给定一颗二叉树,返回节点值得先序遍历,请使用迭代(非递归)方式实现。 642.验证一棵树是否为有效的二叉搜索树BST 643.从一个链表中删除节点 644.二叉搜索树BST中第Kth小的元素 题目:给定⼀个BST,写一个函数kthSmallest来找到第kth小的元素 645.题目:给定含有n个整数的数组S,S中是否存在三个元素a,b,c使得a + b + c = 0? 找到所有这样的三元 组,并且结果集中不包含重复的三元组。 646.子集问题 647.迭代方法实现二叉树的先序遍历:题目: 给定一颗⼆叉树,返回节点值得先序遍历,请使用迭代(非递归)方式实现。 648.验证二叉搜索树BST:题目: 验证一棵树是否为有效的二叉搜索树BST比如,二叉树[2, 1, 3],返回true二叉树[1, 2, 3], 返回false 649.编辑距离题目: 给定两个单词word1和word2,找到最小的操作步骤使得word1转换成word2,每次操作算作一 步。你可以对单词进行以下三种操作:1)插入一个字符2)删除一个字符3)替换一个字符 650.买卖股票问题:题目: 你有一个数组,第i个元素表示第i天某个股票的价格,设计一个算法找到最大的利润,并且你只能最多完成两次交易。 651.[编程]任给n个整数和一个整数x。请计算n个整数中有多少对整数之和等于x。 652.[编程]请说明快速排序算法的设计思想和时间复杂度,并用高级语言写出对整数数组进行一趟快排的函数实现。 653.对于一段形如:1,-1~3,1~15×3的输入 654.有两个字符串:目标串S=“s1s2.......sn”,模式串T="t1t2.......tm"。若存在T的每个字符一次和S中的一个连续字符序列相等,则匹配成功,返回T中第一个字符在S中的位置。否则匹配不成功,返回0。写出你的算法,要求线性时间复杂度 655.如何生成一个0-100的随机整数? 656.请编写一段Java程序将两个有序数组合并成一个有序数组 657.在最佳情况下,以下哪个时间复杂度最高(D) 658.一个数组,元素为从0到m的整数,判断其中是否有重复元素,使用java语言编写一个方法 659.某二叉树的先序遍历是12453,中序遍历是42513,那么其后序遍历是(A) 660.设一颗二叉树中有3个叶子节点,有八个度为1的节点,则该二叉树中总的节点数为() 661.给出下面的二叉树先序、中序、后序遍历的序列? 662.你知道的排序算法都哪些?用Java写一个排序系统 663.写一个二分查找(折半搜索)的算法。 664.统计一篇英文文章单词个数。 665.输入年月日,计算该日期是这一年的第几天。 666.回文素数:所谓回文数就是顺着读和倒着读一样的数(例如:11,121,1991…),回文素数就是既是回文数又是素数(只能被1和自身整除的数)的数。编程找出11~9999之间的回文素数。 667.全排列:给出五个数字12345的所有排列。 668.对于一个有N个整数元素的一维数组,找出它的子数组(数组中下标连续的元素组成的数组)之和的最大值。 669.用递归实现字符串倒转 670.输入一个正整数,将其分解为素数的乘积。 671.一个有n级的台阶,一次可以走1级、2级或3级,问走完n级台阶有多少种走法。 672.写一个算法判断一个英文单词的所有字母是否全都不同(不区分大小写) 673.有一个已经排好序的整数数组,其中存在重复元素,请将重复元素删除掉,例如,A= [1, 1, 2, 2, 3],处理之后的数组应当为A= [1, 2, 3]。 674.给一个数组,其中有一个重复元素占半数以上,找出这个元素。 675.编写一个方法求一个字符串的字节长度?
第三篇:热门专业学习之路
前言

本题集由尚学堂学员整理,列举了众多IT公司面试真题,对应聘Java程序员职位的常见考点和知识体系都进行的分类和归纳整理。

本题集适合应聘Java和JavaEE职位的程序员作为面试复习、学习和强化的资料,也适合其他程序员作为拓展读物进行阅读。

本题集包含了常见的算法、面试题,也包含了新的高级技术,比如:微服务架构等技术的面试题目。本题集非常全面,对于工作1-5年左右的java程序员面试有非常好的指导作用。

大家也可以访问(直接在线观看最新版的面试题):www.bjsxt.com/javamianshiti.html

1.大学生高端复合人才成长
1.JAVA专业,1000课 3.大数据专业,500课
2.Python专业,500课    4.人工智能专业,500课

四个专业都要学,从零开始2000小时,成为高端人才,打下一生技术基础,不再是低端码农。

2.扫一扫,咨询详情:

访问官网 www.itbaizhan.cn

Java基础、语法:

1.Java跨平台原理(字节码文件、虚拟机)

C/C++语言都直接编译成针对特定平台机器码。如果要跨平台,需要使用相应的编译器重新编译。

Java源程序(.java)要先编译成与平台无关的字节码文件(.class),然后字节码文件再解释成机器码运行。解释是通过Java虚拟机来执行的。

字节码文件不面向任何具体平台,只面向虚拟机。

Java虚拟机是可运行Java字节码文件的虚拟计算机。不同平台的虚拟机是不同的,但它们都提供了相同的接口。

Java语言具有一次编译,到处运行的特点。就是说编译后的.class可以跨平台运行,前提是该平台具有相应的Java虚拟机。但是性能比C/C++要低。

Java的跨平台原理决定了其性能没有C/C++高

2.Java的安全性

语言层次的安全性主要体现在:

Java取消了强大但又危险的指针,而代之以引用。由于指针可进行移动运算,指针可随便指向一个内存区域,而不管这个区域是否可用,这样做是危险的,因为原来这个内存地址可能存储着重要数据或者是其他程序运行所占用的,并且使用指针也容易数组越界。

垃圾回收机制:不需要程序员直接控制内存回收,由垃圾回收器在后台自动回收不再使用的内存。避免程序忘记及时回收,导致内存泄露。避免程序错误回收程序核心类库的内存,导致系统崩溃。

异常处理机制:Java异常机制主要依赖于try、catch、finally、throw、throws五个关键字。

强制类型转换:只有在满足强制转换规则的情况下才能强转成功。

底层的安全性可以从以下方面来说明

Java在字节码的传输过程中使用了公开密钥加密机制(PKC)。

在运行环境提供了四级安全性保障机制:

字节码校验器 -类装载器 -运行时内存布局 -文件访问限制

3.Java三大版本

Java2平台包括标准版(J2SE)、企业版(J2EE)和微缩版(J2ME)三个版本:

Standard Edition(标准版) J2SE 包含那些构成Java语言核心的类。

比如:数据库连接、接口定义、输入/输出、网络编程

Enterprise Edition(企业版) J2EE 包含J2SE 中的类,并且还包含用于开发企业级应用的类。

比如servlet、JSP、XML、事务控制

Micro Edition(微缩版) J2ME 包含J2SE中一部分类,用于消费类电子产品的软件开发。

比如:呼机、智能卡、手机、PDA、机顶盒

他们的范围是:J2SE包含于J2EE中,J2ME包含了J2SE的核心类,但新添加了一些专有类

应用场合,API的覆盖范围各不相同。

4.什么是JVM?什么是JDK? 什么是JRE?

JVM :JVM是Java Virtual Machine(Java虚拟机)的缩写,它是整个java实现跨平台的最核心的部分,所有的java程序会首先被编译为.class的类文件,这种类文件可以在虚拟机上执行,也就是说class并不直接与机器的操作系统相对应,而是经过虚拟机间接与操作系统交互,由虚拟机将程序解释给本地系统执行。JVM是Java平台的基础,和实际的机器一样,它也有自己的指令集,并且在运行时操作不同的内存区域。 JVM通过抽象操作系统和CPU结构,提供了一种与平台无关的代码执行方法,即与特殊的实现方法、主机硬件、主机操作系统无关。JVM的主要工作是解释自己的指令集(即字节码)到CPU的指令集或对应的系统调用,保护用户免被恶意程序骚扰。 JVM对上层的Java源文件是不关心的,它关注的只是由源文件生成的类文件(.class文件)。

JRE:JRE是java runtime environment(java运行环境)的缩写。光有JVM还不能让class文件执行,因为在解释class的时候JVM需要调用解释所需要的类库lib。在JDK的安装目录里你可以找到jre目录,里面有两个文件夹bin和lib,在这里可以认为bin里的就是jvm,lib中则是jvm工作所需要的类库,而jvm和lib和起来就称为jre。所以,在你写完java程序编译成.class之后,你可以把这个.class文件和jre一起打包发给朋友,这样你的朋友就可以运行你写程序了(jre里有运行.class的java.exe)。JRE是Sun公司发布的一个更大的系统,它里面就有一个JVM。JRE就与具体的CPU结构和操作系统有关,是运行Java程序必不可少的(除非用其他一些编译环境编译成.exe可执行文件……),JRE的地位就象一台PC机一样,我们写好的Win32应用程序需要操作系统帮我们运行,同样的,我们编写的Java程序也必须要JRE才能运行。 

JDK:JDK是java development kit(java开发工具包)的缩写。每个学java的人都会先在机器上装一个JDK,那 让我们看一下JDK的安装目录。在目录下面有六个文件夹、一个src类库源码压缩包、和其他几个声明文件。其中,真正在运行java时起作用的是以下四个文件夹:bin、include、lib、jre。现在我们可以看出这样一个关系,JDK包含JRE,而JRE包含JVM。

bin:最主要的是编译器(javac.exe)

include:java和JVM交互用的头文件

lib:类库      

jre:java运行环境 

(注意:这里的bin、lib文件夹和jre里的bin、lib是不同的)总的来说JDK是用于java程序的开发,而jre则是只能运行class而没有编译的功能。eclipse、idea等其他IDE有自己的编译器而不是用JDK bin目录中自带的,所以在安装时你会发现他们只要求你选jre路径就ok了。

JDK,JRE,JVM三者关系概括如下:

jdk是JAVA程序开发时用的开发工具包,其内部也有JRE运行环境JRE。JRE是JAVA程序运行时需要的运行环境,就是说如果你光是运行JAVA程序而不是去搞开发的话,只安装JRE就能运行已经存在的JAVA程序了。JDk、JRE内部都包含JAVA虚拟机JVM,JAVA虚拟机内部包含许多应用程序的类的解释器和类加载器等等。

5.Java三种注释类型

共有单行注释、多行注释、文档注释3种注释类型。使用如下:

单行注释,采用“//”方式.只能注释一行代码。如://类成员变量

多行注释,采用“/*...*/”方式,可注释多行代码,其中不允许出现嵌套。如:

/*System.out.println("a");

System.out.println("b");

System.out.println("c");*/

文档注释,采用“/**...*/”方式。如:

/**

* 子类 Dog

* @author Administrator

**/

public class Dog extends Animal{}

6.8种基本数据类型及其字节数
数据类型 关键字 字节数
数值型 整数型 byte 1
short 2
int 4
long 8
浮点型 float 4
double 8
布尔型 boolean 1(位)
字符型 char 2
7.i++和++i的异同之处

共同点:

1、i++和++i都是变量自增1,都等价于i=i+1

2、如果i++,++i是一条单独的语句,两者没有任何区别

3、i++和++i的使用仅仅针对变量。 5++和++5会报错,因为5不是变量。

不同点:

如果i++,++i不是一条单独的语句,他们就有区别i++ :先运算后增1。如:

int x=5;
int y=x++;
System.out.println("x="+x+", y="+y);
    //以上代码运行后输出结果为:x=6, y=5

++i : 先增1后运算。如:

int x=5;
int y=++x;
System.out.println("x="+x+", y="+y);
    //以上代码运行后输出结果为:x=6, y=6
8.&和&&的区别和联系,|和||的区别和联系

&和&&的联系(共同点):

&和&&都可以用作逻辑与运算符,但是要看使用时的具体条件来决定。

操作数1&操作数2,操作数1&&操作数2,

表达式1&表达式2,表达式1&&表达式2,

情况1:当上述的操作数是boolean类型变量时,&和&&都可以用作逻辑与运算符。

情况2:当上述的表达式结果是boolean类型变量时,&和&&都可以用作逻辑与运算符。

表示逻辑与(and),当运算符两边的表达式的结果或操作数都为true时,整个运算结果才为true,否则,只要有一方为false,结果都为false。

&和&&的区别(不同点):

(1)、&逻辑运算符称为逻辑与运算符,&&逻辑运算符称为短路与运算符,也可叫逻辑与运算符。

对于&:无论任何情况,&两边的操作数或表达式都会参与计算。

对于&&:当&&左边的操作数为false或左边表达式结果为false时,&&右边的操作数或表达式将不参与计算,此时最终结果都为false。

综上所述,如果逻辑与运算的第一个操作数是false或第一个表达式的结果为false时,对于第二个操作数或表达式是否进行运算,对最终的结果没有影响,结果肯定是false。推介平时多使用&&,因为它效率更高些。

、&还可以用作位运算符。当&两边操作数或两边表达式的结果不是boolean类型时,&用于按位与运算符的操作。

|和||的区别和联系与&和&&的区别和联系类似

9.用最有效率的方法算出2乘以8等于多少

使用位运算来实现效率最高。位运算符是对操作数以二进制比特位为单位进行操作和运算,操作数和结果都是整型数。对于位运算符“<<”, 是将一个数左移n位,就相当于乘以了2的n次方,那么,一个数乘以8只要将其左移3位即可,位运算cpu直接支持的,效率最高。所以,2乘以8等于几的最效率的方法是2 << 3

10.基本数据类型的类型转换规则

基本类型转换分为自动转换和强制转换。

自动转换规则:容量小的数据类型可以自动转换成容量大的数据类型,也可

以说低级自动向高级转换。这儿的容量指的不是字节数,而是指类型表述的范围。

强制转换规则:高级变为低级需要强制转换。

如何转换:

(1)赋值运算符“=”右边的转换,先自动转换成表达式中级别最高的数据类型,再进行运算。

(2)赋值运算符“=”两侧的转换,若左边级别>右边级别,会自动转换;若左边级别 == 右边级别,不用转换;若左边级别 < 右边级别,需强制转换。

(3)可以将整型常量直接赋值给byte, short, char等类型变量,而不需要进行强制类型转换,前提是不超出其表述范围,否则必须进行强制转换。

11.if多分支语句和switch多分支语句的异同之处

相同之处:都是分支语句,多超过一种的情况进行判断处理。

不同之处:

switch更适合用于多分支情况,就是有很多种情况需要判断处理,判断条件类型单一,只有一个入口,在分支执行完后(如果没有break跳出),不加判断地执行下去;而if—elseif---else多分枝主要适用于分支较少的分支结构,判断类型不是单一,只要一个分支被执行后,后边的分支不再执行。switch为等值判断(不允许比如>= <=),而if为等值和区间都可以,if的使用范围大。

12.while和do-while循环的区别

while先判断后执行,第一次判断为false,循环体一次都不执行

do while先执行 后判断,最少执行1次。

如果while循环第一次判断为true, 则两种循环没有区别。

13.break和continue的作用

break: 结束当前循环并退出当前循环体。

break还可以退出switch语句

continue: 循环体中后续的语句不执行,但是循环没有结束,继续进行循环条件的判断(for循环还会i++)。continue只是结束本次循环。

14.请使用递归算法计算n!
package com.bjsxt;
import java.io.File;
public class $ {
public static void main(String[] args) {
        String path = "D:/301SXT";
        test(path);
    }
    private static void test(String path) {
        File f = new File(path);
        File[] fs = f.listFiles();
        if (fs == null) {
            return;
        }
        for (File file : fs) {
            if (file.isFile()) {
                System.out.println(file.getPath());
            } else {
                test(file.getPath());
            }
        }
    }
15.递归的定义和优缺点

递归算法是一种直接或者间接地调用自身算法的过程。在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解。

递归算法解决问题的特点:

(1) 递归就是在过程或函数里调用自身。

(2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。

(3) 递归算法解题通常显得很简洁,但运行效率较低。所以一般不提倡用递归算法设计程序。

(4) 在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。所以一般不提倡用递归算法设计程序。

16.数组的特征

数组是(相同类型数据)的(有序)(集合)

数组会在内存中开辟一块连续的空间,每个空间相当于之前的一个变量,称为数组的元素element

元素的表示 数组名[下标或者索引] scores[7] scores[0] scores[9]

索引从0开始

每个数组元素有默认值 double 0.0 boolean false int 0

数组元素有序的,不是大小顺序,是索引 的顺序

数组中可以存储基本数据类型,可以存储引用数据类型;但是对于一个数组而言,数组的类型是固定的,只能是一个

length:数组的长度

数组的长度是固定的,一经定义,不能再发生变化(数组的扩容)

17.请写出冒泡排序代码
package com.bjsxt;

public class TestBubbleSort {
public static void sort(int[] a) {
int temp = 0;
// 外层循环,它决定一共走几趟
for (int i = 0; i <a.length-1; ++i) {
//内层循环,它决定每趟走一次
for (int j = 0; j <a.length-i-1 ; ++j) {
//如果后一个大于前一个
if (a[j + 1] < a[j]) {
//换位
temp = a[j];a[j] = a[j + 1];a[j + 1] = temp;
}
}
}

public static void sort2(int[] a) {
int temp = 0;
for (int i = 0; i <a.length-1; ++i) {
//通过符号位可以减少无谓的比较,如果已经有序了,就退出循环
int flag = 0;
for (int j = 0; j <a.length-1-i ; ++j) {
if (a[j + 1] < a[j]) {
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
flag = 1;
}
}
if(flag == 0){
break;
}
}
}
}
18.请写出选择排序的代码
package com.bjsxt;

public class TestSelectSort {
public static void sort(int arr[]) {
int temp = 0;
for (int i = 0; i < arr.length - 1; i++) {
// 认为目前的数就是最小的, 记录最小数的下标
int minIndex = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[minIndex] > arr[j]) {
// 修改最小值的下标
minIndex = j;
}
}
// 当退出for就找到这次的最小值
if (i != minIndex) {
temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
}
}
19.请写出插入排序的代码
package com.bjsxt;

public class TestInsertSort {
public static void sort(int arr[]) {
int i, j;
for (i = 1; i < arr.length; i++) {
int temp = arr[i];
for (j = i; j > 0 && temp < arr[j - 1]; j--) {
arr[j] = arr[j - 1];
}
arr[j] = temp;
}
}
}
20.可变参数的作用和特点

总结1:可变参数

1.可变参数的形式 ...

2.可变参数只能是方法的形参

3.可变参数对应的实参可以0,1,2.....个,也可以是一个数组

4.在可变参数的方法中,将可变参数当做数组来处理

5.可变参数最多有一个,只能是最后一个

6.可变参数好处:方便 简单 减少重载方法的数量

7.如果定义了可变参数的方法,不允许同时定义相同类型数组参数的方法

总结2:数组做形参和可变参数做形参联系和区别

联系:

1.实参都可以是数组;2.方法体中,可变参数当做数组来处理

区别:

1.个数不同 可变参数只能有一个数组参数可以多个

2.位置不同 可变参数只能是最后一个 数组参数位置任意

3.实参不同 可变参数实参可以0,1,2.....个,也可以是一个数组,数组的实参只能是数组

21.类和对象的关系

类是对象的抽象,而对象是类的具体实例。类是抽象的,不占用内存,而对象是具体的,占用存储空间。类是用于创建对象的蓝图,它是一个定义包括在特定类型的对象中的方法和变量的软件模板。

类和对象好比图纸和实物的关系,模具和铸件的关系。

比如人类就是一个概念,人类具有身高,体重等属性。人类可以做吃饭、说话等方法。

小明就是一个具体的人,也就是实例,他的属性是具体的身高200cm,体重180kg,他做的方法是具体的吃了一碗白米饭,说了“12345”这样一句话。

22.面向过程和面向对象的区别

两者都是软件开发思想,先有面向过程,后有面向对象。在大型项目中,针对面向过程的不足推出了面向对象开发思想。

比喻

蒋介石和毛泽东分别是面向过程和面向对象的杰出代表,这样充分说明,在解决复制问题时,面向对象有更大的优越性。

面向过程是蛋炒饭,面向对象是盖浇饭。盖浇饭的好处就是“菜”“饭”分离,从而提高了制作盖浇饭的灵活性。饭不满意就换饭,菜不满意换菜。用软件工程的专业术语就是“可维护性”比较好,“饭” 和“菜”的耦合度比较低。

区别

编程思路不同: 面向过程以实现功能的函数开发为主,而面向对象要首先抽象出类、属性及其方法,然后通过实例化类、执行方法来完成功能。

封装性:都具有封装性,但是面向过程是封装的是功能,而面向对象封装的是数据和功能。

面向对象具有继承性和多态性,而面向过程没有继承性和多态性,所以面向对象优势是明显。

方法重载和方法重写(覆盖)的区别

英文 位置不同 作用不同
重载 overload 同一个类中 在一个类里面为一种行为提供多种实现方式并提高可读性
重写 override 子类和父类间 父类方法无法满足子类的要求,子类通过方法重写满足要求
修饰符 返回值 方法名 参数 抛出异常
重载 无关 无关 相同 不同 无关
重写 大于等于 小于等于 相同 相同 小于等于
23.this和super关键字的作用

this是对象内部指代自身的引用,同时也是解决成员变量和局部变量同名问题;this可以调用成员变量,不能调用局部变量;this也可以调用成员方法,但是在普通方法中可以省略this,在构造方法中不允许省略,必须是构造方法的第一条语句。,而且在静态方法当中不允许出现this关键字。

super代表对当前对象的直接父类对象的引用,super可以调用直接父类的成员变量(注意权限修饰符的影响,比如不能访问private成员)

super可以调用直接父类的成员方法(注意权限修饰符的影响,比如不能访问private成员);super可以调用直接父类的构造方法,只限构造方法中使用,且必须是第一条语句。

24.static关键字的作用

static可以修饰变量、方法、代码块和内部类

static属性属于这个类所有,即由该类创建的所有对象共享同一个static属性。可以对象创建后通过对象名.属性名和类名.属性名两种方式来访问。也可以在没有创建任何对象之前通过类名.属性名的方式来访问。

static变量和非static变量的区别(都是成员变量,不是局部变量)

1.在内存中份数不同

不管有多少个对象,static变量只有1份。对于每个对象,实例变量都会有单独的一份

static变量是属于整个类的,也称为类变量。而非静态变量是属于对象的,也称为实例变量

2.在内存中存放的位置不同

2.在内存中存放的位置不同

3.访问的方式不同

实例变量: 对象名.变量名 stu1.name="小明明";

静态变量:对象名.变量名 stu1.schoolName="西二旗小学"; 不推荐如此使用

类名.变量名 Student.schoolName="东三旗小学"; 推荐使用

4.在内存中分配空间的时间不同

Student.schoolName="东三旗小学";或者Student stu1 = new Student("小明","男",20,98);

static方法也可以通过对象名.方法名和类名.方法名两种方式来访问

static代码块。当类被第一次使用时(可能是调用static属性和方法,或者创建其对象)执行静态代码块,且只被执行一次,主要作用是实现static属性的初始化。

static内部类:属于整个外部类,而不是属于外部类的每个对象。不能访问外部类的非静态成员(变量或者方法),.可以访问外部类的静态成员

25.final和abstract关键字的作用

final和abstract是功能相反的两个关键字,可以对比记忆

abstract可以用来修饰类和方法,不能用来修饰属性和构造方法;使用abstract修饰的类是抽象类,需要被继承,使用abstract修饰的方法是抽象方法,需要子类被重写。

final可以用来修饰类、方法和属性,不能修饰构造方法。使用final修饰的类不能被继承,使用final修饰的方法不能被重写,使用final修饰的变量的值不能被修改,所以就成了常量。

特别注意:final修饰基本类型变量,其值不能改变,由原来的变量变为常量;但是final修饰引用类型变量,栈内存中的引用不能改变,但是所指向的堆内存中的对象的属性值仍旧可以改变。例如

package com.bjsxt;

class Test {
    public static void main(String[] args) {
        final Dog dog = new Dog("欧欧");
        dog.name = "美美";//正确
        dog = new Dog("亚亚");//错误
    }
}
26.final、finally、finalize的区别

final修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承例如:String类、Math类等。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重写,但是能够重载。 使用final修饰的对象,对象的引用地址不能变,但是对象的值可以变!

finally在异常处理时提供 finally 块来执行任何清除操作。如果有finally的话,则不管是否发生异常,finally语句都会被执行。一般情况下,都把关闭物理连接(IO流、数据库连接、Socket连接)等相关操作,放入到此代码块中。

finalize方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要清理工作。finalize() 方法是在垃圾收集器删除对象之前被调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。 一般情况下,此方法由JVM调用,程序员不要去调用!

27.写出java.lang.Object类的六个常用方法

(1)public boolean equals(java.lang.Object)

比较对象的地址值是否相等,如果子类重写,则比较对象的内容是否相等;

(2)public native int hashCode() 获取哈希码

(3)public java.lang.String toString() 把数据转变成字符串

(4)public final native java.lang.Class getClass() 获取类结构信息

(5)protected void finalize() throws java.lang.Throwable

垃圾回收前执行的方法

(6)protected native Object clone() throws

java.lang.CloneNotSupportedException 克隆

(7)public final void wait() throws java.lang.InterruptedException

多线程中等待功能

(8)public final native void notify() 多线程中唤醒功能

(9)public final native void notifyAll() 多线程中唤醒所有等待线程的功能

28.private/默认/protected/public权限修饰符的区别
同一个类 同一个包 子类 所有类
private *
defailt * *
protected * * *
public * * * *

类的访问权限只有两种

public公共的 可被同一项目中所有的类访问。 (必须与文件名同名)

default默认的 可被同一个包中的类访问。

成员(成员变量或成员方法)访问权限共有四种:

public 公共的 可以被项目中所有的类访问。(项目可见性)

protected 受保护的 可以被这个类本身访问;同一个包中的所有其他的类访问;被它的子类(同一个包以及不同包中的子类)访问。(子类可见性)

default 默认的被这个类本身访问;被同一个包中的类访问。(包可见性)

private 私有的 只能被这个类本身访问。(类可见性)

29.继承条件下构造方法的执行过程

继承条件下构造方法的调用规则如下:

情况1:如果子类的构造方法中没有通过super显式调用父类的有参构造方法,也没有通过this显式调用自身的其他构造方法,则系统会默认先调用父类的无参构造方法。在这种情况下,写不写“super();”语句,效果是一样的。

情况2:如果子类的构造方法中通过super显式调用父类的有参构造方法,那将执行父类相应构造方法,而不执行父类无参构造方法。

情况3:如果子类的构造方法中通过this显式调用自身的其他构造方法,在相应构造方法中应用以上两条规则。

特别注意的是,如果存在多级继承关系,在创建一个子类对象时,以上规则会多次向更高一级父类应用,一直到执行顶级父类Object类的无参构造方法为止。

30.==和equals的区别和联系

“==”是关系运算符,equals()是方法,同时他们的结果都返回布尔值;

“==”使用情况如下:

a) 基本类型,比较的是值

b) 引用类型,比较的是地址

c) 不能比较没有父子关系的两个对象

equals()方法使用如下:

a) 系统类一般已经覆盖了equals(),比较的是内容。

b) 用户自定义类如果没有覆盖equals(),将调用父类的equals (比如是Object),而Object的equals的比较是地址(return (this == obj);)

c) 用户自定义类需要覆盖父类的equals()

注意:Object的==和equals比较的都是地址,作用相同

31.谈谈Java的多态

实现多态的三个条件(前提条件,向上转型、向下转型)

1、继承的存在;(继承是多态的基础,没有继承就没有多态)

2、子类重写父类的方法。(多态下会调用子类重写后的方法)

3、父类引用变量指向子类对象。(涉及子类到父类的类型转换)

向上转型 Student person = new Student()

将一个父类的引用指向一个子类对象,成为向上转型,自动进行类型转换。此时通过父类引用变量调用的方法是子类覆盖或继承父类的方法,而不是父类的方法此时通过父类引用变量无法调用子类特有的方法。

向下转型 Student stu = (Student)person;

将一个指向子类对象的引用赋给一个子类的引用,成为向下转型,此时必须进行强制类型转换。向下转型必须转换为父类引用指向的真实子类类型,,否则将出现ClassCastException,不是任意的强制转换

向下转型时可以结合使用instanceof运算符进行强制类型转换,比如出现转换异常---ClassCastException

32.简述Java的垃圾回收机制

传统的C/C++语言,需要程序员负责回收已经分配内存。

显式回收垃圾回收的缺点:

1)程序忘记及时回收,从而导致内存泄露,降低系统性能。

2)程序错误回收程序核心类库的内存,导致系统崩溃。

Java语言不需要程序员直接控制内存回收,是由JRE在后台自动回收不再使用的内存,称为垃圾回收机制,简称GC;

1)可以提高编程效率。

2)保护程序的完整性。

3)其开销影响性能。Java虚拟机必须跟踪程序中有用的对象,确定哪些是无用的。

垃圾回收机制的 特点

1)垃圾回收机制回收JVM堆内存里的对象空间,不负责回收栈内存数据。

2)对其他物理连接,比如数据库连接、输入流输出流、Socket连接无能为力。

3)垃圾回收发生具有不可预知性,程序无法精确控制垃圾回收机制执行。

4)可以将对象的引用变量设置为null,暗示垃圾回收机制可以回收该对象。

现在的JVM有多种垃圾回收 实现算法,表现各异。

垃圾回收机制回收任何对象之前,总会先调用它的finalize方法(如果覆盖该方法,让一个新的引用变量重新引用该对象,则会重新激活对象)。

程序员可以通过System.gc()或者Runtime.getRuntime().gc()来通知系统进行垃圾回收,会有一些效果,但是系统是否进行垃圾回收依然不确定。

永远不要主动调用某个对象的finalize方法,应该交给垃圾回收机制调用。

33.基本数据类型和包装类

1) 八个基本数据类型的包装类

基本数据类型 包装类
byte Byte
boolean Boolean
short Short
char Character
int Integer
long Long
float Float
double Double

2)为什么为基本类型引入包装类

2.1基本数据类型有方便之处,简单、高效。

2.2但是Java中的基本数据类型却是不面向对象的(没有属性、方法),这在实际使用时存在很多的不便(比如集合的元素只能是Object)。

为了解决这个不足,在设计类时为每个基本数据类型设计了一个对应的类进行包装,这样八个和基本数据类型对应的类统称为包装类(Wrapper Class)。

3) 包装类和基本数据类型之间的转换

3.1包装类------ wrapperInstance.xxxValue() ------>基本数据类型

3.2包装类-------new WrapperClass(primitive)

3.2包装类-------new WrapperClass(primitive)

4) 自动装箱和自动拆箱

JDK1.5提供了自动装箱(autoboxing)和自动拆箱(autounboxing)功能, 从而实现了包装类和基本数据类型之间的自动转换

5) 包装类还可以实现基本类型变量和字符串之间的转换

基本类型变量--->String.valueof()--->字符串 基本类型变量<---WrapperClass.parseXxx(string)---字符串

34.Integer与int的区别

int是java提供的8种原始数据类型之一,Java为每个原始类型提供了封装类,Integer是java为int提供的封装类。

int是java提供的8种原始数据类型之一,Java为每个原始类型提供了封装类,Integer是java为int提供的封装类。

在Hibernate中,如果将OID定义为Integer类型,那么Hibernate就可以根据其值是否为null而判断一个对象是否是临时的,如果将OID定义为了int类型,还需要在hbm映射文件中设置其unsaved-value属性为0。

另外,Integer提供了多个与整数相关的操作方法,例如,将一个字符串转换成整数,Integer中还定义了表示整数的最大值和最小值的常量。

35.java.sql.Date和java.util.Date的联系和区别

1) java.sql.Date是java.util.Date的子类,是一个包装了毫秒值的瘦包装器,允许 JDBC 将毫秒值标识为 SQL DATE 值。毫秒值表示自 1970 年 1 月 1 日 00:00:00 GMT 以来经过的毫秒数。 为了与 SQL DATE 的定义一致,由 java.sql.Date 实例包装的毫秒值必须通过将时间、分钟、秒和毫秒设置为与该实例相关的特定时区中的零来“规范化”。 说白了,java.sql.Date就是与数据库Date相对应的一个类型,而java.util.Date是纯java的Date。

2)JAVA里提供的日期和时间类,java.sql.Date和java.sql.Time,只会从数据库里读取某部分值,这有时会导致丢失数据。例如一个包含2002/05/22 5:00:57 PM的字段,读取日期时得到的是2002/05/22,而读取时间时得到的是5:00:57 PM. 你需要了解数据库里存储时间的精度。有些数据库,比如MySQL,精度为毫秒,然而另一些数据库,包括Oracle,存储SQL DATE类型数据时,毫秒部分的数据是不保存的。以下操作中容易出现不易被发现的BUG:获得一个JAVA里的日期对象。 从数据库里读取日期 试图比较两个日期对象是否相等。如果毫秒部分丢失,本来认为相等的两个日期对象用Equals方法可能返回false。.sql.Timestamp类比java.util.Date类精确度要高。这个类包了一个getTime()方法,但是它不会返回额外精度部分的数据,因此必须使用...

总之,java.util.Date 就是Java的日期对象,而java.sql.Date 是针对SQL语句使用的,只包含日期而没有时间部分。

36.使用递归算法输出某个目录下所有文件和子目录列表
package com.bjsxt;
import java.io.File;
public class $ {
public static void main(String[] args) {
        String path = "D:/301SXT";
        test(path);
    }
    private static void test(String path) {
        File f = new File(path);
        File[] fs = f.listFiles();
        if (fs == null) {
            return;
        }
        for (File file : fs) {
            if (file.isFile()) {
                System.out.println(file.getPath());
            } else {
                test(file.getPath());
            }
        }
    }
37.关于Java编译,下面哪一个正确()(选择一项)
A Java程序经编译后产生machine code
B. Java程序经编译后会生产byte code
C. Java程序经编译后会产生DLL
D. 以上都不正确
答案:B
分析: Java是解释型语言,编译出来的是字节码; 因此A不正确,C是C/C++语言编译动态链接库的文件为.DLL; 正确答案为B
38.下列说法正确的有()(选择一项)
A class中的construtor不可省略
B. construtor与class同名,但方法不能与class同名
C. construtor在一个对象被new时执行
D. 一个class只能定义一个construtor
答案:C
分析:A:如果class中的construtor省略不写,系统会默认提供一个无参构造
B:方法名可以与类名同名,只是不符合命名规范
D:一个class中可以定义N多个construtor,这些construtor构成构造方法的重载
39.Java中接口的修饰符可以为()(选择一项)
A private
B. protected
C. final
D. abstract
答案:D
分析:接口中的访问权限修饰符只可以是public或default
接口中的所有的方法必须要实现类实现,所以不能使用final
接口中所有的方法默认都是abstract的,所以接口可以使用abstract修饰,但通常abstract可以省略不写
40.给定以下代码,程序将输出 ()(选择一项)
class A {
public A(){
System.out.println("A");
}
}
class B extends A{
public B(){
System.out.println("B");
}
public static void main(String[] args) {
B b=new B();
}
}
A 不能通过编译
B. 通过编译,输出AB
C. 通过编译,输出B
D. 通过编译,输出A
答案:B
分析:在继承关系下,创建子类对象,先执行父类的构造方法,再执行子类的构造方法。
41.下列关于关键字的使用说法错误的是()(选择一项)
A abstract不能与final并列修饰同一个类
B. abstract类中可以有private的成员
C. abstract方法必须在abstract类中
D. static方法能处理非static的属性
答案:D
分析:因为static得方法在装载class得时候首先完成,比 构造方法早,此时非static得属性和方法还没有完成初始化所以不能调用。
42.下列哪些语句关于内存回收的说法是正确的()(选择一项)
A 程序员必须创建一个线程来释放内存
B. 内存回收程序负责释放无用内存
C. 内存回收程序允许程序员直接释放内存
D. 内存回收程序可以在指定的时间释放内存对象
答案:B
分析: A. 程序员不需要创建线程来释放内存.
C. 也不允许程序员直接释放内存.
D. 不一定在什么时刻执行垃圾回收.
43.选出合理的标识符()(选择两项)
A _sysl_111
B. 2 mail
C. $change
D. class
答案:AC
分析: 标识符的命令规范,可以包含字母、数字、下划线、$,不能以数字开头,不能是Java关键字
44.下列说法正确的是()(选择多项)
A java.lang.Cloneable是类
B. java.langRunnable是接口
C. Double对象在java.lang包中
D. Double a=1.0是正确的java语句
Double a=1.0是正确的java语句
分析:java.lang.Cloneable是接口
45.定义一个类名为”MyClass.java”的类,并且该类可被一个工程中的所有类访问,那么该类的正确声明为()(选择两项)
A 45.定义一个类名为”MyClass.java”的类,并且该类可被一个工程中的所有类访问,那么该类的正确声明为()(选择两项)
B. class MyClass extends Object
C. public class MyClass
D. public class MyClass extends Object
答案:CD
分析: A 类的访问权限只能是public或default
B使用默认访问权限的类,只能在本包中访问
46.面向对象的特征有哪些方面?请用生活中的例子来描述。

答: 面向对象的三大特征:封装、继承、多态。

举例:(比如设计一个游戏)我现在创建了一个对象,名叫战士。

战士的属性是—性别,年龄,职业,等级,战斗力,血量。

它的方法—战斗,逃跑,吃饭,睡觉,死。

后来,我又建了一个对象,叫人。

属性:性别,年龄,职业,等级,血量

方法:逃跑,吃饭,睡觉,死。

我让人,成为战士的父类,战士可以直接继承人的属性和方法。

战士修改成—

属性:战斗力。

方法:战斗。

看上去战士的资料变少了,实际上没有,我们仍然可以调用方法—战士.死。

而且我们还可以重载战士.死的方法,简称重载死法。

我还建了一个对象—法师,父类也是人。

属性:法力值

方法:施法,泡妞。

你看,用了继承,创建对象变得更方便了。

再后来,我又建立了一个对象,叫怪物。

属性:等级,战力,血量。

方法:战斗,死。

建了个对象,叫白兔怪,父类怪物,可继承怪物所有的属性和方法。

属性:毛色。

方法:卖萌,吃胡萝卜。

47.说明内存泄漏和内存溢出的区别和联系,结合项目经验描述Java程序中如何检测?如何解决?

答:

内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。

内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。

memory leak会最终会导致out of memory!

48.什么是Java的序列化,如何实现Java的序列化?列举在哪些程序中见过Java序列化?

答:Java中的序列化机制能够将一个实例对象(只序列化对象的属性值,而不会去序列化什么所谓的方法。)的状态信息写入到一个字节流中使其可以通过socket进行传输、或者持久化到存储数据库或文件系统中;然后在需要的时候通过字节流中的信息来重构一个相同的对象。一般而言,要使得一个类可以序列化,只需简单实现java.io.Serializable接口即可。

对象的序列化主要有两种用途:

1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;

2) 在网络上传送对象的字节序列。

在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存。比如最常见的是Web服务器中的Session对象,当有 10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,于是Web容器就会把一些seesion先序列化到硬盘中,等要用了,再把保存在硬盘中的对象还原到内存中。

当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。

49.不通过构造函数也能创建对象吗?

答:Java创建对象的几种方式(重要):

1、 用new语句创建对象,这是最常见的创建对象的方法。

2、 运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。

3、 调用对象的clone()方法。

4、运用反序列化手段,调用java.io.ObjectInputStream对象的 readObject()方法。

(1)和(2)都会明确的显式的调用构造函数 ;(3)是在内存上对已有对象的影印,所以不会调用构造函数 ;(4)是从文件中还原类的对象,也不会调用构造函数。

50.匿名内部类可不可以继承或实现接口。为什么?

答:匿名内部类是没有名字的内部类,不能继承其它类,但一个内部类可以作为一个接口,由另一个内部类实现.

1、由于匿名内部类没有名字,所以它没有构造函数。因为没有构造函数,所以它必须完全借用父类的构造函数来实例化,换言之:匿名内部类完全把创建对象的任务交给了父类去完成。

2、在匿名内部类里创建新的方法没有太大意义,但它可以通过覆盖父类的方法达到神奇效果,如上例所示。这是多态性的体现。

3、因为匿名内部类没有名字,所以无法进行向下的强制类型转换,持有对一个匿名内部类对象引用的变量类型一定是它的直接或间接父类类型。

51.在Java中,为什么基本类型不能做为HashMap的键值,而只能是引用类型,把引用类型做为HashMap的健值,需要注意哪些地方。

(1) 在Java中是使用泛型来约束HashMap中的key和value的类型的,即HashMap< K, V>;而泛型在Java的规定中必须是对象Object类型的,也就是说HashMap< K, V>可以理解为HashMap< Object, Object>,很显然基本数据类型不是Object类型的,因此不能作为键值,只能是引用类型。虽然我们在HashMap中可以这样添加数据:“map.put(1, “Java”);”,但实际上是将其中的key值1进行了自动装箱操作,变为了Integer类型。

(1) 在Java中是使用泛型来约束HashMap中的key和value的类型的,即HashMap< K, V>;而泛型在Java的规定中必须是对象Object类型的,也就是说HashMap< K, V>可以理解为HashMap< Object, Object>,很显然基本数据类型不是Object类型的,因此不能作为键值,只能是引用类型。虽然我们在HashMap中可以这样添加数据:“map.put(1, “Java”);”,但实际上是将其中的key值1进行了自动装箱操作,变为了Integer类型。

52.简述Java中如何实现多态

实现多态有三个前提条件:

1、 继承的存在;(继承是多态的基础,没有继承就没有多态)。

2、子类重写父类的方法。(多态下会调用子类重写后的方法)。

3、父类引用变量指向子类对象。(涉及子类到父类的类型转换)。

最后使用父类的引用变量调用子类重写的方法即可实现多态。

53.以下对继承的描述锚误的是 ()
A Java中的继承允许一个子类继承多个父类
B. 父类更具有通用性,子类更具体
C. Java中的继承存在着传递性
D. 当实例化子类时会递归调用父类中的构造方法
答案:A
分析:Java是单继承的,一个类只能继承一个父类。
54.Java 中 Math.random()/Math.random()值为?

54.Java 中 Math.random()/Math.random()值为?

如果除数与被除数均为0.0的话,则运行结果为NaN(Not a Number的简写),计算错误。

55.Java中,如果Manager是Employee的子类,那么Pair是Pair的子类吗?

不是,两者没有任何关联;

Pair是单独的类,只不过用不同类型的参数(泛型)进行了相应的实例化而已;所以,Pair< Manager>和Pair< Employee>不是子类的关系。

56.接口和抽象类的区别

56.接口和抽象类的区别

抽象类和接口均包含抽象方法,类必须实现所有的抽象方法,否则是抽象类

抽象类和接口都不能实例化,他们位于继承树的顶端,用来被其他类继承和实现

两者的区别主要体现在两方面:语法方面和设计理念方面

语法方面的区别是比较低层次的,非本质的,主要表现在:

接口中只能定义全局静态常量,不能定义变量。抽象类中可以定义常量和变量。

接口中所有的方法都是全局抽象方法。抽象类中可以有0个、1个或多个,甚至全部都是抽象方法。

抽象类中可以有构造方法,但不能用来实例化,而在子类实例化是执行,完成属于抽象类的初始化操作。接口中不能定义构造方法。

一个类只能有一个直接父类(可以是抽象类),但可以充实实现多个接口。一个类使用extends来继承抽象类,使用implements来实现接口。

一个类只能有一个直接父类(可以是抽象类),但可以充实实现多个接口。一个类使用extends来继承抽象类,使用implements来实现接口。

抽象类体现了一种继承关系,目的是复用代码,抽象类中定义了各个子类的相同代码,可以认为父类是一个实现了部分功能的“中间产品”,而子类是“最终产品”。父类和子类之间必须存在“is-a”的关系,即父类和子类在概念本质上应该是相同的。

接口并不要求实现类和接口在概念本质上一致的,仅仅是实现了接口定义的约定或者能力而已。接口定义了“做什么”,而实现类负责完成“怎么做”,体现了功能(规范)和实现分离的原则。接口和实现之间可以认为是一种“has-a的关系”

57.同步代码块和同步方法有什么区别

相同点:

同步方法就是在方法前加关键字synchronized,然后被同步的方法一次只能有一个线程进入,其他线程等待。而同步代码块则是在方法内部使用大括号使得一个代码块得到同步。同步代码块会有一个同步的“目标”,使得同步块更加灵活一些(同步代码块可以通过“目标”决定需要锁定的对象)。

一般情况下,如果此“目标”为this,同步方法和代码块没有太大的区别。

区别:

同步方法直接在方法上加synchronized实现加锁,同步代码块则在方法内部加锁。很明显,同步方法锁的范围比较大,而同步代码块范围要小点。一般同步的范围越大,性能就越差。所以一般需要加锁进行同步的时候,范围越小越好,这样性能更好。

58.静态内部类和内部类有什么区别

静态内部类不需要有指向外部类的引用。但非静态内部类需要持有对外部类的引用。

静态内部类可以有静态成员(方法,属性),而非静态内部类则不能有静态成员(方法,属性)。

非静态内部类能够访问外部类的静态和非静态成员。静态内部类不能访问外部类的非静态成员,只能访问外部类的静态成员。

实例化方式不同:

1) 静态内部类:不依赖于外部类的实例,直接实例化内部类对象

2) 非静态内部类:通过外部类的对象实例生成内部类对象

59.反射的概念与作用

反射的概念:

反射,一种计算机处理方式。是程序可以访问、检测和修改它本身状态或行为的一种能力。

Java反射可以于运行时加载,探知和使用编译期间完全未知的类.

程序在运行状态中, 可以动态加载一个只有名称的类, 对于任意一个已经加载的类,都能够知道这个类的所有属性和方法; 对于任意一个对象,都能调用他的任意一个方法和属性;

加载完类之后, 在堆内存中会产生一个Class类型的对象(一个类只有一个Class对象), 这个对象包含了完整的类的结构信息,而且这个Class对象就像一面镜子,透过这个镜子看到类的结构,所以被称之为:反射.

java反射使得我们可以在程序运行时动态加载一个类,动态获取类的基本信息和定义的方法,构造函数,域等。

除了检阅类信息外,还可以动态创建类的实例,执行类实例的方法,获取类实例的域值。反射使java这种静态语言有了动态的特性。

反射的作用:

通过反射可以使程序代码访问装载到JVM 中的类的内部信息

1) 获取已装载类的属性信息

2) 获取已装载类的方法

3) 获取已装载类的构造方法信息

反射的优点:

增加程序的灵活性。

如struts中。请求的派发控制。

当请求来到时。struts通过查询配置文件。找到该请求对应的action。已经方法。

然后通过反射实例化action。并调用响应method。

如果不适用反射,那么你就只能写死到代码里了。

所以说,一个灵活,一个不灵活。

很少情况下是非用反射不可的。大多数情况下反射是为了提高程序的灵活性。因此一般框架中使用较多。因为框架要适用更多的情况。对灵活性要求较高。

60.提供Java存取数据库能力的包是()
A java.sql
B. java.awt
C. java.lang
D. java.swing
答案:A
分析:
java.awt和javax.swing两个包是图形用户界面编程所需要的包;
java.lang包则提供了Java编程中用到的基础类。
61.下列运算符合法的是()(多选)
A &&
B. <>
C. if
D. =
答案:AD
分析:
&&是逻辑运算符中的短路与;
<>表示不等于,但是Java中不能这么使用,应该是!=;
if不是运算符;
=是赋值运算符。

62.执行如下程序代码,c的值打印出来是()
public class Test1 {
public static void main(String[] args) {
int a = 0;
int c = 0;
do{
--c;
a = a - 1;
} while (a > 0);
System.out.println(c);
}
}
A 0
B. 1
C. -1
D. 死循环
答案:C
分析:
do-while循环的特点是先执行后判断,所以代码先执行--c操作,得到c为-1,之后执行a=a-1的操作,得到a为-1,然后判断a是否大于0,判断条件不成立,退出循环,输出c为-1。
63.下列哪一种叙述是正确的()
A abstract修饰符可修饰字段,方法和类
B. 抽象方法的body部分必须用一对大括号{}包住
C. 声明抽象方法,大括号可有可无
D. 声明抽象方法不可写出大括号
答案:D
分析:
abstract只能修饰方法和类,不能修饰字段;
抽象方法不能有方法体,即没有{};
同B。
64.下列语句正确的是()
A 形式参数可被视为local Variable
B. 形式参数可被视为local Variable
C. 形式参数可被所有的字段修饰符修饰
D. 形式参数为方法被调用时,真正被传递的参数
答案:A
分析:
local Variable为局部变量,形参和局部变量一样都只有在方法内才会发生作用,也只能在方法中使用,不会在方法外可见;
对于形式参数只能用final修饰符,其它任何修饰符都会引起编译器错误;
真正被传递的参数是实参;
形式参数可是基本数据类型也可以是引用类型(对象)。
65.下列哪种说法是正确的()
A 实例方法可直接调用超类的实例方法
B. 实例方法可直接调用超类的类方法
C. 实例方法可直接调用其他类的实例方法
D. 实例方法可直接调用本类的类方法
答案:D
分析:
实例方法不可直接调用超类的私有实例方法;
实例方法不可直接调用超类的私有的类方法;
要看访问权限。
66.Java程序的种类有()(多选)
A 类 (Class)
B. Applet
C. Application
D. Servlet
答案:BCD
分析:
是Java中的类,不是程序;
内嵌于Web文件中,由浏览器来观看的Applet;
可独立运行的 Application;
服务器端的 Servlet。
67.下列说法正确的有()(多选)
A 环境变量可在编译source code时指定
B. 在編译程序时,所指定的环境变置不包括class path
C. javac —次可同时编译数个Java 源文件
D. javac.exe能指定编译结果要置于哪个目录(directory)
答案:BCD
分析:
环境变量一般都是先配置好再编译源文件。
68.下列标识符不合法的有()(多选)
A new
B. $Usdollars
C. 1234
D. car.taxi
答案:ACD
分析:
new是Java的关键字;
C. 数字不能开头;
D. 不能有“.”。
69.下列说法错误的有()(多选)
A 数组是—种对象
B. 数组属于一种原生类
C. int number[]=(31,23,33,43,35,63)
D. 数组的大小可以任意改变
答案:BCD
分析:
B. Java中的原生类(即基本数据类型)有8种,但不包括数组;
C. 语法错误,应该“{···}”,而不是“(···)”;
D. 数组的长度一旦确定就不能修改。
70.不能用来修饰interface的有()(多选)
A private
B. public
C. protected
D. static
答案:ACD
分析:
能够修饰interface的只有public、abstract以及默认的三种修饰符。
71.下列正确的有()(多选)
A call by value不会改变实际参数的数值
B. call by reference能改变实际参数的参考地址
C. call by reference 不能改变实际参数的参考地址
D. call by reference 能改变实际参数的内容
答案:ACD
分析:
Java中参数的传递有两种,一种是按值传递(call by value:传递的是具体的值,如基础数据类型),另一种是按引用传递(call by reference:传递的是对象的引用,即对象的存储地址)。前者不能改变实参的数值,后者虽然不能改变实参的参考地址,但可以通过该地址访问地址中的内容从而实现内容的改变。
72.下列说法错误的有()(多选)
A 在类方法中可用this来调用本类的类办法
B. 在类方法中调用本类的类方法时可以直接调用
C. 在类方法中只能调用本类中的类方法
D. 在类方法中绝对不能调用实例方法
答案:ACD
分析:
类方法是在类加载时被加载到方法区存储的,此时还没有创建对象,所以不能使用this或者super关键字;
C. 在类方法中还可以调用其他类的类方法;
D. 在类方法可以通过创建对象来调用实例方法。
73.下列说法错误的有()(多选)
A Java面向对象语言容许单独的过栈与函数存在
B. Java面向对象语言容许单独的方法存在
C. Java语言中的方法属于类中的成员(member)
D. Java语言中的方法必定隶属于某一类(对象),调用方法与过程或函数相同
答案:ABC
分析:
B. Java不允许单独的方法,过程或函数存在,需要隶属于某一类中;
C. 静态方法属于类的成员,非静态方法属于对象的成员。
74.下列说法错误的有()(多选)
A 能被java.exe成功运行的java class文件必须有main()方法
B. J2SDK就是Java API
C. Appletviewer.exe可利用jar选项运行.jar文件
D. 能被Appletviewer成功运行的java class文件必须有main()方法
答案:BCD
分析:
B. J2SDK是sun公司编程工具,API是指的应用程序编程接口;
C. Appletviewer.exe就是用来解释执行java applet应用程序的,一种执行HTML文件上的Java小程序类的Java浏览器;
D. 能被Appletviewer成功运行的java class文件可以没有main()方法。
75.请问0.3332的数据类型是()
A float
B. double
C. Float
D. Double
答案:B
分析:
小数默认是双精度浮点型即double类型的。
76.Java接口的修饰符可以为()
A private
B. protected
C. final
D. abstract
答案:D
分析:
能够修饰interface的只有public、abstract以及默认的三种修饰符。
77.不通过构造函数也能创建对象么()
A
B.
答案:A
分析:
Java创建对象的几种方式:
(1) 用new语句创建对象,这是最常见的创建对象的方法。
(2) 运用反射手段,调用java.lang.Class或者
java.lang.reflect.Constructor类的newInstance()实例方法。
(3) 调用对象的clone()方法。
(4) 运用反序列化手段,调用java.io.ObjectInputStream对象的readObject()方法。
(1)和(2)都会明确的显式的调用构造函数;(3)是在内存上对已有对象的影印,所以不会调用构造函数;(4)是从文件中还原类的对象,也不会调用构造函数。
78.存在使i+1< i的数么?

78.存在使i+1< i的数么?

79.接口可否继承接口?抽象类是否可实现接口?抽象类是否可继承实体类?

接口可以继承接口,抽象类可以实现接口,抽象类可以继承实体类。

80.int与Integer有什么区别?

int是java提供的8种原始数据类型之一。Java为每个原始类型提供了封装类,Integer是java为int提供的封装类。int的默认值为0,而Integer的默认值为null,即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况,例如,要想表达出没有参加考试和考试成绩为0的区别,则只能使用Integer。在JSP开发中,Integer的默认为null,所以用el表达式在文本框中显示时,值为空白字符串,而int默认的默认值为0,所以用el表达式在文本框中显示时,结果为0,所以,int不适合作为web层的表单数据的类型。

在Hibernate中,如果将OID定义为Integer类型,那么Hibernate就可以根据其值是否为null而判断一个对象是否是临时的,如果将OID定义为了int类型,还需要在hbm映射文件中设置其unsaved-value属性为0。另外,Integer提供了多个与整数相关的操作方法,例如,将一个字符串转换成整数,Integer中还定义了表示整数的最大值和最小值的常量。

81.可序列化对象为什么要定义serialversionUID值?

SerialVersionUid,简言之,其目的是序列化对象版本控制,有关各版本反序列化时是否兼容。如果在新版本中这个值修改了,新版本就不兼容旧版本,反序列化时会抛出InvalidClassException异常。如果修改较小,比如仅仅是增加了一个属性,我们希望向下兼容,老版本的数据都能保留,那就不用修改;如果我们删除了一个属性,或者更改了类的继承关系,必然不兼容旧数据,这时就应该手动更新版本号,即SerialVersionUid。

82.写一个Java正则,能过滤出html中的< a href=”url”>title< /a>形式中的链接地址和标题.

< a\b[^>]+\bhref="([^"]*)"[^>]*>([\s\S]*?)< /a>

< a\b[^>]+\bhref="([^"]*)"[^>]*>([\s\S]*?)< /a>

83.十进制数72转换成八进制数是多少?

答: 110

84.Java程序中创建新的类对象,使用关键字new,回收无用的类对象使用关键字free正确么?

答:Java程序中创建新的类对象,使用关键字new是正确的; 回收无用的类对象使用关键字free是错误的.

85.Class类的getDeclaredFields()方法与getFields()的区别?

答:getDeclaredFields(): 可以获取所有本类自己声明的方法, 不能获取继承的方法

getFields(): 只能获取所有public声明的方法, 包括继承的方法

86.在switch和if-else语句之间进行选取,当控制选择的条件不仅仅依赖于一个x时,应该使用switch结构;正确么?

答:不正确。

通常情况下,进行比较判断的处理,switch 和if-else可以互相转换来写;if-else作用的范围比switch-case作用范围要大,但是当switch-case和if-else都可以用的情况下,通常推荐使用switch-case。

比如:

switch (ch) {
case 'a':
System.out.println("A");
break;
case 'b':
System.out.println("B");
break;
case 'c':
System.out.println("C");
break;
case 'd':
System.out.println("D");
break;
case 'e':
System.out.println("E");
break;
default:
System.out.println("other");
break;
}

换为if-else

if (ch == 'a') {
System.out.println("A");
} else if (ch == 'b') {
System.out.println('B');
} else if (ch == 'c') {
System.out.println("C");
} else if (ch == 'd') {
System.out.println("D");
} else if (ch == 'e') {
System.out.println("E");
} else {
System.out.println("Other");
}
87.描述&和&&的区别。

&和&&的联系(共同点):

&和&&都可以用作逻辑与运算符,但是要看使用时的具体条件来决定。

操作数1&操作数2,操作数1&&操作数2,

操作数1&操作数2,操作数1&&操作数2,

情况1:当上述的操作数是boolean类型变量时,&和&&都可以用作逻辑与运算符。

情况2:当上述的表达式结果是boolean类型变量时,&和&&都可以用作逻辑与运算符。

表示逻辑与(and),当运算符两边的表达式的结果或操作数都为true时,整个运算结果才为true,否则,只要有一方为false,结果都为false。

表示逻辑与(and),当运算符两边的表达式的结果或操作数都为true时,整个运算结果才为true,否则,只要有一方为false,结果都为false。

(1)、&逻辑运算符称为逻辑与运算符,&&逻辑运算符称为短路与运算符,也可叫逻辑与运算符。

对于&:无论任何情况,&两边的操作数或表达式都会参与计算。

对于&&:当&&左边的操作数为false或左边表达式结果为false时,&&右边的操作数或表达式将不参与计算,此时最终结果都为false。

综上所述,如果逻辑与运算的第一个操作数是false或第一个表达式的结果为false时,对于第二个操作数或表达式是否进行运算,对最终的结果没有影响,结果肯定是false。推介平时多使用&&,因为它效率更高些。

(2)、&还可以用作位运算符。当&两边操作数或两边表达式的结果不是boolean类型时,&用于按位与运算符的操作。

88.使用final关键字修饰符一个变量时,是引用不能变,还是引用的对象不能变?

final修饰基本类型变量,其值不能改变。

但是final修饰引用类型变量,栈内存中的引用不能改变,但是所指向的堆内存中的对象的属性值仍旧可以改变。

例如:

class Test {
    public static void main(String[] args) {
        final Dog dog = new Dog("欧欧");
        dog.name = "美美";//正确
        dog = new Dog("亚亚");//错误
    }
}
89.请解释以下常用正则含义:\d,\D,\s,.,*,?,|,[0-9]{6},\d+

\d: 匹配一个数字字符。等价于[0-9]

\D: 匹配一个非数字字符。等价于[^0-9]

\s: 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]

. :匹配除换行符 \n 之外的任何单字符。要匹配 . ,请使用 \. 。

*:匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 \*。

+:匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+。

|:将两个匹配条件进行逻辑“或”(Or)运算

[0-9]{6}:匹配连续6个0-9之间的数字

\d+:匹配至少一个0-9之间的数字

90.已知表达式int m[] = {0,1,2,3,4,5,6}; 下面那个表达式的值与数组的长度相等()
A m.length()
B. m.length
C. m.length()+1
D. m.length+1
答案:B
分析:数组的长度是.length
91.下面那些声明是合法的?()
A long l = 4990
B. int i = 4L
C. float f = 1.1
D. double d = 34.4
答案:AD
分析:B int属于整数型应该是int=4 C应该是float f=1.1f
92.以下选项中选择正确的java表达式()
A int k=new String(“aa”)
B. String str = String(“bb”)
C. char c=74;
D. long j=8888;
答案:CD
分析:A需要强制类型转换 B String str =new String(“bb”)
93.下列代码的输出结果是
System.out.println(""+("12"=="12"&&"12".equals("12")));
(“12”==”12”&&”12”.equals(“12”))
“12”==”12”&&”12”.equals(“12”)

true

false

94.以下哪些运算符是含有短路运算机制的?请选择:()
A &
B. &&
C. |
D. ||
答案:BD
分析:A C是逻辑与计算
95.下面哪个函数是public void example(){....}的重载函数?()
A private void example(int m){...}
B. public int example(){...}
C. public void example2(){...}
D. public int example(int m.float f){...}
答案:AD
分析:BC定义的是新函数
96.给定某java程序片段,该程序运行后,j的输出结果为()
int  i=1;
 Int  j=i++;
 If((j>++j)&&(i++==j)){j+=i:}
 System.out.println(j);
A 1
B. 2
C. 3
D. 4
答案:B
分析: i++先引用后。++i 先增加后引用
97.在java中,无论测试条件是什么,下列()循环将至少执行一次。
A for
B. do...while
C. while
D. while...do
答案:B
分析: ACD都不一定进行循环
98.打印结果:
package com.bjsxt;

public class smaillT{
public static void main(String args[]){
smaillT t=new smaillT();
int b = t.get();
System.out.println(b);
}

public int get()
{
try {
return 1;
}finally{
return 2;
}
}
}

输出结果:2

99.指出下列程序的运行结果
int i=9;
switch (i) {
default:
System.out.println("default");
case 0:
System.out.println("zero");
break;
case 1:
System.out.println("one");
break;
case 2:
System.out.println("two");
break;
}

打印结果:

打印结果:

zero

100.解释继承、重载、覆盖。

继承(英语:inheritance)是面向对象软件技术当中的一个概念。如果一个类别A“继承自”另一个类别B,就把这个A称为“B的子类别”,而把B称为“A的父类别”也可以称“B是A的超类”。继承可以使得子类别具有父类别的各种属性和方法,而不需要再次编写相同的代码。在令子类别继承父类别的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类别的原有属性和方法,使其获得与父类别不同的功能。另外,为子类别追加新的属性和方法也是常见的做法。 一般静态的面向对象编程语言,继承属于静态的,意即在子类别的行为在编译期就已经决定,无法在执行期扩充。

那么如何使用继承呢?用extends关键字来继承父类。

如上面A类与B类,当写继承语句时, class A类 extends B类{ } 其中A类是子类,B类是父类。

英文 位置不同 作用不同
重载 overload 同一个类中
在一个类里面为一种行为提供多种实现方式并提高可读性
现方式并提高可读性
重写 override 子类和父类间
父类方法无法满足子类的要求,子类通
过方法重写满足要求
101.什么是编译型语言,什么是解释型语言?java可以归类到那种?

计算机不能直接理解高级语言,只能理解和运行机器语言,所以必须要把高级语言翻译成机器语言,计算机才能运行高级语言所编写的程序。翻译的方式有两种,一个是编译,一个是解释。

用编译型语言写的程序执行之前,需要一个专门的编译过程,通过编译系统把高级语言翻译成机器语言,把源高级程序编译成为机器语言文件,比如windows下的exe文件。以后就可以直接运行而不需要编译了,因为翻译只做了一次,运行时不需要翻译,所以一般而言,编译型语言的程序执行效率高。

解释型语言在运行的时候才翻译,比如VB语言,在执行的时候,专门有一个解释器能够将VB语言翻译成机器语言,每个语句都是执行时才翻译。这样解释型语言每执行一次就要翻译一次,效率比较低。

编译型与解释型,两者各有利弊。前者由于程序执行速度快,同等条件下对系统要求较低,因此像开发操作系统、大型应用程序、数据库系统等时都采用它,像C/C++、Pascal/Object Pascal(Delphi)等都是编译语言,而一些网页脚本、服务器脚本及辅助开发接口这样的对速度要求不高、对不同系统平台间的兼容性有一定要求的程序则通常使用解释性语言,如JavaScript、VBScript、Perl、Python、Ruby、MATLAB 等等。

JAVA语言是一种编译型-解释型语言,同时具备编译特性和解释特性(其实,确切的说java就是解释型语言,其所谓的编译过程只是将.java文件编程成平台无关的字节码.class文件,并不是向C一样编译成可执行的机器语言,在此请读者注意Java中所谓的“编译”和传统的“编译”的区别)。作为编译型语言,JAVA程序要被统一编译成字节码文件——文件后缀是class。此种文件在java中又称为类文件。java类文件不能再计算机上直接执行,它需要被java虚拟机翻译成本地的机器码后才能执行,而java虚拟机的翻译过程则是解释性的。java字节码文件首先被加载到计算机内存中,然后读出一条指令,翻译一条指令,执行一条指令,该过程被称为java语言的解释执行,是由java虚拟机完成的。

102.简述操作符(&,|)与操作符(&&,||)的区别&和&&的联系(共同点)

&和&&都可以用作逻辑与运算符,但是要看使用时的具体条件来决定。

操作数1&操作数2 操作数1&&操作数2
表达式1&表达式2 表达式1&&表达式2

情况1:当上述的操作数是boolean类型变量时,&和&&都可以用作逻辑与运算符。

情况2:当上述的表达式结果是boolean类型变量时,&和&&都可以用作逻辑与运算符。

表示逻辑与(and),当运算符两边的表达式的结果或操作数都为true时,整个运算结果才为true,否则,只要有一方为false,结果都为false。

&和&&的区别(不同点):

(1)、&逻辑运算符称为逻辑与运算符,&&逻辑运算符称为短路与运算符,也可叫逻辑与运算符。

对于&:无论任何情况,&两边的操作数或表达式都会参与计算。

对于&&:当&&左边的操作数为false或左边表达式结果为false时,&&右边的操作数或表达式将不参与计算,此时最终结果都为false。

综上所述,如果逻辑与运算的第一个操作数是false或第一个表达式的结果为false时,对于第二个操作数或表达式是否进行运算,对最终的结果没有影响,结果肯定是false。推介平时多使用&&,因为它效率更高些。

(2)、&还可以用作位运算符。当&两边操作数或两边表达式的结果不是boolean类型时,&用于按位与运算符的操作。

|和||的区别和联系与&和&&的区别和联系类似

103.try{}里面有一个return语句,那么紧跟在这个try后的finally, 里面的语句在异常出现后,都会执行么?为什么?

在异常处理时提供 finally 块来执行任何清除操作。

如果有finally的话,则不管是否发生异常,finally语句都会被执行,包括遇到return语句。

finally中语句不执行的唯一情况中执行了System.exit(0)语句。

104.有一段java应用程序,它的主类名是al,那么保存它的源文件可以是?()
A al.java
B. al.class
C. al
D. 都对
答案:A
分析:.class是java的解析文件
105.Java类可以作为()
A 类型定义机制
B. 数据封装机制
C. 类型定义机制和数据封装机制
D. 上述都不对
答案:C
106.在调用方法时,若要使方法改变实参的值,可以?()
A 用基本数据类型作为参数
B. 用对象作为参数
C. A和B都对
D. A和B都不对
答案:B
分析:基本数据类型不能改变实参的值
107.Java语言具有许多优点和特点,哪个反映了java程序并行机制的()
A 安全性
B. 多线性
C. 跨平台
D. 可移植
可移植
108.下关于构造函数的描述错误是()
A 构造函数的返回类型只能是void型
B. 构造函数是类的一种特殊函数,它的方法名必须与类名相同
C. 构造函数的主要作用是完成对类的对象的初始化工作
D. 一般在创建新对象时,系统会自动调用构造函数
答案:A
分析:构造函数的名字与类的名字相同,并且不能指定返回类型。
109.若需要定义一个类域或类方法,应使用哪种修饰符?()
A static
B. package
C. private
D. public
答案:A
110.下面代码执行后的输出是什么()
package com.bjsxt;
public class Test {
public static void main(String[] args) {
outer: for (int i = 0; i < 3; i++)
inner: for (int j = 0; j < 2; j++) {
if (j == 1)
continue outer;
System.out.println(j + " and " + i);
}
}
}
A
0 and 0
0 and 1
0 and 2
B.
1 and 0
1 and 1
1 and 2
C.
2 and 0
2 and 1
2 and 2
答案:A
111.给出如下代码,如何使成员变量m被函数fun()直接访问()
package com.bjsxt;
public class Test {
private int m;

public static void fun() {
// some code…
}
}
A 将private int m 改为 protected int m
B. 将private int m 改为 public int m
C. 将private int m 改为 static int m
D. 将private int m 改为int m
答案:C
112.下面哪几个函数是public void example(){….}的重载函数()

A public void example(int m){…}
B. public int example(int m){…}
C. public void example2(){…}
D. public int example(int m,float f){…}
答案:ABD
113.请问以下代码执行会打印出什么?

父类:

package com.bjsxt;

public class FatherClass {
public FatherClass() {
System.out.println("FatherClassCreate");
}
}

子类:

package com.bjsxt;

import com.bjsxt.FatherClass;
public class ChildClass extends FatherClass {
public ChildClass() {
System.out.println("ChildClass Create");
}
public static void main(String[] args) {
FatherClass fc = new FatherClass();
ChildClass cc = new ChildClass();
}
}

执行:C:\>java com.bjsxt.ChildClass

输出结果:?

答:

FatherClassCreate

FatherClassCreate

ChildClass Create

114.如果有两个类A、B(注意不是接口),你想同时使用这两个类的功能,那么你会如何编写这个C类呢?

答:因为类A、B不是接口,所以是不可以直接实现的,但可以将A、B类定义成父子类,那么C类就能实现A、B类的功能了。假如A为B的父类,B为C的父类,此时C就能使用A、B的功能。

115.一个类的构造方法是否可以被重载(overloading),是否可以被子类重写(overrding)?

答:构造方法可以被重载,但是构造方法不能被重写,子类也不能继承到父类的构造方法

116.Java中byte表示的数值范围是什么?

答:范围是-128至127

117.如何将日期类型格式化为:2013-02-18 10:53:10?
public class TestDateFormat2 {
public static void main(String[] args) throws Exception {
//第一步:将字符串(2013-02-18 10:53:10)转换成日期Date
DateFormat  sdf=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String sdate="2013-02-18 10:53:10";
Date date=sdf.parse(sdate);
System.out.println(date);

//第二步:将日期Date转换成字符串String
DateFormat  sdf2=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String sdate2=sdf2.format(date);
System.out.println(sdate2);
}
}
118.不通过构造函数也能创建对象吗()
A.
B.
分析:答案:A
Java创建对象的几种方式(重要):
(1) 用new语句创建对象,这是最常见的创建对象的方法。
(2) 运用反射手段,调用java.lang.Class或者
java.lang.reflect.Constructor类的newInstance()实例方法。
(3) 调用对象的clone()方法
(4) 运用反序列化手段,调用java.io.ObjectInputStream对象的 readObject()方法。
(1)和(2)都会明确的显式的调用构造函数 ;(3)是在内存上对已有对象的影印,所以不会调用构造函数 ;(4)是从文件中还原类的对象,也不会调用构造函数。
(1)和(2)都会明确的显式的调用构造函数 ;(3)是在内存上对已有对象的影印,所以不会调用构造函数 ;(4)是从文件中还原类的对象,也不会调用构造函数。
119.下面哪些是对称加密算法()

A. DES
B. MD5
C. DSA
D. RSA
分析:答案:A
分析:常用的对称加密算法有:DES、3DES、RC2、RC4、AES
常用的非对称加密算法有:RSA、DSA、ECC
使用单向散列函数的加密算法:MD5、SHA
120.下面的代码段,当输入为2的时候返回值是()
publicstaticint get Value(int i){
int result=0;
switch(i){
case 1:
result=result +i
case 2:
result=result+i*2
case 3:
result=result+i*3
}
return result;
}
A. 0
B. 2
C. 4
D. 10
答案:C
分析:result = 0 + 2 * 2;
121.以下Java代码段会产生几个对象
publicvoid test(){
String a="a";
String b="b";
String c="c";
c=a+""+b+""+c;
System.out.print(c);
}

分析:答案: 一个对象,因为编译期进行了优化,3个字符串常量直接折叠为一个

122.Math.round(-11.2)的运行结果是。

答案: -11

分析:小数点后第一位=5

正数:Math.round(11.5)=12

负数:Math.round(-11.5)=-11

小数点后第一位<5

正数:Math.round(11.46)=11

负数:Math.round(-11.46)=-11

小数点后第一位>5

正数:Math.round(11.68)=12

负数:Math.round(-11.68)=-12

根据上面例子的运行结果,我们还可以按照如下方式总结,或许更加容易记忆:

参数的小数点后第一位<5,运算结果为参数整数部分。

参数的小数点后第一位>5,运算结果为参数整数部分绝对值+1,符号(即正负)不变。

参数的小数点后第一位=5,正数运算结果为整数部分+1,负数运算结果为整数部分。

终结:大于五全部加,等于五正数加,小于五全不加。

123.十进制数278的对应十六进制数

分析:十进制数278的对应十六进制数是116

124.Java中int.long占用的字节数分别是

分析:

1:“字节”是byte,“位”是bit ;

2: 1 byte = 8 bit ;

char 在Java中是2个字节。java采用unicode,2个字节(16位)来表示一个字符。

short 2个字节

int 4个字节

long 8个字节

125.System.out.println(‘a’+1);的结果是

分析:'a'是char型,1 是int行,int与char相加,char会被强转为int行,char的ASCII码对应的值是97,所以加一起打印98

126.下列语句那一个正确()
A. java程序经编译后会产生machine code
B. java程序经编译后会产生 byte code
C. java程序经编译后会产生DLL
D. 以上都不正确
答案:B
分析:java程序编译后会生成字节码文件,就是.class文件
127.下列说法正确的有()
A. class中的constructor不可省略
B. constructor必须与class同名,但方法不能与class同名
C. constructor在一个对象被new时执行
D. 一个class只能定义一个constructor
答案:C
128.执行如下程序代码()
a=0;c=0;
do{
——c;
a=a-1;
}while(a>0);
后,c的值是()
A. 0
B. 1
C. -1
D. 死循环
答案:C
do{...}while(...);语句至少执行一次
129.下列哪一种叙述是正确的()
A. abstract修饰符可修饰字段、方法和类
B. 抽象方法的body部分必须用一对大括号{}包住
C. 声明抽象方法,大括号可有可无
D. 声明抽象方法不可写出大括号
答案:D
分析: abstract不能修饰字段。既然是抽象方法,当然是没有实现的方法,根本就没有body部分。
130.下列语句正确的是()
A. 形式参数可被视为local variable
B. 形式参数可被字段修饰符修饰
C. 形式参数为方法被调用时,真正被传递的参数
D. 形式参数不可以是对象
答案A:
分析:
A:形式参数可被视为local variable。形参和局部变量一样都不能离开方法。都只有在方法内才会发生作用,也只有在方法中使用,不会在方法外可见。
B:对于形式参数只能用final修饰符,其它任何修饰符都会引起编译器错误。但是用这个修饰符也有一定的限制,就是在方法中不能对参数做任何修改。 不过一般情况下,一个方法的形参不用final修饰。只有在特殊情况下,那就是:方法内部类。  一个方法内的内部类如果使用了这个方法的参数或者局部变量的话,这个参数或局部变量应该是final。 
C:形参的值在调用时根据调用者更改,实参则用自身的值更改形参的值(指针、引用皆在此列),也就是说真正被传递的是实参。
D:方法的参数列表指定要传递给方法什么样的信息,采用的都是对象的形式。因此,在参数列表中必须指定每个所传递对象的类型及名字。想JAVA中任何传递对象的场合一样,这里传递的实际上也是引用,并且引用的类型必须正确。--《Thinking in JAVA》
131.成员变量用static修饰和不用static修饰有什么区别?

1、两个变量的生命周期不同。

成员变量随着对象的创建而存在,随着对象的被回收而释放。

静态变量随着类的加载而存在,随着类的消失而消失。

2、调用方式不同。

成员变量只能被对象调用。

成员变量只能被对象调用。

成员变量只能被对象调用。

类名调用 :Person.country

3、别名不同。

成员变量也称为实例变量。

静态变量称为类变量。 

4、数据存储位置不同。

成员变量数据存储在堆内存的对象中,所以也叫对象的特有数据.

静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据.

132.如果变量用final修饰,则怎样?如果方法final修饰,则怎样?

1、用final修饰的类不能被扩展,也就是说不可能有子类;

2、用final修饰的方法不能被替换或隐藏:

① 使用final修饰的实例方法在其所属类的子类中不能被替换(overridden);

② 使用final修饰的静态方法在其所属类的子类中不能被重定义(redefined)而隐藏(hidden);

3、用final修饰的变量最多只能赋值一次,在赋值方式上不同类型的变量或稍有不同:

① 静态变量必须明确赋值一次(不能只使用类型缺省值);作为类成员的静态变量,赋值可以在其声明中通过初始化表达式完成,也可以在静态初始化块中进行;作为接口成员的静态变量,赋值只能在其声明中通过初始化表达式完成;

② 实例变量同样必须明确赋值一次(不能只使用类型缺省值);赋值可以在其声明中通过初始化表达式完成,也可以在实例初始化块或构造器中进行;

③ 方法参数变量在方法被调用时创建,同时被初始化为对应实参值,终止于方法体 (body)结束,在此期间其值不能改变;

④ 构造器参数变量在构造器被调用(通过实例创建表达式或显示的构造器调用)时创建,同时被初始化,为对应实参值,终止于构造器体结束,在此期间其值不能改变;

⑤ 异常处理器参数变量在有异常被try语句的catch子句捕捉到时创建,同时被初始化为实际的异常对象,终止于catch语句块结束,在此期间其值不能改变;

⑥ 局部变量在其值被访问之前必须被明确赋值;

133.在二进制数据中,小数点向右移一位,则数据()
A. 除以10
B. 除以2
C. 乘以2
D. 乘以10
乘以10
分析:可以看个例子
101.1 对应的十进制为 2^2*1 + 2^1*0 + 2^0*1 + 2^-1*1 = 5.5小数点右移一位
1011 对应的十进制为 2^3*1 + 2^2*0 + 2^1*1 + 2^0*1 = 11所以是扩大到原来的2倍
134.面向对象的特征有哪些方面?

答:面向对象的特征主要有以下几个方面:

1、抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。

2、继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类、基类);得到继承信息的类被称为子类(派生类)。继承让变化中的软件系统有了一定的延续性,同时继承也是封装程序中可变因素的重要手段(如果不能理解请阅读阎宏博士的《Java与模式》或《设计模式精解》中关于桥梁模式的部分)。

3、封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象。我们在类中编写的方法就是对实现细节的一种封装;我们编写一个类就是对数据和数据操作的封装。可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程接口(可以想想普通洗衣机和全自动洗衣机的差别,明显全自动洗衣机封装更好因此操作起来更简单;我们现在使用的智能手机也是封装得足够好的,因为几个按键就搞定了所有的事情)。

4、多态性:多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。如果将对象的方法视为对象向外界提供的服务,那么运行时的多态性可以解释为:当A系统访问B系统提供的服务时,B系统有多种提供服务的方式,但一切对A系统来说都是透明的(就像电动剃须刀是A系统,它的供电系统是B系统,B系统可以使用电池供电或者用交流电,甚至还有可能是太阳能,A系统只会通过B类对象调用供电的方法,但并不知道供电系统的底层实现是什么,究竟通过何种方式获得了动力)。方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。运行时的多态是面向对象最精髓的东西,要实现多态需要做两件事:1. 方法重写(子类继承父类并重写父类中已有的或抽象的方法);2. 对象造型(用父类型引用引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)。

135.float f=3.4;是否正确?

答:不正确。3.4是双精度数,将双精度型(double)赋值给浮点型(float)属于下转型(down-casting,也称为窄化)会造成精度损失,因此需要强制类型转换float f =(float)3.4; 或者写成float f =3.4F;。

136.short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗?

答:对于short s1 = 1; s1 = s1 + 1;由于1是int类型,因此s1+1运算结果也是int 型,需要强制转换类型才能赋值给short型。而short s1 = 1; s1 += 1;可以正确编译,因为s1+= 1;相当于s1 = (short)(s1 + 1);其中有隐含的强制类型转换。

137.Java 有没有goto?

答: goto 是Java中的保留字,在目前版本的Java中没有使用。(根据James Gosling(Java之父)编写的《The Java Programming Language》一书的附录中给出了一个Java关键字列表,其中有goto和const,但是这两个是目前无法使用的关键字,因此有些地方将其称之为保留字,其实保留字这个词应该有更广泛的意义,因为熟悉C语言的程序员都知道,在系统类库中使用过的有特殊意义的单词或单词的组合都被视为保留字)

138.int 和Integer 有什么区别?

答:Java是一个近乎纯洁的面向对象编程语言,但是为了编程的方便还是引入不是对象的基本数据类型,但是为了能够将这些基本数据类型当成对象操作,Java为每一个基本数据类型都引入了对应的包装类型(wrapper class),int的包装类就是Integer,从JDK 1.5开始引入了自动装箱/拆箱机制,使得二者可以相互转换。

Java 为每个原始类型提供了包装类型:

原始类型: boolean,char,byte,short,int,long,float,double

包装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double

package com.bjsxt;

public class AutoUnboxingTest {

    public static void main(String[] args) {
        Integer a = new Integer(3);
        Integer b = 3;              // 将3自动装箱成Integer类型
        int c = 3;
        System.out.println(a == b); // false 两个引用没有引用同一对象
        System.out.println(a == c); // true a自动拆箱成int类型再和c比较
    }
}

补充:最近还遇到一个面试题,也是和自动装箱和拆箱相关的,代码如下所示:

public class Test03 {

   public static void main(String[] args) {
       Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;
        System.out.println(f1 == f2);
        System.out.println(f3 == f4);
    }
}

如果不明就里很容易认为两个输出要么都是true要么都是false。首先需要注意的是f1、f2、f3、f4四个变量都是Integer对象,所以下面的==运算比较的不是值而是引用。装箱的本质是什么呢?当我们给一个Integer对象赋一个int值的时候,会调用Integer类的静态方法valueOf,如果看看valueOf的源代码就知道发生了什么。

public static Integer valueOf(int i) {
       if (i >= IntegerCache.low && i <= IntegerCache.high)
          return IntegerCache.cache[i + (-IntegerCache.low)];
       return new Integer(i);
   }

IntegerCache是Integer的内部类,其代码如下所示:

/* Cache to support the object identity semantics of autoboxing for values between
     * -128 and 127 (inclusive) as required by JLS.
     *
     * The cache is initialized on first usage.  The size of the cache
     * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
     * During VM initialization, java.lang.Integer.IntegerCache.high property
     * may be set and saved in the private system properties in the
     * sun.misc.VM class.
     */

    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
}

简单的说,如果字面量的值在-128到127之间,那么不会new新的Integer对象,而是直接引用常量池中的Integer对象,所以上面的面试题中f1==f2的结果是true,而f3==f4的结果是false。越是貌似简单的面试题其中的玄机就越多,需要面试者有相当深厚的功力。

139.&和&&的区别?

答:&运算符有两种用法:(1)按位与;(2)逻辑与。&&运算符是短路与运算。逻辑与跟短路与的差别是非常巨大的,虽然二者都要求运算符左右两端的布尔值都是true整个表达式的值才是true。&&之所以称为短路运算是因为,如果&&左边的表达式的值是false,右边的表达式会被直接短路掉,不会进行运算。很多时候我们可能都需要用&&而不是&,例如在验证用户登录时判定用户名不是null而且不是空字符串,应当写为:username != null &&!username.equals(“”),二者的顺序不能交换,更不能用&运算符,因为第一个条件如果不成立,根本不能进行字符串的equals比较,否则会产生NullPointerException异常。注意:逻辑或运算符(|)和短路或运算符(||)的差别也是如此。

补充:如果你熟悉JavaScript,那你可能更能感受到短路运算的强大,想成为 JavaScript的高手就先从玩转短路运算开始吧。

140.Math.round(11.5) 等于多少? Math.round(-11.5)等于多少?

答:Math.round(11.5)的返回值是12,Math.round(-11.5)的返回值是-11。四舍五入的原理是在参数上加0.5然后进行下取整。

141.swtich 是否能作用在byte 上,是否能作用在long 上,是否能作用在String上?

答:早期的JDK中,switch(expr)中,expr可以是byte、short、char、int。从1.5版开始,Java中引入了枚举类型(enum),expr也可以是枚举,从JDK 1.7版开始,还可以是字符串(String)。长整型(long)是不可以的。

142.用最有效率的方法计算2乘以8?

答: 2 << 3(左移3位相当于乘以2的3次方,右移3位相当于除以2的3次方)。

补充: 我们为编写的类重写hashCode方法时,可能会看到如下所示的代码,其实我们不太理解为什么要使用这样的乘法运算来产生哈希码(散列码),而且为什么这个数是个素数,为什么通常选择31这个数?前两个问题的答案你可以自己百度一下,选择31是因为可以用移位和减法运算来代替乘法,从而得到更好的性能。说到这里你可能已经想到了:31 * num <==> (num << 5) - num,左移5位相当于乘以2的5次方(32)再减去自身就相当于乘以31。现在的VM都能自动完成这个优化。

package com.bjsxt;

public class PhoneNumber {
    private int areaCode;
    private String prefix;
    private String lineNumber;

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + areaCode;
        result = prime * result
                + ((lineNumber == null) ? 0 : lineNumber.hashCode());
        result = prime * result + ((prefix == null) ? 0 : prefix.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        PhoneNumber other = (PhoneNumber) obj;
        if (areaCode != other.areaCode)
            return false;
        if (lineNumber == null) {
            if (other.lineNumber != null)
                return false;
        } else if (!lineNumber.equals(other.lineNumber))
            return false;
        if (prefix == null) {
            if (other.prefix != null)
                return false;
        } else if (!prefix.equals(other.prefix))
            return false;
        return true;
    }

}
143.在Java 中,如何跳出当前的多重嵌套循环?

答:在最外层循环前加一个标记如A,然后用break A;可以跳出多重循环。(Java中支持带标签的break和continue语句,作用有点类似于C和C++中的goto语句,但是就像要避免使用goto一样,应该避免使用带标签的break和continue,因为它不会让你的程序变得更优雅,很多时候甚至有相反的作用,所以这种语法其实不知道更好)

144.构造器(constructor)是否可被重写(override)?

答:构造器不能被继承,因此不能被重写,但可以被重载。

145.两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?

答:不对,如果两个对象x和y满足x.equals(y) == true,它们的哈希码(hash code)应当相同。Java对于eqauls方法和hashCode方法是这样规定的:(1)如果两个对象相同(equals方法返回true),那么它们的hashCode值一定要相同;(2)如果两个对象的hashCode相同,它们并不一定相同。当然,你未必要按照要求去做,但是如果你违背了上述原则就会发现在使用容器时,相同的对象可以出现在Set集合中,同时增加新元素的效率会大大下降(对于使用哈希存储的系统,如果哈希码频繁的冲突将会造成存取性能急剧下降)。

补充:关于equals和hashCode方法,很多Java程序都知道,但很多人也就是仅仅知道而已,在Joshua Bloch的大作《Effective Java》(很多软件公司,《Effective Java》、《Java编程思想》以及《重构:改善既有代码质量》是Java程序员必看书籍,如果你还没看过,那就赶紧去亚马逊买一本吧)中是这样介绍equals方法的:首先equals方法必须满足自反性(x.equals(x)必须返回true)、对称性(x.equals(y)返回true时,y.equals(x)也必须返回true)、传递性(x.equals(y)和y.equals(z)都返回true时,x.equals(z)也必须返回true)和一致性(当x和y引用的对象信息没有被修改时,多次调用x.equals(y)应该得到同样的返回值),而且对于任何非null值的引用x,x.equals(null)必须返回false。实现高质量的equals方法的诀窍包括:1. 使用==操作符检查“参数是否为这个对象的引用”;2. 使用instanceof操作符检查“参数是否为正确的类型”;3. 对于类中的关键属性,检查参数传入对象的属性是否与之相匹配;4. 编写完equals方法后,问自己它是否满足对称性、传递性、一致性;5. 重写equals时总是要重写hashCode;6. 不要将equals方法参数中的Object对象替换为其他的类型,在重写时不要忘掉@Override注解。

146.当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?

答:是值传递。Java 编程语言只有值传递参数。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的属性可以在被调用过程中被改变,但对象的引用是永远不会改变的。C++和C#中可以通过传引用或传输出参数来改变传入的参数的值。

补充:Java中没有传引用实在是非常的不方便,这一点在Java 8中仍然没有得到改进,正是如此在Java编写的代码中才会出现大量的Wrapper类(将需要通过方法调用修改的引用置于一个Wrapper类中,再将Wrapper对象传入方法),这样的做法只会让代码变得臃肿,尤其是让从C和C++转型为Java程序员的开发者无法容忍。

147.重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?

答:Java的三大特征之一,多态机制,包括方法的多态和对象的多态;方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。重载(overload)发生在同一个类中,相同的方法,如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写(override)发生在子类与父类之间也就是继承机制当中,当父类的方法不能满足子类的要求,此时子类重写父类的方法;要求:方法名、形参列表相同;返回值类型和异常类型,子类小于等于父类;访问权限,子类大于等于父类,切记父类的私有方法以及被final修饰的方法不能被子类重写;重载对返回类型没有特殊的要求。

148.华为的面试题中曾经问过这样一个问题:为什么不能根据返回类型来区分重载,为什么?

答:方法的重载,即使返回值类型不同,也不能改变实现功能相同或类似这一既定事实;同时方法的重载只是要求两同三不同,即在同一个类中,相同的方法名称,参数列表当中的参数类型、个数、顺序不同;跟权限修饰符和返回值类无关

149.静态嵌套类(Static Nested Class)和内部类(Inner Class)的不同?

答:内部类就是在一个类的内部定义的类,内部类中不能定义静态成员(静态成员不是对象的特性,只是为了找一个容身之处,所以需要放到一个类中而已,这么一点小事,你还要把它放到类内部的一个类中,过分了啊!提供内部类,不是为让你干这种事情,无聊,不让你干。我想可能是既然静态成员类似c语言的全局变量,而内部类通常是用于创建内部对象用的,所以,把“全局变量”放在内部类中就是毫无意义的事情,既然是毫无意义的事情,就应该被禁止),内部类可以直接访问外部类中的成员变量,内部类可以定义在外部类的方法外面,也可以定义在外部类的方法体中,如下所示:

public class Outer
{
        int out_x  = 0;
        public void method()
              {
               Inner1 inner1 = new Inner1();
               public class Inner2  //在方法体内部定义的内部类
               {
                      public method()
                      {
                             out_x = 3;
                      }
               }
               Inner2 inner2 = new Inner2();
        }

        public class Inner1  //在方法体外面定义的内部类
        {
        }

}

在方法体外面定义的内部类的访问类型可以是public,protecte,默认的,private等4种类型,这就好像类中定义的成员变量有4种访问类型一样,它们决定这个内部类的定义对其他类是否可见;对于这种情况,我们也可以在外面创建内部类的实例对象,创建内部类的实例对象时,一定要先创建外部类的实例对象,然后用这个外部类的实例对象去创建内部类的实例对象,代码如下:

Outer outer = new Outer();

Outer.Inner1 inner1 = outer.new Innner1();

在方法内部定义的内部类前面不能有访问类型修饰符,就好像方法中定义的局部变量一样,但这种内部类的前面可以使用final或abstract修饰符。这种内部类对其他类是不可见的其他类无法引用这种内部类,但是这种内部类创建的实例对象可以传递给其他类访问。这种内部类必须是先定义,后使用,即内部类的定义代码必须出现在使用该类之前,这与方法中的局部变量必须先定义后使用的道理也是一样的。这种内部类可以访问方法体中的局部变量,但是,该局部变量前必须加final修饰符。

对于这些细节,只要在eclipse写代码试试,根据开发工具提示的各类错误信息就可以马上了解到。

在方法体内部还可以采用如下语法来创建一种匿名内部类,即定义某一接口或类的子类的同时,还创建了该子类的实例对象,无需为该子类定义名称:

public class Outer
{
        public void start()
        {
               new Thread(
new Runable(){
         public void run(){};
}
).start();
        }
}

最后,在方法外部定义的内部类前面可以加上static关键字,从而成为Static Nested Class,它不再具有内部类的特性,所有,从狭义上讲,它不是内部类。Static Nested Class与普通类在运行时的行为和功能上没有什么区别,只是在编程引用时的语法上有一些差别,它可以定义成public、protected、默认的、private等多种类型,而普通类只能定义成public和默认的这两种类型。在外面引用Static Nested Class类的名称为“外部类名.内部类名”。在外面不需要创建外部类的实例对象,就可以直接创建Static Nested Class,例如,假设Inner是定义在Outer类中的Static Nested Class,那么可以使用如下语句创建Inner类:

Outer.Inner inner = newOuter.Inner();

由于static Nested Class不依赖于外部类的实例对象,所以,static Nested Class能访问外部类的非static成员变量(不能直接访问,需要创建外部类实例才能访问非静态变量)。当在外部类中访问Static Nested Class时,可以直接使用Static Nested Class的名字,而不需要加上外部类的名字了,在Static Nested Class中也可以直接引用外部类的static的成员变量,不需要加上外部类的名字。

在静态方法中定义的内部类也是Static Nested Class,这时候不能在类前面加static关键字,静态方法中的Static Nested Class与普通方法中的内部类的应用方式很相似,它除了可以直接访问外部类中的static的成员变量,还可以访问静态方法中的局部变量,但是,该局部变量前必须加final修饰符。

备注:首先根据你的印象说出你对内部类的总体方面的特点:例如,在两个地方可以定义,可以访问外部类的成员变量,不能定义静态成员,这是大的特点。然后再说一些细节方面的知识,例如,几种定义方式的语法区别,静态内部类,以及匿名内部类。

Static Nested Class是被声明为静态(static)的内部类,它可以不依赖于外部类实例被实例化。而通常的内部类需要在外部类实例化后才能实例化,其语法看起来挺诡异的,如下所示。

package com.bjsxt;
/**
* 扑克类(一副扑克)
  * @author sxt
  *
 */
public class Poker {
    private static String[] suites = {"黑桃", "红桃", "草花", "方块"};
    private static int[] faces = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
          private Card[] cards;
    /**
      * 构造器
     */
    public Poker() {
        cards = new Card[52];
        for(int i = 0; i < suites.length; i++) {
              for(int j = 0; j < faces.length; j++) {
                cards[i * 13 + j] = new Card(suites[i], faces[j]);
            }
        }
    }

    /**
          * 洗牌 (随机乱序)
          */
    public void shuffle() {
        for(int i = 0, len = cards.length; i < len; i++) {
            int index = (int) (Math.random() * len);
                   Card temp = cards[index];
            cards[index] = cards[i];
            cards[i] = temp;
        }
    }
     /**
     * 发牌
     * @param index 发牌的位置
     */
    public Card deal(int index) {
        return cards[index];
    }

    /**
     * 卡片类(一张扑克)
     * [内部类]
     * @author sxt
     */
    public class Card {
  private String suite;   // 花色
        private int face;       // 点数
  public Card(String suite, int face) {
            this.suite = suite;
            this.face = face;
       }
        @Override
        public String toString() {
            String faceStr = "";
            switch(face) {
                  case 1: faceStr = "A"; break;
            case 11: faceStr = "J"; break;
            case 12: faceStr = "Q"; break;
            case 13: faceStr = "K"; break;
            default: faceStr = String.valueOf(face);
            }
            return suite + faceStr;
        }
    }
}

测试类:

package com.bjsxt;

class PokerTest {
   public static void main(String[] args) {
        Poker poker = new Poker();
        poker.shuffle();            // 洗牌
        Poker.Card c1 = poker.deal(0);  // 发第一张牌
              // 对于非静态内部类Card
        // 只有通过其外部类Poker对象才能创建Card对象
        Poker.Card c2 = poker.new Card("红心", 1);    // 自己创建一张牌
        System.out.println(c1);     // 洗牌后的第一张
        System.out.println(c2);     // 打印: 红心A
    }
}
150.抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被synchronized修饰?

答:都不能。抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。本地方法是由本地代码(如C代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。synchronized和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。

151.静态变量和实例变量的区别?

答:静态变量是被static修饰符修饰的变量,也称为类变量,它属于类,不属于类的任何一个对象,一个类不管创建多少个对象,静态变量在内存中有且仅有一个拷贝;实例变量必须依存于某一实例,需要先创建对象然后通过对象才能访问到它,静态变量可以实现让多个对象共享内存。两者的相同点:都有默认值而且在类的任何地方都可以调用。在Java开发中,上下文类和工具类中通常会有大量的静态成员。 

152.是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用?

答:不可以,静态方法只能访问静态成员,因为非静态方法的调用要先创建对象,因此在调用静态方法时可能对象并没有被初始化。 

153.如何实现对象克隆?
package com.bjsxt;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class MyUtil {
      private MyUtil() {
        throw new AssertionError();
    }
      public static <T> T clone(T obj) throws Exception {
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bout);
        oos.writeObject(obj);
        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bin);
        return (T) ois.readObject();
        // 说明:调用ByteArrayInputStream或ByteArrayOutputStream对象的close方法没有任何意义
        // 这两个基于内存的流只要垃圾回收器清理对象就能够释放资源
}
}

答:有两种方式:

1.实现Cloneable接口并重写Object类中的clone()方法;

2.实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆,代码如下。

下面是测试代码:

package com.bjsxt;
import java.io.Serializable;
/**
 * 人类
 * @author sxt
*/
class Person implements Serializable {
    private static final long serialVersionUID = -9102017020286042305L;
    private String name;    // 姓名
    private int age;        // 年龄
    private Car car;        // 座驾

    public Person(String name, int age, Car car) {
        this.name = name;
        this.age = age;
        this.car = car;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Car getCar() {
        return car;
    }
    public void setCar(Car car) {
        this.car = car;
    }
    @Override
    public String toString() {
     return "Person [name=" + name + ", age=" + age + ", car=" + car + "]";
    }
  }
  /**
 * 小汽车类
 * @author sxt
*/
class Car implements Serializable {
    private static final long serialVersionUID = -5713945027627603702L;
    private String brand;       // 品牌
    private int maxSpeed;       // 最高时速

    public Car(String brand, int maxSpeed) {
        this.brand = brand;
        this.maxSpeed = maxSpeed;
    }
    public String getBrand() {
        return brand;
    }
    public void setBrand(String brand) {
        this.brand = brand;
    }
    public int getMaxSpeed() {
        return maxSpeed;
    }

    public void setMaxSpeed(int maxSpeed) {
        this.maxSpeed = maxSpeed;
    }

    @Override
    public String toString() {
        return "Car [brand=" + brand + ", maxSpeed=" + maxSpeed + "]";
    }
  }

class CloneTest {
  public static void main(String[] args) {
        try {
            Person p1 = new Person("Hao LUO", 33, new Car("Benz", 300));
            Person p2 = MyUtil.clone(p1);   // 深度克隆
            p2.getCar().setBrand("BYD");
            // 修改克隆的Person对象p2关联的汽车对象的品牌属性
            // 原来的Person对象p1关联的汽车不会受到任何影响
            // 因为在克隆Person对象时其关联的汽车对象也被克隆了
            System.out.println(p1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

注意:基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型限定,可以检查出要克隆的对象是否支持序列化,这项检查是编译器完成的,不是在运行时抛出异常,这种是方案明显优于使用Object类的clone方法克隆对象。

154.接口是否可继承(extends)接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承具体类(concrete class)?

答:接口可以继承接口。抽象类可以实现(implements)接口,抽象类可以继承具体类。抽象类中可以有静态的main方法。

备注:只要明白了接口和抽象类的本质和作用,这些问题都很好回答,你想想,如果你是java语言的设计者,你是否会提供这样的支持,如果不提供的话,有什么理由吗?如果你没有道理不提供,那答案就是肯定的了。

只有记住抽象类与普通类的唯一区别就是不能创建实例对象和允许有abstract方法。 

155.一个“.java”源文件中是否可以包含多个类(不是内部类)?有什么限制?

答:可以,但一个源文件中最多只能有一个公开类(public class)而且文件名必须和公开类的类名完全保持一致。 

156.Anonymous Inner Class(匿名内部类)是否可以继承其它类?是否可以实现接口?

答:可以继承其他类或实现其他接口,在Swing编程中常用此方式来实现事件监听和回调。 但是有一点需要注意,它只能继承一个类或一个接口。

157.内部类可以引用它的包含类(外部类)的成员吗?有没有什么限制?

答:一个内部类对象可以访问创建它的外部类对象的成员,包括私有成员。如果要访问外部类的局部变量,此时局部变量必须使用final修饰,否则无法访问。

158.Java 中的final关键字有哪些用法?

(1) 修饰类:表示该类不能被继承;

(2) 修饰方法:表示方法不能被重写但是允许重载;

(3) 修饰变量:表示变量只能一次赋值以后值不能被修改(常量);

(4) 修饰对象:对象的引用地址不能变,但是对象的初始化值可以变。

159.指出下面程序的运行结果:
package com.bjsxt;
class A{
  static{
        System.out.print("1");
    }
  public A(){
        System.out.print("2");
    }
}
class B extends A{
  static{
        System.out.print("a");
    }
    public B(){
        System.out.print("b");
    }
}

public class Hello{
  public static void main(String[] args){
        A ab = new B();
        ab = new B();
    }
}

答:执行结果:1a2b2b。创建对象时构造器的调用顺序是:先初始化静态成员,然后调用父类构造器,再初始化非静态成员,最后调用自身构造器。 

考点:静态代码块优先级 > 构造方法的优先级如果再加一个普通代码块,优先顺序如下:静态代码块>普通代码块>构造方法

160.说说数据类型之间的转换:

1 ) 如何将字符串转换为基本数据类型?

2 ) 如何将基本数据类型转换为字符串?

答:

1 ) 调用基本数据类型对应的包装类中的方法parseXXX(String)或valueOf(String)即可返回相应基本类型;

2 ) 一种方法是将基本数据类型与空字符串(””)连接(+)即可获得其所对应的字符串;另一种方法是调用String 类中的valueOf(…)方法返回相应字符串 

161.如何实现字符串的反转及替换?

答:方法很多,可以自己写实现也可以使用String或StringBuffer / StringBuilder中的方法。有一道很常见的面试题是用递归实现字符串反转,代码如下所示:

package com.bjsxt;
public class A{
    public static String reverse(String originStr) {
 if(originStr == null || originStr.length() <= 1)
     return originStr;
       return reverse(originStr.substring(1)) + originStr.charAt(0);
     }
}
162.怎样将GB2312编码的字符串转换为ISO-8859-1编码的字符串?

答:代码如下所示:

String s1 = "你好";

String s2 = newString(s1.getBytes("GB2312"), "ISO-8859-1"); 

在String类的构造方法当中,存在一个字符集设置的方法,具体如下:

163.Java中的日期和时间:

1 ) 如何取得年月日、小时分钟秒?

2 ) 如何取得从1970年1月1日0时0分0秒到现在的毫秒数?

3 ) 如何取得某月的最后一天?

4 ) 如何格式化日期?

答:操作方法如下所示:

1 ) 创建java.util.Calendar 实例,调用其get()方法传入不同的参数即可获得参数所对应的值

2 ) 以下方法均可获得该毫秒数:

Calendar.getInstance().getTimeInMillis();

time.getActualMaximum(Calendar.DAY_OF_MONTH);

4 ) 利用java.text.DataFormat 的子类(如SimpleDateFormat类)中的format(Date)方法可将日期格式化。

164.打印昨天的当前时刻。
package com.bjsxt;
import java.util.Calendar;
public class YesterdayCurrent {
 public static void main(String[] args){
 Calendar cal = Calendar.getInstance();
 cal.add(Calendar.DATE, -1);
 System.out.println(cal.getTime());
 }
}
165.Java反射技术主要实现类有哪些,作用分别是什么?

在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中

1)Class类:代表一个类

2)Field 类:代表类的成员变量(属性)

3)Method类:代表类的成员方法

4)Constructor 类:代表类的构造方法

5)Array类:提供了动态创建数组,以及访问数组的元素的静态方法

166.Class类的作用?生成Class对象的方法有哪些?

Class类是Java 反射机制的起源和入口,用于获取与类相关的各种信息,提供了获取类信息的相关方法。Class类继承自Object类

Class类是所有类的共同的图纸。每个类有自己的对象,好比图纸和实物的关系;每个类也可看做是一个对象,有共同的图纸Class,存放类的 结构信息,能够通过相应方法取出相应信息:类的名字、属性、方法、构造方法、父类和接口

方 法
示 例
对象名
.getClass()
String str="bdqn";
Class clazz = str.getClass();
对象名
.getSuperClass()
Student stu = new Student();
Class c1 = stu.getClass();
Class c2 = stu.getSuperClass();
Class.forName()
Class clazz = Class.forName("java.lang.Object");
Class.forName("oracle.jdbc.driver.OracleDriver");
类名.class
类名.class
Class c2 = Student.class;
Class c2 = int.class
包装类.TYPE
包装类.TYPE
Class c2 = Boolean.TYPE;
167.反射的使用场合和作用、及其优缺点

1)使用场合

在编译时根本无法知道该对象或类可能属于哪些类,程序只依靠运行时信息来发现该对象和类的真实信息。

2)主要作用

通过反射可以使程序代码访问装载到JVM 中的类的内部信息,获取已装载类的属性信息,获取已装载类的方法,获取已装载类的构造方法信息

3)反射的优点

反射提高了Java程序的灵活性和扩展性,降低耦合性,提高自适应能力。它允许程序创建和控制任何类的对象,无需提前硬编码目标类;反射是其它一些常用语言,如C、C++、Fortran 或者Pascal等都不具备的

4) Java反射技术应用领域很广,如软件测试等;许多流行的开源框架例如Struts、Hibernate、Spring在实现过程中都采用了该技术

5)反射的缺点

性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此Java反射机制主要应用在对灵活性和扩展性要求很高的系统框架上,普通程序不建议使用。

使用反射会模糊程序内部逻辑:程序人员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂。

168.面向对象设计原则有哪些

面向对象设计原则是面向对象设计的基石,面向对象设计质量的依据和保障,设计模式是面向对象设计原则的经典应用

1)单一职责原则SRP

2)开闭原则OCP

3)里氏替代原则LSP

4)依赖注入原则DIP

5)接口分离原则ISP

6)迪米特原则LOD

7)组合/聚合复用原则CARP

8)开闭原则具有理想主义的色彩,它是面向对象设计的终极目标。其他设计原则都可以看作是开闭原则的实现手段或方法

String相关:

169.下面程序的运行结果是()(选择一项)
String str1="hello";

String str2=new String("hello");

System.out.println(str1==str2);
A. true
B. false
C. hello
D. he
答案:B
分析:str1没有使用new关键字,在堆中没有开辟空间,其值”hello”在常量池中,str2使用new关键字创建了一个对象,在堆中开辟了空间,”==”比较的是对象的引用,即内存地址,所以str1与str2两个对象的内存地址是不相同的
170.Java语言中,String类中的indexOf()方法返回值的类型是()
A. int16
B. int32
C. int
D. long
答案:C
171.给定以下代码,程序的运行结果是 ()(选择一项)
public class Example {
String str=new String("good");
char [] ch={'a','b','c'};

public static void main(String[] args) {
Example ex=new Example();
ex.change(ex.str, ex.ch);
System.out.print(ex.str+"and");
System.out.print(ex.ch);
}

public void change(String  str,char ch[]){
str="test ok";
ch[0]='g';
}
}
A. goodandabc
B. goodandgbc
C. test okandabc
D. test okandgbc
答案:B
分析:在方法调用时,在change方法中对str的值进行修改,是将str指向了常量江池中的”test ok”,而主方法中的ex.str仍然指向的是常量池中的”good”。字符型数组在方法调用时,将主方法中ex.ch的引用传递给change方法中的ch,指向是堆中的同一堆空间,所以修改ch[0]的时候,ex.ch可以看到相同的修改后的结果。
172.执行下列代码后,哪个结论是正确的()(选择两项)

String[] s=new String[10];

A. s[10]为””
B. s[9]为null
C. s[0]为未定义
D. s.length为10
答案:BD
分析: 引用数据类型的默认值均为null
s.length数组的长度
173.实现String类的replaceAll方法

思路说明:replaceAll方法的本质是使用正则表达式进行匹配,最终调用的其实是Matcher对象的replaceAll方法。

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TestStringReplaceAll {
public static void main(String[] args) {
String str = "a1s2d3f4h5j6k7";
// 将字符串中的数字全部替换为0
System.out.println(replaceAll(str, "\\d", "0"));
}

/**
 * @param str:源字符串
 * @param regex:正则表达式
 * @param newStr:替换后的子字符串
 * @return 返回替换成功后的字符串
 */
public static String replaceAll(String str, String regex, String newStr) {
Pattern pattern = Pattern.compile(regex);
Matcher mathcer = pattern.matcher(str);
String reslut = mathcer.replaceAll(newStr);
return reslut;
}
}
174.在“=”后填写适当的内容:

String []a=new String[10];

则:a[0]~a[9]=null;

a.length=10;

如果是int[]a=new int[10];

则:a[0]~a[9]= (0)

a.length= (10)

175.是否可以继承String类?

答:不可以,因为String类有final修饰符,而final修饰的类是不能被继承的,实现细节不允许改变。

public final class String implements java.io.Serializable,

Comparable< String>, CharSequence

176.给定两个字符串s和t, 写一个函数来决定是否t是s的重组词。你可以假设字符串只包含小写字母。
public class Solution {
    public boolean isAnagram(String s, String t) {
        if(s.length()!=t.length())
            return false;
        int bit[] = new int[26];
        for(int i=0;i<s.length();i++){
            bit[s.charAt(i)-'a']++;
        }

        for(int i=0;i<s.length();i++){
            if(--bit[t.charAt(i)-'a']<0)
                return false;
        }
        return true;
    }

}
177.String s=new String(“abc”);创建了几个String对象。

两个或一个,”abc”对应一个对象,这个对象放在字符串常量缓冲区,常量”abc”不管出现多少遍,都是缓冲区中的那一个。New String每写一遍,就创建一个新的对象,它一句那个常量”abc”对象的内容来创建出一个新String对象。如果以前就用过’abc’,这句代表就不会创建”abc”自己了,直接从缓冲区拿。

178.输出结果?
String str1=“hello”;
Sring str2=“he”+new String(“llo”);
Sysem.out.println(str1==str2));
Sysem.out.println(str.equal(str2));

false

true

179.下列程序的输出结果是什么?
import java.util.*;
public class Test 6{
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
Integer k=new Integer(i);
System.out.println(k+" Hello world");
}
}
}

0 Hello world

1 Hello world

2 Hello world

3 Hello world

4 Hello world

5 Hello world

6 Hello world

7 Hello world

8 Hello world

9 Hello world

180.关于java.lang.String类,以下描述正确的一项是()
A. String类是final类故不可继承
B. String类final类故可以继承
C. String类不是final类故不可继承
D. String;类不是final类故可以继承
答案:A
181.下面哪个是正确的()
A. String temp[ ] = new String{“a”,”b”,”c”};
B. String temp[ ] = {“a”,”b”,”c”};
C. String temp= {“a”,”b”,”c”};
D. String[ ] temp = {“a”,”b”,”c”};
答案:BD
182.已知如下代码:执行结果是什么()
package com.bjsxt;
public class Test {
public static void main(String[] args) {
String s1 = new String("Hello");
String s2 = new String("Hello");
System.out.print(s1 == s2);
String s3 = "Hello";
String s4 = "Hello";
System.out.print(s3 == s4);
s1 = s3;
s2 = s4;
System.out.print(s1 == s2);
}
}
A. false true true
B. true false true
C. true true false
D. true true false
答案:A
183.字符串如何转换为int类型
public class Test {
public static void main(String[] args) {
 //方式一
 int num=Integer.parseInt("123");
 //方式二
 int num2=Integer.valueOf("123");
 System.out.println(num+"  "+num2);
}
}
184.写一个方法,实现字符串的反转,如:输入abc,输出cba
public class Test {
public static void main(String[] args) {
String result=reverse("abc");
System.out.println(result);
}
public static String reverse(String str){
StringBuilder result=new StringBuilder("");
char[] chArra=str.toCharArray();
for(int i=chArra.length-1;i>=0;i--){
char ch=chArra[i];
result.append(ch);
}
return result.toString();
}
}
185.编写java,将“I follow Bill Gate.Tom Gate.John Gate”中的“Gate”全部替换为“Gates”
public classDemo1 {
publicstaticvoid main(String[] args) {
String s="I follow Bill Gate.Tom Gate.John Gate";
System.out.println(s);
s=s.replaceAll("Gate","Gates");
System.out.println(s);
}
}
186.String 是最基本的数据类型吗?

答: 不是 。Java中的基本数据类型只有8个:byte、short、int、long、float、double、char、boolean;除了基本类型(primitive type)和枚举类型(enumeration type),剩下的都是引用类型(reference type)。

187.String 和StringBuilder、StringBuffer 的区别?

答: Java 平台提供了两种类型的字符串:String和StringBuffer / StringBuilder

相同点:

它们都可以储存和操作字符串,同时三者都使用final修饰,都属于终结类不能派生子类,操作的相关方法也类似例如获取字符串长度等;

不同点:

其中String是只读字符串,也就意味着String引用的字符串内容是不能被改变的,而StringBuffer和StringBuilder类表示的字符串对象可以直接进行修改,在修改的同时地址值不会发生改变。StringBuilder是JDK 1.5中引入的,它和StringBuffer的方法完全相同,区别在于它是在单线程环境下使用的,因为它的所有方面都没有被synchronized修饰,因此它的效率也比StringBuffer略高。在此重点说明一下,String、StringBuffer、StringBuilder三者类型不一样,无法使用equals()方法比较其字符串内容是否一样!

补充1:有一个面试题问:有没有哪种情况用+做字符串连接比调用StringBuffer / StringBuilder对象的append方法性能更好?如果连接后得到的字符串在静态存储区中是早已存在的,那么用+做字符串连接是优于StringBuffer / StringBuilder的append方法的。

补充2:下面也是一个面试题,问程序的输出,看看自己能不能说出正确答案。

package com.bjsxt;
public class smallT {
public static void main(String[] args) {
        String a = "Programming";
        String b = new String("Programming");
        String c = "Program" + "ming";
              System.out.println(a == b);
              System.out.println(a == c);
               System.out.println(a.equals(b));
               System.out.println(a.equals(c));
               System.out.println(a.intern() == b.intern());
}
}

解析:

String类存在intern()方法,含义如下:返回字符串对象的规范化表示形式。它遵循以下规则:对于任意两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true。

字符串比较分为两种形式,一种使用比较运算符”==”比较,他们比较的是各自的字符串在内存当中的地址值是否相同;一种是使用equals()方法进行比较,比较的是两个字符串的内容是否相同!

结果如下:

a == b-->false

a == c-->true

a.equals(b)-->true

a.equals(c)-->true

a.intern() == b.intern()-->true

188.String类为什么是final的

答:1) 为了效率。若允许被继承,则其高度的被使用率可能会降低程序的性能。

2)为了安全。JDK中提供的好多核心类比如String,这类的类的内部好多方法的实现都不是java编程语言本身编写的,好多方法都是调用的操作系统本地的API,这就是著名的“本地方法调用”,也只有这样才能做事,这种类是非常底层的,和操作系统交流频繁的,那么如果这种类可以被继承的话,如果我们再把它的方法重写了,往操作系统内部写入一段具有恶意攻击性质的代码什么的,这不就成了核心病毒了么?不希望别人改,这个类就像一个工具一样,类的提供者给我们提供了, 就希望我们直接用就完了,不想让我们随便能改,其实说白了还是安全性,如果随便能改了,那么java编写的程序肯定就很不稳定,你可以保证自己不乱改, 但是将来一个项目好多人来做,管不了别人,再说有时候万一疏忽了呢?他也不是估计的, 所以这个安全性是很重要的,java和C++相比,优点之一就包括这一点。

189.String类型是基本数据类型吗?基本数据类型有哪些

1) 基本数据类型包括byte、short/char、int、long、float、double、boolean

2 ) java.lang.String类是引用数据类型,并且是final类型的,因此不可以继承这个类、不能修改这个类。为了提高效率节省空间,我们应该用StringBuffer类

190.String s="Hello";s=s+"world!";执行后,是否是对前面s指向空间内容的修改?

答:不是对前面s指向空间内容的直接修改。

因为String被设计成不可变(immutable)类,所以它的所有对象都是不可变对象。在这段代码中,s原先指向一个String对象,内容是 "Hello",然后我们对s进行了+操作,那么s所指向的那个对象是否发生了改变呢?答案是没有。这时,s不指向原来那个对象了,而指向了另一个 String对象,内容为"Hello world!",原来那个对象还存在于内存之中,只是s这个引用变量不再指向它了。

通过上面的说明,我们很容易导出另一个结论,如果经常对字符串进行各种各样的修改,或者说,不可预见的修改,那么使用String来代表字符串的话会引起很大的内存开销。因为 String对象建立之后不能再改变,所以对于每一个不同的字符串,都需要一个String对象来表示。这时,应该考虑使用StringBuffer类,它允许修改,而不是每个不同的字符串都要生成一个新的对象。并且,这两种类的对象转换十分容易。

同时,我们还可以知道,如果要使用内容相同的字符串,不必每次都new一个String。例如我们要在构造器中对一个名叫s的String引用变量进行初始化,把它设置为初始值,应当这样做:

public class Demo {
private String s;
...
public Demo {
s = "Initial Value";
}
...
}

而非

s = new String("Initial Value");

后者每次都会调用构造器,生成新对象,性能低下且内存开销大,并且没有意义,因为String对象不可改变,所以对于内容相同的字符串,只要一个String对象来表示就可以了。也就说,多次调用上面的构造器创建多个对象,他们的String类型属性s都指向同一个对象。

上面的结论还基于这样一个事实:对于字符串常量,如果内容相同,Java认为它们代表同一个String对象。而用关键字new调用构造器,总是会创建一个新的对象,无论内容是否相同。

至于为什么要把String类设计成不可变类,是它的用途决定的。其实不只String,很多Java标准类库中的类都是不可变的。在开发一个系统的时候,我们有时候也需要设计不可变类,来传递一组相关的值,这也是面向对象思想的体现。不可变类有一些优点,比如因为它的对象是只读的,所以多线程并发访问也不会有任何问题。当然也有一些缺点,比如每个不同的状态都要一个对象来代表,可能会造成性能上的问题。所以Java标准类库还提供了一个可变版本,即 StringBuffer。

191.String s = new String("xyz");创建几个String Object?

答:两个或一个,”xyz”对应一个对象,这个对象放在字符串常量缓冲区,常量”xyz”不管出现多少遍,都是缓冲区中的那一个。New String每写一遍,就创建一个新的对象,它一句那个常量”xyz”对象的内容来创建出一个新String对象。如果以前就用过’xyz’,这句代表就不会创建”xyz”自己了,直接从缓冲区拿。

192.下面这条语句一共创建了多少个对象:String s="a"+"b"+"c"+"d";

答:对于如下代码:

String s1 = "a";

String s2 = s1 + "b";

String s3 = "a" + "b";

System.out.println(s2 == "ab");

System.out.println(s3 == "ab");

第一条语句打印的结果为false,第二条语句打印的结果为true,这说明javac编译可以对字符串常量直接相加的表达式进行优化,不必要等到运行期去进行加法运算处理,而是在编译时去掉其中的加号,直接将其编译成一个这些常量相连的结果。

题目中的第一行代码被编译器在编译时优化后,相当于直接定义一个”abcd”的字符串,所以,上面的代码应该只创建了一个String对象。

写如下两行代码,

String s = "a" + "b" + "c" + "d";

System.out.println(s == "abcd");

最终打印的结果应该为true。

集合:

193.Java集合体系结构(List、Set、Collection、Map的区别和联系)

1、Collection 接口存储一组不唯一,无序的对象

2、List 接口存储一组不唯一,有序(插入顺序)的对象

3、Set 接口存储一组唯一,无序的对象

4、Map接口存储一组键值对象,提供key到value的映射。Key无序,唯一。value不要求有序,允许重复。(如果只使用key存储,而不使用value,那就是Set)

194.Vector和ArrayList的区别和联系

相同点:

1)实现原理相同---底层都使用数组

2)功能相同---实现增删改查等操作的方法相似

3)都是长度可变的数组结构,很多情况下可以互用

不同点:

1)Vector是早期JDK版本提供,ArrayList是新版本替代Vector的

2)Vector线程安全,ArrayList重速度轻安全,线程非安全长度需增长时,Vector默认增长一倍,ArrayList增长50%

195.ArrayList和LinkedList的区别和联系

相同点:

两者都实现了List接口,都具有List中元素有序、不唯一的特点。

不同点:

ArrayList实现了长度可变的数组,在内存中分配连续空间。遍历元素和随机访问元素的效率比较高;

LinkedList采用链表存储方式。插入、删除元素时效率比较高

196.HashMap和Hashtable的区别和联系

相同点:

实现原理相同,功能相同,底层都是哈希表结构,查询速度快,在很多情况下可以互用

不同点:

1、Hashtable是早期提供的接口,HashMap是新版JDK提供的接口

2、Hashtable继承Dictionary类,HashMap实现Map接口

3、Hashtable线程安全,HashMap线程非安全

4、Hashtable不允许null值,HashMap允许null值

197.HashSet的使用和原理(hashCode()和equals())

1)哈希表的查询速度特别快,时间复杂度为O(1)。

2)HashMap、Hashtable、HashSet这些集合采用的是哈希表结构,需要用到hashCode哈希码,hashCode是一个整数值。

3)系统类已经覆盖了hashCode方法 自定义类如果要放入hash类集合,必须重写hashcode。如果不重写,调用的是Object的hashcode,而Object的hashCode实际上是地址。

4)向哈希表中添加数据的原理:当向集合Set中增加对象时,首先集合计算要增加对象的hashCode码,根据该值来得到一个位置用来存放当前对象,如在该位置没有一个对象存在的话,那么集合Set认为该对象在集合中不存在,直接增加进去。如果在该位置有一个对象存在的话,接着将准备增加到集合中的对象与该位置上的对象进行equals方法比较,如果该equals方法返回false,那么集合认为集合中不存在该对象,在进行一次散列,将该对象放到散列后计算出的新地址里。如果equals方法返回true,那么集合认为集合中已经存在该对象了,不会再将该对象增加到集合中了。

5)在哈希表中判断两个元素是否重复要使用到hashCode()和equals()。hashCode决定数据在表中的存储位置,而equals判断是否存在相同数据。

6) Y=K(X) :K是函数,X是哈希码,Y是地址

198.TreeSet的原理和使用(Comparable和comparator)

1)TreeSet集合,元素不允许重复且有序(自然顺序)

2)TreeSet采用树结构存储数据,存入元素时需要和树中元素进行对比,需要指定比较策略。

3)可以通过Comparable(外部比较器)和Comparator(内部比较器)来指定比较策略,实现了Comparable的系统类可以顺利存入TreeSet。自定义类可以实现Comparable接口来指定比较策略。

4)可创建Comparator接口实现类来指定比较策略,并通过TreeSet构造方法参数传入。这种方式尤其对系统类非常适用。

199.集合和数组的比较(为什么引入集合)

数组不是面向对象的,存在明显的缺陷,集合完全弥补了数组的一些缺点,比数组更灵活更实用,可大大提高软件的开发效率而且不同的集合框架类可适用于不同场合。具体如下:

1)数组的效率高于集合类.

2)数组能存放基本数据类型和对象,而集合类中只能放对象。

3)数组容量固定且无法动态改变,集合类容量动态改变。

4)数组无法判断其中实际存有多少元素,length只告诉了array的容量。

5)集合有多种实现方式和不同的适用场合,而不像数组仅采用顺序表方式。

6)集合以类的形式存在,具有封装、继承、多态等类的特性,通过简单的方法和属性调用即可实现各种复杂操作,大大提高软件的开发效率。

200.Collection和Collections的区别

1)Collection是Java提供的集合接口,存储一组不唯一,无序的对象。它有两个子接口List和Set。

2)Java中还有一个Collections类,专门用来操作集合类 ,它提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。

201.下列说法正确的有()(选择一项)
A. LinkedList继承自List
B. AbstractSet继承自Set
C. HashSet继承自AbstractSet
D. TreeMap继承自HashMap
答案: C
分析:A:LinkedList实现List接口
B:AbstractSet实现Set接口
D:TreeMap继承AbstractMap
202.Java的HashMap和Hashtable有什么区别HashSet和HashMap有什么区别?使用这些结构保存的数需要重载的方法是哪些?

答:HashMap与Hashtable实现原理相同,功能相同,底层都是哈希表结构,查询速度快,在很多情况下可以互用

两者的主要区别如下

1、Hashtable是早期JDK提供的接口,HashMap是新版JDK提供的接口

2、Hashtable继承Dictionary类,HashMap实现Map接口

3、Hashtable线程安全,HashMap线程非安全

4、Hashtable不允许null值,HashMap允许null值

HashSet与HashMap的区别

1、HashSet底层是采用HashMap实现的。HashSet 的实现比较简单,HashSet 的绝大部分方法都是通过调用 HashMap 的方法来实现的,因此 HashSet 和 HashMap 两个集合在实现本质上是相同的。

2、HashMap的key就是放进HashSet中对象,value是Object类型的。

3、当调用HashSet的add方法时,实际上是向HashMap中增加了一行(key-value对),该行的key就是向HashSet增加的那个对象,该行的value就是一个Object类型的常量

203.列出Java中的集合类层次结构?

答:Java中集合主要分为两种:Collection和Map。Collection是List和Set接口的父接口;ArrayList和LinkedList是List的实现类;HashSet和TreeSet是Set的实现类;LinkedHashSet是HashSet的子类。HashMap和TreeMap是Map的实现类;LinkedHashMap是HashMap的子类。

图中:虚线框中为接口,实线框中为类。

204.List,Set,Map各有什么特点

答:List 接口存储一组不唯一,有序(插入顺序)的对象。

Set 接口存储一组唯一,无序的对象。

Map接口存储一组键值对象,提供key到value的映射。key无序,唯一。value不要求有序,允许重复。(如果只使用key存储,而不使用value,那就是Set)。

205.ArrayList list=new ArrayList(20);中的list扩充几次()
A. 0
B. 1
C. 2
D. 3
答案:A
分析:已经指定了长度, 所以不扩容
206.List、Set、Map哪个继承自Collection接口,一下说法正确的是()
A. List Map
B. Set Map
C. List Set
D. List Map Set
答案:C
分析:Map接口继承了java.lang.Object类,但没有实现任何接口.
207.合并两个有序的链表
public class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null || l2 == null) {
            return l1 != null ? l1 : l2;
        }
        ListNode head = l1.val < l2.val ? l1 : l2;
        ListNode other = l1.val >= l2.val ? l1 : l2;
        ListNode prevHead = head;
        ListNode prevOther = other;
        while (prevHead != null) {
            ListNode next = prevHead.next;
            if (next != null && next.val > prevOther.val) {
                prevHead.next = prevOther;
                prevOther = next;
            }
            if(prevHead.next==null){
                prevHead.next=prevOther;
                break;
            }
            prevHead=prevHead.next;
        }
        return head;
}
}
208.用递归方式实现链表的转置。
/**
Definition for singly-linked list.
public class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode reverseList(ListNode head) {
if(head==null||head.next ==null)
            return head;
        ListNode prev = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return prev;
}
}
209.给定一个不包含相同元素的整数集合,nums,返回所有可能的子集集合。解答中集合不能包含重复的子集。
public class Solution {
    public List<List<Integer>> subsets (int[] nums) {
        List<List<Integer>> res = new ArrayList<ArrayList<Integer>>();
        List<Integer> item = new ArrayList<Integer>();
        if(nums.length == 0 || nums == null)
            return res;
        Arrays.sort(nums); //排序
        dfs(nums, 0, item, res);  //递归调用
        res.add(new ArrayList<Integer>());  //最后加上一个空集
        return res;
    }
    public static void dfs(int[] nums, int start, List<Integer> item, List<List<Integer>> res){
        for(int i = start; i < nums.length; i ++){
            item.add(nums[i]);
            //item是以整数为元素的动态数组,而res是以数组为元素的数组,在这一步,当item增加完元素后,item所有元素构成一个完整的子串,再由res纳入
            res.add(new ArrayList<Integer>(item));
            dfs(nums, i + 1, item, res);
            item.remove(item.size() - 1);
        }
    }
}
210.以下结构中,哪个具有同步功能()
A. HashMap
B. ConcurrentHashMap
C. WeakHashMap
D. TreeMap
答案:B
分析:
A,C,D都线程不安全,B线程安全,具有同步功能
211.以下结构中,插入性能最高的是()
A. ArrayList
B. Linkedlist
C. tor
D. Collection
答案:B
分析:
数组插入、删除效率差,排除A
tor不是java里面的数据结构,是一种网络路由技术;因此排除C
Collection 是集合的接口,不是某种数据结构;因此排除D
212.以下结构中,哪个最适合当作stack使用()
A. LinkedHashMap
B. LinkedHashSet
C. LinkedList
LinkedList
分析:
Stack是先进后出的线性结构;所以链表比较合适;不需要散列表的数据结构
213.Map的实现类中,哪些是有序的,哪些是无序的,有序的是如何保证其有序性,你觉得哪个有序性性能更高,你有没有更好或者更高效的实现方式?

答:1. Map的实现类有HashMap,LinkedHashMap,TreeMap

2. HashMap是有无序的,LinkedHashMap和TreeMap都是有序的(LinkedHashMap记录了添加数据的顺序;TreeMap默认是自然升序)

3. LinkedHashMap底层存储结构是哈希表+链表,链表记录了添加数据的顺序

4. TreeMap底层存储结构是二叉树,二叉树的中序遍历保证了数据的有序性

5. LinkedHashMap有序性能比较高,因为底层数据存储结构采用的哈希表

214.下面的代码在绝大部分时间内都运行得很正常,请问什么情况下会出现问题?根源在哪里?
package com.bjsxt;
import java.util.LinkedList;
public class Stack {
LinkedList list = new LinkedList();
public synchronized void push(Object x) {
synchronized (list) {
list.addLast(x);
notify();
}
}
public  synchronized Object pop() throws  Exception{
synchronized(list){
if(list.size()<=0){
wait();
}
return list.removeLast( );
}
}
}

答:将if( list.size() <= 0 )改成:while( list.size() <= 0 )

215.TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?

答:TreeSet要求存放的对象所属的类必须实现Comparable接口,该接口提供了比较元素的compareTo()方法,当插入元素时会 回调该方法比较元素的大小。TreeMap要求存放的键值对映射的键必须实现Comparable接口从而根据键对元素进行排序。Collections 工具类的sort方法有两种重载的形式,第一种要求传入的待排序容器中存放的对象比较实现Comparable接口以实现元素的比较;第二种不强制性的要求容器中的元素必须可比较,但是要求传入第二个参数,参数是Comparator接口的子类型(需要重写compare方法实现元素的比较),相当于一个临时定义的排序规则,其实就是是通过接口注入比较元素大小的算法,也是对回调模式的应用。

216.List里面如何剔除相同的对象?请简单用代码实现一种方法
public class Test {
public static void main(String[] args) {
  List<String> li1 = new ArrayList<String>();
  li1.add("8");
  li1.add("8");
  li1.add("9");
  li1.add("9");
  li1.add("0");
  System.out.println(li1);
  //方法:将List中数据取出来来存到Set中
  HashSet<String> set = new HashSet<String>();
  for(int i=0;i<li1.size();i++){
  set.add(li1.get(i));
  }
  System.out.println(set);
}
}
217.Java.util.Map的实现类有

分析:Java中的java.util.Map的实现类

1、HashMap

2、Hashtable

3、LinkedHashMap

4、TreeMap

218.下列叙述中正确的是()
A. 循环队列有队头和队尾两个指针,因此,循环队列是非线性结构
B. 在循环队列中,只需要队头指针就能反映队列中元素的动态变化情况
C. 在循环队列中,只需要队尾指针就能反映队列中元素的动态变化情况
D. 在循环队列中元素的个数是由队头指针和队尾指针共同决定的
答案:D
分析:循环队列中元素的个数是由队首指针和队尾指针共同决定的,元素的动态变化也是通过队首指针和队尾指针来反映的,当队首等于队尾时,队列为空。
219.List、Set、Map 是否继承自Collection 接口?

答:List、Set 的父接口是Collection,Map 不是其子接口,而是与Collection接口是平行关系,互不包含。

Map是键值对映射容器,与List和Set有明显的区别,而Set存储的零散的元素且不允许有重复元素(数学中的集合也是如此),List是线性结构的容器,适用于按数值索引访问元素的情形。 

220.说出ArrayList、Vector、LinkedList 的存储性能和特性?

答:ArrayList 和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized 方法(线程安全),通常性能上较ArrayList 差,而LinkedList 使用双向链表实现存储(将内存中零散的内存单元通过附加的引用关联起来,形成一个可以按序号索引的线性结构,这种链式存储方式与数组的连续存储方式相比,其实对内存的利用率更高),按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。Vector属于遗留容器(早期的JDK中使用的容器,除此之外Hashtable、Dictionary、BitSet、Stack、Properties都是遗留容器),现在已经不推荐使用,但是由于ArrayList和LinkedListed都是非线程安全的,如果需要多个线程操作同一个容器,那么可以通过工具类Collections中的synchronizedList方法将其转换成线程安全的容器后再使用(这其实是装潢模式最好的例子,将已有对象传入另一个类的构造器中创建新的对象来增加新功能)。

补充:遗留容器中的Properties类和Stack类在设计上有严重的问题,Properties是一个键和值都是字符串的特殊的键值对映射,在设计上应该是关联一个Hashtable并将其两个泛型参数设置为String类型,但是Java API中的Properties直接继承了Hashtable,这很明显是对继承的滥用。这里复用代码的方式应该是HAS-A关系而不是IS-A关系,另一方面容器都属于工具类,继承工具类本身就是一个错误的做法,使用工具类最好的方式是HAS-A关系(关联)或USE-A关系(依赖) 。同理,Stack类继承Vector也是不正确的。 

221.List、Map、Set 三个接口,存取元素时,各有什么特点?

答:List以特定索引来存取元素,可有重复元素。

Set不能存放重复元素(用对象的equals()方法来区分元素是否重复) 。Map保存键值对(key-value pair)映射,映射关系可以是一对一或多对一。Set和Map容器都有基于哈希存储和排序树(红黑树)的两种实现版本,基于哈希存储的版本理论存取时间复杂度为O(1),而基于排序树版本的实现在插入或删除元素时会按照元素或元素的键(key)构成排序树从而达到排序和去重的效果。 

222.TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?

答:TreeSet要求存放的对象所属的类必须实现Comparable接口,该接口提供了比较元素的compareTo()方法,当插入元素时会回调该方法比较元素的大小。

TreeMap要求存放的键值对映射的键必须实现Comparable接口从而根据键对元素进行排序。

Collections工具类的sort方法有两种重载的形式,第一种要求传入的待排序容器中存放的对象比较实现Comparable接口以实现元素的比较;第二种不强制性的要求容器中的元素必须可比较,但是要求传入第二个参数,参数是Comparator接口的子类型 (需要重写compare方法实现元素的比较),相当于一个临时定义的排序规则,其实就是是通过接口注入比较元素大小的算法,也是对回调模式的应用。

例子1:

Student.java

package com.bjsxt;

public class Student implements Comparable<Student> {
    private String name;        // 姓名
    private int age;            // 年龄
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + "]";
    }
    @Override
    public int compareTo(Student o) {
        return this.age - o.age; // 比较年龄(年龄的升序)
    }
  }

Test01.java

package com.bjsxt;
import java.util.Set;
import java.util.TreeSet;

class Test01 {
  public static void main(String[] args) {
        Set<Student> set = new TreeSet<>();     // Java 7的钻石语法(构造器后面的尖括号中不需要写类型)
        set.add(new Student("Hao LUO", 33));
        set.add(new Student("XJ WANG", 32));
        set.add(new Student("Bruce LEE", 60));
        set.add(new Student("Bob YANG", 22));
          for(Student stu : set) {
            System.out.println(stu);
        }
//      输出结果:
//      Student [name=Bob YANG, age=22]
//      Student [name=XJ WANG, age=32]
//      Student [name=Hao LUO, age=33]
//      Student [name=Bruce LEE, age=60]
    }
}

例子2:

Student.java

package com.bjsxt;

public class Student {
    private String name;    // 姓名
    private int age;        // 年龄
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    /**
     * 获取学生姓名
     */
    public String getName() {
        return name;
    }
    /**
     * 获取学生年龄
     */
    public int getAge() {
        return age;
    }
    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + "]";
    }
  }

Test02.java

package com.bjsxt;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

  class Test02 {
   public static void main(String[] args) {
        List<Student> list = new ArrayList<>();     // Java 7的钻石语法(构造器后面的尖括号中不需要写类型)
        list.add(new Student("Hao LUO", 33));
        list.add(new Student("XJ WANG", 32));
        list.add(new Student("Bruce LEE", 60));
        list.add(new Student("Bob YANG", 22));

        // 通过sort方法的第二个参数传入一个Comparator接口对象
        // 相当于是传入一个比较对象大小的算法到sort方法中
        // 由于Java中没有函数指针、仿函数、委托这样的概念
        // 因此要将一个算法传入一个方法中唯一的选择就是通过接口回调
        Collections.sort(list, new Comparator<Student> () {
         @Override
            public int compare(Student o1, Student o2) {
                return o1.getName().compareTo(o2.getName());    // 比较学生姓名
            }
        });

        for(Student stu : list) {
            System.out.println(stu);
        }
//      输出结果:
//      Student [name=Bob YANG, age=22]
//      Student [name=Bruce LEE, age=60]
//      Student [name=Hao LUO, age=33]
//      Student [name=XJ WANG, age=32]
    }
}

多线程:

223.下面程序的运行结果()(选择一项)
public static void main(String[] args) {
Thread t=new Thread(){
public void run(){
pong();
}
};
t.run();
System.out.println("ping");
}
static void pong(){
System.out.println("pong");
}
A. pingpong
B. pongping
C. pingpong和pongping都有可能
D. 都不输出
答案:B
分析:启动线程需要调用start()方法,而t.run()方法,则是使用对象名.分析:启动线程需要调用start()方法,而t.run()方法,则是使用对象名.
224.下列哪个方法可用于创建一个可运行的类()
A. public class X implements Runnable{public void run() {……}}
B. public class X extends Thread{public void run() {……}}
C. public class X extends Thread{public int run() {……}}
D. public class X implements Runnable{protected void run() {……}}
答案:AB
分析: 继承Thread和实现Runable接口
225.说明类java.lang.ThreadLocal的作用和原理。列举在哪些程序中见过ThreadLocal的使用?

作用:

要编写一个多线程安全(Thread-safe)的程序是困难的,为了让线程共享资源,必须小心地对共享资源进行同步,同步带来一定的效能延迟,而另一方面,在处理同步的时候,又要注意对象的锁定与释放,避免产生死结,种种因素都使得编写多线程程序变得困难。

尝试从另一个角度来思考多线程共享资源的问题,既然共享资源这么困难,那么就干脆不要共享,何不为每个线程创造一个资源的复本。将每一个线程存取数据的行为加以隔离,实现的方法就是给予每个线程一个特定空间来保管该线程所独享的资源。

比如:在Hibernate中的Session就有使用。

ThreadLocal的原理

ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单,在ThreadLocal类中有一个Map,用于存储每一个线程的变量的副本。

226.说说乐观锁与悲观锁

答:悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。

两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果经常产生冲突,上层应用会不断的进行retry,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适。

227.在Java中怎么实现多线程?描述线程状态的变化过程。

答:当多个线程访问同一个数据时,容易出现线程安全问题,需要某种方式来确保资源在某一时刻只被一个线程使用。需要让线程同步,保证数据安全线程同步的实现方案: 同步代码块和同步方法,均需要使用synchronized关键字

同步代码块:public void makeWithdrawal(int amt) {

synchronized (acct) { }

}

同步方法:public synchronized void makeWithdrawal(int amt) { }

线程同步的好处:解决了线程安全问题

线程同步的缺点:性能下降,可能会带来死锁

228.请写出多线程代码使用Thread或者Runnable,并说出两种的区别。

方式1:继承Java.lang.Thread类,并覆盖run() 方法。优势:编写简单;劣势:无法继承其它父类

public class ThreadDemo1 {
public static void main(String args[]) {
MyThread1 t = new MyThread1();
t.start();
while (true) {
System.out.println("兔子领先了,别骄傲");
}
}
}
class MyThread1 extends Thread {
public void run() {
while (true) {
System.out.println("乌龟领先了,加油");
}
}
}

方式2:实现Java.lang.Runnable接口,并实现run()方法。优势:可继承其它类,多线程可共享同一个Thread对象;劣势:编程方式稍微复杂,如需访问当前线程,需调用Thread.currentThread()方法

public class ThreadDemo2 {
public static void main(String args[]) {
MyThread2 mt = new MyThread2();
Thread t = new Thread(mt);
t.start();
while (true) {
System.out.println("兔子领先了,加油");
}
}
}
class MyThread2 implements Runnable {
public void run() {
while (true) {
System.out.println("乌龟超过了,再接再厉");
}
}
}
229.在多线程编程里,wait方法的调用方式是怎样的?

答:wait方法是线程通信的方法之一,必须用在 synchronized方法或者synchronized代码块中,否则会抛出异常,这就涉及到一个“锁”的概念,而wait方法必须使用上锁的对象来调用,从而持有该对象的锁进入线程等待状态,直到使用该上锁的对象调用notify或者notifyAll方法来唤醒之前进入等待的线程,以释放持有的锁。

230.Java线程的几种状态

答:线程是一个动态执行的过程,它有一个从产生到死亡的过程,共五种状态:

新建(new Thread)

当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)

例如:Thread t1=new Thread();

就绪(runnable)

线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。例如:t1.start();

运行(running)

线程获得CPU资源正在执行任务(run()方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。

死亡(dead)

当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。

自然终止:正常运行run()方法后终止

异常终止:调用stop()方法让一个线程终止运行

堵塞(blocked)

由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。

正在睡眠:用sleep(long t) 方法可使线程进入睡眠方式。一个睡眠着的线程在指定的时间过去可进入就绪状态。

正在等待:调用wait()方法。(调用motify()方法回到就绪状态)

被另一个线程所阻塞:调用suspend()方法。(调用resume()方法恢复)

231.在Java多线程中,请用下面哪种方式不会使线程进入阻塞状态()
A. sleep()
B. Suspend()
C. wait()
D. yield()
答案:D
分析:yield会是线程进入就绪状态
232.volatile关键字是否能保证线程安全?

答:不能。虽然volatile提供了同步的机制,但是知识一种弱的同步机制,如需要强线程安全,还需要使用synchronized。

Java语言提供了一种稍弱的同步机制,即volatile变量,用来确保将变量的更新操作通知到其他线程。当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他内存操作一起重排序。volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取volatile类型的变量时总会返回最新写入的值。

一、volatile的内存语义是:

当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量值立即刷新到主内存中。

当读一个volatile变量时,JMM会把该线程对应的本地内存设置为无效,直接从主内存中读取共享变量。

二、volatile底层的实现机制

如果把加入volatile关键字的代码和未加入volatile关键字的代码都生成汇编代码,会发现加入volatile关键字的代码会多出一个lock前缀指令。

1 、重排序时不能把后面的指令重排序到内存屏障之前的位置

2、使得本CPU的Cache写入内存

3、写入动作也会引起别的CPU或者别的内核无效化其Cache,相当于让新写入的值对别的线程可见。

233.请写出常用的Java多线程启动方式,Executors线程池有几种常用类型?

(1) 继承Thread类

public class java_thread extends Thread{
    public static void main(String args[]) {
        new java_thread().run();
        System.out.println("main thread run ");
    }
    public synchronized  void run() {
        System.out.println("sub thread run ");
    }
}

(2) 实现Runnable接口

public class java_thread implements Runnable{
    public static void main(String args[]) {
        new Thread(new java_thread()).start();
        System.out.println("main thread run ");
    }
    public void run() {
        System.out.println("sub thread run ");
    }
}

在Executor框架下,利用Executors的静态方法可以创建三种类型的常用线程池:

1)FixedThreadPool这个线程池可以创建固定线程数的线程池。

2)SingleThreadExecutor是使用单个worker线程的Executor。

3)CachedThreadPool是一个”无限“容量的线程池,它会根据需要创建新线程。

234.关于sleep()和wait(),以下描述错误的一项是()
A. sleep是线程类(Thread)的方法,wait是Object类的方法
B. Sleep不释放对象锁,wait放弃对象锁
C. Sleep暂停线程、但监控状态任然保持,结束后会自动恢复
D. Wait后进入等待锁定池,只针对此对象发出notify方法后获取对象锁进入运行状态。
答案:D
分析:针对此对象的notify方法后获取对象锁并进入就绪状态,而不是运行状态。另外针对此对象的notifyAll方法后也可能获取对象锁并进入就绪状态,而不是运行状态
235.进程和线程的区别是什么?

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.

线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.

区别 进程 线程
根本区别  作为资源分配的单位  调度和执行的单位
开销  每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销。  线程可以看成时轻量级的进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换的开销小。 
所处环境  系统在运行的时候会为每个进程分配不同的内存区域  除了CPU之外,不会为线程分配内存(线程所使用的资源是它所属的进程的资源),线程组只能共享资源 
分配内存  系统在运行的时候会为每个进程分配不同的内存区域  除了CPU之外,不会为线程分配内存(线程所使用的资源是它所属的进程的资源),线程组只能共享资源 
包含关系  没有线程的进程是可以被看作单线程的,如果一个进程内拥有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的。  线程是进程的一部分,所以线程有的时候被称为是轻权进程或者轻量级进程。 
236.以下锁机机制中,不能保证线程安全的是()
A. Lock
B. Synchronized
C. Volatile
答案:C
237.创建n多个线程,如何保证这些线程同时启动?看清,是“同时”。

答:用一个for循环创建线程对象,同时调用wait()方法,让所有线程等待;直到最后一个线程也准备就绪后,调用notifyAll(), 同时启动所有线程。

比如:给你n个赛车,让他们都在起跑线上就绪后,同时出发,Java多线程如何写代码?

思路是,来一辆赛车就加上一把锁,并修改对应的操作数,如果没有全部就绪就等待,并释放锁,直到最后一辆赛车到场后唤醒所有的赛车线程。代码参考如下:

public class CarCompetion {
    // 参赛赛车的数量
    protected final int totalCarNum = 10;
    // 当前在起跑线的赛车数量
    protected int nowCarNum = 0;
}
public class Car implements Runnable{
    private int carNum;
    private CarCompetion competion = null;
    public Car(int carNum, CarCompetion competion) {
        this.carNum = carNum;
        this.competion = competion;
    }
    @Override
    public void run() {
        synchronized (competion) {
            competion.nowCarNum++;
            while (competion.nowCarNum < competion.totalCarNum) {
                try {
                    competion.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            competion.notifyAll();
        }
        startCar();
    }
    private void startCar() {
        System.out.println("Car num " + this.carNum + " start to run.");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Car num " + this.carNum + " get to the finish line.");
    }
}
public static void main(String[] args) {
    CarCompetion carCompetion = new CarCompetion();
    final ExecutorService carPool =
        Executors.newFixedThreadPool(carCompetion.totalCarNum);
    for (int i = 0; i < carCompetion.totalCarNum; i++) {
        carPool.execute(new Car(i, carCompetion));

}
238.同步和异步有何异同,在什么情况下分别使用它们?

答:1.如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。

2.当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。

3.举个例子: 打电话是同步 发消息是异步

239.Java线程中,sleep()和wait()区别

答:sleep是线程类(Thread)的方法;作用是导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复;调用sleep()不会释放对象锁。

wait是Object类的方法;对此对象调用wait方法导致本线程放弃对象锁,进入等 待此对象的等待锁定池。只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池,准备获得对象锁进行运行状态。

240.下面所述步骤中,是创建进程做必须的步骤是()
A. 由调度程序为进程分配CPU
B. 建立一个进程控制块
C. 为进程分配内存
D. 为进程分配文件描述符
答案:BC
241.无锁化编程有哪些常见方法?()
A. 针对计数器,可以使用原子加
B. 只有一个生产者和一个消费者,那么就可以做到免锁访问环形缓冲区(Ring Buffer)
C. RCU(Read-Copy-Update),新旧副本切换机制,对于旧副本可以采用延迟释放的做法
D. CAS(Compare-and-Swap),如无锁栈,无锁队列等待
答案:D
分析:A 这方法虽然不太好,但是常见
B ProducerConsumerQueue就是这个,到处都是
C linux kernel里面大量使用
D 本质上其实就是乐观锁,操作起来很困难。。单生产者多消费者或者多生产者单消费者的情况下比较常见,也不容易遇到ABA问题。
242.sleep()和yield()有什么区别?

答:① sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会;

② 线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态;

③ sleep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常;

④ sleep()方法比yield()方法(跟操作系统相关)具有更好的可移植性。 

243.当一个线程进入一个对象的synchronized方法A之后,其它线程是否可进入此对象的synchronized方法?

答:不能。其它线程只能访问该对象的非同步方法,同步方法则不能进入。 只有等待当前线程执行完毕释放锁资源之后,其他线程才有可能进行执行该同步方法!

延伸 对象锁分为三种:共享资源、this、当前类的字节码文件对象

244.请说出与线程同步相关的方法。

答:1. wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁;

2. sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException 异常;

3. notify():唤醒一个处于等待状态的线程,当然在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且与优先级无关;

4. notityAll():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争;

5. JDK 1.5通过Lock接口提供了显式(explicit)的锁机制,增强了灵活性以及对线程的协调。Lock接口中定义了加锁(lock())和解锁(unlock())的方法,同时还提供了newCondition()方法来产生用于线程之间通信的Condition对象;

6. JDK 1.5还提供了信号量(semaphore)机制,信号量可以用来限制对某个共享资源进行访问的线程的数量。在对资源进行访问之前,线程必须得到信号量的许可(调用Semaphore对象的acquire()方法);在完成对资源的访问后,线程必须向信号量归还许可(调用Semaphore对象的release()方法)。

下面的例子演示了100个线程同时向一个银行账户中存入1元钱,在没有使用同步机制和使用同步机制情况下的执行情况。

银行账户类:

package com.bjsxt;
/**
 * 银行账户
 * @author sxt
 *
 */
public class Account {
    private double balance;     // 账户余额
    /**
     * 存款
     * @param money 存入金额
     */
    public void deposit(double money) {
        double newBalance = balance + money;
        try {
            Thread.sleep(10);   // 模拟此业务需要一段处理时间
        }
        catch(InterruptedException ex) {
            ex.printStackTrace();
        }
        balance = newBalance;
    }
    /**
     * 获得账户余额
     */
    public double getBalance() {
        return balance;
    }
}

存钱线程类:

package com.bjsxt;
/**
 * 存钱线程
 * @author sxt李端阳
 *
 */
public class AddMoneyThread implements Runnable {
    private Account account;    // 存入账户
    private double money;       // 存入金额

    public AddMoneyThread(Account account, double money) {
        this.account = account;
        this.money = money;
    }

    @Override
    public void run() {
        account.deposit(money);
    }
 }

测试类:

package com.bjsxt;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

 public class Test01 {
public static void main(String[] args) {
        Account account = new Account();
        ExecutorService service = Executors.newFixedThreadPool(100);
        for(int i = 1; i <= 100; i++) {
            service.execute(new AddMoneyThread(account, 1));
        }
        service.shutdown();
        while(!service.isTerminated()) {}
        System.out.println("账户余额: " + account.getBalance());
    }
}

在没有同步的情况下,执行结果通常是显示账户余额在10元以下,出现这种状况的原因是,当一个线程A试图存入1元的时候,另外一个线程B也能够进入存款的方法中,线程B读取到的账户余额仍然是线程A存入1元钱之前的账户余额,因此也是在原来的余额0上面做了加1元的操作,同理线程C也会做类似的事情,所以最后100个线程执行结束时,本来期望账户余额为100元,但实际得到的通常在10元以下。解决这个问题的办法就是同步,当一个线程对银行账户存钱时,需要将此账户锁定,待其操作完成后才允许其他的线程进行操作,代码有如下几种调整方案:

1. 在银行账户的存款(deposit)方法上同步(synchronized)关键字

package com.bjsxt;
/**
 * 银行账户
 * @author SXT李端阳
*/
public class Account {
    private double balance;     // 账户余额
    /**
     * 存款
     * @param money 存入金额
     */
    public synchronized void deposit(double money) {
        double newBalance = balance + money;
        try {
            Thread.sleep(10);   // 模拟此业务需要一段处理时间
        }
        catch(InterruptedException ex) {
            ex.printStackTrace();
        }
        balance = newBalance;
    }

    /**
     * 获得账户余额
     */
    public double getBalance() {
        return balance;
    }
}

2. 在线程调用存款方法时对银行账户进行同步

package com.bjsxt;
/**
 * 存钱线程
 * @author SXT
 *
 */
public class AddMoneyThread implements Runnable {
    private Account account;    // 存入账户
    private double money;       // 存入金额

    public AddMoneyThread(Account account, double money) {
        this.account = account;
        this.money = money;
    }
    @Override
    public void run() {
        synchronized (account) {
            account.deposit(money);
        }
    }
}

3. 通过JDK 1.5显示的锁机制,为每个银行账户创建一个锁对象,在存款操作进行加锁和解锁的操作

package com.bjsxt;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 银行账户
 *
 * @author SXT李端阳
 *
 */
public class Account {
    private Lock accountLock = new ReentrantLock();
    private double balance; // 账户余额
   /**
     * 存款
     *
     * @param money
     *            存入金额
     */
    public void deposit(double money) {
        accountLock.lock();
        try {
            double newBalance = balance + money;
            try {
                Thread.sleep(10); // 模拟此业务需要一段处理时间
            }
            catch (InterruptedException ex) {
                ex.printStackTrace();
            }
            balance = newBalance;
        }
        finally {
            accountLock.unlock();
        }
    }
    /**
     * 获得账户余额
     */
    public double getBalance() {
        return balance;
    }
}

按照上述三种方式对代码进行修改后,重写执行测试代码Test01,将看到最终的账户余额为100元。 

245.编写多线程程序有几种实现方式?

答:Java 5以前实现多线程有两种实现方法:一种是继承Thread类;另一种是实现Runnable接口。两种方式都要通过重写run()方法来定义线程的行为,推荐使用后者,因为Java中的继承是单继承,一个类有一个父类,如果继承了Thread类就无法再继承其他类了,同时也可以实现资源共享,显然使用Runnable接口更为灵活。

补充:Java 5以后创建线程还有第三种方式:实现Callable接口,该接口中的call方法可以在线程执行结束时产生一个返回值,代码如下所示:

package com.bjsxt;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

  class MyTask implements Callable<Integer> {
    private int upperBounds;

    public MyTask(int upperBounds) {
        this.upperBounds = upperBounds;
    }

    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for(int i = 1; i <= upperBounds; i++) {
            sum += i;
        }
        return sum;
    }

}

public class Test {
  public static void main(String[] args) throws Exception {
        List<Future<Integer>> list = new ArrayList<>();
        ExecutorService service = Executors.newFixedThreadPool(10);
        for(int i = 0; i < 10; i++) {
        list.add(service.submit(new MyTask((int) (Math.random() * 100))));
        }
        int sum = 0;
        for(Future<Integer> future : list) {
            while(!future.isDone()) ;
            sum += future.get();
        }
          System.out.println(sum);
    }
}
246.synchronized关键字的用法?

答:synchronized关键字可以将对象或者方法标记为同步,以实现对对象和方法的互斥访问,可以用synchronized(对象) { … }定义同步代码块,或者在声明方法时将synchronized作为方法的修饰符。在第60题的例子中已经展示了synchronized关键字的用法。 

247.启动一个线程是用run()还是start()方法?

答:启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM 调度并执行,这并不意味着线程就会立即运行。run()方法是线程启动后要进行回调(callback)的方法。 

API解释如下:

248.什么是线程池(thread pool)?

答:在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源。在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收。所以提高服务程序效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些很耗资源的对象创建和销毁,这就是"池化资源"技术产生的原因。线程池顾名思义就是事先创建若干个可执行的线程放入一个池(容器)中,需要的时候从池中获取线程不用自行创建,使用完毕不需要销毁线程而是放回池中,从而减少创建和销毁线程对象的开销。

Java 5+中的Executor接口定义一个执行线程的工具。它的子类型即线程池接口是ExecutorService。要配置一个线程池是比较复杂的,尤其是对于线程池的原理不是很清楚的情况下,因此在工具类Executors面提供了一些静态工厂方法,生成一些常用的线程池,如下所示:

newSingleThreadExecutor:创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。

newFixedThreadPool:创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。

newCachedThreadPool:创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。

newScheduledThreadPool:创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。

newSingleThreadExecutor:创建一个单线程的线程池。此线程池支持定时以及周期性执行任务的需求。

有通过Executors工具类创建线程池并使用线程池执行线程的代码。如果希望在服务器上使用线程池,强烈建议使用newFixedThreadPool方法来创建线程池,这样能获得更好的性能。 

249.线程的基本状态以及状态之间的关系?

除去起始(new)状态和结束(finished)状态,线程有三种状态,分别是:就绪(ready)、运行(running)和阻塞(blocked)。其中就绪状态代表线程具备了运行的所有条件,只等待CPU调度(万事俱备,只欠东风);处于运行状态的线程可能因为CPU调度(时间片用完了)的原因回到就绪状态,也有可能因为调用了线程的yield方法回到就绪状态,此时线程不会释放它占有的资源的锁,坐等CPU以继续执行;运行状态的线程可能因为I/O中断、线程休眠、调用了对象的wait方法而进入阻塞状态(有的地方也称之为等待状态);而进入阻塞状态的线程会因为休眠结束、调用了对象的notify方法或notifyAll方法或其他线程执行结束而进入就绪状态。注意:调用wait方法会让线程进入等待池中等待被唤醒,notify方法或notifyAll方法会让等待锁中的线程从等待池进入等锁池,在没有得到对象的锁之前,线程仍然无法获得CPU的调度和执行。

250.简述synchronized 和java.util.concurrent.locks.Lock的异同?

答:Lock是Java 5以后引入的新的API,和关键字synchronized相比主要相同点:Lock 能完成synchronized所实现的所有功能;主要不同点:Lock 有比synchronized 更精确的线程语义和更好的性能。synchronized 会自动释放锁,而Lock 一定要求程序员手工释放,并且必须在finally 块中释放(这是释放外部资源的最好的地方)。 

251.创建线程的两种方式分别是什么,优缺点是什么?

方式1:继承Java.lang.Thread类,并覆盖run() 方法。

优势:编写简单;

劣势:单继承的限制----无法继承其它父类,同时不能实现资源共享。

package com.bjsxt;

public class ThreadDemo1 {
public static void main(String args[]) {
MyThread1 t = new MyThread1();
t.start();
while (true) {
System.out.println("兔子领先了,别骄傲");
}
}
}
class MyThread1 extends Thread {
public void run() {
while (true) {
System.out.println("乌龟领先了,加油");
}
}
}

方式2:实现Java.lang.Runnable接口,并实现run()方法。

优势:可继承其它类,多线程可共享同一个Thread对象;

劣势:编程方式稍微复杂,如需访问当前线程,需调用Thread.currentThread()方法

package com.bjsxt;

public class ThreadDemo2 {
public static void main(String args[]) {
MyThread2 mt = new MyThread2();
Thread t = new Thread(mt);
t.start();
while (true) {
System.out.println("兔子领先了,加油");
}
}
}
class MyThread2 implements Runnable {
public void run() {
while (true) {
System.out.println("乌龟超过了,再接再厉");
}
}
}
252.Java创建线程后,调用start()方法和run()的区别

两种方法的区别

1) start方法:

用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run()方法,这里方法run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。

2) run():

run()方法只是类的一个普通方法而已,如果直接调用run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待,run方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。

总结:调用start方法方可启动线程,而run方法只是thread的一个普通方法调用,还是在主线程里执行。这两个方法应该都比较熟悉,把需要并行处理的代码放在run()方法中,start()方法启动线程将自动调用 run()方法,这是由jvm的内存机制规定的。并且run()方法必须是public访问权限,返回值类型为void。

两种方式的比较 :

实际中往往采用实现Runable接口,一方面因为java只支持单继承,继承了Thread类就无法再继续继承其它类,而且Runable接口只有一个run方法;另一方面通过结果可以看出实现Runable接口才是真正的多线程。

253.线程的生命周期

线程是一个动态执行的过程,它也有一个从产生到死亡的过程。

生命周期的五种状态

新建(new Thread)

当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)

例如:Thread t1=new Thread();

就绪(runnable)

线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。例如:t1.start();

运行(running)

线程获得CPU资源正在执行任务(run()方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。

死亡(dead)

当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。

自然终止:正常运行run()方法后终止

异常终止:调用stop()方法让一个线程终止运行

堵塞(blocked)

由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。

正在睡眠:用sleep(long t) 方法可使线程进入睡眠方式。一个睡眠着的线程在指定的时间过去可进入就绪状态。

正在等待:调用wait()方法。(调用motify()方法回到就绪状态)

被另一个线程所阻塞:调用suspend()方法。(调用resume()方法恢复)

254.如何实现线程同步?

当多个线程访问同一个数据时,容易出现线程安全问题,需要某种方式来确保资源在某一时刻只被一个线程使用。需要让线程同步,保证数据安全

线程同步的实现方案:

1)同步代码块,使用synchronized关键字

同步代码块:

synchronized (同步锁) {
授课代码;
}

同步方法:

public synchronized void makeWithdrawal(int amt) { }

线程同步的好处:解决了线程安全问题

线程同步的缺点:性能下降,可能会带来死锁

注意: 同步代码块,所使用的同步锁可以是三种,

1、this 2、 共享资源 3、 字节码文件对象

同步方法所使用的同步锁,默认的是this

255.说说关于同步锁的更多细节

答:Java中每个对象都有一个内置锁。

当程序运行到非静态的synchronized同步方法上时,自动获得与正在执行代码类的当前实例(this实例)有关的锁。获得一个对象的锁也称为获取锁、锁定对象、在对象上锁定或在对象上同步。

当程序运行到synchronized同步方法或代码块时才该对象锁才起作用。

一个对象只有一个锁。所以,如果一个线程获得该锁,就没有其他线程可以获得锁,直到第一个线程释放(或返回)锁。这也意味着任何其他线程都不能进入该对象上的synchronized方法或代码块,直到该锁被释放。

释放锁是指持锁线程退出了synchronized同步方法或代码块。

关于锁和同步,有一下几个要点:

1)只能同步方法,而不能同步变量和类;

2)每个对象只有一个锁;当提到同步时,应该清楚在什么上同步?也就是说,在哪个对象上同步?

3)不必同步类中所有的方法,类可以同时拥有同步和非同步方法。

4)如果两个线程要执行一个类中的synchronized方法,并且两个线程使用相同的实例来调用方法,那么一次只能有一个线程能够执行方法,另一个需要等待,直到锁被释放。也就是说:如果一个线程在对象上获得一个锁,就没有任何其他线程可以进入(该对象的)类中的任何一个同步方法。

5)如果线程拥有同步和非同步方法,则非同步方法可以被多个线程自由访问而不受锁的限制。

6)线程睡眠时,它所持的任何锁都不会释放。

7)线程可以获得多个锁。比如,在一个对象的同步方法里面调用另外一个对象的同步方法,则获取了两个对象的同步锁。

8)同步损害并发性,应该尽可能缩小同步范围。同步不但可以同步整个方法,还可以同步方法中一部分代码块。

9)在使用同步代码块时候,应该指定在哪个对象上同步,也就是说要获取哪个对象的锁。

256.Java中实现线程通信的三个方法的作用是什么?

Java提供了3个方法解决线程之间的通信问题,均是java.lang.Object类的方法,都只能在同步方法或者同步代码块中使用,否则会抛出异常。

方法名 作 用
final void wait() 表示线程一直等待,直到其它线程通知
void wait(long timeout) 线程等待指定毫秒参数的时间
final void wait(long timeout,int nanos) 线程等待指定毫秒、微妙的时间
final void notify() 唤醒一个处于等待状态的线程。注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。
final void notifyAll() 唤醒同一个对象上所有调用wait()方法的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争
IO流:
257.下面哪个流类属于面向字符的输入流()选择一项)
A. BufferedWriter
B. FileInputStream
C. ObjectInputStream
D. InputStreamReader
答案:D
分析:A:字符输出的缓冲流
B:字节输入流
C:对象输入流

258.要从文件”file.dat”文件中读出第10个字节到变量c中,下列哪个正确()(选择一项)
A.
FileInputStream in=new FileInputStream("file.dat");
in.skip(9);
int c=in.read();
B.
FileInputStream in=new FileInputStream("file.dat");
in.skip(10);
int c=in.read();
C.
FileInputStream in=new FileInputStream("file.dat");
int c=in.read();
D.
RandomAccessFile in=new RandomAccessFile("file.dat");
in.skip(7);
int c=in.readByte();
答案:A
分析: skip(long n)该方法中的n指的是要跳过的字节数
259.新建一个流对象,下面那个选项的代码是错误的?()
A. new BufferedWriter(new FileWriter(“a.txt”));
B. new BufferedReader (new FileInputStream(“a.dat”));
C. new GZIPOutputStream(new FileOutputStream(“a.zip”));
D. new ObjectInputStream(new FileInputStream(“a.dat”));
答案:B
分析:BufferedReader类的参数只能是Reader类型的,不能是InputStream类型。
260.下面哪个流是面向字符的输入流()
A. BufferedWriter
B. FileInputStream
C. ObjectInputStream
D. InputStreamReader
答案:D
以InputStream(输入流)/OutputStream(输出流)为后缀的是字节流;
以Reader(输入流)/Writer(输出流)为后缀的是字符流。
261.Java类库中,将信息写入内存的类是()
A. Java.io.FileOutputStream
B. java.ByteArrayOutputStream
C. java.io.BufferedOutputStream
D. java,.io.DataOutputStream
答案:B
分析: ACD都是io到文件
262.请写出一段代码,能够完成将字符串写入文件
public class test {
public static void main(String[] args) {
String str = "bjsxt";
writeFile(str);
}

public static void writeFile(String str) {
File file = new File("c:/test.txt");
PrintStream ps = null;
try {
OutputStream fos = new FileOutputStream(file);
ps = new PrintStream(fos);
ps.print(str);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
ps.close();
}
}
}
263.下面哪个流类属于面向字符的输入流()
A. BufferedWriter
B. FileInputStream
C. ObjectInputStream
D. InputStreamReader
答案:D
264.Java中如何实现序列化,有什么意义?

答:序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决对象流读写操作时可能引发的问题(如果不进行序列化可能会存在数据乱序的问题)。

要实现序列化,需要让一个类实现Serializable接口,该接口是一个标识性接口,标注该类对象是可被序列化的,然后使用一个输出流来构造一个对象输出流并通过writeObject(Object obj)方法就可以将实现对象写出(即保存其状态);如果需要反序列化则可以用一个输入流建立对象输入流,然后通过readObject方法从流中读取对象。序列化除了能够实现对象的持久化之外,还能够用于对象的深度克隆(参见Java面试题集1-29题) 

265.Java 中有几种类型的流?

答:两种流分别是字节流,字符流。

字节流继承于InputStream、OutputStream,字符流继承于Reader、Writer。在java.io 包中还有许多其他的流,主要是为了提高性能和使用方便。

补充:关于Java的IO需要注意的有两点:一是两种对称性(输入和输出的对称性,字节和字符的对称性);二是两种设计模式(适配器模式和装潢模式)。另外Java中的流不同于C#的是它只有一个维度一个方向。

补充:下面用IO和NIO两种方式实现文件拷贝,这个题目在面试的时候是经常被问到的。

package com.bjsxt;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class MyUtil {
  private MyUtil() {
        throw new AssertionError();
    }

    public static void fileCopy(String source, String target) throws IOException {
        try (InputStream in = new FileInputStream(source)) {
            try (OutputStream out = new FileOutputStream(target)) {
                byte[] buffer = new byte[4096];
                int bytesToRead;
                while((bytesToRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, bytesToRead);
                }
            }
        }
    }

    public static void fileCopyNIO(String source, String target) throws IOException {
        try (FileInputStream in = new FileInputStream(source)) {
            try (FileOutputStream out = new FileOutputStream(target)) {
                FileChannel inChannel = in.getChannel();
                FileChannel outChannel = out.getChannel();
                ByteBuffer buffer = ByteBuffer.allocate(4096);
                while(inChannel.read(buffer) != -1) {
                    buffer.flip();
                    outChannel.write(buffer);
                    buffer.clear();
                 }
            }
        }
    }
}

注意:上面用到Java 7的TWR,使用TWR后可以不用在finally中释放外部资源 ,从而让代码更加优雅。

266.写一个方法,输入一个文件名和一个字符串,统计这个字符串在这个文件中出现的次数。

答:代码如下:

package com.bjsxt;
import java.io.BufferedReader;
import java.io.FileReader;

public class Account {
    // 工具类中的方法都是静态方式访问的因此将构造器私有不允许创建对象(绝对好习惯)
    private Account() {
        throw new AssertionError();
    }
    /**
     * 统计给定文件中给定字符串的出现次数
     * @param filename  文件名
     * @param word 字符串
     * @return 字符串在文件中出现的次数
     */
    public static int countWordInFile(String filename, String word) {
        int counter = 0;
        try (FileReader fr = new FileReader(filename)) {
            try (BufferedReader br = new BufferedReader(fr)) {
                String line = null;
                while ((line = br.readLine()) != null) {
                    int index = -1;
                    while (line.length() >= word.length() && (index = line.indexOf(word)) >= 0) {
                        counter++;
                        line = line.substring(index + word.length());
                    }
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return counter;
    }
}
267.输入流和输出流联系和区别,节点流和处理流联系和区别

首先,你要明白什么是“流”。直观地讲,流就像管道一样,在程序和文件之间,输入输出的方向是针对程序而言,向程序中读入东西,就是输入流,从程序中向外读东西,就是输出流。

输入流是得到数据,输出流是输出数据,而节点流,处理流是流的另一种划分,按照功能不同进行的划分。节点流,可以从或向一个特定的地方(节点)读写数据。处理流是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader。处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。

268.字符流字节流联系区别;什么时候使用字节流和字符流?

字符流和字节流是流的一种划分,按处理照流的数据单位进行的划分。两类都分为输入和输出操作。在字节流中输出数据主要是使用OutputStream完成,输入使的是InputStream,在字符流中输出主要是使用Writer类完成,输入流主要使用Reader类完成。这四个都是抽象类。

字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组或字符串,而字节流处理单元为1个字节,操作字节和字节数组。字节流是最基本的,所有的InputStrem和OutputStream的子类都是,主要用在处理二进制数据,它是按字节来处理的 但实际中很多的数据是文本,又提出了字符流的概念,它是按虚拟机的编码来处理,也就是要进行字符集的转化 这两个之间通过 InputStreamReader,OutputStreamWriter来关联,实际上是通过byte[]和String来关联的。

269.列举常用字节输入流和输出流并说明其特点,至少5对。

FileInputStream 从文件系统中的某个文件中获得输入字节。

FileOutputStream 从程序当中的数据,写入到指定文件。

ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。 ObjectOutputStream 和ObjectInputStream 分别与FileOutputStream 和 FileInputStream 一起使用时,可以为应用程序提供对对象图形的持久存储。ObjectInputStream 用于恢复那些以前序列化的对象。其他用途包括使用套接字流在主机之间传递对象,或者用于编组和解组远程通信系统中的实参和形参。

ByteArrayInputStream 包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪 read 方法要提供的下一个字节。

FilterInputStream 包含其他一些输入流,它将这些流用作其基本数据源,它可以直接传输数据或提供一些额外的功能。FilterInputStream 类本身只是简单地重写那些将所有请求传递给所包含输入流的 InputStream 的所有方法。FilterInputStream 的子类可进一步重写这些方法中的一些方法,并且还可以提供一些额外的方法和字段。

StringBufferInputStream此类允许应用程序创建输入流,在该流中读取的字节由字符串内容提供。应用程序还可以使用ByteArrayInputStream 从 byte 数组中读取字节。 只有字符串中每个字符的低八位可以由此类使用。

ByteArrayOutputStream此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() 和 toString() 获取数据。

FileOutputStream文件输出流是用于将数据写入 File 或FileDescriptor 的输出流。文件是否可用或能否可以被创建取决于基础平台。特别是某些平台一次只允许一个 FileOutputStream(或其他文件写入对象)打开文件进行写入。在这种情况下,如果所涉及的文件已经打开,则此类中的构造方法将失败。

FilterOutputStream类是过滤输出流的所有类的超类。这些流位于已存在的输出流(基础 输出流)之上,它们将已存在的输出流作为其基本数据接收器,但可能直接传输数据或提供一些额外的功能。 FilterOutputStream 类本身只是简单地重写那些将所有请求传递给所包含输出流的 OutputStream 的所有方法。FilterOutputStream 的子类可进一步地重写这些方法中的一些方法,并且还可以提供一些额外的方法和字段。

ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。

PipedOutputStream可以将管道输出流连接到管道输入流来创建通信管道。管道输出流是管道的发送端。通常,数据由某个线程写入 PipedOutputStream 对象,并由其他线程从连接的 PipedInputStream 读取。不建议对这两个对象尝试使用单个线程,因为这样可能会造成该线程死锁。如果某个线程正从连接的管道输入流中读取数据字节,但该线程不再处于活动状态,则该管道被视为处于毁坏状态。

270.说明缓冲流的优点和原理

不带缓冲的流的工作原理:

它读取到一个字节/字符,就向用户指定的路径写出去,读一个写一个,所以就慢了。

带缓冲的流的工作原理:

读取到一个字节/字符,先不输出,等凑足了缓冲的最大容量后一次性写出去,从而提高了工作效率

优点:减少对硬盘的读取次数,降低对硬盘的损耗。

271.序列化的定义、实现和注意事项

想把一个对象写在硬盘上或者网络上,对其进行序列化,把他序列化成为一个字节流。

实现和注意事项:

1)实现接口Serializable Serializable接口中没有任何的方法,实现该接口的类不需要实现额外的方法。

2)如果对象中的某个属性是对象类型,必须也实现Serializable接口才可以,序列化对静态变量无效

3)如果不希望某个属性参与序列化,不是将其static,而是transient串行化保存的只是变量的值,对于变量的任何修饰符,都不能保存序列化版本不兼容

272.使用IO流完成文件夹复制

(结合递归)

package com.bjsxt;

import java.io.*;
/**
 * CopyDocJob定义了实际执行的任务,即
 * 从源目录拷贝文件到目标目录
*/
public class CopyDir2 {
public static void main(String[] args) {
try {
copyDirectiory("d:/301sxt","d:/301sxt2");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
 * 复制单个文件
 * @param sourceFile 源文件
 * @param targetFile 目标文件
 * @throws IOException
 */
    private static void copyFile(File sourceFile, File targetFile) throws IOException {
        BufferedInputStream inBuff = null;
        BufferedOutputStream outBuff = null;
        try {
            // 新建文件输入流
            inBuff = new BufferedInputStream(new FileInputStream(sourceFile));
            // 新建文件输出流
            outBuff = new BufferedOutputStream(new FileOutputStream(targetFile));
            // 缓冲数组
            byte[] b = new byte[1024 * 5];
            int len;
            while ((len = inBuff.read(b)) != -1) {
                outBuff.write(b, 0, len);
            }
            // 刷新此缓冲的输出流
            outBuff.flush();
        } finally {
            // 关闭流
            if (inBuff != null)
                inBuff.close();
            if (outBuff != null)
                outBuff.close();
        }
    }

    /**
     * 复制目录
     * @param sourceDir 源目录
     * @param targetDir 目标目录
     * @throws IOException
     */
    private static void copyDirectiory(String sourceDir, String targetDir) throws IOException {
        // 检查源目录
     File fSourceDir = new File(sourceDir);
     if(!fSourceDir.exists() || !fSourceDir.isDirectory()){
      return;
     }
     //检查目标目录,如不存在则创建
     File fTargetDir = new File(targetDir);
     if(!fTargetDir.exists()){
      fTargetDir.mkdirs();
     }
        // 遍历源目录下的文件或目录
        File[] file = fSourceDir.listFiles();
        for (int i = 0; i < file.length; i++) {
            if (file[i].isFile()) {
                // 源文件
                File sourceFile = file[i];
                // 目标文件
                File targetFile = new File(fTargetDir, file[i].getName());
                copyFile(sourceFile, targetFile);
            }
            //递归复制子目录
            if (file[i].isDirectory()) {
                // 准备复制的源文件夹
                String subSourceDir = sourceDir + File.separator + file[i].getName();
                // 准备复制的目标文件夹
                String subTargetDir = targetDir + File.separator + file[i].getName();
                // 复制子目录
                copyDirectiory(subSourceDir, subTargetDir);
            }
        }
    }
}
273.说说BIO、NIO和AIO的区别

Java BIO: 同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。

Java NIO: 同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。

Java AIO: 异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。

NIO比BIO的改善之处是把一些无效的连接挡在了启动线程之前,减少了这部分资源的浪费(因为我们都知道每创建一个线程,就要为这个线程分配一定的内存空间)

AIO比NIO的进一步改善之处是将一些暂时可能无效的请求挡在了启动线程之前,比如在NIO的处理方式中,当一个请求来的话,开启线程进行处理,但这个请求所需要的资源还没有就绪,此时必须等待后端的应用资源,这时线程就被阻塞了。

适用场景分析:

BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解,如之前在Apache中使用。

NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持,如在 Nginx,Netty中使用。

AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持,在成长中,Netty曾经使用过,后来放弃。

网络编程:

274.IP地址和端口号

1)IP地址

用来标志网络中的一个通信实体的地址。通信实体可以是计算机,路由器等。

2)IP地址分类

IPV4:32位地址,以点分十进制表示,如192.168.0.1

IPV6:128位(16个字节)写成8个16位的无符号整数,每个整数用四个十六进制位表示,数之间用冒号(:)分开,如:3ffe:3201:1401:1280:c8ff:fe4d:db39:1984

3)特殊的IP地址

127.0.0.1 本机地址

192.168.0.0--192.168.255.255私有地址,属于非注册地址,专门为组织机构内部使用。

4)端口:port

IP地址用来标志一台计算机,但是一台计算机上可能提供多种应用程序,使用端口来区分这些应用程序。 端口是虚拟的概念,并不是说在主机上真的有若干个端口。通过端口,可以在一个主机上运行多个网络应用程序。 端口范围0---65535,16位整数

5)端口分类

公认端口 0—1023 比如80端口分配给WWW,21端口分配给FTP,22端口分配给SSH,23端口分配给telnet,25端口分配给smtp

注册端口 1024—49151 分配给用户进程或应用程序

动态/私有端口 49152--65535

6)理解IP和端口的关系

IP地址好比每个人的地址(门牌号),端口好比是房间号。必须同时指定IP地址和端口号才能够正确的发送数据

IP地址好比为电话号码,而端口号就好比为分机号。

275.介绍OSI七层模型和TCP/IP模型

OSI(Open System Interconnection),开放式系统互联参考模型 。是一个逻辑上的定义,一个规范,它把网络协议从逻辑上分为了7层。每一层都有相关、相对应的物理设备,比如常规的路由器是三层交换设备,常规的交换机是二层交换设备。OSI七层模型是一种框架性的设计方法,建立七层模型的主要目的是为解决异种网络互连时所遇到的兼容性问题,其最主要的功能就是帮助不同类型的主机实现数据传输。它的最大优点是将服务、接口和协议这三个概念明确地区分开来,通过七个层次化的结构模型使不同的系统不同的网络之间实现可靠的通讯。

TCP/IP协议是Internet最基本的协议、Internet国际互联网络的基础,主要由网络层的IP协议和传输层的TCP协议组成。TCP/IP 定义了电子设备如何连入因特网,以及数据如何在它们之间传输的标准。协议采用了4层的层级结构,每一层都呼叫它的下一层所提供的协议来完成自己的需求。

ISO制定的OSI参考模型的过于庞大、复杂招致了许多批评。伴随着互联网的流行,其本身所采用的TCP/IP协议栈获得了更为广泛的应用和认可。在TCP/IP参考模型中,去掉了OSI参考模型中的会话层和表示层(这两层的功能被合并到应用层实现)。同时将OSI参考模型中的数据链路层和物理层合并为主机到网络层。

276.TCP协议和UDP协议的比较

TCP和UDP是TCP/IP协议栈中传输层的两个协议,它们使用IP路由功能把数据包发送到目的地,从而为应用程序及应用层协议(包括:HTTP、SMTP、SNMP、FTP和Telnet)提供网络服务。

TCP的server和client之间通信就好比两个人打电话,需要互相知道对方的电话号码,然后开始对话。所以在两者的连接过程中间需要指定端口和地址。

UDP的server和client之间的通信就像两个人互相发信。我只需要知道对方的地址,然后就发信过去。对方是否收到我不知道,也不需要专门对口令似的来建立连接。具体区别如下:

1)TCP是面向连接的传输。UDP是无连接的传输

2)TCP有流量控制、拥塞控制,检验数据数据按序到达,而UDP则相反。

3)TCP的路由选择只发生在建立连接的时候,而UDP的每个报文都要进行路由选择

4)TCP是可靠性传输,他的可靠性是由超时重发机制实现的,而UDP则是不可靠传输

5)UDP因为少了很多控制信息,所以传输速度比TCP速度快

6)TCP适合用于传输大量数据,UDP适合用于传输小量数据

277.什么是Socket编程

Socket编程的定义如下:

所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过"套接字"向网络发出请求或者应答网络请求。

我们开发的网络应用程序位于应用层,TCP和UDP属于传输层协议,在应用层如何使用传输层的服务呢?在应用层和传输层之间,则是使用套接字来进行分离。

套接字就像是传输层为应用层开的一个小口,应用程序通过这个小口向远程发送数据,或者接收远程发来的数据;而这个小口以内,也就是数据进入这个口之后,或者数据从这个口出来之前,是不知道也不需要知道的,也不会关心它如何传输,这属于网络其它层次的工作。

Socket实际是传输层供给应用层的编程接口。传输层则在网络层的基础上提供进程到进程问的逻辑通道,而应用层的进程则利用传输层向另一台主机的某一进程通信。Socket就是应用层与传输层之间的桥梁

使用Socket编程可以开发客户机和服务器应用程序,可以在本地网络上进行通信,也可通过Internet在全球范围内通信。

生活案例1如果你想写封邮件发给远方的朋友,如何写信、将信打包,属于应用层。信怎么写,怎么打包完全由我们做主;而当我们将信投入邮筒时,邮筒的那个口就是套接字,在进入套接字之后,就是传输层、网络层等(邮局、公路交管或者航线等)其它层次的工作了。我们从来不会去关心信是如何从西安发往北京的,我们只知道写好了投入邮筒就OK了。

生活案例2:可以把Socket比作是一个港口码头,应用程序只要将数据交给Socket,就算完成了数据的发送,具体细节由Socket来完成,细节不必了解。同理,对于接收方,应用程序也要创建一个码头,等待数据的到达,并获取数据。

278.简述基于TCP和UDP的Socket编程的主要步骤

Java分别为TCP和UDP 两种通信协议提供了相应的Socket编程类,这些类存放在java.net包中。与TCP对应的是服务器的ServerSocket和客户端的Socket,与UDP对应的是DatagramSocket。

基于TCP创建的套接字可以叫做流套接字,服务器端相当于一个监听器,用来监听端口。 服务器与客服端之间的通讯都是输入输出流来实现的。基于UDP的套接字就是数据报套接字,•  两个都要先构造好相应的数据包。

基于TCP协议的Socket编程的主要步骤

服务器端(server):

1. 构建一个ServerSocket实例,指定本地的端口。这个socket就是用来监听指定端口的连接请求的。

2. 重复如下几个步骤:

a. 调用socket的accept()方法来获得下面客户端的连接请求。通过accept()方法返回的socket实例,建立了一个和客户端的新连接。

b. 通过这个返回的socket实例获取InputStream和OutputStream,可以通过这两个stream来分别读和写数据。

c. 结束的时候调用socket实例的close()方法关闭socket连接。

客户端(client):

1.构建Socket实例,通过指定的远程服务器地址和端口来建立连接。

2.通过Socket实例包含的InputStream和OutputStream来进行数据的读写。

3.操作结束后调用socket实例的close方法,关闭。

UDP

服务器端(server):

1. 构造DatagramSocket实例,指定本地端口。

2. 通过DatagramSocket实例的receive方法接收DatagramPacket.DatagramPacket中间就包含了通信的内容。

3. 通过DatagramSocket的send和receive方法来收和发DatagramPacket.

客户端(client):

1. 构造DatagramSocket实例。

2. 通过DatagramSocket实例的send和receive方法发送DatagramPacket报文。

3. 结束后,调用DatagramSocket的close方法关闭。

异常处理:

279.下列哪种异常是检查型异常,需要在编写程序时声明()
A. NullPointerException
B. ClassCastException
C. FileNotFoundException
D. IndexOutOfBoundsException
答案:C
分析:NullPointerException空指针异常
ClassCastException类型转换异常
IndexOutOfBoundsException索引超出边界的异常
以上这些异常都是程序在运行时发生的异常,所以不需要在编写程序时声明
280.Java出现OutOf MemoryError(OOM 错误)的原因有哪些?出现OOM错误后,怎么解决?

答:OutOf MemoryError这种错误可以细分为多种不同的错误,每种错误都有自身的原因和解决办法,如下所示:

java.lang.OutOfMemoryError: Java heap space

错误原因:此OOM是由于JVM中heap的最大值不满足需要。

解决方法:1) 调高heap的最大值,即-Xmx的值调大。2) 如果你的程序存在内存泄漏,一味的增加heap空间也只是推迟该错误出现的时间而已,所以要检查程序是否存在内存泄漏。

java.lang.OutOfMemoryError: GC overhead limit exceeded

错误原因:此OOM是由于JVM在GC时,对象过多,导致内存溢出,建议调整GC的策略,在一定比例下开始GC而不要使用默认的策略,或者将新代和老代设置合适的大小,需要进行微调存活率。

解决方法:改变GC策略,在老代80%时就是开始GC,并且将-XX:SurvivorRatio(-XX:SurvivorRatio=8)和-XX:NewRatio(-XX:NewRatio=4)设置的更合理。

java.lang.OutOfMemoryError: Java perm space

错误原因:此OOM是由于JVM中perm的最大值不满足需要。

解决方法:调高heap的最大值,即-XX:MaxPermSize的值调大。

另外,注意一点,Perm一般是在JVM启动时加载类进来,如果是JVM运行较长一段时间而不是刚启动后溢出的话,很有可能是由于运行时有类被动态加载进来,此时建议用CMS策略中的类卸载配置。如:-XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled。

java.lang.OutOfMemoryError: unable to create new native thread

错误原因:当JVM向OS请求创建一个新线程时,而OS却由于内存不足无法创建新的native线程。

解决方法:如果JVM内存调的过大或者可利用率小于20%,可以建议将heap及perm的最大值下调,并将线程栈调小,即-Xss调小,如:-Xss128k。

java.lang.OutOfMemoryError: Requested array size exceeds VM limit

错误原因:此类信息表明应用程序(或者被应用程序调用的APIs)试图分配一个大于堆大小的数组。例如,如果应用程序new一个数组对象,大小为512M,但是最大堆大小为256M,因此OutOfMemoryError会抛出,因为数组的大小超过虚拟机的限制。

解决方法:1) 首先检查heap的-Xmx是不是设置的过小。2) 如果heap的-Xmx已经足够大,那么请检查应用程序是不是存在bug,例如:应用程序可能在计算数组的大小时,存在算法错误,导致数组的size很大,从而导致巨大的数组被分配。

java.lang.OutOfMemoryError: request < size> bytes for < reason>. Out of swap space

错误原因:抛出这类错误,是由于从native堆中分配内存失败,并且堆内存可能接近耗尽。这类错误可能跟应用程序没有关系,例如下面两种原因也会导致错误的发生:1) 操作系统配置了较小的交换区。2)系统的另外一个进程正在消耗所有的内存。

解决办法:1) 检查os的swap是不是没有设置或者设置的过小。2) 检查是否有其他进程在消耗大量的内存,从而导致当前的JVM内存不够分配。

注意:虽然有时< reason>部分显示导致OOM的原因,但大多数情况下,< reason>显示的是提示分配失败的源模块的名称,所以有必要查看日志文件,如crash时的hs文件。

281.列举常见的运行时异常

答:ClassCastException(类转换异常)

比如 Object obj=new Object(); String s=(String)obj; 

IndexOutOfBoundsException(下标越界异常)

NullPointerException(空指针异常)

ArrayStoreException(数据存储异常,操作数组时类型不一致)

BufferOverflowException(IO操作时出现的缓冲区上溢异常)

InputMismatchException(输入类型不匹配异常)

ArithmeticException(算术异常)

注意:运行时异常都是RuntimeException子类异常。

282.下面关于 Java.lang.Exception类的说法正确的是()
A. 继承自 Throwable
B. 不支持Serializable
C. 继承自 AbstractSet
D. 继承自FitelnputStream
答案:A
分析:Throwable是Exception和Error的父类,Exception虽然没有实现Serializable接口,但是其父类Throwable已经实现了该接口,因此Exception也支持Serializable。
283.Unsupported major.minor version 52是什么异常,怎么造成的,如何解决?

答:问题的根本原因是工程中某个jar包的版本(jar包编译时的所用的jdk版本)高于工程build path中jdk的版本,这个是不兼容的! 编程中遇到此异常Unsupported major.minor version 52.0(根据版本号,这里可以为其他数值,52是1.8jdk jar包与 1.8以下低版本jdk不匹配),在将build path中jdk的版本调整与jar包匹配后,解决异常。

284.try{}里有一个return语句,那么紧跟在这个try后的finally{}里的code会不会被执行,什么时候被执行,在return前还是后?

答:会执行,在方法返回调用者前执行。Java允许在finally中改变返回值的做法是不好的,因为如果存在finally代码块,try中的return语句不会立马返回调用者,而是记录下返回值待finally代码块执行完毕之后再向调用者返回其值,然后如果在finally中修改了返回值,这会对程序造成很大的困扰,C#中就从语法上规定不能做这样的事。 

(也许你的答案是在return之前,但往更细地说,我的答案是在return中间执行,请看下面程序代码的运行结果:

public classTest {

    /**
     * @paramargs add by zxx ,Dec 9, 2008
     */
    public static voidmain(String[] args) {
       // TODO Auto-generated method stub
       System.out.println(newTest().test());;
    }

    static int test()
    {
       int x = 1;
       try
       {
           returnx;
       }
       finally
       {
           ++x;
       }
    }

}

执行结果

运行结果是1,为什么呢?主函数调用子函数并得到结果的过程,好比主函数准备一个空罐子,当子函数要返回结果时,先把结果放在罐子里,然后再将程序逻辑返回到主函数。所谓返回,就是子函数说,我不运行了,你主函数继续运行吧,这没什么结果可言,结果是在说这话之前放进罐子里的。

285.Java 语言如何进行异常处理,关键字:throws、throw、try、catch、finally分别如何使用?

答:Java 通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了良好的接口。在Java 中,每个异常都是一个对象,它是Throwable 类或其子类的实例。当一个方法出现异常后便抛出一个异常对象,该对象中包含有异常信息,调用这个对象的方法可以捕获到这个异常并进行处理。Java 的异常处理是通过5 个关键词来实现的:try、catch、throw、throws和finally。一般情况下是用try来执行一段程序,如果出现异常,系统会抛出(throw)一个异常,这时候你可以通过它的类型来捕捉(catch)它,或最后(finally)由缺省处理器来处理;try用来指定一块预防所有“异常”的程序;catch 子句紧跟在try块后面,用来指定你想要捕捉的“异常”的类型;throw 语句用来明确地抛出一个“异常”;throws用来标明一个成员函数可能抛出的各种“异常”;finally 为确保一段代码不管发生什么“异常”都被执行一段代码;可以在一个成员函数调用的外面写一个try语句,在这个成员函数内部写另一个try语句保护其他代码。每当遇到一个try 语句,“异常”的框架就放到栈上面,直到所有的try语句都完成。如果下一级的try语句没有对某种“异常”进行处理,栈就会展开,直到遇到有处理这种“异常”的try 语句。 

286.运行时异常与受检异常有何异同?

答:异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误,只要程序设计得没有问题通常就不会发生。受检异常跟程序运行的上下文环境有关,即使程序设计无误,仍然可能因使用的问题而引发。Java编译器要求方法必须声明抛出可能发生的受检异常,但是并不要求必须声明抛出未被捕获的运行时异常。异常和继承一样,是面向对象程序设计中经常被滥用的东西,神作《Effective Java》中对异常的使用给出了以下指导原则:

不要将异常处理用于正常的控制流(设计良好的API不应该强迫它的调用者为了正常的控制流而使用异常)

对可以恢复的情况使用受检异常,对编程错误使用运行时异常

避免不必要的使用受检异常(可以通过一些状态检测手段来避免异常发生)

优先使用标准的异常

每个方法抛出的异常都要有文档

保持异常的原子性

不要在catch中忽略掉捕获到的异常 

(异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。)

287.类ExampleA 继承Exception,类ExampleB 继承ExampleA

有如下代码片断:

try{
throw new ExampleB("b")
}catch(ExampleA e){
System.out.println("ExampleA");
}catch(Exception e){
System.out.println("Exception");
}
 }

请问执行此段代码的输出是什么?

答:输出:ExampleA。(根据里氏代换原则[能使用父类型的地方一定能使用子类型],抓取ExampleA类型异常的catch块能够抓住try块中抛出的ExampleB类型的异常)

补充: 比此题略复杂的一道面试题如下所示(此题的出处是《Java编程思想》),说出你的答案吧!

package com.bjsxt;
class Annoyance extends Exception {}
class Sneeze extends Annoyance {}
 class Human {
  public static void main(String[] args)
        throws Exception {
        try {
            try {
                throw new Sneeze();
            }
            catch ( Annoyance a ) {
                System.out.println("Caught Annoyance");
                throw a;
            }
        }
        catch ( Sneeze s ) {
            System.out.println("Caught Sneeze");
            return ;
        }
        finally {
            System.out.println("Hello World!");
        }
    }
}

输出为:

Caught Annoyance

Caught Sneeze

Hello World!

288.Error和Exception的区别

Error类,表示仅靠程序本身无法恢复的严重错误,比如说内存溢出、动态链接异常、虚拟机错误。应用程序不应该抛出这种类型的对象。假如出现这种错误,除了尽力使程序安全退出外,在其他方面是无能为力的。所以在进行程序设计时,应该更关注Exception类。

Exception类,由Java应用程序抛出和处理的非严重错误,比如所需文件没有找到、零作除数,数组下标越界等。它的各种不同子类分别对应不同类型异常。可分为两类:Checked异常和Runtime异常

289.Java异常处理try-catch-finally的执行过程

try-catch-finally程序块的执行流程以及执行结果比较复杂。

基本执行过程如下:

1)程序首先执行可能发生异常的try语句块。

2)如果try语句没有出现异常则执行完后跳至finally语句块执行;

3)如果try语句出现异常,则中断执行并根据发生的异常类型跳至相应的catch语句块执行处理。

4)catch语句块可以有多个,分别捕获不同类型的异常。

5)catch语句块执行完后程序会继续执行finally语句块。

finally语句是可选的,如果有的话,则不管是否发生异常,finally语句都会被执行。需要注意的是即使try和catch块中存在return语句,finally语句也会执行,是在执行完finally语句后再通过return退出。

290.异常处理中throws和throw的区别

1)作用不同:

throw用于程序员自行产生并抛出异常;

throws用于声明在该方法内抛出了异常

2) 使用的位置不同:

throw位于方法体内部,可以作为单独语句使用;

throws必须跟在方法参数列表的后面,不能单独使用。

3)内容不同:

throw抛出一个异常对象,且只能是一个;

throws后面跟异常类,而且可以有多个。

Web方面相关:
291.WEB应用中如果有.class和.jar类型的文件一般分别应该放在什么位置?

答:.class文件放在WEB-INF/classes文件下,.jar文件放在WEB-INF/lib文件夹下

292.元素中有一个输入框(< input type='text' name=”username”id=”username”value=””/>,请用JavaScript语言写一行代码,取得这个输入框中的值。

答:document.getElementById(“username”).value;

293.简单描述一下Servlet与JSP的的相同点和区别点。

区别:

JSP是在HTML代码里写JAVA代码,框架是HTML;而Servlet是在JAVA代码中写HTML代码,本身是个JAVA类。

JSP使人们把显示和逻辑分隔成为可能,这意味着两者的开发可并行进行;而Servlet并没有把两者分开。

Servlet独立地处理静态表示逻辑与动态业务逻辑.这样,任何文件的变动都需要对此服务程序重新编译;JSP允许用特殊标签直接嵌入到HTML页面, HTML内容与JAVA内容也可放在单独文件中,HTML内容的任何变动会自动编译装入到服务程序.

Servlet需要在web.xml中配置,而JSP无需配置。

目前JSP主要用在视图层,负责显示,而Servlet主要用在控制层,负责调度

联系:

都是Sun公司推出的动态网页技术。

先有Servlet,针对Servlet缺点推出JSP。JSP是Servlet的一种特殊形式,每个JSP页面就是一个Servlet实例——JSP页面由系统翻译成Servlet,Servlet再负责响应用户请求。

294.请简单描述下几个您熟悉JavaScript库,它们有哪些作用和特点?

JavaScript 高级程序设计(特别是对浏览器差异的复杂处理),通常很困难也很耗时。为了应对这些调整,许多的 JavaScript库应运而生。这些 JavaScript 库常被称为 JavaScript 框架。

jQuery:

Ext JS - 可定制的 widget,用于构建富因特网应用程序(rich Internet applications)。

Prototype

MooTools。

YUI - Yahoo! User Interface Framework,涵盖大量函数的大型库,从简单的 JavaScript 功能到完整的 internet widget。

295.简单描述HTML,CSS,Javascript在Web开发中分别起什么作用?

1、什么是HTML(超文本标记语言 Hyper Text Markup Language),HTML 是用来描述网页的一种语言。

2、CSS(层叠样式表 Cascading Style Sheets),样式定义如何显示 HTML 元素,语法为:selector {property:value} (选择符 {属性:值})

3、JavaScript是一种脚本语言,其源代码在发往客户端运行之前不需经过编译,而是将文本格式的字符代码发送给浏览器由浏览器解释运行

对于一个网页,HTML定义网页的结构,CSS描述网页的样子,JavaScript设置一个很经典的例子是说HTML就像 一个人的骨骼、器官,而CSS就是人的皮肤,有了这两样也就构成了一个植物人了,加上javascript这个植物人就可以对外界刺激做出反应,可以思 考、运动、可以给自己整容化妆(改变CSS)等等,成为一个活生生的人。

如果说HTML是肉身、CSS就是皮相、Javascript就是灵魂。没有Javascript,HTML+CSS是植物人,没有Javascript、CSS是个毁容的植物人。

如果说HTML是建筑师,CSS就是干装修的,Javascript是魔术师。

296.当DOM加载完成后要执行的函数,下面哪个是正确的()
A. JQuery(expression, [context])
B. JQuery(html, [ownerDocument])
C. JQuery(callback)
答案:C
297.举例说明JAVA中如何解析xml,不同方式有和优缺点?

答:1. DOM(Document Object Model)

DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准。DOM是以层次结构组织的节点或信息片断的集合。这个层次结构允许开发人员在树中寻找特定信息。分析该结构通常需要加载整个文档和构造层次结构,然后才能做任何工作。由于它是基于信息层次的,因而DOM被认为是基于树或基于对象的。

【优点】

①允许应用程序对数据和结构做出更改。

②访问是双向的,可以在任何时候在树中上下导航,获取和操作任意部分的数据。

【缺点】

①通常需要加载整个XML文档来构造层次结构,消耗资源大。

2. SAX(Simple API for XML)

SAX处理的优点非常类似于流媒体的优点。分析能够立即开始,而不是等待所有的数据被处理。而且,由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中。这对于大型文档来说是个巨大的优点。事实上,应用程序甚至不必解析整个文档;它可以在某个条件得到满足时停止解析。一般来说,SAX还比它的替代者DOM快许多。

选择DOM还是选择SAX? 对于需要自己编写代码来处理XML文档的开发人员来说, 选择DOM还是SAX解析模型是一个非常重要的设计决策。 DOM采用建立树形结构的方式访问XML文档,而SAX采用的是事件模型。

DOM解析器把XML文档转化为一个包含其内容的树,并可以对树进行遍历。用DOM解析模型的优点是编程容易,开发人员只需要调用建树的指令,然后利用navigation APIs访问所需的树节点来完成任务。可以很容易的添加和修改树中的元素。然而由于使用DOM解析器的时候需要处理整个XML文档,所以对性能和内存的要求比较高,尤其是遇到很大的XML文件的时候。由于它的遍历能力,DOM解析器常用于XML文档需要频繁的改变的服务中。

SAX解析器采用了基于事件的模型,它在解析XML文档的时候可以触发一系列的事件,当发现给定的tag的时候,它可以激活一个回调方法,告诉该方法制定的标签已经找到。SAX对内存的要求通常会比较低,因为它让开发人员自己来决定所要处理的tag.特别是当开发人员只需要处理文档中所包含的部分数据时,SAX这种扩展能力得到了更好的体现。但用SAX解析器的时候编码工作会比较困难,而且很难同时访问同一个文档中的多处不同数据。

【优势】

①不需要等待所有数据都被处理,分析就能立即开始。

②只在读取数据时检查数据,不需要保存在内存中。

③可以在某个条件得到满足时停止解析,不必解析整个文档。

④效率和性能较高,能解析大于系统内存的文档。

【缺点】

①需要应用程序自己负责TAG的处理逻辑(例如维护父/子关系等),文档越复杂程序就越复杂。

②单向导航,无法定位文档层次,很难同时访问同一文档的不同部分数据,不支持XPath。

3. JDOM(Java-based Document Object Model)

JDOM的目的是成为Java特定文档模型,它简化与XML的交互并且比使用DOM实现更快。由于是第一个Java特定模型,JDOM一直得到大力推广和促进。正在考虑通过“Java规范请求JSR-102”将它最终用作“Java标准扩展”。从2000年初就已经开始了JDOM开发。

JDOM与DOM主要有两方面不同。首先,JDOM仅使用具体类而不使用接口。这在某些方面简化了API,但是也限制了灵活性。第二,API大量使用了Collections类,简化了那些已经熟悉这些类的Java开发者的使用。

JDOM文档声明其目的是“使用20%(或更少)的精力解决80%(或更多)Java/XML问题”(根据学习曲线假定为20%)。JDOM对于大多数Java/XML应用程序来说当然是有用的,并且大多数开发者发现API比DOM容易理解得多。JDOM还包括对程序行为的相当广泛检查以防止用户做任何在XML中无意义的事。然而,它仍需要您充分理解XML以便做一些超出基本的工作(或者甚至理解某些情况下的错误)。这也许是比学习DOM或JDOM接口都更有意义的工作。

JDOM自身不包含解析器。它通常使用SAX2解析器来解析和验证输入XML文档(尽管它还可以将以前构造的DOM表示作为输入)。它包含一些转换器以将JDOM表示输出成SAX2事件流、DOM模型或XML文本文档。JDOM是在Apache许可证变体下发布的开放源码。

【优点】

①使用具体类而不是接口,简化了DOM的API。

②大量使用了Java集合类,方便了Java开发人员。

【缺点】

①没有较好的灵活性。

②性能较差。

4. DOM4J(Document Object Model for Java)

虽然DOM4J代表了完全独立的开发结果,但最初,它是JDOM的一种智能分支。它合并了许多超出基本XML文档表示的功能,包括集成的XPath支持、XML Schema支持以及用于大文档或流化文档的基于事件的处理。它还提供了构建文档表示的选项,它通过DOM4J API和标准DOM接口具有并行访问功能。从2000下半年开始,它就一直处于开发之中。

为支持所有这些功能,DOM4J使用接口和抽象基本类方法。DOM4J大量使用了API中的Collections类,但是在许多情况下,它还提供一些替代方法以允许更好的性能或更直接的编码方法。直接好处是,虽然DOM4J付出了更复杂的API的代价,但是它提供了比JDOM大得多的灵活性。

在添加灵活性、XPath集成和对大文档处理的目标时,DOM4J的目标与JDOM是一样的:针对Java开发者的易用性和直观操作。它还致力于成为比JDOM更完整的解决方案,实现在本质上处理所有Java/XML问题的目标。在完成该目标时,它比JDOM更少强调防止不正确的应用程序行为。

DOM4J是一个非常非常优秀的Java XML API,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件。如今你可以看到越来越多的Java软件都在使用DOM4J来读写XML,特别值得一提的是连Sun的JAXM也在用DOM4J.

【优点】

①大量使用了Java集合类,方便Java开发人员,同时提供一些提高性能的替代方法。

②支持XPath。

③有很好的性能。

【缺点】

①大量使用了接口,API较为复杂。

二、比较

1. DOM4J性能最好,连Sun的JAXM也在用DOM4J。目前许多开源项目中大量采用DOM4J,例如大名鼎鼎的Hibernate也用DOM4J来读取XML配置文件。如果不考虑可移植性,那就采用DOM4J.

2. JDOM和DOM在性能测试时表现不佳,在测试10M文档时内存溢出,但可移植。在小文档情况下还值得考虑使用DOM和JDOM.虽然JDOM的开发者已经说明他们期望在正式发行版前专注性能问题,但是从性能观点来看,它确实没有值得推荐之处。另外,DOM仍是一个非常好的选择。DOM实现广泛应用于多种编程语言。它还是许多其它与XML相关的标准的基础,因为它正式获得W3C推荐(与基于非标准的Java模型相对),所以在某些类型的项目中可能也需要它(如在JavaScript中使用DOM)。

3. SAX表现较好,这要依赖于它特定的解析方式-事件驱动。一个SAX检测即将到来的XML流,但并没有载入到内存(当然当XML流被读入时,会有部分文档暂时隐藏在内存中)。

我的看法:如果XML文档较大且不考虑移植性问题建议采用DOM4J;如果XML文档较小则建议采用JDOM;如果需要及时处理而不需要保存数据则考虑SAX。但无论如何,还是那句话:适合自己的才是最好的,如果时间允许,建议大家讲这四种方法都尝试一遍然后选择一种适合自己的即可。

298.char型变量中能不能存储一个中文汉字?

答:1.java采用unicode编码,2个字节(16位)来表示一个字符, 无论是汉字还是数字,字母,或其他语言都可以存储。

2.char 在java中是2个字节,所以可以存储中文

299.一个类可以实现多个接口,但只能继承一个抽象类。

下面接着再说说两者在应用上的区别:

接口更多的是在系统架构设计方法发挥作用,主要用于定义模块之间的通信契约。而抽象类在代码实现方面发挥作用,可以实现代码的重用,例如,模板方法设计模式是抽象类的一个典型应用,假设某个项目的所有Servlet类都要用相同的方式进行权限判断、记录访问日志和处理异常,那么就可以定义一个抽象的基类,让所有的Servlet都继承这个抽象基类,在抽象基类的service方法中完成权限判断、记录访问日志和处理异常的代码,在各个子类中只是完成各自的业务逻辑代码,伪代码如下:

public abstract classBaseServlet extends HttpServlet{
        public final void service(HttpServletRequest request,HttpServletResponse response) throws IOExcetion,ServletException       {
               记录访问日志
               进行权限判断
if(具有权限){
       try{
              doService(request,response);
}
       catch(Excetpion e)  {
                     记录异常信息
       }
}
        }
        protected abstract void doService(HttpServletRequest request,HttpServletResponse response) throws IOExcetion,ServletException;
//注意访问权限定义成protected,显得既专业,又严谨,因为它是专门给子类用的
}

public class MyServlet1 extendsBaseServlet
{
protected voiddoService(HttpServletRequest request, HttpServletResponse response) throwsIOExcetion,ServletException
        {
               本Servlet只处理的具体业务逻辑代码
        }

}

父类方法中间的某段代码不确定,留给子类干,就用模板方法设计模式。

备注:这道题的思路是先从总体解释抽象类和接口的基本概念,然后再比较两者的语法细节,最后再说两者的应用区别。比较两者语法细节区别的条理是:先从一个类中的构造方法、普通成员变量和方法(包括抽象方法),静态变量和方法,继承性等6个方面逐一去比较回答,接着从第三者继承的角度的回答,特别是最后用了一个典型的例子来展现自己深厚的技术功底。

300.比较一下Java 和JavaSciprt

答:JavaScript 与Java是两个公司开发的不同的两个产品。Java 是原Sun 公司推出的面向对象的程序设计语言,特别适合于互联网应用程序开发;而JavaScript是Netscape公司的产品,为了扩展Netscape浏览器的功能而开发的一种可以嵌入Web页面中运行的基于对象和事件驱动的解释性语言,它的前身是LiveScript;而Java 的前身是Oak语言。

下面对两种语言间的异同作如下比较:

1)基于对象和面向对象:Java是一种真正的面向对象的语言,即使是开发简单的程序,必须设计对象;JavaScript是种脚本语言,它可以用来制作与网络无关的,与用户交互作用的复杂软件。它是一种基于对象(Object-Based)和事件驱动(Event-Driven)的编程语言。因而它本身提供了非常丰富的内部对象供设计人员使用;

2)解释和编译:Java 的源代码在执行之前,必须经过编译;JavaScript 是一种解释性编程语言,其源代码不需经过编译,由浏览器解释执行;

3)强类型变量和类型弱变量:Java采用强类型变量检查,即所有变量在编译之前必须作声明;JavaScript中变量声明,采用其弱类型。即变量在使用前不需作声明,而是解释器在运行时检查其数据类型;

4)代码格式不一样。

补充:上面列出的四点是原来所谓的标准答案中给出的。其实Java和JavaScript最重要的区别是一个是静态语言,一个是动态语言。目前的编程语言的发展趋势是函数式语言和动态语言。在Java中类(class)是一等公民,而JavaScript中函数(function)是一等公民。对于这种问题,在面试时还是用自己的语言回答会更加靠谱。 

301.什么时候用assert?

答:assertion(断言)在软件开发中是一种常用的调试方式,很多开发语言中都支持这种机制。一般来说,assertion用于保证程序最基本、关键的正确性。assertion检查通常在开发和测试时开启。为了提高性能,在软件发布后, assertion检查通常是关闭的。在实现中,断言是一个包含布尔表达式的语句,在执行这个语句时假定该表达式为true;如果表达式计算为false,那么系统会报告一个AssertionError。

断言用于调试目的:

assert(a > 0); // throws an AssertionError if a <= 0

断言可以有两种形式:

assert Expression1;

assert Expression1 : Expression2 ;

Expression1 应该总是产生一个布尔值。

Expression2 可以是得出一个值的任意表达式;这个值用于生成显示更多调试信息的字符串消息。

断言在默认情况下是禁用的,要在编译时启用断言,需使用source 1.4 标记:

javac -source 1.4 Test.java

要在运行时启用断言,可使用-enableassertions 或者-ea 标记。

要在运行时选择禁用断言,可使用-da 或者-disableassertions 标记。

要在系统类中启用断言,可使用-esa 或者-dsa 标记。还可以在包的基础上启用或者禁用断言。可以在预计正常情况下不会到达的任何位置上放置断言。断言可以用于验证传递给私有方法的参数。不过,断言不应该用于验证传递给公有方法的参数,因为不管是否启用了断言,公有方法都必须检查其参数。不过,既可以在公有方法中,也可以在非公有方法中利用断言测试后置条件。另外,断言不应该以任何方式改变程序的状态。 

302.UML是什么?UML中有哪些图?

答:UML是统一建模语言(Unified Modeling Language)的缩写,它发表于1997年,综合了当时已经存在的面向对象的建模语言、方法和过程,是一个支持模型化和软件系统开发的图形化语言,为软件开发的所有阶段提供模型化和可视化支持。使用UML可以帮助沟通与交流,辅助应用设计和文档的生成,还能够阐释系统的结构和行为。UML定义了多种图形化的符号来描述软件系统部分或全部的静态结构和动态结构,包括:用例图(use case diagram)、类图(class diagram)、时序图(sequence diagram)、协作图(collaboration diagram)、状态图(statechart diagram)、活动图(activity diagram)、构件图(component diagram)、部署图(deployment diagram)等。在这些图形化符号中,有三种图最为重要,分别是:用例图(用来捕获需求,描述系统的功能,通过该图可以迅速的了解系统的功能模块及其关系)、类图(描述类以及类与类之间的关系,通过该图可以快速了解系统)、时序图(描述执行特定任务时对象之间的交互关系以及执行顺序,通过该图可以了解对象能接收的消息也就是说对象能够向外界提供的服务)。

用例图:

303.XML 文档定义有几种形式?它们之间有何本质区别?解析XML 文档有哪几种方式?

答: XML文档定义分为DTD和Schema两种形式;其本质区别在于Schema本身也是一个XML文件,可以被XML解析器解析。对XML的解析主要有DOM(文档对象模型)、SAX、StAX(JDK 1.6中引入的新的解析XML的方式,Streaming API for XML) 等,其中DOM处理大型文件时其性能下降的非常厉害,这个问题是由DOM 的树结构所造成的,这种结构占用的内存较多,而且DOM 必须在解析文件之前把整个文档装入内存,适合对XML 的随机访问(典型的用空间换取时间的策略);SAX是事件驱动型的XML解析方式,它顺序读取XML文件,不需要一次全部装载整个文件。当遇到像文件开头,文档结束,或者标签开头与标签结束时,它会触发一个事件,用户通过在其回调事件中写入处理代码来处理XML文件,适合对XML 的顺序访问;如其名称所暗示的那样,StAX把重点放在流上。实际上,StAX与其他方法的区别就在于应用程序能够把XML作为一个事件流来处理。将XML作为一组事件来处理的想法并不新颖(事实上 SAX 已经提出来了),但不同之处在于StAX允许应用程序代码把这些事件逐个拉出来,而不用提供在解析器方便时从解析器中接收事件的处理程序。 

304.你在项目中哪些地方用到了XML?

答: XML的主要作用有两个方面:数据交换(曾经被称为业界数据交换的事实标准,现在此项功能在很多时候都被JSON取代)和信息配置。在做数据交换时,XML将数据用标签组装成起来,然后压缩打包加密后通过网络传送给接收者,接收解密与解压缩后再从XML文件中还原相关信息进行处理。目前很多软件都使用XML来存储配置信息,很多项目中我们通常也会将作为配置的硬代码(hard code)写在XML文件中,Java的很多框架也是这么做的。 

305.用JavaScript实现用正则表达式验证,某个字符串是合法的6位数字的邮编的函数
Function testE(ss){
  var reg=/^[1-9][0-9]{5}$/;
  if(req.test(ss)){
    alert(“邮编OK”)
}else{
  alert(“邮编格式不正确”);
}
}
306.请使用JQuery将页面上的所有元素边框设置为2pix宽的虚线?

$(“*”).css(“border”,”2px dashed”)

307.如何设定JQuery异步调用还是同步调用?

答案:调用jQuery中的ajax函数,设置其async属性来表明是异步还是同步,如下:

$.ajax({
async:true//表示异步,false表示同步
})

308.说出3条以上firefox和IE的浏览器兼容问题?

答案:兼容firefox的 outerHTML,FF中没有outerHtml的方法

IE下,可以使用()或[]获取集合类对象;Firefox下,只能使用[]获取集合类对象.解决方法:统一使用[]获取集合类对象.

IE下,可以使用获取常规属性的方法来获取自定义属性,也可以使用getAttribute()获取自定义属性;Firefox下,只能使用getAttribute()获取自定义属性.解决方法:统一通过getAttribute()获取自定义属性

309.请用Jquery语言写出ajax请求或者post请求代码
$.post(“show”,{uname=”张三”,pwd=”123”},function(data){
  alert(data)
})
310.body中的onload ()函数和jQuery中document.ready()有什么区别?

答案:ready 事件的触发,表示文档结构已经加载完成(不包含图片等非文字媒体文件)

onload 事件的触发,表示页面包含图片等文件在内的所有元素都加载完成。

311.jQuery中有哪几种类型的选择器?

答案:

基本选择器

层次选择器

基本过滤选择器

内容过滤选择器

可见性过滤选择器

属性过滤选择器

子元素过滤选择器

表单选择器

表单过滤选择器

312.EasyUI中datagrid刷新当前数据的方法?

答案:使用reload()即可

313.分别写出一个div居中和其中的内容居中的css属性设置

Div居中:

margin:auto 0px;

内容居中:

text-align:center;

314.概述一下session与cookie的区别

答案:

存储角度:

Session是服务器端的数据存储技术,cookie是客户端的数据存储技术

解决问题角度:

Session解决的是一个用户不同请求的数据共享问题,cookie解决的是不同请求的请求数据的共享问题

生命周期角度:

Session的id是依赖于cookie来进行存储的,浏览器关闭id就会失效

Cookie可以单独的设置其在浏览器的存储时间。

315.JavaScript 中 null和 undefined 是否有区别?有哪些区别?

答案:

赋值角度说明:

null 表示此处没有值,undefined表示此处定义了但是没有赋值

从数据转换角度:

Null在做数值转换时会被转换为0,undefined会被转换为NaN

316.Servlet中的doPost和doGet方法有什么区别?它们在传递和获取参数上有什么区别?

答案:

区别:doPost用来处理post请求,doGet用来处理get请求,获取参数:获取的参数是相同的都是HttpServletRequest \HttpServletResponse

317.请写出一段jQuery代码,实现把当前页面中所有的a元索中class 属性为“view-link”的链接都改为在新窗口中打开

答案:$(“a[class=view-link]”).attr(“target”,”_blank”)

318.如下JavaScript代码的输出为:
var scope ="global scope";
function checkscope() {
var scope ="local scope”;
 return function() { return scope}
}
console.log (checkscope()());

319.Jquery中’.get()’与’.eq()’的区别

eq返回的是一个jquery对象 get返回的是一个html对象

320.如何给weblogic定内存的大小?

在启动Weblogic的脚本中(位于所在Domian对应服务器目录下的startServerName),增加set MEM_ARGS=-Xms32m -Xmx200m,可以调整最小内存为32M,最大200M

321.TCP为何采用三次握手来建立连接,若釆用二次握手可以吗,请说明理由?

三次握手是为了防止已失效的连接请求再次传送到服务器端。 二次握手不可行,因为:如果由于网络不稳定,虽然客户端以前发送的连接请求以到达服务方,但服务方的同意连接的应答未能到达客户端。则客户方要重新发送连接请求,若采用二次握手,服务方收到重传的请求连接后,会以为是新的请求,就会发送同意连接报文,并新开进程提供服务,这样会造成服务方资源的无谓浪费

322.以下HTTP相应状态码的含义描述正确的是()
A. 200ok表示请求成功
B. 400不良请求表示服务器未发现与请求URL匹配内容
C. 404未发现表示由于语法错误儿导致服务器无法理解请求信息
D. 500内部服务器错误,无法处理请求
答案:D
分析:
A 200ok 表示的意思是一切正常。一般用于相应GET和POST请求。这个状态码对servlet是缺省的;如果没有调用setStatus方法的话,就会得到200。
B 400 表示指出客户端请求中的语法错误
C 404 客户端所给的地址无法找到任何资源
323.JSP页面包括哪些元素?()
A. JSP命令
B. JSP Action
C. JSP脚本
D. JSP控件
答案:C
分析:JSP页面元素构成如下,因此ABD错误
A 200ok 表示的意思是一切正常。一般用于相应GET和POST请求。这个状态码对servlet是缺省的;如果没有调用setStatus方法的话,就会得到200。
B 400 表示指出客户端请求中的语法错误
C 404 客户端所给的地址无法找到任何资源
324.Ajax有四种技术组成:DOM,CSS,JavaScript,XmlHttpRequest,其中控制文档结构的是()
A. DOM
B. CSS
C. JavaScript
D. XmlHttpRequest
答案:A
325.下面关于session的用法哪些是错误的?()
A. HttpSession session=new HttpSession();
B. String haha=session getParameler(:haha”);
C. session.removeAttribute(“haha”);
D. session.setAttribute(:haha:);XmlHttpRequest
答案:A
326.Jsp九大内置对象

答案:1、request对象

request 对象是 javax.servlet.httpServletRequest类型的对象。 该对象代表了客户端的请求信息,主要用于接受通过HTTP协议传送到服务器的数据。(包括头信息、系统信息、请求方式以及请求参数等)。request对象的作用域为一次请求。

2、response对象

response 代表的是对客户端的响应,主要是将JSP容器处理过的对象传回到客户端。response对象也具有作用域,它只在JSP页面内有效。

3、session对象

session 对象是由服务器自动创建的与用户请求相关的对象。服务器为每个用户都生成一个session对象,用于保存该用户的信息,跟踪用户的操作状态。session对象内部使用Map类来保存数据,因此保存数据的格式为 “Key/value”。 session对象的value可以使复杂的对象类型,而不仅仅局限于字符串类型。

4、application对象

 application 对象可将信息保存在服务器中,直到服务器关闭,否则application对象中保存的信息会在整个应用中都有效。与session对象相比,application对象生命周期更长,类似于系统的“全局变量”。

5、out 对象

out 对象用于在Web浏览器内输出信息,并且管理应用服务器上的输出缓冲区。在使用 out 对象输出数据时,可以对数据缓冲区进行操作,及时清除缓冲区中的残余数据,为其他的输出让出缓冲空间。待数据输出完毕后,要及时关闭输出流。

6、pageContext 对象

pageContext 对象的作用是取得任何范围的参数,通过它可以获取 JSP页面的out、request、reponse、session、application 等对象。pageContext对象的创建和初始化都是由容器来完成的,在JSP页面中可以直接使用 pageContext对象。

7、config 对象

config 对象的主要作用是取得服务器的配置信息。通过 pageConext对象的 getServletConfig() 方法可以获取一个config对象。当一个Servlet 初始化时,容器把某些信息通过 config对象传递给这个 Servlet。 开发者可以在web.xml 文件中为应用程序环境中的Servlet程序和JSP页面提供初始化参数。

8、page 对象

page 对象代表JSP本身,只有在JSP页面内才是合法的。 page隐含对象本质上包含当前 Servlet接口引用的变量,类似于Java编程中的 this 指针。

9、exception 对象

exception 对象的作用是显示异常信息,只有在包含 isErrorPage="true" 的页面中才可以被使用,在一般的JSP页面中使用该对象将无法编译JSP文件。excepation对象和Java的所有对象一样,都具有系统提供的继承结构。exception 对象几乎定义了所有异常情况。在Java程序中,可以使用try/catch关键字来处理异常情况; 如果在JSP页面中出现没有捕获到的异常,就会生成 exception 对象,并把 exception 对象传送到在page指令中设定的错误页面中,然后在错误页面中处理相应的 exception 对象。

327.如何配置一个servlet?

在web.xml中使用如下标签:

<servlet>
 <servlet-name></servlet-name>
 <servlet-class></servlet-class>
</servlet>
<servlet-mapping>
 <servlet-name></servlet-name>
 <url-pattern></url-pattern>
 </servlet-mapping>
 或者使用注解方式:
@WebServlet(name="servlet", urlPatterns={"/*"})
328.JavaScript,如何定义含有数值1至8的数组?

答: var arr=[1,2,3,4,5,6,7,8]

329.以下JavaScipt语句会产生运行错误的是_()
A. var obj=( );
B. var obj=[ ];
C. var obj=//;
D. var obj=1;
答案:AC
330.在JSP中,下面__()__块中可以定义一个新类:
A. <% %>
B. <% ! %>
C. <%@ %>
D. <%=%>
答案:B
分析:B <% ! %> 可用作声明
A不正确
C为引用xxx,比如<% @page xxxxx%>
D为表达式
331.HTML含义和版本变化

HTML含义:

Hyper Text Markup Language 超文本标记语言,是一种用来制作“网页”的简单标记语言;用HTML编写的超文本文档称为HTML文档,HTML文档的扩展名是html或者htm

版本变化:

HTML1.0——在1993年6月作为IETF工作草案发布(并非标准)

HTML 2.0——1995年11月作为RFC 1866发布

HTML 3.2——1997年1月14日,W3C推荐标准

HTML 4.0——1997年12月18日,W3C推荐标准

HTML 4.01(微小改进)——1999年12月24日,W3C推荐标准

HTML 5—2014年10月28日,W3C推荐标准HTML文档结构;

HTML 5.1 - 2016年

HTML 5.2 – 2018年最新版本

HTML 5.3 is coming…

332.什么是锚链接

锚链接是带有文本的超链接。可以跳转到页面的某个位置,适用于页面内容较多,超过一屏的场合 。分为页面内的锚链接和页面间的锚链接 。

例如:1F2F

跳转到2F标记位置

说明:

1.在标记位置利用a标签的name属性设置标记。

2.在导航位置通过a标签的href属性用#开头加name属性值即可跳转锚点位置。

333.HTML字符实体的作用及其常用字符实体

有些字符,比如说“<”字符,在HTML中有特殊的含义,因此不能在文本中使用。想要在HTML中显示一个小于号“<”,需要用到字符实体:<或者<

字符实体拥有三个部分:一个and符号(&),一个实体名或者一个实体号,最后是一个分号(;)

常用字符实体:

显示结果 描述 实体 实体号
空格    
< 小于 < <
> 大于 > &#
& and符号 & &
' 单引号 ' (IE不支持) '
" 引号 " "
£ 英镑 £ £
¥ 人民币元 ¥ ¥
§ 章节 ¥ ¥
© 版权 © ©
334.HTML表单的作用和常用表单项类型

表单的作用:

利用表单可以收集客户端提交的有关信息。

常用表单项类型:

input标签
type属性
功能 input标签
type属性
功能
text 单行本框 reset 重置按钮
password 密码框 submit 提交按钮
radio 单选按钮 textarea 文本域
checkbox 复选框 select 下拉框
button 普通按钮 hidden 隐藏域

335.表格、框架、div三种HTML布局方式的特点

优点 缺点 应用场合
表格 方便排列有规律、结构均匀的内容或数据 产生垃圾代码、影响页面下载时间、灵活性不大难于修改 内容或数据整齐的页面
框架 支持滚动条、方便导航 节省页面下载时间等 兼容性不好,保存时不方便、应用范围有限 小型商业网站、论坛后台管理
Div 代码精简、提高页面下载速度、表现和内容分离 比较灵活、难于控制 复杂的不规则页面、业务种类较多的大型商业网站

336.form中input设置为readonly和disabled的区别

readonly disabled
有效对象 .只针对type为text/password有效 对所有表单元素有效
表单提交 当表单元素设置readonly后,表单提交能将该表单元素的值传递出去。 当表单元素设置disabled后,表单提交不能将该表单元素的值传递出去。

337.CSS的定义和作用

CSS的定义:CSS是Cascading Style Sheets(层叠样式表)的简称。

CSS是一系列格式规则,它们控制网页内容的外观。CSS简单来说就是用来美化网页用的。

CSS的具体作用包括:

使网页丰富多彩,易于控制。

页面的精确控制,实现精美、复杂页面 。

338.CSS2常用选择器类型及其含义

选择器名称 案例 语法格式
标签选择器 h3{font-size:24px;font-family:"隶书“; }< h3>JSP< /h3> 元素标签名{样式属性}
类选择器 .red {color:#F00;} < li class="red">Oracle< /li> . 元素标签class属性值{样式属性}
ID选择器 #p1 {background-color:#0F0;} < p id="p1">content< /p> #元素标签id属性值{样式属性}
包含选择器 div h3{color:red;} < div> < h3>CSS层叠样式表< /h3> < /div> 父元素标签 子元素标签{ 样式属性 }
子选择器 div>ul{color:blue;} < div> < ul> < li>测试1 < ol> < li>嵌套元素< /li> < li>嵌套元素< /li> < li>嵌套元素< /li> < li>嵌套元素< /li> < /ol> < /li> < li>测试1< /li> < li>测试1< /li> < /ul> < /div> 父元素标签名>子元素名{ 样式属性 }

339.引入样式的三种方式及其优先级别

三种引用方式:

1. 外部样式表(存放.css文件中)

不需要style标签

< link rel=”stylesheet” href=”引用文件地址” />

2. 嵌入式样式表

< style type=“text/css”>

p{color:red;}

< /style>

3.内联样式

标签属性名为style

< p style=“color:red;”>< /p>

优先级级别:内联定义最高、内部CSS次之、外部CSS优先级最低。。

340.盒子模型

盒子模型类似于生活中的盒子,具有4个属性,外边距,内边距,边框,内容。

外边距:margin,用于设置元素和其他元素之间的距离。

内边距:padding,用于设置元素内容和边框之间的距离。

边框:border,用于设置元素边框粗细,颜色,线型。

内容:width,height,用于设置元素内容显示的大小。

例如:

<style>
    body{
      margin: 0;  /*取消body默认的外边距*/
    }
#img1{
width:200px;   /*设置图片的宽度*/
border: 2px solid black; /*设置图片边框*/
margin: 5px;
/*设置图片外边距(表示该图片与其他图片的距离为5px)*/
padding:10px; /*设置图片与边框之间的距离*/
}
#img2{
height: 200px; /* 设置图片的高度*/
border: 2px solid black; /*设置图片的边框*/
margin: 5px; /*设置图片外边距*/
padding: 20px; /*设置图片与边框之间的距离*/
}
</style>
<img id="img1" src="img/2.jpg" />
<img id="img2" src="img/lss.jpg" />

341.JavaScript语言及其特点

Javascript一种基于对象(object-based)和事件驱动(Event Driven)的简单的并具有安全性能的脚本语言。特点:

解释性: JavaScript不同于一些编译性的程序语言,例如C、C++等,它是一种解释性的程序语言,它的源代码不需要经过编译,而直接在浏览器中运行时被解释。

基于对象: JavaScript是一种基于对象的语言。这意味着它能运用自己已经创建的对象。因此,许多功能可以来自于脚本环境中对象的方法与脚本的相互作用。

事件驱动: JavaScript可以直接对用户或客户输入做出响应,无须经过Web服务程序。它对用户的响应,是以事件驱动的方式进行的。所谓事件驱动,就是指在主页中执行了某种操作所产生的动作,此动作称为“事件”。比如按下鼠标、移动窗口、选择菜单等都可以视为事件。当事件发生后,可能会引起相应的事件响应。

跨平台:JavaScript依赖于浏览器本身,与操作环境无关,只要能运行浏览器的计算机,并支持JavaScript的浏览器就可正确执行。

342.JavaScript常用数据类型有哪些

1、数值型(Number):整数和浮点数统称为数值。例如85或3.1415926等。

2、字符串型(String):由0个,1个或多个字符组成的序列。在JavaScript中,用双引号或单引号括起来表示,如“您好”、‘学习JavaScript’等。 不区分单引号、双引号。

3、逻辑(布尔)型(Boolean):用true或false来表示。

4、空(null)值(Null):表示没有值,用于定义空的或不存在的引用。

要注意,空值不等同于空字符串""或0。

5、未定义(Undefined)值:它也是一个保留字。表示变量虽然已经声明,但却没有赋值。

除了以上五种基本的数据类型之外,JavaScript还支持复合数据类型,包括对象和数组两种。

343.html语法中哪条命令用于使一行文本折行,而不是插入一个新的段落? (B)

A. < TD>
B. < BR>
C. < P>
D. < H1>
分析:
A < td>定义标准表格
C < p>表示文本一个段落
D < h1>表示对文本标题进行强调的一种标签

344.Ajax的优点和缺点

优点:减轻服务器的负担,按需取数据,最大程度的减少冗余请求,局部刷新页面,减少用户心理和实际的等待时间,带来更好的用户体验,基于xml标准化,并被广泛支持,不需安装插件等,进一步促进页面和数据的分离

缺点:AJAX大量的使用了javascript和ajax引擎,这些取决于浏览器的支持.在编写的时候考虑对浏览器的兼容性.

345.怎样防止表单刷新重复提交问题?(说出思路即可)

JS脚本方式:

第一种:定义全局变量,在form提交前判断是否已有提交过

<script>
   var checkSubmitFlg = false;
   function checkSubmit(){
     if(checkSubmitFlg == true){
return false;
     }
     checkSubmitFlg = true;
     return true;
  }
 </script>
<form action="" onsubmit="return checkSubmit();">
</form>

第二种:单击提交按钮后,立刻禁用改按钮

第三种:单击提交按钮后,弹出屏蔽层,防止用户第二次点击

346.JQuery.get()和JQuery.ajax()方法之间的区别是什么?

JQuery.ajax()是对原生的javaScript的ajax的封装,简化了ajax的步骤,用户可用JQuery.ajax()发送get或者post方式请求,Jquery.get()是对ajax的get方式的封装,只能发送get方式的请求。

347.Jquery里的缓存问题如何解决?例如($.ajax()以及$.get())

$.ajax()请求时候加上cache:false的参数,如:

$.ajax({
    type : "get",
    url : "XX",
    dataType : "json",
    cache:false,
    success : function(json) {
    }
});

$.get()请求时候加上时间,如:

$.get("url","data"+new Date(),function(data){});

348.Javascript是面向对象的,怎么体现Javascript的继承关系?

Javascript里面没有像java那样的继承,javascript中的继承机制仅仅是靠模拟的,可以使用prototype原型来实现

349.Javascript的有几种种变量。变量范围有什么不同?

可以分为三种

1、原生类型(string,number,boolean)

2、对象(Date,Array)

3、特殊类型(var vara;(只什么没有定义),var varb = null;(定义一个变量并赋值为null))

350.Js如何获取页面的dom对象

1、直接获取

//1.1 -- id方式获取

var varid = document.getElementById("unameid");

//1.2 -- name获取(获取的是数组对象)

var varname = document.getElementsByName("sex");

//1.3 -- 元素获取(获取的是数组对象)

var varinput = document.getElementsByTagName("input");

2、间接方式获取

//2.1 父子关系 --childNodes

var varchilds = document.getElementById("div01").childNodes;

//2.2 子父关系--parentNode

var varfather2 = document.getElementById("unameid").parentNode;

//2.3 兄弟之间相互获取 nextSibling:下一个节点 previousSibling:上一个节点

351.Servlet API中forward() 与redirect()的区别?

答:为实现程序的模块化,就需要保证在不同的Servlet之间可以相互跳转,而Servlet中主要有两种实现跳转的方式:FORWARD方式与redirect方式。 

Forward() : 是服务器内部的重定向,服务器直接访问目标地址的URL,把那个URL的响应内容读取出来,而客户端并不知道,因此在客户端浏览器的地址栏里不会显示跳转后的地址,还是原来的地址。由于在整个定向的过程中用的是同一个Request,因此FORWARD会将Request的信息带到被定向的JSP或Servlet中使用。

Redirect():则是客户端的重定向,是完全的跳转,即客户端浏览器会获取跳转后的地址,然后重新发送请求,因此浏览器中会显示跳转后的地址。同时,由于这种方式比FORWARD方式多了一次网络请求,因此其效率低于FORWARD方式,需要注意到的是,客户端的重定向可以通过设置特定的HTTP 头或写JavaScript脚本来实现。

鉴于以上的区别,一般当FORWARD方式可以满足需求时,尽可能的使用FORWARD方式。但在有些情况下,例如,需要跳转到一个其他服务器上的资源时,则必须使用redirect 方式。

352.Session域和request域什么区别?

作用域:存放数据,获取数据(传递数据)

有效的作用域:生命周期,作用范围

httpServeltRequest:

生命周期:一次请求之间

作用范围:所有被请求转发过的servlet都能获取到

httpSession:

生命周期:一次会话

作用范围:所有的servlet都可以获取到

servletContex:

生命周期:从项目开始运行到服务器关闭

作用范围:所有的servlet都可以获取到 

作用域如何选用?

httpServeltRequest:和当前请求有关的信息

httpSession:和当前用户有关的信息

servletContex:访问量比较大,不易更改

353.页面中有一个命名为bankNo的下拉列表,写js脚本获取当前选项的索引值,如果用jquery如何获取

var a = document.getElementsByName("bankNo")[0].value;

var b = $("select[name=bankNo]").val();

354.写出要求11位数字的正则表达式

^[1-9]\d{10}$

355.分别获取指定name、Id的javascript对象,如果用jquey如何获取

js:
  id--document.getElementById("id");
  name--document.getElementsByName("name");
jquery
  id--$("#id");
  name--$("元素名称[name="name值"]");

356.一个页面有两个form,如何获取第一个form

用id方式获取;document.getElementById("id");

357.如何设置一个层的可见/隐藏

可见 : document.getElementById("divid").style.display = "block";

隐藏 : document.getElementById("divid").style.display = "none";

358.描述JSP中动态INCLUDE与静态INCLUDE的区别?

动态导入

1、会将多个jsp页面分别再编写成java文件,编译成class文件

2、jsp文件中允许有相同的变量名,每个页面互不影响

3、当java代码比较多优先选用动态导入

4、效率相对较低,耦合性低

静态导入

1、会将多个jsp页面合成一个jsp页面,再编写成java文件,编译成class文件

2、jsp文件中不允许有相同的变量名

3、当java代码比较少或者没有java代码是优先选用静态导入

4、效率相对较高,耦合性高

359.列举JSP的内置对象及方法

request表示HttpServletRequest对象。它包含了有关浏览器请求的信息,并且提供了几个用于获取cookie, header, 和session数据的有用的方法。 

response表示HttpServletResponse对象,并提供了几个用于设置送回 浏览器的响应的方法(如cookies,头信息等) 

out对象是javax.jsp.JspWriter的一个实例,提供了几个方法使你能用于向浏览器回送输出结果

pageContext表示一个javax.servlejt.sp.PageContext对象。它是用于方便存取各种范围的名字空间、servlet相关的对象的API,并且包装了通用的servlet相关功能的方法。 

session表示一个请求的javax.servlet.http.HttpSession对象。Session可以存贮用户的状态信息

applicaton 表示一个javax.servle.ServletContext对象。这有助于查找有关servlet引擎和servlet环境的信息 

config表示一个javax.servlet.ServletConfig对象。该对象用于存取servlet实例的初始化参数。 

page表示从该页面产生的一个servlet实例

Exception异常

360.列举jsp的四大作用域

page、request、session、application

361.html和xhtml的区别是什么?

HTML与XHTML之间的差别,粗略可以分为两大类比较:一个是功能上的差别,另外是书写习惯的差别。关于功能上的差别,主要是XHTML可兼容各大浏览器、手机以及PDA,并且浏览器也能快速正确地编译网页。

因为XHTML的语法较为严谨, 所以如果你是习惯松散结构的HTML编写者,那需要特别注意XHTML的规则。但也不必太过担心,因为XHTML的规则并不太难。下面列出了几条容易犯的错误,供大家引用。

1:所有标签都必须小写

在XHTML中,所有的标签都必须小写,不能大小写穿插其中,也不能全部都是大写。看一个例子。

错误:< Head>< /Head>< Body>< /Body>

正确:< head>< /head>< body>< /body>

2:标签必须成双成对

像是< p>...< /p>、< a>...< /a>、< div>...< /div>标签等,当出现一个标签时,必须要有对应的结束标签,缺一不可,就像在任何程序语言中的括号一样。

错误:大家好< p>我是muki

正确:< p>大家好< /p>< p>我是muki< /p>

3:标签顺序必须正确

标签由外到内,一层层包覆着,所以假设你先写div后写h1,结尾就要先写h1后写div。只要记住一个原则“先进后出”,先弹出的标签要后结尾。

错误:< div>< h1>大家好< /div>< /h1>

正确:< div>< h1>大家好< /h1>< /div>

4:所有属性都必须使用双引号

在XHTML 1.0中规定连单引号也不能使用,所以全程都得用双引号。

错误:< div style=font-size:11px>hello< /div>

正确:< div style="font-size:11px">hello< /div

5:不允许使用target="_blank"

从XHTML 1.1开始全面禁止target属性,如果想要有开新窗口的功能,就必须改写为rel="external",并搭配JavaScript实现此效果。

错误:< a href="http://blog.mukispace.com" target="_blank">MUKI space< /a>

正确:< a href="http://blog.mukispace.com" rel="external">MUKI space< /a>

362.你做的页面用哪些浏览器测试过?这些测试的内核分别是什么?

1、Trident内核代表产品Internet Explorer,又称其为IE内核。 Trident(又称为MSHTML),是微软开发的一种排版引擎。使用Trident渲染引擎的浏览器包括:IE、傲游、世界之窗浏览器、Avant、腾讯TT、Netscape 8、NetCaptor、Sleipnir、GOSURF、GreenBrowser和KKman等。 

2、Gecko内核代表作品Mozilla ,FirefoxGecko是一套开放源代码的、以C++编写的网页排版引擎。Gecko是最流行的排版引擎之一,仅次于Trident。使用它的最著名浏览器有Firefox、Netscape6至9

3、WebKit内核代表作品Safari、Chromewebkit , 是一个开源项目,包含了来自KDE项目和苹果公司的一些组件,主要用于Mac OS系统,它的特点在于源码结构清晰、渲染速度极快。缺点是对网页代码的兼容性不高,导致一些编写不标准的网页无法正常显示。主要代表作品有Safari和Google的浏览器Chrome。 

4、Presto内核代表作品OperaPresto, 是由Opera Software开发的浏览器排版引擎,供Opera 7.0及以上使用。它取代了旧版Opera 4至6版本使用的Elektra排版引擎,包括加入动态功能,例如网页或其部分可随着DOM及Script语法的事件而重新排版。

363.你遇到了哪些浏览器的兼容性问题?怎么解决的?

答:因为不同的浏览器对同一段代码有不同的解析,造成页面显示效果不统一的情况;这是我们常见的兼容性问题。

解决方法:

1、针对不同的浏览器写不同的代码

2、使用jquery屏蔽浏览器差异

遇到不同的兼容问题,需要针对前端进行兼容适配;

364.你知道的常用的js库有哪些?

1.moment.js

举个例子:

用js转换时间戳为日期

let date = new Date(1437925575663);
        let year = date.getFullYear() + '-';
        let month = ( date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) :
date.getMonth() + 1 ) + '-';
        let day = date.getDate();
...
        return year + month + day;
用moment.js
return moment(1437925575663).format('YYYY-MM-DD HH:mm:ss')

2.chart.js

绘制简单的柱状图,曲线图,蛛网图,环形图,饼图等完全够用,用法比较简单。

3.D3.js

功能太强大了,看首页就知道了,感觉没有什么图d3绘不出来的。

4.Rx.js

很好的解决了异步和事件组合的问题。

5.lodash.js

365.Js中的三种弹出式消息提醒(警告窗口、确认窗口、信息输入窗口)的命令是什么?

alter(),confirm(),prompt()

366.谈谈js的闭包

答:闭包无处不在,比如:jQuery、zepto的核心代码都包含在一个大的闭包中,所以下面我先写一个最简单最原始的闭包,以便让你在大脑里产生闭包的画面:

function A(){
function B(){
console.log("Hello Closure!");
}
return B;
}
var C = A();
C();//Hello Closure!

这是最简单的闭包。

有了初步认识后,我们简单分析一下它和普通函数有什么不同,上面代码翻译成自然语言如下:

(1)定义普通函数 A

(2)在 A 中定义普通函数 B

(3)在 A 中返回 B

(4)执行 A, 并把 A 的返回结果赋值给变量 C

(5)执行 C

把这5步操作总结成一句话就是:

函数A的内部函数B被函数A外的一个变量 c 引用。

把这句话再加工一下就变成了闭包的定义:

当一个内部函数被其外部函数之外的变量引用时,就形成了一个闭包。

因此,当你执行上述5步操作时,就已经定义了一个闭包!

这就是闭包。

367.写一段js,遍历所有的li,将每个li的内容逐个alert出来

<body>
      <ul>
        <li>张三:123</li>
        <li>李四:456</li>
        <li>王五:789</li>
        <li>赵六:147</li>
<ul>
   <body>
function test(){
  var varli = document.getElementsByTagName("li");
  for (var i=0;i<varli.length;i++) {
    alert(varli[i].innerText);
  }
}

368.页面上如何用JavaScript对多个checkbox全选

//全选
function checkAll(){
//获取复选框对象--数组对象
var varcheck = document.getElementsByName("name");
//alert(varcheck.length);
//遍历for
for(var i=0;i<varcheck.length;i++){
varcheck[i].checked = true;
}
}

369.写一个简单的JQuery的ajax

<script type="text/javascript" src="js/jquery-1.9.1.js" charset="utf-8"></script>

<script type="text/javascript">
function testJqAjax(){
//url  :请求地址
//type :请求的方式 get/post
//data :请求的参数(json/String)
//cache:true(走缓存 )  false(不走缓存)
//result:当ajax发送成功后会调用success后面的函数,result:相当于形参,返回的数据
//async:是否为异步请求 默认true异步 , false同步
$.ajax({
url:"TestJqAjax",
type:"get",
/* data:"uname=zhangsan&realname=张三丰", */
data:{uname:"zhangsan",realname:"张三丰"},
cache:false,
async:false,
success:function(result){
alert(result);
}
});
}

//ajax的get方式的请求
function jqAjaxGet(){
//url,[data],[callback](当ajax发送成功后调用的函数)
$.get("TestJqAjax",{uname:"zhangsan",realname:"张三丰"},function(result){
alert(result);
});

}

function  jqAjaxPost() {
//url,[data],[callback](当ajax发送成功后调用的函数)
$.post("TestJqAjax",{uname:"zhangsan",realname:"张三丰"},function(result){
alert(result);
});
}
</script>

370.Js截取字符串abcdefg的efg

function test2(){
var str = "abcdefg";
var substr = str.substring(4);
alert(substr);
}

371.http的请求头信息包含了什么?

请求行(请求方式,资源路径,协议和协议版本号)

若干请求头

请求实体内容

372.http的响应码200,404,302,500表示的含义分别是?

200 - 确定。客户端请求已成功

302 - 临时移动转移,请求的内容已临时移动新的位置

404 - 未找到文件或目录

500 - 服务器内部错误

373.Servlet中request对象的方法有?

/获取网络信息
private void getNet(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("TestHttpRequest.getNet(获取客户端的ip):"+req.getRemoteAddr());
System.out.println("TestHttpRequest.getNet(获取客户端的端口):"+req.getRemotePort());
System.out.println("TestHttpRequest.getNet(获取服务器的ip):"+req.getLocalAddr());
System.out.println("TestHttpRequest.getNet(获取服务器的端口):"+req.getLocalPort());

}

//获取实体内容
private void getContent(HttpServletRequest req, HttpServletResponse resp) {
//获取单条信息
String uname = req.getParameter("uname");
//获取多条信息,数组格式
String[] favs = req.getParameterValues("fav");
//遍历数组
//判断
if(favs!=null&&favs.length>0){
for (int i = 0; i < favs.length; i++) {
System.out.println("TestHttpRequest.getContent(fav):"+favs[i]);
}
}


String un = req.getParameter("un");
System.out.println("TestHttpRequest.getContent():"+uname+"--"+favs+"--"+un);

}

//获取请求头信息
private void getHeads(HttpServletRequest req, HttpServletResponse resp) {
//获取单条头信息
//System.out.println("TestHttpRequest.getHeads(获取请求头信息-浏览器头信息):"+req.getHeader("User-Agent"));
//获取所有头信息--返回枚举类型
Enumeration strHeads = req.getHeaderNames();
//遍历枚举类型
while (strHeads.hasMoreElements()) {
String strhead = (String) strHeads.nextElement();
System.out.println("TestHttpRequest.getHeads(获取头信息):"+req.getHeader(strhead));
}

}

//获取请求行的信息
private void getLines(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("TestHttpRequest.getLines(请求方式***):"+req.getMethod());
System.out.println("TestHttpRequest.getLines(资源路径):"+req.getRequestURI());
System.out.println("TestHttpRequest.getLines(地址):"+req.getRequestURL());
System.out.println("TestHttpRequest.getLines(协议):"+req.getScheme());
System.out.println("TestHttpRequest.getLines(协议的版本号):"+req.getProtocol());
System.out.println("TestHttpRequest.getLines(获取参数信息):"+req.getQueryString());
System.out.println("TestHttpRequest.getLines(项目名称***):"+req.getContextPath());
}

374.Javascript的常用对象有哪些

常用对象包括日期对象Date,字符串对象String,数组对象Array

//获取并显示系统当前时间

function testDate(){
var date = new Date();
var fmtDate = date.getFullYear()+"-"+(date.getMonth()+1)+
"-"+date.getDate()+"-"+date.getHours()
+":"+date.getMinutes()+":"+date.getSeconds();
alert(fmtDate);
}

//获取出’sxt’的下标位置

function testString(){
var str = 'welcome to beijingsxt';
alert(str.indexOf('sxt'));
 }

//遍历数组信息

function testArray(){
var arr = new Array('a',123,'c',true,'e');
for(var item in arr){
   document.write(arr[item]+" ");
}
}

375.DOM和BOM及其关系

BOM浏览器对象模型,由一系列对象组成,是访问、控制、修改浏览器的属性的方法。

DOM文档对象模型,由一系列对象组成,是访问、检索、修改XHTML文档内容与结构的标准方法。

关系:

–BOM描述了与浏览器进行交互的方法和接口

–DOM描述了处理网页内容的方法和接口

–DOM属于BOM的一个属性

376.JavaScript中获取某个元素的三种方式JavaScript中的三种弹出式消息提醒命令是什么?

window.alert() 显示一个提示信息

window.confirm() 显示一个带有提示信息、确定和取消按钮的对话框

window.prompt() 显示可提示用户输入的对话框

setTimeout与setInterval 的区别

setTimeout和setInterval的语法相同。它们都有两个参数,一个是将要执行的代码字符串,还有一个是以毫秒为单位的时间间隔,当过了那个时间段之后就将执行那段代码。

不过这两个函数还是有区别的,setInterval在执行完一次代码之后,经过了那个固定的时间间隔,它还会自动重复执行代码,而setTimeout只执行一次那段代码。

window.setTimeout("function",time);//设置一个超时对象,只执行一次,无周期

window.setInterval("function",time);//设置一个超时对象,周期='交互时间'

377.JavaScript操作CSS的两种方式

第一种方式:操作元素的属性(对象.style.样式名=样式值;)

//改变直接样式

var child2 = document.createElement("div");
    child2.innerHTML = "child2";
    child2.style.fontWeight = "bold";
    parent.appendChild(child2);

第二种方式:操作元素的类(对象.className=类;)

例如:

var parent = document.getElementById("parent");
   //改变className
   var child0 = document.createElement("div");
   child0.innerHTML = "child0";
   child0.className = "newDiv";
parent.appendChild(child0);

378.静态网页和动态网页的联系和区别

联系:

1)静态网页是网站建设的基础,静态网页和动态网页都要使用到HTMl语言。

2)静态网页是相对于动态网页而言,指没有后台数据库、不含程序和不可交互的网页、是标准的HTML文件,它的文件扩展名是.htm或.html。你编的是什么它显示的就是什么、不会有任何改变。

3)静态网页和动态网页之间并不矛盾,为了网站适应搜索引擎检索的需要,动态网站可以采用静动结合的原则,适合采用动态网页的地方用动态网页,如果必要使用静态网页,则可以考虑用静态网页的方法来实现,在同一个网站上,动态网页内容和静态网页内容同时存在也是很常见的事情。

区别:

1)程序是否在服务器端运行,是重要标志。在服务器端运行的程序、网页、组件,属于动态网页,它们会随不同客户、不同时间,返回不同的网页,例如ASP、PHP、JSP、ASP.net、CGI等。运行于客户端的程序、网页、插件、组件,属于静态网页,例如html页、Flash、javascript、VBscript等等,它们是永远不变的。

2)编程技术不同。静态网页和动态网页主要根据网页制作的语言来区分。静态网页使用语言:HTML。 动态网页使用语言:HTML+ASP 或 HTML+PHP 或 HTML+JSP 等其它网站动态语言。

3)被搜索引擎收录情况不同。由于编程技术不容,静态网页是纯粹HTML格式的网页,页面内容稳定,不论是网页是否被访问,页面都被保存在网站服务器上,很容易被搜索引擎收录。而动态网页的内容是当用户点击请求时才从数据库中调出返回给用户一个网页的内容,并不是存放在服务器上的独立文件,相比较于静态网页而言,动态网页很难被搜索引擎收录。

4)用户访问速度不同。用户访问动态网页时,网页在获得搜索指令后经过数据库的调查匹配,再将与指令相符的内容传递给服务器,通过服务器的编译将网页编译成标准的HTML代码,从而传递给用户浏览器,多个读取过程大大降低了用户的访问速度。而静态网页不同,由于网页内容直接存取在服务器上,省去了服务器的编译过程,用户访问网页速度很快。

5)制作和后期维护工作量不同。动态网页的设计以数据库技术为基础,可以实现多种功能,降低了网站维护的工作量。而静态网页由于没有数据库的支持,网页内容更改时需要直接修改代码,在网站内容制作和维护中,所需的工作量更大。动态网页与静态网页各有特点,网站设计师在网页设计时,主要根据网站的功能需求和网站内容多少选择不同网页。如,网站包含信息量太大时,就需要选择动态网页,反之,则选择静态网页。

379.JSP/ASP/PHP的比较

ASP(Active Server Pages),JSP(JavaServer Pages),PHP(Hypertext Preprocessor)是目前主流的三种动态网页语言。

ASP是微软(Microsoft)所开发的一种后台脚本语言,它的语法和Visual BASIC类似,可以像SSI(Server Side Include)那样把后台脚本代码内嵌到HTML页面中。虽然ASP简单易用,但是它自身存在着许多缺陷,最重要的就是安全性问题。

PHP是一种跨平台的服务器端的嵌入式脚本语言。它大量地借用C,Java和Perl语言的语法, 并耦合PHP自己的特性,使WEB开发者能够快速地写出动态产生页面。它支持目前绝大多数数据库。

JSP是一个简化的Servlet,它是由Sun公司倡导、许多公司参与一起建立的一种动态网页技术标准。JSP技术有点类似ASP技术,它是在传统的网页HTML中插入Java程序段和JSP标记(tag),从而形成JSP文件,后缀名为(*.jsp)。 用JSP开发的Web应用是跨平台的,既能在Linux下运行,也能在其他操作系统上运行。

ASP优点: 无需编译、易于生成、独立于浏览器、面向对象、与任何ActiveX scripting 语言兼容、源程序码不会外漏。

缺点:

1)Windows本身的所有问题都会一成不变的也累加到了它的身上。安全性、稳定性、跨平台性都会因为与NT的捆绑而显现出来。

2)ASP由于使用了COM组件所以它会变的十分强大,但是这样的强大由于Windows NT系统最初的设计问题而会引发大量的安全问题。只要在这样的组件或是操作中一不注意,那么外部攻击就可以取得相当高的权限而导致网站瘫痪或者数据丢失。

3)还无法完全实现一些企业级的功能:完全的集群、负载均横。

PHP优点:

1)一种能快速学习、跨平台、有良好数据库交互能力的开发语言。

2)简单轻便,易学易用。

3 ) 与Apache及其它扩展库结合紧密。

缺点:

1 ) 数据库支持的极大变化。

2 ) 不适合应用于大型电子商务站点。

JSP优点:

1 ) 一处编写随处运行。

2 ) 系统的多台平支持。

3 ) 强大的的可伸缩性。

4 ) 多样化和功能强大的开发工具支持。

缺点:

1) 与ASP一样,Java的一些优势正是它致命的问题所在。

2 ) 开发速度慢

380.CGI/Servlet/JSP的比较

CGI(Common Gateway Interface),通用网关接口,是一种根据请求信息动态产生回应内容的技术。

通过CGI,Web 服务器可以将根据请求不同启动不同的外部程序,并将请求内容转发给该程序,在程序执行结束后,将执行结果作为回应返回给客户端。也就是说,对于每个请求,都要产生一个新的进程进行处理。

Servlet 是在服务器上运行的小程序。在实际运行的时候Java Servlet与Web服务器会融为一体。与CGI不同的是,Servlet对每个请求都是单独启动一个线程,而不是进程。这种处理方式大幅度地降低了系统里的进程数量,提高了系统的并发处理能力。

比较:

1) JSP从本质上说就是Servlet。JSP技术产生于Servlet之后,两者分工协作,Servlet侧重于解决运算和业务逻辑问题,JSP则侧重于解决展示问题。

2 ) 与CGI相比,Servlet效率更高。Servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁。而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于Servlet 。

3)与CGI相比,Servlet更容易使用,功能更强大,具有更好的可移植性,更节省投资。在未来的技术发展过程中,Servlet有可能彻底取代CGI。

381.HTTP协议工作原理及其特点

超文本传输协议(HTTP:Hypertext Transport Protocol)是万维网应用层的协议,它通过两个程序实现:一个是客户端程序(各种浏览器),另一个是服务器 (常称Web服务器) 。这两个通常运行在不同的主机上,通过交换报文来完成网页请求和响应,报文可简单分为请求报文和响应报文。

工作原理(流程):

客户机与服务器建立连接后,浏览器可以向web服务器发送请求并显示收到的网页,当用户在浏览器地址栏中输入一个URL或点击一个超连接时,浏览器就向服务器发出了HTTP请求,请求方式的格式为:统一资源标识符、协议版本号,后边是MIME(Multipurpose Internet Mail Extensions)信息包括请求修饰符、客户机信息和可能的内容。该请求被送往由URL指定的WEB服务器,WEB服务器接收到请求后,进行相应反映,其格式为:一个状态行包括信息的协议版本号、一个成功或错误的代码,后边服务器信息、实体信息和可能的内容。即以HTTP规定的格式送回所要求的文件或其他相关信息,再由用户计算机上的浏览器负责解释和显示。

特点:

1)支持客户/服务器模式。

2)简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。

3)灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。

4)无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。

5)无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

382.get和post的区别

1. Get是不安全的,因为在传输过程,数据被放在请求的URL中;Post的所有操作对用户来说都是不可见的。

2. Get传送的数据量较小,这主要是因为受URL长度限制;Post传送的数据量较大,一般被默认为不受限制。

3. Get限制Form表单的数据集的值必须为ASCII字符;而Post支持整个ISO10646字符集。

4. Get执行效率却比Post方法好。Get是form提交的默认方法。

383.如何解决表单提交的中文乱码问题

1)设置页面编码,若是jsp页面,需编写代码

<%@page language="java" pageEncoding="UTF-8" contentType="text/html;charset=UTF-8" %>

若是html页面,在网页头部(< head>< /head>)中添加下面这段代码

< meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

2)将form表单提交方式变为post方式,即添加method="post";)在Servlet类中编写代码request.setCharacterEncoding("UTF-8"),而且必须写在第一行。

3)如果是get请求,在Servlet类中编写代码

byte [] bytes = str.getBytes("iso-8859-1");

String cstr = new String(bytes,"utf-8");

或者直接修改Tomcat服务器配置文件server.xml增加内容:

URIEncoding="utf-8"

384.绝对路径、根路径、相对路径的含义及其区别

绝对路径指对站点的根目录而言某文件的位置,相对路径指以当前文件所处目录而言某文件的位置,相对路径-以引用文件之网页所在位置为参考基础,而建立出的目录路径。绝对路径-以Web站点根目录为参考基础的目录路径。

先给出一个网站结构图做实例加深理解,A网站(域名为http://www.a.com):/include/a-test.html,/img/a-next.jpg;B网站(域名为http://www.b.com):/include/b-test.html,/img/b-next.jpg。

相对路径是从引用的网页文件本身开始构建的,如果在A网站中的a-test.html中要插入图片a-next.jpg,可以这样做:< img src="../img/a-next.jpg" />,重点是img前面的../,表示从html处于的include开始起步,输入一个../表示回到上面一级父文件夹下,然后再接着img/表示又从父级文件夹下的img文件开始了,最后定位img下面的next.jpg。

根路径是从网站的最底层开始起,一般的网站的根目录就是域名下对应的文件夹,就如D盘是一个网站,双击D盘进入到D盘看到的就是网站的根目录,这种路径的链接样式是这样的:如果在A网站中的a-test.html中要插入图片a-next.jpg,可以这样做:< img src="/img/a-next.jpg" >,以/开头表示从网站根目录算起,找到根目录下面的img文件夹下的next.jpg。

绝对路径就很好理解了,这种路径一般带有网站的域名,如果在A网站中的a-test.html中要插入图片a-next.jpg,需要这样这样写:< img src="http://www.a.com/img/a-next.jpg" >,将图片路径上带有了域名信息,再打个比方:如果在A网站中的a-test.html中要插入B网站的图片b-next.jpg,就需要这样写:< img src="http://www.b.com/img/b-next.jpg" >,这种方法适用与在不同网站之间插入外部网站的图片。

385.如实现servlet的单线程模式

实现servlet的单线程的jsp命令是: <%@ page isThreadSafe=”false”%>。默认isThreadSafe值为true。

属性isThreadSafe=false模式表示它是以Singleton模式运行,该模式implements了接口SingleThreadMode, 该模式同一时刻只有一个实例,不会出现信息同步与否的概念。若多个用户同时访问一个这种模式的页面,那么先访问者完全执行完该页面后,后访问者才开始执行。

属性isThreadSafe=true模式表示它以多线程方式运行。该模式的信息同步,需访问同步方法(用synchronized标记的)来实现。 一般格式如下:

 public synchronized void syncmethod(...){
      while(...) {
        this.wait();
      }
      this.notifyAll();
 }

386.Servlet的生命周期

1、加载:在下列时刻加载 Servlet:(1)如果已配置自动加载选项,则在启动服务器时自动

2、加载 (web.xml中设置< load-on-start>);(2)在服务器启动后,客户机首次向 Servlet 发出请求时;(3)重新加载 Servlet 时(只执行一次)

3、实例化:加载 Servlet 后,服务器创建一个 Servlet 实例。(只执行一次)

4、初始化:调用 Servlet 的 init() 方法。在初始化阶段,Servlet 初始化参数被传递给 Servlet 配置对象ServletConfig。 (只执行一次)

5、请求处理:对于到达服务器的客户机请求,服务器创建针对此次请求的一个“请求”对象和一个“响应”对象。服务器调用 Servlet 的 service() 方法,该方法用于传递“请求”和“响应”对象。service() 方法从“请求”对象获得请求信息、处理该请求并用“响应”对象的方法以将响应传回客户机。service() 方法可以调用其它方法来处理请求,例如 doGet()、doPost() 或其它的方法。(每次请求都执行该步骤)

6、销毁:当服务器不再需要 Servlet, 或重新装入 Servlet 的新实例时,服务器会调用 Servlet 的 destroy() 方法。(只执行一次)

387.转发和重定向的区别

转发是在服务端直接做的事情,是对客户端的同一个request进行传递,浏览器并不知道。重定向是由浏览器来做的事情。重定向时,服务端返回一个response,里面包含了跳转的地址,由浏览器获得后,自动发送一个新request。转发像呼叫转移或者110报警中心,重定向似114查号台。

a) 区别1:跳转效率的不同

转发效率相对高;重定向效率相对低

b) 区别2:实现语句不同

转发 request.getRequestDispatcher("xxxx").forward(request,response) ;

重定向 response.sendRedirect("xxxx")

c) 区别3:是否共有同一个request的数据

转发源组件与目标组件共有同一个request数据

重定向源组件与目标组件不共有同一个request数据(可使用session共有数据)

d) 区别4:浏览器URL地址的不同

转发后浏览器URL地址保持不变(源组件地址)

重定向后浏览器URL地址改变为重定向后的地址(目标组件地址)

e) 区别5:"/"路径的含义不同

转发时"/"代表当前项目的根路径 ;重定向时"/"代表当前服务器的根路径

f) 区别6:跳转范围的不同

只能转发到同一应用中的URL(默认) ;可以重定向任何服务器、任何应用的URL

g) 区别7:刷新是否导致重复提交

转发会导致重复提交(可以通过同步令牌解决);重定向不会导致重复提交

h) 区别8:是否经过过滤器

转发不经过过滤器(默认情况);重定向经过过滤器

388.JSP的执行过程

在JSP运行过程中,首先由客户端发出请求,Web服务器接收到请求后,如果是第一次访问某个jsp页面,Web服务器对它进行以下3个操作。

1)翻译:由.jsp变为.java,由JSP引擎实现。

2)编译:由.java变为.class,由 Java编译器实现。

3)执行:由.class变为.html,用Java虚拟机执行编译文件,然后将执行结果返回给Web服务器,并最终返回给客户端

如果不是第一次访问某个JSP页面,则只执行第三步。所以第一次访问JSP较慢。

389.JSP动作有哪些,简述作用?

jsp:include:在页面被请求的时候引入一个文件。

jsp:useBean:寻找或者实例化一个JavaBean。 jsp:setProperty:设置JavaBean的属性。

jsp:getProperty:输出某个JavaBean的属性。

jsp:forward:把请求转到一个新的页面。 jsp:plugin:根据浏览器类型为Java插件生成OBJECT或EMBED标记。

390.page/request/session/application作用域区别

page:当前页面范围

request:当前页面范围+转发页面(forward)+包含页面(include)

session:当前会话:session在以下几种情况下失效

1)销毁session:Session.invalidate();

2)超过最大非活动间隔时间

3)手动关闭浏览器(session并没有立刻失效,因为服务器端session仍旧存在,超过最大非活动间隔时间后真正失效)

application:当前应用;服务器重新启动前一直有效

391.JSP和Servlet的区别和联系

区别:

1)JSP是在HTML代码里写JAVA代码,框架是HTML;而Servlet是在JAVA代码中写HTML代码,本身是个JAVA类。

2)JSP使人们把显示和逻辑分隔成为可能,这意味着两者的开发可并行进行;而Servlet并没有把两者分开。

3)Servlet独立地处理静态表示逻辑与动态业务逻辑.这样,任何文件的变动都需要对此服务程序重新编译;JSP允许用特殊标签直接嵌入到HTML页面, HTML内容与JAVA内容也可放在单独文件中,HTML内容的任何变动会自动编译装入到服务程序.

4)Servlet需要在web.xml中配置,而JSP无需配置。

5)目前JSP主要用在视图层,负责显示,而Servlet主要用在控制层,负责调度

联系:

1)都是Sun公司推出的动态网页技术。

2)先有Servlet,针对Servlet缺点推出JSP。JSP是Servlet的一种特殊形式,每个JSP页面就是一个Servlet实例——JSP页面由系统翻译成Servlet,Servlet再负责响应用户请求。

392.谈谈过滤器原理及其作用?

原理:

过滤器是运行在服务器端的一个拦截作用的web组件,一个请求来到时,web容器会判断是否有过滤器与该信息资源相关联,如果有则交给过滤器处理,然后再交给目标资源,响应的时候则以相反的顺序交给过滤器处理,最后再返回给用户浏览器

一般用于日志记录、性能、安全、权限管理等公共模块。

过滤器开发:

过滤器是一个实现了javax.servlet.Filter接口的java类

主要业务代码放在doFilter方法中

业务代码完成后要将请求向后传递,即调用FilterChain对象的doFilter方法

配置:

在web.xml中增加如下代码
<filter>
    <filter-name>MyFilter</filter-name>
    <filter-class>Filter完整类名</filter-class>
</filter>
<filter-mapping>
    <filter-name>MyFilter</filter-name>
    <url-pattern>/*(要过虑的url,此处*表示过虑所有的url)</url-pattern>
</filter-mapping>

谈谈监听器作用及其分类?

监听器也叫Listener,是一个实现特定接口的java类,使用时需要在web.xml中配置,它是web服务器端的一个组件,它们用于监听的事件源分别为SerlvetConext,HttpSession和ServletRequest这三个域对象

主要有以下三种操作:

–监听三个域对象创建和销毁的事件监听器

–监听域对象中属性的增加和删除的事件监听器

–监听绑定到HttpSession域中的某个对象的状态的时间监听器

接口分类:

–ServletContextListener

HttpSessionListener

–ServletRequestListener

–ServletContextAttributeListener

–HttpSessionAttributeListener

ServletRequestAttributeListener

–HttpSessionBindingListener(不需要配置)

–HttpSessionActivationListener(不需要配置)

配置:

< listener>< listener-class>实现以上任意接口的java类全名< /listener-class>< /listener>

393.jQuery相比JavaScript的优势在哪里

jQuery的语法更加简单。

jQuery消除了JavaScript跨平台兼容问题。

相比其他JavaScript和JavaScript库,jQuery更容易使用。

jQuery有一个庞大的库/函数。

jQuery有良好的文档和帮助手册。

jQuery支持AJAX

394.DOM对象和jQuery对象的区别及其转换

DOM对象,是我们用传统的方法(javascript)获得的对象,jQuery对象即是用jQuery类库的选择器获得的对象,它是对DOM对象的一种封装,jQuery对象不能使用DOM对象的方法,只能使用jQuery对象自己的方法。

普通的dom对象一般可以通过$()转换成jquery对象

如:var cr=document.getElementById("cr"); //dom对象

var $cr = $(cr); //转换成jquery对象

由于jquery对象本身是一个集合。所以如果jquery对象要转换为dom对象则必须取出其中的某一项,一般可通过索引取出

如:$("#msg")[0],$("div").eq(1)[0],$("div").get()[1],$("td")[5]这几种语法在jQuery中都是合法的

395.jQuery中$的作用主要有哪些

1)$用作选择器

例如:根据id获得页面元素$("#元素ID")

2)$相当于window.onload 和 $(document).ready(...)

例如:$(function(){...}); function(){...}会在DOM树加载完毕之后执行。

3)$用作JQuery的工具函数的前缀

例如: var str = ' Welcome to shanghai.com ';

str = $.trim(str);去掉空格

4)$(element):把DOM节点转化成jQuery节点

例如:var cr=document.getElementById("cr"); //dom对象

var $cr = $(cr); //转换成jquery对象

5)$(html):使用HTML字符串创建jQuery节点

例如:var obj = $("< div>尚学堂,实战化教学第一品牌< /div>")

396.Ajax含义及其主要技术

Ajax (Asynchronous JavaScript and XML 阿贾克斯)不是一个新的技术,事实上,它是一些旧有的成熟的技术以一种全新的更加强大的方式整合在一起。

Ajax的关键技术:

1)使用CSS构建用户界面样式,负责页面排版和美工

2)使用DOM进行动态显示和交互,对页面进行局部修改

3)使用XMLHttpRequest异步获取数据

4)使用JavaScript将所有元素绑定在一起

397.Ajax的工作原理

Ajax的原理简单来说通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM而更新页面。这其中最关键的一步就是从服务器获得请求数据。要清楚这个过程和原理,我们必须对 XMLHttpRequest有所了解。

XMLHttpRequest是ajax的核心机制,它是在IE5中首先引入的,是一种支持异步请求的技术。简单的说,也就是javascript可以及时向服务器提出请求和处理响应,而不阻塞用户。达到无刷新的效果。

398.JSON及其作用

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,是理想的数据交换格式。同时,JSON是 JavaScript 原生格式,这意味着在 JavaScript 中处理 JSON数据不须要任何特殊的 API 或工具包。

在JSON中,有两种结构:对象和数组。

{} 对象

[] 数组

, 分隔属性

: 左边为属性名,右边为属性值 

属性名可用可不用引号括起,属性值为字符串一定要用引号括起

举例:

varo={
    "xlid": "cxh",
    "xldigitid": 123456,
    "topscore": 2000,
    "topplaytime": "2009-08-20"
};

jsonranklist=[
    {
        "xlid": "cxh",
        "xldigitid": 123456,
        "topscore": 2000,
        "topplaytime": "2009-08-20"
    },
    {
        "xlid": "zd",
        "xldigitid": 123456,
        "topscore": 1500,
        "topplaytime": "2009-11-20"
    }
];

399.文件上传组件Common-fileUpload的常用类及其作用?

DiskFileItemFactory:磁盘文件工厂类,设置上传文件保存的磁盘目录,缓冲区大小。

ServletFileUpload:上传处理类,此类真正读取客户上传的文件,同时可以设置最大接收大小。

FileItem:上传的文件对象,可以是多个文件,每个上传的文件都是一个单独的FileItem对象。

400.说出Servlet的生命周期,并说出Servlet和CGI的区别?

答:Web容器加载Servlet并将其实例化后,Servlet生命周期开始,容器运行其init()方法进行Servlet的初始化;请求到达时调用Servlet的service方法,service方法会调用与请求对应的doGet或doPost等方法;当服务器关闭会项目被卸载时服务器会将Servlet实例销毁,此时会调用Servlet的destroy方法。Servlet与CGI的区别在于Servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI 对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于Servlet。

【补充1】SUN公司在1996年发布Servlet技术就是为了和CGI进行竞争,Servlet是一个特殊的Java程序,一个基于Java的Web应用通常包含一个或多个Servlet类。 Servlet不能够自行创建并执行,它是在Servlet容器中运行的,容器将用户的请求传递给Servlet程序,此外将Servlet的响应回传给用户。通常一个Servlet会关联一个或多个JSP页面。以前CGI经常因为性能开销上的问题被诟病,然而Fast CGI早就已经解决了CGI效率上的问题,所以面试的时候大可不必诟病CGI,腾讯的网站就使用了CGI技术,相信你也没感觉它哪里不好。

【补充2】Servlet接口定义了5个方法,其中前三个方法与Servlet生命周期相关:

void init(ServletConfig config) throws ServletException

void service(ServletRequest req, ServletResponse resp) throws ServletException, java.io.IOException

void destory()

java.lang.String getServletInfo()

ServletConfig getServletConfig()

401.JSP 和Servlet 有有什么关系?

答:其实这个问题在上面已经阐述过了,Servlet是一个特殊的Java程序,它运行于服务器的JVM中,能够依靠服务器的支持向浏览器提供显示内容。JSP本质上是Servlet的一种简易形式, JSP会被服务器处理成一个类似于Servlet的Java程序,可以简化页面内容的生成。Servlet和JSP最主要的不同点在于,Servlet 的应用逻辑是在Java 文件中,并且完全从表示层中的HTML分离开来。而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp 的文件(有人说,Servlet就是在Java中写HTML,而JSP就是在HTML中写Java代码,当然,这个说法还是很片面的)。JSP侧重于视图,Servlet更侧重于控制逻辑,在MVC架构模式中,JSP适合充当视图(view)而Servlet适合充当控制器(controller)。

402.JSP中的四种作用域?

答:page、request、session和application,具体如下:

①page 代表与一个页面相关的对象和属性。

②request 代表与Web客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个Web 组件;需要在页面显示的临时数据可以置于此作用域

③session代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户自己的session中

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

403.如何实现JSP或Servlet的单线程模式?

<%@page isThreadSafe=”false”%>

【补充】Servlet默认的工作模式是单实例多线程,如果Servlet实现了标识接口SingleThreadModel又或是JSP页面通过page指令设置isThreadSafe属性为false,那么它们生成的Java代码会以单线程多实例方式工作。显然,这样做会导致每个请求创建一个Servlet实例,这种实践将导致严重的性能问题。

404.实现会话跟踪的技术有哪些?

答:由于HTTP协议本身是无状态的,服务器为了区分不同的用户,就需要对用户会话进行跟踪,简单的说就是为用户进行登记,为用户分配唯一的ID,下一次用户在请求中包含此ID,服务器据此判断到底是哪一个用户。

①URL 重写:在URL中添加用户会话的信息作为请求的参数,或者将唯一的会话ID添加到URL结尾以标识一个会话。

②设置表单隐藏域:将和会话跟踪相关的字段添加到隐式表单域中,这些信息不会在浏览器中显示但是提交表单时会提交给服务器。

这两种方式很难处理跨越多个页面的信息传递,因为如果每次都要修改URL或在页面中添加隐式表单域来存储用户会话相关信息,事情将变得非常麻烦。

③cookie:cookie有两种,一种是基于窗口的,浏览器窗口关闭后,cookie就没有了;另一种是将信息存储在一个临时文件中,并设置存在的时间。当用户通过浏览器和服务器建立一次会话后,会话ID就会随响应信息返回存储在基于窗口的cookie中,那就意味着只要浏览器没有关闭,会话没有超时,下一次请求时这个会话ID又会提交给服务器让服务器识别用户身份。会话中可以为用户保存信息。会话对象是在服务器内存中的,而基于窗口的cookie是在客户端内存中的。如果浏览器禁用了cookie,那么就需要通过下面两种方式进行会话跟踪。当然,在使用cookie时要注意几点:首先不要在cookie中存放敏感信息;其次cookie存储的数据量有限(4k),不能将过多的内容存储cookie中;再者浏览器通常只允许一个站点最多存放20个cookie。当然,和用户会话相关的其他信息(除了会话ID)也可以存在cookie方便进行会话跟踪。

④HttpSession:在所有会话跟踪技术中,HttpSession对象是最强大也是功能最多的。当一个用户第一次访问某个网站时会自动创建HttpSession,每个用户可以访问他自己的HttpSession。可以通过HttpServletRequest对象的getSession方法获得HttpSession,通过HttpSession的setAttribute方法可以将一个值放在HttpSession中,通过调用HttpSession对象的getAttribute方法,同时传入属性名就可以获取保存在HttpSession中的对象。与上面三种方式不同的是,HttpSession放在服务器的内存中,因此不要将过大的对象放在里面,即使目前的Servlet容器可以在内存将满时将HttpSession中的对象移到其他存储设备中,但是这样势必影响性能。添加到HttpSession中的值可以是任意Java对象,这个对象最好实现了Serializable接口,这样Servlet容器在必要的时候可以将其序列化到文件中,否则在序列化时就会出现异常。

405.过滤器有哪些作用和用法?

答: Java Web开发中的过滤器(filter)是从Servlet 2.3规范开始增加的功能,并在Servlet 2.4规范中得到增强。对Web应用来说,过滤器是一个驻留在服务器端的Web组件,它可以截取客户端和服务器之间的请求与响应信息,并对这些信息进行过滤。当Web容器接受到一个对资源的请求时,它将判断是否有过滤器与这个资源相关联。如果有,那么容器将把请求交给过滤器进行处理。在过滤器中,你可以改变请求的内容,或者重新设置请求的报头信息,然后再将请求发送给目标资源。当目标资源对请求作出响应时候,容器同样会将响应先转发给过滤器,再过滤器中,你可以对响应的内容进行转换,然后再将响应发送到客户端。

常见的过滤器用途主要包括:对用户请求进行统一认证、对用户的访问请求进行记录和审核、对用户发送的数据进行过滤或替换、转换图象格式、对响应内容进行压缩以减少传输量、对请求或响应进行加解密处理、触发资源访问事件、对XML的输出应用XSLT等。

和过滤器相关的接口主要有:Filter、FilterConfig、FilterChain

406.监听器有哪些作用和用法?

答:Java Web开发中的监听器(listener)就是application、session、request三个对象创建、销毁或者往其中添加修改删除属性时自动执行代码的功能组件,如下所示:

①ServletContextListener:对Servlet上下文的创建和销毁进行监听。

②ServletContextAttributeListener:监听Servlet上下文属性的添加、删除和替换。

③HttpSessionListener:对Session的创建和销毁进行监听。

补充:session的销毁有两种情况:1session超时(可以在web.xml中通过< session-config>/< session-timeout>标签配置超时时间);2通过调用session对象的invalidate()方法使session失效。

④HttpSessionAttributeListener:对Session对象中属性的添加、删除和替换进行监听。

⑤ServletRequestListener:对请求对象的初始化和销毁进行监听。

⑥ServletRequestAttributeListener:对请求对象属性的添加、删除和替换进行监听。

407.你的项目中使用过哪些JSTL标签?

答:项目中主要使用了JSTL的核心标签库,包括< c:if>、< c:choose>、< c: when>、< c: otherwise>、< c:forEach>等,主要用于构造循环和分支结构以控制显示逻辑。

【说明】虽然JSTL标签库提供了core、sql、fmt、xml等标签库,但是实际开发中建议只使用核心标签库(core),而且最好只使用分支和循环标签并辅以表达式语言(EL),这样才能真正做到数据显示和业务逻辑的分离,这才是最佳实践。

408.使用标签库有什么好处?如何自定义JSP标签?

答:使用标签库的好处包括以下几个方面:

分离JSP页面的内容和逻辑,简化了Web开发;

开发者可以创建自定义标签来封装业务逻辑和显示逻辑;

标签具有很好的可移植性、可维护性和可重用性;

避免了对Scriptlet(小脚本)的使用(很多公司的项目开发都不允许在JSP中书写小脚本)

自定义JSP标签包括以下几个步骤:

编写一个Java类实现实现Tag/BodyTag/IterationTag接口(通常不直接实现这些接口而是继承TagSupport/BodyTagSupport/SimpleTagSupport类,这是对适配器模式中缺省适配模式的应用)

重写doStartTag()、doEndTag()等方法,定义标签要完成的功能

编写扩展名为tld的标签描述文件对自定义标签进行部署,tld文件通常放在WEB-INF文件夹或其子目录

在JSP页面中使用taglib指令引用该标签库

下面是一个例子:

package com.bjsxt;
package com.lovo.tags;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.TagSupport;

public class TimeTag extends TagSupport {
    private static final long serialVersionUID = 1L;

    private String format = "yyyy-MM-dd hh:mm:ss";
    private String foreColor = "black";
    private String backColor = "white";

    public int doStartTag() throws JspException {
         SimpleDateFormat sdf = new SimpleDateFormat(format);
         JspWriter writer = pageContext.getOut();
         StringBuilder sb = new StringBuilder();
         sb.append(String.format("<span style='color:%s;background-color:%s'>%s</span>",
             foreColor, backColor, sdf.format(new Date())));
         try {
           writer.print(sb.toString());
         } catch(IOException e) {
           e.printStackTrace();
         }
         return SKIP_BODY;
      }

    public void setFormat(String format) {
        this.format = format;
    }

    public void setForeColor(String foreColor) {
        this.foreColor = foreColor;
    }

    public void setBackColor(String backColor) {
        this.backColor = backColor;
    }
}

标签库描述文件(该文件通常放在WEB-INF目录或其子目录下)

<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
    http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
    version="2.0">

    <description>定义标签库</description>
    <tlib-version>1.0</tlib-version>
    <short-name>MyTag</short-name>
    <tag>
        <name>time</name>
        <tag-class>com.lovo.tags.TimeTag</tag-class>
        <body-content>empty</body-content>
        <attribute>
            <name>format</name>
            <required>false</required>
        </attribute>
        <attribute>
            <name>foreColor</name>
        </attribute>
        <attribute>
            <name>backColor</name>
        </attribute>
    </tag>
</taglib>

JSP页面

<%@ page pageEncoding="UTF-8"%>
<%@ taglib prefix="my" uri="/WEB-INF/tld/my.tld" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE html>
<html>
  <head>
    <base href="<%=basePath%>">
    <title>首页</title>
    <style type="text/css">
        * { font-family: "Arial"; font-size:72px; }
    </style>
  </head>

  <body>
    <my:time format="yyyy-MM-dd" backColor="blue" foreColor="yellow"/>
  </body>
</html>

运行结果

【注意】如果要将自定义的标签库发布成JAR文件,需要将标签库描述文件(tld文件)放在JAR文件的META-INF目录下,可以JDK自带的jar工具完成JAR文件的生成。

409.表达式语言(EL)的隐式对象及其作用?

答: pageContext、initParam(访问上下文参数)、param(访问请求参数)、paramValues、header(访问请求头)、headerValues、cookie(访问cookie)、applicationScope(访问application作用域)、sessionScope(访问session作用域)、requestScope(访问request作用域)、pageScope(访问page作用域)。用法如下所示:

${pageContext.request.method}

${pageContext["request"]["method"]}

${pageContext.request["method"]}

${pageContext["request"].method}

${initParam.defaultEncoding}

${header["accept-language"]}

${headerValues["accept-language"][0]}

${cookie.jsessionid.value}

${sessionScope.loginUser.username}

【补充】表达式语言的.和[]运算作用是一致的,唯一的差别在于如果访问的属性名不符合Java标识符命名规则,例如上面的accept-language就不是一个有效的Java标识符,那么这时候就只能用[]运算符而不能使用.获取它的值

410.表达式语言(EL)支持哪些运算符?

答:除了.和[]运算符,EL还提供了:

算术运算符:+、-、*、/或div、%或mod

关系运算符:==或eq、!=或ne、>或gt、>=或ge、< 或lt、< =或le

逻辑运算符:&&或and、||或or、!或not

条件运算符:${statement? A : B}(跟Java的条件运算符类似)

empty运算符:检查一个值是否为null或者空(数组长度为0或集合中没有元素也返回true)

411.Servlet 3中的异步处理指的是什么?

答:在Servlet 3中引入了一项新的技术可以让Servlet异步处理请求。有人可能会质疑,既然都有多线程了,还需要异步处理请求吗?答案是肯定的,因为如果一个任务处理时间相当长,那么Servlet或Filter会一直占用着请求处理线程直到任务结束,随着并发用户的增加,容器将会遭遇线程超出的风险,这这种情况下很多的请求将会被堆积起来而后续的请求可能会遭遇拒绝服务,直到有资源可以处理请求为止。异步特性可以帮助应用节省容器中的线程,特别适合执行时间长而且用户需要得到结果的任务,如果用户不需要得到结果则直接将一个Runnable对象交给Executor(如果不清楚请查看前文关于多线程和线程池的部分)并立即返回即可。

【补充】多线程在Java诞生初期无疑是一个亮点,而Servlet单实例多线程的工作方式也曾为其赢得美名,然而技术的发展往往会颠覆我们很多的认知,就如同当年爱因斯坦的相对论颠覆了牛顿的经典力学一般。事实上,异步处理绝不是Serlvet 3首创,如果你了解Node.js的话,对Servlet 3的这个重要改进就不以为奇了。

412.如何在基于Java的Web项目中实现文件上传和下载?

答:(稍后呈现,我准备用HTML5写一个带进度条的客户端,然后再用Servlet 3提供的文件上传支持来做一个多文件上传的例子)

413.简述值栈(Value-Stack)的原理和生命周期

答: Value-Stack贯穿整个 Action 的生命周期,保存在request作用域中,所以它和request的生命周期一样。当Struts 2接受一个请求时,会创建ActionContext、Value-Stack和Action对象,然后把Action存放进Value-Stack,所以Action的实例变量可以通过OGNL访问。由于Action是多实例的,和使用单例的Servlet不同, 每个Action都有一个对应的Value-Stack,Value-Stack存放的数据类型是该Action的实例,以及该Action中的实例变量,Action对象默认保存在栈顶。

414.阐述Session加载实体对象的过程。

答:Session加载实体对象的步骤是:

① Session在调用数据库查询功能之前, 首先会在缓存中进行查询, 在一级缓存中, 通过实体类型和主键进行查找, 如果一级缓存查找命中且数据状态合法, 则直接返回

② 如果一级缓存没有命中, 接下来Session会在当前NonExists记录(相当于一个查询黑名单, 如果出现重复的无效查询可以迅速判断, 从而提升性能)中进行查找, 如果NonExists中存在同样的查询条件,则返回null

③ 对于load方法, 如果一级缓存查询失败则查询二级缓存, 如果二级缓存命中则直接返回

④ 如果之前的查询都未命中, 则发出SQL语句, 如果查询未发现对应记录则将此次查询添加到Session的NonExists中加以记录, 并返回null

⑤ 根据映射配置和SQL语句得到ResultSet,并创建对应的实体对象

⑥ 将对象纳入Session(一级缓存)管理

⑦ 执行拦截器的onLoad方法(如果有对应的拦截器)

⑧ 将数据对象纳入二级缓存

⑨ 返回数据对象

415.怎么防止重复提交

1.禁掉提交按钮。表单提交后使用Javascript使提交按钮disable。这种方法防止心急的用户多次点击按钮。但有个问题,如果客户端把Javascript给禁止掉,这种方法就无效了。

2.Post/Redirect/Get模式。在提交后执行页面重定向,这就是所谓的Post-Redirect-Get (PRG)模式。简言之,当用户提交了表单后,你去执行一个客户端的重定向,转到提交成功信息页面。

这能避免用户按F5导致的重复提交,而其也不会出现浏览器表单重复提交的警告,也能消除按浏览器前进和后退按导致的同样问题。

3.在session中存放一个特殊标志。当表单页面被请求时,生成一个特殊的字符标志串,存在session中,同时放在表单的隐藏域里。接受处理表单数据时,检查标识字串是否存在,并立即从session中删除它,然后正常处理数据。

如果发现表单提交里没有有效的标志串,这说明表单已经被提交过了,忽略这次提交。

4.在数据库里添加约束。在数据库里添加唯一约束或创建唯一索引,防止出现重复数据。这是最有效的防止重复提交数据的方法。

416.$(document).ready(function(){}) jQuery(document).ready(function(){}); 有什么区别?

window.jQuery = window.$ = jQuery;

这两者可以互换使用。一般建议优先使用$

417.写出输出结果

<script>
                        function Foo() {
                        getName = function (){alert(1);};
                        return this;
                        }
                        Foo.getName = function() {alert (2);};
                        Foo.prototype.getName = function (){ alert (3);};
                        var getName = function (){alert (4);};
                        function getName(){alert (5);}
                        </script>

//请写出以下输出结果:

Foo.getName(); // 2

getName(); // 4

Foo().getName(); // 1

getName(); // 1

new Foo.getName(); // 2

new Foo().getName(); // 3

new new Foo().getName(); // 3

418.web项目从浏览器发起交易响应缓慢,请简述从哪些方面如数分析

从前端后端分别取考虑,后台是不是数据库死锁等。

前台看看是不是js 错误,或者图片过大,dom 渲染dom树,画面优化。cmd amd 规范等

设计模式
419.请写出您熟悉的几种设计模式,并做简单介绍。

答:工厂设计模式:程序在接口和子类之间加入了一个过渡端,通过此过渡端可以动态取得实现了共同接口的子类实例化对象。

代理设计模式:指由一个代理主题来操作真实主题,真实主题执行具体的业务操作,而代理主题负责其他相关业务的处理。比如生活中的通过代理访问网络,客户通过网络代理连接网络(具体业务),由代理服务器完成用户权限和访问限制等与上网相关的其他操作(相关业务)

适配器模式:如果一个类要实现一个具有很多抽象方法的接口,但是本身只需要实现接口中的部分方法便可以达成目的,所以此时就需要一个中间的过渡类,但此过渡类又不希望直接使用,所以将此类定义为抽象类最为合适,再让以后的子类直接继承该抽象类便可选择性的覆写所需要的方法,而此抽象类便是适配器类。

420.写出你用过的设计模式,并至少写出2种模式的类图或关键代码。

工厂设计模式:

思路说明:由一个工厂类根据传入的参数(一般是字符串参数),动态决定应该创建哪一个产品子类(这些产品子类继承自同一个父类或接口)的实例,并以父类形式返回

优点:客户端不负责对象的创建,而是由专门的工厂类完成;客户端只负责对象的调用,实现了创建和调用的分离,降低了客户端代码的难度;

缺点:如果增加和减少产品子类,需要修改简单工厂类,违背了开闭原则;如果产品子类过多,会导致工厂类非常的庞大,违反了高内聚原则,不利于后期维护。

public class SimpleFactory {
public static Product createProduct(String pname){
Product product=null;
if("p1".equals(pname)){
product = new Product1();
}else if("p2".equals(pname)){
product = new Product2();
}else if("pn".equals(pname)){
product = new ProductN();
}
return product;
}
}

单例模式

/**
 * 饿汉式的单例模式
 * 在类加载的时候创建单例实例,而不是等到第一次请求实例的时候的时候创建
* 1、私有 的无参数构造方法Singleton(),避免外部创建实例
 * 2、私有静态属性instance
 * 3、公有静态方法getInstance()
 */
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton(){ }
public static Singleton getInstance(){
return instance;
}
}
/**
 * 懒汉式的单例模式
 *在类加载的时候不创建单例实例,只有在第一次请求实例的时候的时候创建
*/
public class Singleton {
private static Singleton instance;
private Singleton(){ }
/**
 * 多线程情况的单例模式,避免创建多个对象
*/
public static Singleton getInstance(){
if(instance ==null){//避免每次加锁,只有第一次没有创建对象时才加锁
synchronized(Singleton.class){//加锁,只允许一个线程进入
if(instance==null){ //只创建一次对象
instance = new Singleton();
}
}
}
return instance;
}}
421.列出除Singleton外的常用的3种设计模式,并简单描述

答:工厂模式:工厂模式是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

适配器模式:适配器模式是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。

模板模式:在模板模式中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。

422.Action是单实例还是多实例,为什么?

答:struts2中action是多例的,即一个session产生一个action

背景:

1) Struts2会对每一个请求,产生一个Action的实例来处理.

2) Spring的Ioc容器管理的bean默认是单实例的.

首先从数据安全性的问题上考虑,我们的Action应该保证是多例的,这样才不会出现数据问题。但是如果有的action比如只有admin才能操作,或者某些action,全站公用一个来提高性能,这样的话,就可以使用单例模式。

不过幸好,Spring的bean可以针对每一个设置它的scope,所以,上面的问题就不是问题了。如果用单例,就在spring的action bean配置的时候设置scope=”prototype”

如果是单例的话,若出现两个用户都修改一个对象的属性值,则会因为用户修改时间不同,两个用户访问得到的属性不一样,操作得出的结果不一样.

举个例子:有一块布长度300cm,能做一件上衣(用掉100cm)和一件裤子(用掉200cm);甲和乙同时访问得到的长度都是300cm,

甲想做上衣和裤子,他先截取100cm去做上衣,等上衣做完再去做裤子,而乙这时正好也拿100cm去做上衣,那好,等甲做完上衣再做裤子的时候发现剩下的布(100cm)已经不够做裤子了…..这就是影响系统的性能,解决的办法就是给甲和乙一人一块300cm的布,就不会出现布被别人偷用的事情,也是就单实例和多实例的区别

如果设置成单例,那么多个线程会共享一个ActionContext和ValueStack,这样并发访问的时候就会出现问题了

struts 2的Action是多实例的并非单例,也就是每次请求产生一个Action的对象。原因是:struts 2的Action中包含数据,例如你在页面填写的数据就会包含在Action的成员变量里面。如果Action是单实例的话,这些数据在多线程的环境下就会相互影响,例如造成别人填写的数据被你看到了。所以Struts2的Action是多例模式的。

问题出现了,可以让Struts2的action变成单例模式么?

Struts2中,可以使用注解开发,在Action上@Scope(“prototype”) 指定为多例 , 默认为singleton()单例)

基本上action的scope需要是prototype,就是每次请求都建立新的线程

不写的话,默认是singleton了

423.写一个单例类

答:单例模式主要作用是保证在Java应用程序中,一个类只有一个实例存在。下面给出两种不同形式的单例:

第一种形式:饿汉式单例 

package com.bjsxt;

public class Singleton {
    private Singleton(){}
    private static Singleton instance = new Singleton();
    public static Singleton getInstance(){
        return instance;
    }
}

第二种形式:懒汉式单例

package com.bjsxt;

public class Singleton {
    private static Singleton instance = null;
    private Singleton() {}
    public static synchronized Singleton getInstance(){
        if (instance==null) instance=newSingleton();
        return instance;
    }
}

单例的特点:外界无法通过构造器来创建对象,该类必须提供一个静态方法向外界提供该类的唯一实例。

【补充】用Java进行服务器端编程时,使用单例模式的机会还是很多的,服务器上的资源都是很宝贵的,对于那些无状态的对象其实都可以单例化或者静态化(在内存中仅有唯一拷贝),如果使用了spring这样的框架来进行对象托管,Spring的IoC容器在默认情况下对所有托管对象都是进行了单例化处理的。 

424.说说你所熟悉或听说过的设计模式以及你对设计模式的看法

答:在GoF的《Design Patterns: Elements of Reusable Object-Oriented Software》中给出了三类(创建型[对类的实例化过程的抽象化]、结构型[描述如何将类或对象结合在一起形成更大的结构]、行为型[对在不同的对象之间划分责任和算法的抽象化])共23种设计模式,包括:Abstract Factory(抽象工厂模式),Builder(建造者模式),Factory Method(工厂方法模式),Prototype(原始模型模式),Singleton(单例模式);Facade(门面模式),Adapter(适配器模式),Bridge(桥梁模式),Composite(合成模式),Decorator(装饰模式),Flyweight(享元模式),Proxy(代理模式);Command(命令模式),Interpreter(解释器模式),Visitor(访问者模式),Iterator(迭代子模式),Mediator(调停者模式),Memento(备忘录模式),Observer(观察者模式),State(状态模式),Strategy(策略模式),Template Method(模板方法模式), Chain Of Responsibility(责任链模式)。

所谓设计模式,就是一套被反复使用的代码设计经验的总结(情境中一个问题经过证实的一个解决方案)。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。设计模式使人们可以更加简单方便的复用成功的设计和体系结构。将已证实的技术表述成设计模式也会使新系统开发者更加容易理解其设计思路。

【补充】设计模式并不是像某些地方吹嘘的那样是遥不可及的编程理念,说白了设计模式就是对面向对象的编程原则的实践,面向对象的编程原则包括:

单一职责原则:一个类只做它该做的事情。(单一职责原则想表达的就是“高内聚”,写代码最终极的原则只有六个字“高内聚、低耦合”,就如同葵花宝典或辟邪剑谱的中心思想就八个字“欲练此功必先自宫”,所谓的高内聚就是一个代码模块只完成一项功能,在面向对象中,如果只让一个类完成它该做的事,而不涉及与它无关的领域就是践行了高内聚的原则,这个类就只有单一职责。我们都知道一句话叫“因为专注,所以专业”,一个对象如果承担太多的职责,那么注定它什么都做不好。这个世界上任何好的东西都有两个特征,一个是功能单一,好的相机绝对不是电视购物里面卖的那种一个机器有一百多种功能的,它基本上只能照相;另一个是模块化,好的自行车是组装车,从减震叉、刹车到变速器,所有的部件都是可以拆卸和重新组装的,好的乒乓球拍也不是成品拍,一定是底板和胶皮可以拆分和自行组装的,一个好的软件系统,它里面的每个功能模块也应该是可以轻易的拿到其他系统中使用的,这样才能实现软件复用的目标。)

开闭原则:软件实体应当对扩展开放,对修改关闭。(在理想的状态下,当我们需要为一个软件系统增加新功能时,只需要从原来的系统派生出一些新类就可以,不需要修改原来的任何一行代码。要做到开闭有两个要点:①抽象是关键,一个系统中如果没有抽象类或接口系统就没有扩展点;②封装可变性,将系统中的各种可变因素封装到一个继承结构中,如果多个可变因素混杂在一起,系统将变得复杂而换乱,如果不清楚如何封装可变性,可以参考《设计模式精解》一书中对桥梁模式的讲解的章节。)

依赖倒转原则:面向接口编程。(该原则说得直白和具体一些就是声明方法的参数类型、方法的返回类型、变量的引用类型时,尽可能使用抽象类型而不用具体类型,因为抽象类型可以被它的任何一个子类型所替代,请参考下面的里氏替换原则。)

里氏替换原则:任何时候都可以用子类型替换掉父类型。(关于里氏替换原则的描述,Barbara Liskov女士的描述比这个要复杂得多,但简单的说就是能用父类型的地方就一定能使用子类型。里氏替换原则可以检查继承关系是否合理,如果一个继承关系违背了里氏替换原则,那么这个继承关系一定是错误的,需要对代码进行重构。例如让猫继承狗,或者狗继承猫,又或者让正方形继承长方形都是错误的继承关系,因为你很容易找到违反里氏替换原则的场景。需要注意的是:子类一定是增加父类的能力而不是减少父类的能力,因为子类比父类的能力更多,把能力多的对象当成能力少的对象来用当然没有任何问题。)

接口隔离原则:接口要小而专,绝不能大而全。(臃肿的接口是对接口的污染,既然接口表示能力,那么一个接口只应该描述一种能力,接口也应该是高度内聚的。例如,琴棋书画就应该分别设计为四个接口,而不应设计成一个接口中的四个方法,因为如果设计成一个接口中的四个方法,那么这个接口很难用,毕竟琴棋书画四样都精通的人还是少数,而如果设计成四个接口,会几项就实现几个接口,这样的话每个接口被复用的可能性是很高的。Java中的接口代表能力、代表约定、代表角色,能否正确的使用接口一定是编程水平高低的重要标识。)

合成聚合复用原则:优先使用聚合或合成关系复用代码。(通过继承来复用代码是面向对象程序设计中被滥用得最多的东西,因为所有的教科书都无一例外的对继承进行了鼓吹从而误导了初学者,类与类之间简单的说有三种关系,IS-A关系、HAS-A关系、USE-A关系,分别代表继承、关联和依赖。其中,关联关系根据其关联的强度又可以进一步划分为关联、聚合和合成,但说白了都是HAS-A关系,合成聚合复用原则想表达的是优先考虑HAS-A关系而不是IS-A关系复用代码,原因嘛可以自己从百度上找到一万个理由,需要说明的是,即使在Java的API中也有不少滥用继承的例子,例如Properties类继承了Hashtable类,Stack类继承了Vector类,这些继承明显就是错误的,更好的做法是在Properties类中放置一个Hashtable类型的成员并且将其键和值都设置为字符串来存储数据,而Stack类的设计也应该是在Stack类中放一个Vector对象来存储数据。记住:任何时候都不要继承工具类,工具是可以拥有并可以使用的(HAS/USE),而不是拿来继承的。)

迪米特法则:迪米特法则又叫最少知识原则,一个对象应当对其他对象有尽可能少的了解。(迪米特法则简单的说就是如何做到“低耦合”,门面模式和调停者模式就是对迪米特法则的践行。对于门面模式可以举一个简单的例子,你去一家公司洽谈业务,你不需要了解这个公司内部是如何运作的,你甚至可以对这个公司一无所知,去的时候只需要找到公司入口处的前台美女,告诉她们你要做什么,她们会找到合适的人跟你接洽,前台的美女就是公司这个系统的门面。再复杂的系统都可以为用户提供一个简单的门面,Java Web开发中作为前端控制器的Servlet或Filter不就是一个门面吗,浏览器对服务器的运作方式一无所知,但是通过前端控制器就能够根据你的请求得到相应的服务。调停者模式也可以举一个简单的例子来说明,例如一台计算机,CPU、内存、硬盘、显卡、声卡各种设备需要相互配合才能很好的工作,但是如果这些东西都直接连接到一起,计算机的布线将异常复杂,在这种情况下,主板作为一个调停者的身份出现,它将各个设备连接在一起而不需要每个设备之间直接交换数据,这样就减小了系统的耦合度和复杂度。迪米特法则用通俗的话来将就是不要和陌生人打交道,如果真的需要,找一个自己的朋友,让他替你和陌生人打交道。)

425.Java企业级开发中常用的设计模式有哪些?

答: 按照分层开发的观点,可以将应用划分为:表示层、业务逻辑层和持久层,每一层都有属于自己类别的设计模式。

表示层设计模式:

1) Interceptor Filter:拦截过滤器,提供请求预处理和后处理的方案,可以对请求和响应进行过滤。/p>

2) Front Controller:通过中央控制器提供请求管理和处理,管理内容读取、安全性、视图管理和导航等功能。Struts 2中的StrutsPrepareAndExecuteFilter、Spring MVC中的DispatcherServlet都是前端控制器,后者如下图所示:

3) View Helper:视图帮助器,负责将显示逻辑和业务逻辑分开。显示的部分放在视图组件中,业务逻辑代码放在帮助器中,典型的功能是内容读取、验证与适配。

4) Composite View:复合视图。

业务逻辑层设计模式:

1) Business Delegate:业务委托,减少表示层和业务逻辑层之间的耦合。

2) Value Object:值对象,解决层之间交换数据的开销问题。

3) Session Façade:会话门面,隐藏业务逻辑组件的细节,集中工作流程。

4) Value Object Assembler:灵活的组装不同的值对象

5) Value List Handler:提供执行查询和处理结果的解决方案,还可以缓存查询结果,从而达到提升性能的目的。

6) Service Locator:服务定位器,可以查找、创建和定位服务工厂,封装其实现细节,减少复杂性,提供单个控制点,通过缓存提高性能。

持久层设计模式:

Data Access Object:数据访问对象,以面向对象的方式完成对数据的增删改查。

【补充】如果想深入的了解Java企业级应用的设计模式和架构模式,可以参考这些书籍: 《Pro Java EE Spring Patterns》、《POJO in Action》、《Patterns of Enterprise Application Architecture》。

426.你在开发中都用到了那些设计模式?用在什么场合?

答:面试被问到关于设计模式的知识时,可以拣最常用的作答,例如:

1) 工厂模式:工厂类可以根据条件生成不同的子类实例,这些子类有一个公共的抽象父类并且实现了相同的方法,但是这些方法针对不同的数据进行了不同的操作(多态方法)。当得到子类的实例后,开发人员可以调用基类中的方法而不必考虑到底返回的是哪一个子类的实例。

2) 代理模式:给一个对象提供一个代理对象,并由代理对象控制原对象的引用。实际开发中,按照使用目的的不同,代理可以分为:远程代理、虚拟代理、保护代理、Cache代理、防火墙代理、同步化代理、智能引用代理。

3) 适配器模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起使用的类能够一起工作。

4) 模板方法模式:提供一个抽象类,将部分逻辑以具体方法或构造器的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法(多态实现),从而实现不同的业务逻辑。

除此之外,还可以讲讲上面提到的门面模式、桥梁模式、单例模式、装潢模式(Collections工具类里面的synchronizedXXX方法把一个线程不安全的容器变成线程安全容器就是对装潢模式的应用,而Java IO里面的过滤流(有的翻译成处理流)也是应用装潢模式的经典例子)等,反正原则就是拣自己最熟悉的用得最多的作答,以免言多必失。 

427.什么是设计模式,设计模式的作用。

设计模式是一套被反复使用的、多数人知晓、经过分类编目的优秀代码设计经验的总结。特定环境下特定问题的处理方法。

1)重用设计和代码 重用设计比重用代码更有意义,自动带来代码重用

2)提高扩展性 大量使用面向接口编程,预留扩展插槽,新的功能或特性很容易加入到系统中来

3)提高灵活性 通过组合提高灵活性,可允许代码修改平稳发生,对一处修改不会波及到其他模块

4) 提高开发效率 正确使用设计模式,可以节省大量的时间

428.23种经典设计模式都有哪些,如何分类。
429.写出简单工厂模式的示例代码
package com.bjsxt;

public class SimpleFactory {
public static Product createProduct(String pname){
Product product=null;
if("p1".equals(pname)){
product = new Product();
}else if("p2".equals(pname)){
product = new Product();
}else if("pn".equals(pname)){
product = new Product();
}
return product;
}
}

基本原理:由一个工厂类根据传入的参数(一般是字符串参数),动态决定应该创建哪一个产品子类(这些产品子类继承自同一个父类或接口)的实例,并以父类形式返回

优点:客户端不负责对象的创建,而是由专门的工厂类完成;客户端只负责对象的调用,实现了创建和调用的分离,降低了客户端代码的难度;

缺点:如果增加和减少产品子类,需要修改简单工厂类,违背了开闭原则;如果产品子类过多,会导致工厂类非常的庞大,违反了高内聚原则,不利于后期维护

430.请对你所熟悉的一个设计模式进行介绍

分析:建议挑选有一定技术难度,并且在实际开发中应用较多的设计模式。可以挑选装饰模式和动态代理模式。此处挑选动态代理设计模式。

讲解思路:生活案例引入、技术讲解、优缺点分析、典型应用。

1、生活案例引入:送生日蛋糕:

MM们要过生日了,怎么也得表示下吧。最起码先送个蛋糕。蛋糕多种多样了。巧克力,冰淇淋,奶油等等。这都是基本的了,再加点额外的装饰,如蛋糕里放点花、放贺卡、放点干果吃着更香等等。

分析:

方案1:如果采用继承会造成大量的蛋糕子类

方案2:蛋糕作为主体,花,贺卡,果仁等是装饰者,需要时加到蛋糕上。要啥我就加啥。

技术讲解

装饰模式(别名Wrapper)是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它通过创建一个包装对象,也就是装饰来包裹真实对象,提供了比继承更具弹性的代替方案。

装饰模式一般涉及到的角色

抽象构建角色(Component):给出一个抽象的接口,以规范准备接受附加责任的对象。

具体的构建角色(ConcreteComponent):定义一个将要接受附加责任的类。

抽象的装饰角色 (Decorator):持有一个抽象构建(Component)角色的引用,并定义一个与抽象构件一致的接口。

具体的装饰角色(ConcreteDecorator):负责给构建对象“贴上”附加的责任。

3、优缺点分析

优点

1)Decorator模式与继承关系的目的都是要扩展对象的功能,但是Decorato更多的灵活性。

2)把类中的装饰功能从类中搬移出去,这样可以简化原有的类。有效地把类的核心功能和装饰功能区分开了。

3)通过使用不同的具体装饰类以及这些装饰类的排列组合,可创造出很多不同行为的组合。

缺点

这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。

装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。

符合的设计原则:

多用组合,少用继承。利用继承设计子类的行为是在编译时静态决定的,且所有的子类都会继承到相同的行为。如能够利用组合扩展对象的行为,就可在运行时动态进行扩展。

类应设计的对扩展开放,对修改关闭。

4、典型应用

java IO中需要完成对不同输入输出源的操作,如果单纯的使用继承这一方式,无疑需要很多的类。比如说,我们操作文件需要一个类,实现文件的字节读取需要一个类,实现文件的字符读取又需要一个类....一次类推每个特定的操作都需要一个特定的类。这无疑会导致大量的IO继承类的出现。显然对于编程是很不利的。而是用装饰模式则可以很好的解决这一问题,在装饰模式中:节点流(如FileInputStream)直接与输入源交互,之后通过过滤流(FilterInputStream)进行装饰,这样获得的io对象便具有某几个的功能,很好的拓展了IO的功能。

高级框架

431.什么是Maven?

Maven使用项目对象模型(POM)的概念,可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具。

Maven 除了以程序构建能力为特色之外,还提供高级项目管理工具。由于 Maven 的缺省构建规则有较高的可重用性,所以常常用两三行 Maven 构建脚本就可以构建简单的项目。由于 Maven 的面向项目的方法,许多 Apache Jakarta 项目发布时使用 Maven,而且公司项目采用 Maven 的比例在持续增长。

Maven的出现,解决了开发过程中的jar包升级及依赖的难题。它可以对项目依赖的jar包进行管理,可以让你的项目保持基本的依赖,排除冗余jar包,并且可以让你非常轻松的对依赖的jar包进行版本升级。而这些仅仅是Maven最基本的功能,它可以在这基础上对项目进行清理、编译、测试、打包、发布等等构建项目的工作。 

可以说,Maven是现在Java社区中最强大的项目管理和项目构建工具,而更加值得庆幸的是,这样一个强大的工具,它的使用也是非常简单的。

现在,JavaEE项目使用的开源软件都可以通过Maven来获取,并且,越来越多的公司也开始使用Maven来管理构建项目了。

432.Maven和ANT的区别

1.maven&ant同属apach是流行的构建工具。

都是为了简化软件开发而存在的。但是maven因为自身管理一个项目对象模型(project object model),这个模型其实就是抽象了一个项目的开发流程,它包含了一个项目的生命周期的各个阶段,并将这个周期固定下来,这也就是约定大于配置。约定大于配置的意思就是,我maven将项目开发的各个阶段固定起来了,每个文件的存放位置,每个阶段要生成什么文件、保存为什么格式并且要把它放在什么位置,我都固定好了。我知道一个软件是怎么开发出来,如果一个项目要使用maven,可以,但你要遵循我的规则,文件目录不要乱建乱放,只有这样maven才会将源码用起来。这就是约定大于配置,因为maven已经将流程固定下来了,只要遵守约定,就不需要自己手动去配置了,这将大大地提高开发效率。就像是开车一样,只要知道点火、油门、方向、刹车,就可以将车子开东起来(当然出于安全和法律考虑,还是要考驾照的。),关于车子内部的传动原理,电气原理,工程原理,普通人并不需要了解多少,日常够用就好了。这也是约定大于配置的一个例子。配置就是自己造一辆车去开,有必要,有能力,有时间吗?

2.maven的中央仓库和pom.xml文件。中央仓库统一存放了开发用到的各种jar包,要用时只需要添加依赖到pom文件中,maven就会自动下载,当然为了方便一般会在本地建一个仓库,减少下载时间。pom文件是maven的配置文件,maven就是通过管理pom文件和一些核心插件来管理项目。当然我前面将maven拟人化了,其实maven是没有智力的,一切都是封装好的流程,只是maven将很多操作隐藏起来了。

3.ant的build.xml文件。build文件是ant的配置文件,ant依靠它来执行操作,与maven不同的是ant没有固定一条程序链。你想要执行什么操作以及操作之间的顺序和依赖关系,都需要手动添加到build文件中,一点一滴都要写清楚,否则ant就不会执行。

4.maven和ant区别

Maven 拥有约定,只要遵守约定,它就知道你的源代码在哪里。Maven 是声明式的。你需要做的只是创建一个 pom.xml 文件然后将源代码放到默认的目录。Maven 会帮你处理其它的事情。Maven 有一个生命周期,当你运行 mvn install 的时候被调用。这条命令告诉 Maven 执行一系列的有序的步骤,直到到达你指定的生命周期。缺点是运行许多默认目标。

而ant没有约定,项目生命周期,它是命令式的。所有操作都要手动去创建、布置。甚至连build.xml文件都需要手动创建。

433.Maven仓库是什么

Maven仓库是基于简单文件系统存储的,集中化管理Java API资源(构件)的一个服务。仓库中的任何一个构件都有其唯一的坐标,根据这个坐标可以定义其在仓库中的唯一存储路径。得益于 Maven 的坐标机制,任何 Maven项目使用任何一个构件的方式都是完全相同的,Maven 可以在某个位置统一存储所有的 Maven 项目共享的构件,这个统一的位置就是仓库,项目构建完毕后生成的构件也可以安装或者部署到仓库中,供其它项目使用。

对于Maven来说,仓库分为两类:本地仓库和远程仓库。

434.Maven的工程类型有哪些?

POM工程

POM工程是逻辑工程。用在父级工程或聚合工程中。用来做jar包的版本控制。

JAR工程

将会打包成jar用作jar包使用。即常见的本地工程 - Java Project。

WAR工程

将会打包成war,发布在服务器上的工程。如网站或服务。即常见的网络工程 - Dynamic Web Project。war工程默认没有WEB-INF目录及web.xml配置文件,IDE通常会显示工程错误,提供完整工程结构可以解决。

435.Maven常用命令有哪些?

install

本地安装, 包含编译,打包,安装到本地仓库

编译 - javac

打包 - jar, 将java代码打包为jar文件

安装到本地仓库 - 将打包的jar文件,保存到本地仓库目录中。

clean

清除已编译信息。

删除工程中的target目录。

compile

只编译。 javac命令

deploy

部署。 常见于结合私服使用的命令。

相当于是install+上传jar到私服。

包含编译,打包,安装到本地仓库,上传到私服仓库。

package

打包。 包含编译,打包两个功能。

436.ZooKeeper的作用是什么?

配置管理

在我们的应用中除了代码外,还有一些就是各种配置。比如数据库连接等。一般我们都是使用配置文件的方式,在代码中引入这些配置文件。当我们只有一种配置,只有一台服务器,并且不经常修改的时候,使用配置文件是一个很好的做法,但是如果我们配置非常多,有很多服务器都需要这个配置,这时使用配置文件就不是个好主意了。这个时候往往需要寻找一种集中管理配置的方法,我们在这个集中的地方修改了配置,所有对这个配置感兴趣的都可以获得变更。Zookeeper就是这种服务,它使用Zab这种一致性协议来提供一致性。现在有很多开源项目使用Zookeeper来维护配置,比如在HBase中,客户端就是连接一个Zookeeper,获得必要的HBase集群的配置信息,然后才可以进一步操作。还有在开源的消息队列Kafka中,也使用Zookeeper来维护broker的信息。在Alibaba开源的SOA框架Dubbo中也广泛的使用Zookeeper管理一些配置来实现服务治理。

名字服务

名字服务这个就很好理解了。比如为了通过网络访问一个系统,我们得知道对方的IP地址,但是IP地址对人非常不友好,这个时候我们就需要使用域名来访问。但是计算机是不能是域名的。怎么办呢?如果我们每台机器里都备有一份域名到IP地址的映射,这个倒是能解决一部分问题,但是如果域名对应的IP发生变化了又该怎么办呢?于是我们有了DNS这个东西。我们只需要访问一个大家熟知的(known)的点,它就会告诉你这个域名对应的IP是什么。在我们的应用中也会存在很多这类问题,特别是在我们的服务特别多的时候,如果我们在本地保存服务的地址的时候将非常不方便,但是如果我们只需要访问一个大家都熟知的访问点,这里提供统一的入口,那么维护起来将方便得多了。

分布式锁

其实在第一篇文章中已经介绍了Zookeeper是一个分布式协调服务。这样我们就可以利用Zookeeper来协调多个分布式进程之间的活动。比如在一个分布式环境中,为了提高可靠性,我们的集群的每台服务器上都部署着同样的服务。但是,一件事情如果集群中的每个服务器都进行的话,那相互之间就要协调,编程起来将非常复杂。而如果我们只让一个服务进行操作,那又存在单点。通常还有一种做法就是使用分布式锁,在某个时刻只让一个服务去干活,当这台服务出问题的时候锁释放,立即fail over到另外的服务。这在很多分布式系统中都是这么做,这种设计有一个更好听的名字叫Leader Election(leader选举)。比如HBase的Master就是采用这种机制。但要注意的是分布式锁跟同一个进程的锁还是有区别的,所以使用的时候要比同一个进程里的锁更谨慎的使用。

集群管理

在分布式的集群中,经常会由于各种原因,比如硬件故障,软件故障,网络问题,有些节点会进进出出。有新的节点加入进来,也有老的节点退出集群。这个时候,集群中其他机器需要感知到这种变化,然后根据这种变化做出对应的决策。比如我们是一个分布式存储系统,有一个中央控制节点负责存储的分配,当有新的存储进来的时候我们要根据现在集群目前的状态来分配存储节点。这个时候我们就需要动态感知到集群目前的状态。还有,比如一个分布式的SOA架构中,服务是一个集群提供的,当消费者访问某个服务时,就需要采用某种机制发现现在有哪些节点可以提供该服务(这也称之为服务发现,比如Alibaba开源的SOA框架Dubbo就采用了Zookeeper作为服务发现的底层机制)。还有开源的Kafka队列就采用了Zookeeper作为Cosnumer的上下线管理。

437.什么是Znode?

在Zookeeper中,znode是一个跟Unix文件系统路径相似的节点,可以往这个节点存储或获取数据。

Zookeeper底层是一套数据结构。这个存储结构是一个树形结构,其上的每一个节点,我们称之为“znode”

zookeeper中的数据是按照“树”结构进行存储的。而且znode节点还分为4中不同的类型。

每一个znode默认能够存储1MB的数据(对于记录状态性质的数据来说,够了)

可以使用zkCli命令,登录到zookeeper上,并通过ls、create、delete、get、set等命令操作这些znode节点

438.Znode节点类型有哪些?

答:(1)PERSISTENT 持久化节点: 所谓持久节点,是指在节点创建后,就一直存在,直到有删除操作来主动清除这个节点。否则不会因为创建该节点的客户端会话失效而消失。

(2)PERSISTENT_SEQUENTIAL 持久顺序节点:这类节点的基本特性和上面的节点类型是一致的。额外的特性是,在ZK中,每个父节点会为他的第一级子节点维护一份时序,会记录每个子节点创建的先后顺序。基于这个特性,在创建子节点的时候,可以设置这个属性,那么在创建节点过程中,ZK会自动为给定节点名加上一个数字后缀,作为新的节点名。这个数字后缀的范围是整型的最大值。 在创建节点的时候只需要传入节点 “/test_”,这样之后,zookeeper自动会给”test_”后面补充数字。

(3)EPHEMERAL 临时节点:和持久节点不同的是,临时节点的生命周期和客户端会 话绑定。也就是说,如果客户端会话失效,那么这个节点就会自动被清除掉。注意,这里提到的是会话失效,而非连接断开。另外,在临时节点下面不能创建子节点。 

这里还要注意一件事,就是当你客户端会话失效后,所产生的节点也不是一下子就消失了,也要过一段时间,大概是10秒以内,可以试一下,本机操作生成节点,在服务器端用命令来查看当前的节点数目,你会发现客户端已经stop,但是产生的节点还在。

EPHEMERAL_SEQUENTIAL 临时自动编号节点:此节点是属于临时节点,不过带有顺序,客户端会话结束节点就消失。

439.什么是Dubbo?

Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和Spring框架无缝集成。Dubbo框架,是基于容器运行的.。容器是Spring。

其核心部分包含:

1. 远程通讯: 提供对多种基于长连接的NIO框架抽象封装,包括多种线程模型,序列化,以及“请求-响应”模式的信息交换方式。

2. 集群容错: 提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。

3. 自动发现: 基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。

Dubbo能做什么?

1.透明化的远程方法调用,就像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入。      

2.软负载均衡及容错机制,可在内网替代F5等硬件负载均衡器,降低成本,减少单点。

3. 服务自动注册与发现,不再需要写死服务提供方地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者。

Dubbo的存在简单来说就是要减小service层的压力。

440.什么是RPC远程过程调用?

远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。

441.Dubbo中有哪些角色?

registry

注册中心. 是用于发布和订阅服务的一个平台.用于替代SOA结构体系框架中的ESB服务总线的。

发布

开发服务端代码完毕后, 将服务信息发布出去. 实现一个服务的公开.

订阅

客户端程序,从注册中心下载服务内容 这个过程是订阅.

订阅服务的时候, 会将发布的服务所有信息,一次性下载到客户端.

客户端也可以自定义, 修改部分服务配置信息. 如: 超时的时长, 调用的重试次数等.

Consumer

服务的消费者, 就是服务的客户端.

消费者必须使用Dubbo技术开发部分代码. 基本上都是配置文件定义.

provider

服务的提供者, 就是服务端.

服务端必须使用Dubbo技术开发部分代码. 以配置文件为主.

container

容器. Dubbo技术的服务端(Provider), 在启动执行的时候, 必须依赖容器才能正常启动.

默认依赖的就是spring容器. 且Dubbo技术不能脱离spring框架.

在2.5.3版本的dubbo中, 默认依赖的是spring2.5版本技术. 可以选用spring4.5以下版本.

在2.5.7版本的dubbo中, 默认依赖的是spring4.3.10版本技术. 可以选择任意的spring版本.

monitor

监控中心. 是Dubbo提供的一个jar工程.

主要功能是监控服务端(Provider)和消费端(Consumer)的使用数据的. 如: 服务端是什么,有多少接口,多少方法, 调用次数, 压力信息等. 客户端有多少, 调用过哪些服务端, 调用了多少次等.

442.Dubbo执行流程什么是?

0 start: 启动Spring容器时,自动启动Dubbo的Provider

1、register: Dubbo的Provider在启动后自动会去注册中心注册内容.注册的内容包括:

1.1 Provider的 IP

1.2 Provider 的端口.

1.3 Provider 对外提供的接口列表.哪些方法.哪些接口类

1.4 Dubbo 的版本.

1.5 访问Provider的协议.

2、subscribe: 订阅.当Consumer启动时,自动去Registry获取到所已注册的服务的信息.

3、notify: 通知.当Provider的信息发生变化时, 自动由Registry向Consumer推送通知.

4、invoke: 调用. Consumer 调用Provider中方法

4.1 同步请求.消耗一定性能.但是必须是同步请求,因为需要接收调用方法后的结果.

5、count:次数. 每隔2分钟,provoider和consumer自动向Monitor发送访问次数.Monitor进行统计.

443.说说Dubbo支持的协议有哪些?

1、Dubbo协议(官方推荐协议)

优点:

采用NIO复用单一长连接,并使用线程池并发处理请求,减少握手和加大并发效率,性能较好(推荐使用)

缺点:

大文件上传时,可能出现问题(不使用Dubbo文件上传)

2、RMI(Remote Method Invocation)协议

优点:

JDK自带的能力。可与原生RMI互操作,基于TCP协议

缺点:

偶尔连接失败.

3、Hessian协议

优点:

可与原生Hessian互操作,基于HTTP协议

缺点:

需hessian.jar支持,http短连接的开销大

444.Dubbo支持的注册中心有哪些?

1、Zookeeper(官方推荐)

优点:支持分布式.很多周边产品.

缺点: 受限于Zookeeper软件的稳定性.Zookeeper专门分布式辅助软件,稳定较优

2、Multicast

优点:去中心化,不需要单独安装软件.

缺点:Provider和Consumer和Registry不能跨机房(路由)

3、Redis

优点:支持集群,性能高

缺点:要求服务器时间同步.否则可能出现集群失败问题.

4、Simple

优点: 标准RPC服务.没有兼容问题

缺点: 不支持集群.

445.SessionFactory是线程安全的吗?Session是线程安全的吗,两个线程能够共享同一个Session吗?

答:SessionFactory对应Hibernate的一个数据存储的概念,它是线程安全的,可以被多个线程并发访问。SessionFactory一般只会在启动的时候构建。对于应用程序,最好将SessionFactory通过单例的模式进行封装以便于访问。Session是一个轻量级非线程安全的对象(线程间不能共享session),它表示与数据库进行交互的一个工作单元。Session是由SessionFactory创建的,在任务完成之后它会被关闭。Session是持久层服务对外提供的主要接口。Session会延迟获取数据库连接(也就是在需要的时候才会获取)。为了避免创建太多的session,可以使用ThreadLocal来取得当前的session,无论你调用多少次getCurrentSession()方法,返回的都是同一个session。

446.Session的load和get方法的区别是什么?

答:主要有以下三项区别:

1)如果没有找到符合条件的记录, get方法返回null,load方法抛出异常

2)get方法直接返回实体类对象, load方法返回实体类对象的代理

3)在Hibernate 3之前,get方法只在一级缓存(内部缓存)中进行数据查找, 如果没有找到对应的数据则越过二级缓存, 直接发出SQL语句完成数据读取; load方法则可以充分利用二级缓存中的现有数据;当然从Hibernate 3开始,get方法不再是对二级缓存只写不读,它也是可以访问二级缓存的

简单的说,对于load()方法Hibernate认为该数据在数据库中一定存在可以放心的使用代理来实现延迟加载,如果没有数据就抛出异常,而通过get()方法去取的数据可以不存在。

447.Session的save()、update()、merge()、lock()、saveOrUpdate()和persist()方法有什么区别?

答:Hibernate的对象有三种状态:瞬态、持久态和游离态。游离状态的实例可以通过调用save()、persist()或者saveOrUpdate()方法进行持久化;脱管状态的实例可以通过调用 update()、0saveOrUpdate()、lock()或者replicate()进行持久化。save()和persist()将会引发SQL的INSERT语句,而update()或merge()会引发UPDATE语句。save()和update()的区别在于一个是将瞬态对象变成持久态,一个是将游离态对象变为持久态。merge方法可以完成save()和update()方法的功能,它的意图是将新的状态合并到已有的持久化对象上或创建新的持久化对象。按照官方文档的说明:(1)persist()方法把一个瞬态的实例持久化,但是并"不保证"标识符被立刻填入到持久化实例中,标识符的填入可能被推迟到flush的时间;(2) persist"保证",当它在一个事务外部被调用的时候并不触发一个Insert语句,当需要封装一个长会话流程的时候,一个persist这样的函数是需要的。(3)save"不保证"第2条,它要返回标识符,所以它会立即执行Insert语句,不管是不是在事务内部还是外部。update()方法是把一个已经更改过的脱管状态的对象变成持久状态;lock()方法是把一个没有更改过的脱管状态的对象变成持久状态。

448.什么是VSFTPD?

vsftpd 是“very secure FTP daemon”的缩写,安全性是它的一个最大的特点。vsftpd 是一个 UNIX 类操作系统上运行的服务器的名字,它可以运行在诸如 Linux、BSD、Solaris、 HP-UNIX等系统上面,是一个完全免费的、开放源代码的ftp服务器软件,支持很多其他的 FTP 服务器所不支持的特征。

449.什么是Nginx?

Nginx (engine x) 是一个高性能的HTTP和反向代理服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日。

Nginx 是一个很强大的高性能Web和反向代理服务,它具有很多非常优越的特性:在连接高并发的情况下,Nginx是Apache服务不错的替代品:Nginx在美国是做虚拟主机生意的老板们经常选择的软件平台之一。

450.Nginx有哪些作用?

答:http协议代理

搭建虚拟主机

服务的反向代理

在反向代理中配置集群的负载均衡

451.什么是正向代理?

正向代理,意思是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端才能使用正向代理。

452.什么是反向代理?

反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。

453.什么是Redis?

答:Remote Dictionary Server(Redis)是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。

454.Redis的特点什么是?

1. 支持多种数据结构,如 string(字符串)、 list(双向链表)、dict(hash表)、set(集合)、zset(排序set)、hyperloglog(基数估算)

2. 支持持久化操作,可以进行aof及rdb数据持久化到磁盘,从而进行数据备份或数据恢复等操作,较好的防止数据丢失的手段。

3. 支持通过Replication进行数据复制,通过master-slave机制,可以实时进行数据的同步复制,支持多级复制和增量复制,master-slave机制是Redis进行HA的重要手段。

单进程请求,所有命令串行执行,并发情况下不需要考虑数据一致性问题。

455.Redis数据类型有哪些?

答:String(字符串)

Hash(hash表)

List(链表)

Set(集合)

SortedSet(有序集合zset)

456.Redis中的常用命令哪些?

incr 让当前键值以1的数量递增,并返回递增后的值

incrby 可以指定参数一次增加的数值,并返回递增后的值

incrby 可以指定参数一次增加的数值,并返回递增后的值

decrby 可以指定参数一次递减的数值,并返回递减后的值

incrbyfloat 可以递增一个双精度浮点数

append 作用是向键值的末尾追加value。如果键不存在则将该键的值设置为value。返回值是追加后字符串的总长度。

mget/mset 作用与get/set相似,不过mget/mset可以同时获得/设置多个键的键值

del 根据key来删除value

flushdb 清除当前库的所有数据

hset 存储一个哈希键值对的集合

hget获取一个哈希键的值

hmset 存储一个或多个哈希是键值对的集合

hmget 获取多个指定的键的值

hexists 判断哈希表中的字段名是否存在 如果存在返回1 否则返回0

hdel 删除一个或多个字段

hgetall 获取一个哈希是键值对的集合

hvals 只返回字段值

hkeys 只返回字段名

hlen 返回key的hash的元素个数

lpush key value向链表左侧添加

rpush key value向链表右侧添加

lpop key 从左边移出一个元素

rpop key 从右边移出一个元素

llen key 返回链表中元素的个数 相当于关系型数据库中 select count(*)

lrange key start end lrange命令将返回索引从start到stop之间的所有元素。Redis的列表起始索引为0。

lrange也支持负索引 lrange nn -2 -1 如 -1表示最右边第一个元素 -2表示最右边第二个元素,依次类推。

lindex key indexnumber 如果要将列表类型当做数组来用,lindex命令是必不可少的。lindex命令用来返回指定索引的元素,索引从0开始

如果是负数表示从右边开始计算的索引,最右边元素的索引是-1。

Lset key indexnumber value 是另一个通过索引操作列表的命令,它会将索引为index的元素赋值为value。

sadd key value 添加一个string元素到,key对应的set集合中,成功返回1,如果元素已经在集合中返回0

scard key 返回set的元素个数,如果set是空或者key不存在返回0

smembers key 返回key对应set的所有元素,结果是无序的

sismember key value 判断value 是否在set中,存在返回1,0表示不存在或者key不存在

srem key value 从key对应set中移除给定元素,成功返回1,如果value 在集合中不存在或者key不存在返回0

zadd key score value 将一个或多个value及其socre加入到set中

zrange key start end 0和-1表示从索引为0的元素到最后一个元素(同LRANGE命令相似)

zrange key 0 -1 withscores 也可以连同score一块输出,使用WITHSCORES参数

zremrangebyscore key start end 可用于范围删除操作

ping 测试redis是否链接 如果已链接返回 PONG

echo value测试redis是否链接 如果已链接返回 echo命令后给定的值

keys * 返回所有的key 可以加*通配

exists key判断string类型一个key是否存在 如果存在返回1 否则返回0

expire key time(s) 设置一个key的过期时间 单位秒。时间到达后会删除key及value

ttl key 查询已设置过期时间的key的剩余时间 如果返回-2表示该键值对已经被删除

persist 移除给定key的过期时间

select dbindex 选择数据库(0-15)

move key dbIndex 将当前数据库中的key转移到其他数据库中

dbsize 返回当前数据库中的key的数目

info 获取服务器的信息和统计

flushdb 删除当前选择的数据库中的key

flushall 删除所有数据库中的所有key

quit 退出连接

457.Redis的配置以及持久化方案有几种?

答:以下两种

RDB方式

AOF方式

458.什么是RDB方式?

答:是RDB是对内存中数据库状态进行快照

RDB方式:将Redis在内存中的数据库状态保存到磁盘里面,RDB文件是一个经过压缩的二进制文件,通过该文件可以还原生成RDB文件时的数据库状态(默认下,持久化到dump.rdb文件,并且在redis重启后,自动读取其中文件,据悉,通常情况下一千万的字符串类型键,1GB的快照文件,同步到内存中的 时间是20-30秒)

RDB的生成方式:

 1、执行命令手动生成

有两个Redis命令可以用于生成RDB文件,一个是SAVE,另一个是BGSAVE SAVE命令会阻塞Redis服务器进程,直到RDB文件创建完毕为止,在服务器进程阻塞期间,服务器不能处理任何命令请求,BGSAVE命令会派生出一个子进程,然后由子进程负责创建RDB文件,服务器进程(父进程)继续处理命令请求,创建RDB文件结束之前,客户端发送的BGSAVE和SAVE命令会被服务器拒绝

2、通过配置自动生成

可以设置服务器配置的save选项,让服务器每隔一段时间自动执行一次BGSAVE命令,可以通过save选项设置多个保存条件,但只要其中任意一个条件被满足,服务器就会执行BGSAVE命令

例如:

save 900 1

save 300 10

save 60 10000

那么只要满足以下三个条件中的任意一个,BGSAVE命令就会被执行

服务器在900秒之内,对数据库进行了至少1次修改

服务器在300秒之内,对数据库进行了至少10次修改

服务器在60秒之内,对数据库进行了至少10000次修改

459.什么是AOF方式?

AOF持久化方式在redis中默认是关闭的,需要修改配置文件开启该方式。

AOF:把每条命令都写入文件,类似mysql的binlog日志

AOF方式:是通过保存Redis服务器所执行的写命令来记录数据库状态的文件。

AOF文件刷新的方式,有三种:

appendfsync always - 每提交一个修改命令都调用fsync刷新到AOF文件,非常非常慢,但也非常安全

appendfsync everysec - 每秒钟都调用fsync刷新到AOF文件,很快,但可能会丢失一秒以内的数据

appendfsync no - 依靠OS进行刷新,redis不主动刷新AOF,这样最快,但安全性就差

默认并推荐每秒刷新,这样在速度和安全上都做到了兼顾

AOF数据恢复方式

服务器在启动时,通过载入和执行AOF文件中保存的命令来还原服务器关闭之前的数据库状态,具体过程:

载入AOF文件

创建模拟客户端

从AOF文件中读取一条命令

使用模拟客户端执行命令

循环读取并执行命令,直到全部完成

如果同时启用了RDB和AOF方式,AOF优先,启动时只加载AOF文件恢复数据

460.什么是全文检索?

答:什么叫做全文检索呢?这要从我们生活中的数据说起。

我们生活中的数据总体分为两种:结构化数据和非结构化数据。

1)结构化数据:指具有固定格式或有限长度的数据,如数据库,元数据等。

2)非结构化数据:指不定长或无固定格式的数据,如邮件,word文档等。

非结构化数据又一种叫法叫全文数据。

 按照数据的分类,搜索也分为两种:

1)对结构化数据的搜索:如对数据库的搜索,用SQL语句。

2)对非结构化数据的搜索:如利用windows的搜索也可以搜索文件内容,

全文检索: 就是一种将文件中所有文本与检索项匹配的文字资料检索方法。全文检索首先将要查询的目标文档中的词提取出来,组成索引,通过查询索引达到搜索目标文档的目的。这种先建立索引,再对索引进行搜索的过程就叫全文检索(Full-text Search)。

461.什么是Lucene?

Lucene是一个高效的,基于Java的全文检索库。

Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。Lucene是一套用于全文检索和搜寻的开源程序库,由Apache软件基金会支持和提供。Lucene提供了一个简单却强大的应用程序接口,能够做全文索引和搜寻。在Java开发环境里Lucene是一个成熟的免费开源工具。就其本身而言,Lucene是当前以及最近几年最受欢迎的免费Java信息检索程序库。

462.什么是Solr?

答:Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口。

Solr是一个高性能,采用Java开发,基于Lucene的全文搜索服务器。同时对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展并对查询性能进行了优化,并且提供了一个完善的功能管理界面,是一款非常优秀的全文检索引擎。

文档通过Http利用XML 加到一个搜索集合中。查询该集合也是通过http收到一个XML/JSON响应来实现。它的主要特性包括:高效、灵活的缓存功能,垂直搜索功能,高亮显示搜索结果,通过索引复制来提高可用性,提供一套强大Data Schema来定义字段,类型和设置文本分析,提供基于Web的管理界面等。

463.Solr是由哪两个部分构成?

答:如下两个部分

Solr的web服务

Solr的索引库

464.什么是正排索引?

正排索引是以文档的ID为关键字,索引文档中每个字的位置信息,查找时扫描索引中每个文档中字的信息直到找出所有包含查询关键字的文档。

但是在查询的时候需对所有的文档进行扫描以确保没有遗漏,这样就使得检索时间大大延长,检索效率低下。     

尽管正排索引的工作原理非常的简单,但是由于其检索效率太低,除非在特定情况下,否则实用性价值不大。

465.什么是倒排索引?

对数据进行分析,抽取出数据中的词条,以词条作为key,对应数据的存储位置作为value,实现索引的存储。这种索引称为倒排索引。

当solr存储文档时,solr会首先对文档数据进行分词,创建索引库和文档数据库。所谓的分词是指:将一段字符文本按照一定的规则分成若干个单词。

466.什么是ActiveMQ?

ActiveMQ是一种开源的,实现了JMS1.1规范的,面向消息(MOM)的中间件,为应用程序提供高效的、可扩展的、稳定的和安全的企业级消息通信。ActiveMQ使用Apache提供的授权,任何人都可以对其实现代码进行修改。

ActiveMQ的设计目标是提供标准的,面向消息的,能够跨越多语言和多系统的应用集成消息通信中间件。

ActiveMQ实现了JMS标准并提供了很多附加的特性。这些附加的特性包括,JMX管理(java Management Extensions,即java管理扩展),主从管理(master/salve,这是集群模式的一种,主要体现在可靠性方面,当主中介(代理)出现故障,那么从代理会替代主代理的位置,不至于使消息系统瘫痪)、消息组通信(同一组的消息,仅会提交给一个客户进行处理)、有序消息管理(确保消息能够按照发送的次序被接受者接收)。消息优先级(优先级高的消息先被投递和处理)、订阅消息的延迟接收(订阅消息在发布时,如果订阅者没有开启连接,那么当订阅者开启连接时,消息中介将会向其提交之前的,其未处理的消息)、接收者处理过慢(可以使用动态负载平衡,将多数消息提交到处理快的接收者,这主要是对PTP消息所说)、虚拟接收者(降低与中介的连接数目)、成熟的消息持久化技术(部分消息需要持久化到数据库或文件系统中,当中介崩溃时,信息不会丢失)、支持游标操作(可以处理大消息)、支持消息的转换、通过使用Apache的Camel可以支持EIP、使用镜像队列的形式轻松的对消息队列进行监控等。

467.消息服务的应用场景有哪些?

答:如下3个场景都可以使用消息服务

1、异步处理

2、应用的解耦

3、流量的削峰

468.什么是JMS?

JMS(Java Messaging Service)是Java平台上有关面向消息中间件的技术规范,它便于消息系统中的Java应用程序进行消息交换,并且通过提供标准的产生、发送、接收消息的接口,简化企业应用的开发。

469.JMS有哪些模型?

答:JMS消息机制主要分为两种模型:PTP模型和Pub/Sub模型。

1、PTP模型:(Point  to Point 对点模型) 每一个消息传递给一个消息消费者,保证消息传递给消息消费者,且消息不会同时被多个消费者接收。如果消息消费者暂时不在连接范围内,JMS会自动保证消息不会丢失,直到消息消费者进入连接,消息将自动送达。因此,JMS需要将消息保存到永久性介质上,例如数据库或者文件。

2、Pub-Sub模型:(publish-subscription 发布者订阅者模型)每个主题可以拥有多个订阅者。JMS系统负责将消息的副本传给该主题的每个订阅者。

如果希望每一条消息都能够被处理,那么应该使用PTP消息模型。如果并不要求消息都必须被消息消费者接收到的情况下,可使用pub-sub消息模型。Pub-Sub模型可以在一对多的消息广播时使用。

470.什么是JsonP?

Jsonp(JSON with Padding) 是 json 的一种"使用模式",可以让网页从别的域名(网站)那获取资料,即跨域读取数据。

471.什么是跨域?

跨域是指一个域(网站)下的文档或脚本试图去请求另一个域(网站)下的资源。

472.什么是同源策略?

同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,现在所有支持JavaScript 的浏览器都会使用这个策略。如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源

473.什么是MyCat?

MyCat是目前最流行的基于java语言编写的数据库中间件,是一个实现了MySQL协议的服务器,前端用户可以把它看作是一个数据库代理,用MySQL客户端工具和命令行访问,而其后端可以用MySQL原生协议与多个MySQL服务器通信,也可以用JDBC协议与大多数主流数据库服务器通信,其核心功能是分库分表。配合数据库的主从模式还可实现读写分离。

MyCat是基于阿里开源的Cobar产品而研发,Cobar的稳定性、可靠性、优秀的架构和性能以及众多成熟的使用案例使得MyCat变得非常的强大。

MyCat发展到目前的版本,已经不是一个单纯的MySQL代理了,它的后端可以支持MySQL、SQL Server、Oracle、DB2、PostgreSQL等主流数据库,也支持MongoDB这种新型NoSQL方式的存储,未来还会支持更多类型的存储。而在最终用户看来,无论是那种存储方式,在MyCat里,都是一个传统的数据库表,支持标准的SQL语句进行数据的操作,这样一来,对前端业务系统来说,可以大幅降低开发难度,提升开发速度。

474.什么是纵向切分/垂直切分?

就是把原本存储于一个库的数据存储到多个库上。

由于对数据库的读写都是对同一个库进行操作,所以单库并不能解决大规模并发写入的问题。

例如,我们会建立定义数据库workDB、商品数据库payDB、用户数据库userDB、日志数据库logDB等,分别用于存储项目数据定义表、商品定义表、用户数据表、日志数据表等。

优点

1)减少增量数据写入时的锁对查询的影响。

2)由于单表数量下降,常见的查询操作由于减少了需要扫描的记录,使得单表单次查询所需的检索行数变少,减少了磁盘IO,时延变短。

缺点:

无法解决单表数据量太大的问题。

横向切分/水平切分

把原本存储于一个表的数据分块存储到多个表上。当一个表中的数据量过大时,我们可以把该表的数据按照某种规则,进行划分,然后存储到多个结构相同的表,和不同的库上。

例如,我们userDB中的userTable中数据量很大,那么可以把userDB切分为结构相同的多个userDB:part0DB、part1DB等,再将userDB上的userTable,切分为很多userTable:userTable0、userTable1等,然后将这些表按照一定的规则存储到多个userDB上。

优点:

1)单表的并发能力提高了,磁盘I/O性能也提高了。

2)如果出现高并发的话,总表可以根据不同的查询,将并发压力分到不同的小表里面。

缺点:无法实现表连接查询。

475.简述Tomcat,Apache,JBoss和WebLogic的区别和联系

答:Apache:全球应用最广泛的http服务器,免费,出自apache基金组织 

Tomcat:应用也算非常广泛的web 服务器,支持部分j2ee,免费,出自 apache基金组织 

JBoss:开源的应用服务器,比较受人喜爱,免费(文档要收费) 

weblogic:应该说算是业界第一的app server,全部支持j2ee1.4(收费)

JBoss也支持j2ee

JBoss和WebLogic都含有Jsp和Servlet容器,也就可以做web容器, 

JBoss和WebLogic也包含EJB容器,是完整的J2EE应用服务器

tomcat 只能做jsp和servlet的container

476.以下可以实现负载均衡的是()
A. nagios
B. Jenkins
C. nginx
D. docker
分析:答案: C Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等
477.Tomcat/ WebSphere/WebLogic的作用和特点

作用:

Tomcat:目前应用非常广泛的免费web服务器,支持部分j2ee。

WebSphere:是IBM集成软件平台。可做web服务器,WebSphere提供了可靠、灵活和健壮的集成软件。

Weblogic:是美国bea公司出品的一个基于j2ee架构的中间件。BEA WebLogic是用于开发、集成、部署和管理大型分布式Web应用、网络应用和数据库应用的Java应用服务器。

特点(区别):

1)价位不同:Tomcat的是免费的;WebLogic与WebSphere是收费的,而且价格不菲。

2) 开源性不同:Tomcat的是完全开源的,而其他两个不是。WebLogic与WebSphere都是对业内多种标准的全面支持,包括JSB、JMS、JDBC、XML和WML,使Web应用系统实施更简单,且保护投资,同时也使基于标准的解决方案的开发更加简便。

3) 扩展性的不同:WebLogic和WebSphere都是以其高扩展的架构体系闻名于业内,包括客户机连接的共享、资源 pooling以及动态网页。

4)应用范围的区别:Tomcat 是一个小型的轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。WebLogic和WebSphere是商业软件,功能齐全强大,主要应用于大型企业的大型项目。

5)安全性问题区别:因为Tomcat是开源的,所以它们的安全性相对来说比较低,万一应用服务器本身有什么漏洞,你是没办法向Apache索赔的。而WebLogic和WebSphere其容错、系统管理和安全性能已经在全球数以千记的关键任务环境中得以验证。

478.B/S和C/S的含义及其区别

C/S结构,即Client/Server(客户机/服务器)结构,通过将任务合理分配到Client端和Server端,降低了系统的通讯开销,可充分利用两端硬件环境优势。早期软件系统多以此作为首选设计标准。

B/S结构,即Browser/Server(浏览器/服务器)结构,是随着Internet技术的兴起,对C/S结构的一种变化或者改进的结构。在这种结构下,用户界面完全通过WWW浏览器实现,一部分事务逻辑在前端实现,但是主要事务逻辑在服务器端实现,节约了开发成本,便于软件维护。

区别

1、C/S是建立在局域网的基础上的。B/S是建立在广域网的基础上的,但并不是说B/S结构不能在局域网上使用。

2、B/S业务扩展简单方便,通过增加页面即可增加服务器功能。C/S的客户端还需要安装专用的客户端软件,不利于扩展。

3、B/S维护简单方便。开发、维护等几乎所有工作也都集中在服务器端,当企业对网络应用进行升级时,只需更新服务器端的软件就可以,这减轻了异地用户系统维护与升级的成本

4、B/S响应速度不及C/S;

5、B/S用户体验效果不是很理想

479.说说你对容器的理解

容器也是 java 程序,它的主要作用是为应用程序提供运行环境。容器用来接管安全性、并发性、事务处理、交换到辅助存储器和其它服务的责任

以tomcat为例:Tomcat是一个后台服务进程,其它的servlet(相当于DLL)是在Tomcat容器内运行,Broswer只与Tomcat通迅; Tomcat接受browser的请求,经过一系列动作(如果是静态网页,那么装载,按http协议形成响应流;如果是动态的如JSP,那就要调用JDK 中的servlet.jsp接口,解释形成静态网页,按http协议生成响应流发送回browser)后,形成静态网页,返回响应。

480.为什么要使用连接池?

•传统的数据库连接方式

一个连接对象对应一个物理连接

每次操作都打开一个物理连接,

使用完都关闭连接,造成系统性能低下。

•连接池技术

客户程序得到的连接对象是连接池中物理连接的一个句柄,调用连接对象的close()方法,物理连接并没有关闭,数据源的实现只是删除了客户程序中的连接对象和池中的连接对象之间的联系.

•数据库连接的建立及关闭是耗费系统资源的操作,在大型应用中对系统的性能影响尤为明显。为了能重复利用数据库连接对象,缩短请求的响应时间和提高服务器的性能,支持更多的客户,应采用连接池技术.

481.数据库连接池的原理

数据库连接池的原理

传统连接方式:

首先调用Class.forName()方法加载数据库驱动,

然后调用DriverManager.getConnection()方法建立连接.

连接池技术:

连接池解决方案是在应用程序启动时就预先建立多个数据库连接对象,然后将连接对象保存到连接池中。

当客户请求到来时,从池中取出一个连接对象为客户服务。

当请求完成时,客户程序调用close()方法,将连接对象放回池中.

对于多于连接池中连接数的请求,排队等待。

应用程序还可根据连接池中连接的使用率,动态增加或减少池中的连接数。

482.MVC模式及其优缺点

一、MVC原理

MVC是一种程序开发设计模式,它实现了显示模块与功能模块的分离。提高了程序的可维护性、可移植性、可扩展性与可重用性,降低了程序的开发难度。它主要分模型、视图、控制器三层。

1、模型(model)它是应用程序的主体部分,主要包括业务逻辑模块和数据模块。模型与数据格式无关,这样一个模型能为多个视图提供数据。由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性

2、视图(view) 用户与之交互的界面、在web中视图一般由jsp,html组成

3、控制器(controller)接收来自界面的请求 并交给模型进行处理 在这个过程中控制器不做任何处理只是起到了一个连接的作用

二、MVC的优点

1、降低代码耦合性。在MVC模式中,三个层各施其职,所以如果一旦哪一层的需求发生了变化,就只需要更改相应的层中的代码而不会影响到其他层中的代码。

2、有利于分工合作。在MVC模式中,由于按层把系统分开,那么就能更好的实现开发中的分工。网页设计人员可进行开发视图层中的JSP,而对业务熟悉的人员可开发业务层,而其他开发人员可开发控制层。

3、有利于组件的重用。如控制层可独立成一个能用的组件,表示层也可做成通用的操作界面。可以为一个模型在运行时同时建立和使用多个视图。

三、MVC的不足之处

1、增加了系统结构和实现的复杂性。对于简单的界面,严格遵循MVC,使模型、视图与控制器分离,会增加结构的复杂性,并可能产生过多的更新操作,降低运行效率。

2、视图与控制器间的过于紧密的连接。视图与控制器是相互分离,但确实联系紧密的部件,视图没有控制器的存在,其应用是很有限的,反之亦然,这样就妨碍了他们的独立重用。

3、视图对模型数据的低效率访问。依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问,也将损害操作性能。

4、目前,一般高级的界面工具或构造器不支持模式。改造这些工具以适应MVC需要和建立分离的部件的代价是很高的,从而造成MVC使用的困难。

483.MVC模式完成分页功能的基本思路是什么?

1)页面提交页码(第几页)到Servlet中

2)Servlet接收到页码后,将页码传递给分页工具类(PageBean)

3)Servlet中调用Service层传入PageBean对象

4)Service层调用DAO层传入PageBean对象

5)Servlet中得到查询出来的数据,并setAttrivute保存

6)在页面中得到(getAttribute)数据,遍历输出

484.常用的Web容器

答: Unix和Linux平台下使用最广泛的免费HTTP服务器是Apache服务器,而Windows平台的服务器通常使用IIS作为Web服务器。选择Web服务器应考虑的因素有:性能、安全性、日志和统计、虚拟主机、代理服务器、缓冲服务和集成应用程序等。下面是对常用服务器的简介:

IIS:Microsoft的Web服务器产品为Internet Information Services。IIS 是允许在公共Intranet或Internet上发布信息的Web服务器。IIS是目前最流行的Web服务器产品之一,很多著名的网站都是建立在IIS的平台上。IIS提供了一个图形界面的管理工具,称为Internet服务管理器,可用于监视配置和控制Internet服务。IIS是一种Web服务组件,其中包括Web服务器、FTP服务器、NNTP服务器和SMTP服务器,分别用于网页浏览、文件传输、新闻服务和邮件发送等方面,它使得在网络(包括互联网和局域网)上发布信息成了一件很容易的事。它提供ISAPI(Intranet Server API)作为扩展Web服务器功能的编程接口;同时,它还提供一个Internet数据库连接器,可以实现对数据库的查询和更新。

Kangle:Kangle Web服务器是一款跨平台、功能强大、安全稳定、易操作的高性能Web服务器和反向代理服务器软件。此外,Kangle也是一款专为做虚拟主机研发的Web服务器。实现虚拟主机独立进程、独立身份运行。用户之间安全隔离,一个用户出问题不影响其他用户。支持PHP、ASP、ASP.NET、Java、Ruby等多种动态开发语言。

WebSphere:WebSphere Application Server是功能完善、开放的Web应用程序服务器,是IBM电子商务计划的核心部分,它是基于Java的应用环境,用于建立、部署和管理Internet和Intranet Web应用程序,适应各种Web应用程序服务器的需要,范围从简单到高级直到企业级。

WebLogic:BEA WebLogic Server是一种多功能、基于标准的Web应用服务器,为企业构建自己的应用提供了坚实的基础。各种应用开发、部署所有关键性的任务,无论是集成各种系统和数据库,还是提交服务、跨Internet协作,Weblogic都提供了相应的支持。由于它具有全面的功能、对开放标准的遵从性、多层架构、支持基于组件的开发,基于Internet的企业都选择它来开发、部署最佳的应用。BEA WebLogic Server在使应用服务器成为企业应用架构的基础方面一直处于领先地位,为构建集成化的企业级应用提供了稳固的基础,它们以 Internet的容量和速度,在连网的企业之间共享信息、提交服务,实现协作自动化。

Apache:目前Apache仍然是世界上用得最多的Web服务器,市场占有率约为60%左右。世界上很多著名的网站都是Apache的产物,它的成功之处主要在于它的源代码开放、有一支强大的开发团队、支持跨平台的应用(可以运行在几乎所有的Unix、Windows、Linux系统平台上)以及它的可移植性等方面。

Tomcat:Tomcat是一个开放源代码、运行Servlet和JSP的容器。TomcatServer实现了Servlet和JSP规范。此外,Tomcat还实现了Apache-Jakarta规范而且比绝大多数商业应用软件服务器要好,因此目前也有不少的Web服务器都选择了Tomcat。

Nginx:读作"engine x",是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP代理服务器。 Nginx是由Igor Sysoev为俄罗斯访问量第二的 Rambler.ru站点开发的,第一个公开版本0.1.0发布于2004年10月4日。其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。

485.Java Web开发的Model 1和Model 2分别指的是什么?

答:Model 1是以页面为中心的Java Web开发,只适合非常小型的应用程序,Model 2是基于MVC架构模式的应用,这一点在前文的面试题中已经详细讲解过了。

486.说说什么是框架:

框架(framework)是一个框子--》指约束性,也是一个架子--》指支撑性IT语境中的框架,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,在此结构上可以根据具体问题扩展、按插更多的组成部分,从而更迅速和方便地架构完整的解决问题的方案。

1)框架本身一般不完整到可以解决特定问题,但是可以帮助您快速解决特定问题:

没有框架所有的工作都从零开始做,有了框架,为我们提供了一定的功能。我们就可以在框架的基础上开发,极大的解决了生产力。

不同的框架,是为了解决不同领域的问题,一定要为了解决问题才去学习框架。

2)框架天生就是为了扩展而设计的

3)框架里面可以为后续的组件提供很多辅助性、支撑性的方便易用的实用工具(utilities),也就是框架时常配套一些帮组解决某类问题的库(libraries)或工具(tools).

在java中就是一系列的jar包,其本质就是对jdk功能的扩展。

487.简单说一下MVC框架?

是为了解决传统MVC模式(jsp+servlet+javabean)一些问题而出现的框架

传统MVC模式模式问题:

1) 所有的Servlet和Servlet映射都要配置在web.xml中,如果项目太大,web.xml就太庞大并且不能实现模块化管理。

2)Servlet的主要功能就是接受参数、调用逻辑、跳转页面,比如像其他字符编码、文件上传等功能也要写在Servlet中,不能让Servlet主要功能而需要做处理一些特例。

3)接受参数比较麻烦

(String name = request.getParameter(“name”)),不能通过model接受,只能单个接收,接收完成后转换封装model。

4)跳转页面方式比较单一(forward,redirect),并且当我们的页面名称发生改变时需要改变Servlet源代码。

现在比较常用的MVC框架:

webwork

Struts

Struts2

SpringMVC

488.简单讲一下struts2的执行流程

 一个请求在struts2框架中处理大概分为一下几个步骤:

1)客户浏览器发送一个指向Servlet容器(例如Tomcat)的请求

2)这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin)

3)接着FilterDispatcher(StrutsPrepareAndExecuteFilter)被调用,FilterDispatcher询问ActionMapper来决定这个请是否需要调用某个Action

4)如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy

5)ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类

6)ActionProxy创建一个ActionInvocation的实例。

7)ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。

8)一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也 可 能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2 框架中继承的标签。在这个过程中需要涉及到ActionMapper

489.Struts2中的拦截器,你都用它干什么?

java里的拦截器是动态拦截Action调用的对象,它提供了一种机制可以使开发者定义一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行,同时也提供了一种可以提取action中可重用部分的方式。

在AOP(Aspect Oriented Programming)中拦截器用于在某个方法或字段被访问之前,进行拦截后在之前或之后加入某些操作

1)struts2中的功能(参数处理、文件上传、字符编码等)都是通过系统拦截器实现的

2)当然我们也可以自定义拦截器,进行可插拔配置,可以执行Action的方法前后,加入相关逻辑完成业务。

使用场景:

1)用户登录判断,在执行action的前面判断是否已经登录,如果没有登录的就跳转登录页面。

2)用户权限判断,在执行action的前面判断是否具有,如果没有权限就给出提示信息。

3)操作日志...

490.简单讲一下SpringMVC的执行流程?

1)用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServlet捕获;

2)DispatcherServlet 对请求URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象 (包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;

3)DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(...)方法)

4) 提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:

HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息

数据转换:对请求消息进行数据转换。如String转换成Integer、Double等

数据根式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等

数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中

5)Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;

6)根据返回的ModelAndView,选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet ;

7)ViewResolver 结合Model和View,来渲染视图

8)将渲染结果返回给客户端。

快速记忆:

核心控制器捕获请求,查找Hander,执行Handler,选择ViewResolver,通过ViewResoler渲染视图并返回

491.简单说一下struts2和springMVC有什么不同

目前企业中使用SpringMvc的比例已经远远超过Struts2,那么两者到底有什么区别,是很多初学者比较关注的问题,下面我们就来对SpringMvc和Struts2进行各方面的比较:

1)核心控制器(前端控制器、预处理控制器):对于使用过mvc框架的人来说这个词应该不会陌生,核心控制器的主要用途是处理所有的请求,然后对那些特殊的请求 (控制器)统一的进行处理(字符编码、文件上传、参数接受、异常处理等等),spring mvc核心控制器是Servlet,而Struts2是Filter。

2)控制器实例:Spring Mvc会比Struts快一些(理论上)。Spring Mvc是基于方法设计,而Sturts是基于对象,每次发一次请求都会实例一个action,每个action都会被注入  属性,而Spring更像Servlet一样,只有一个实例,每次请求执行对应的方法即可(注意:由于是单例实例,所以应当避免全局变量的修改,这样会产生线程安全问题 )

3)管理方式:大部分的公司的核心架构中,就会使用到spring,而spring mvc又是spring中的一个模块,所以spring对于spring mvc的控制器管理更加简单方便,而且提供了全 注解方式进行管理,各种功能的注解都比较全面,使用简单,而struts2需要采用XML很多的配置参数来管理(虽然也可以采用注解,但是几乎没有公司那 样使用)

4)参数传递:Struts2中自身提供多种参数接受,其实都是通过(ValueStack)进行传递和赋值,而SpringMvc是通过方法的参数进行接收。

5)学习难度:Struts更加很多新的技术点,比如拦截器、值栈及OGNL表达式,学习成本较高,springmvc 比较简单,很较少的时间都能上手。

6)intercepter 的实现机制:struts有以自己的interceptor机制,spring mvc用的是独立的AOP方式。这样导致struts的配置文件量还是比spring mvc大,虽然struts的配置能继承,所以我觉得论使用上来讲,spring mvc使用更加简洁,开发效率Spring MVC确实比struts2高。spring mvc是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,所以说从架构本身上spring3 mvc就容易实现restful url。struts2是类级别的拦截,一个类对应一个request上下文;实现restful url要费劲,因为struts2 action的一个方法可以对应一个url;而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了。spring3 mvc的方法之间基本上独立的,独享request response数据,请求数据通过参数获取,处理结果通过ModelMap交回给框架方法之间不共享变量,而struts2搞的就比较乱,虽然方法之间 也是独立的,但其所有Action变量是共享的,这不会影响程序运行,却给我们编码,读程序时带来麻烦。

7)spring mvc处理ajax请求,直接通过返回数据,方法中使用注解@ResponseBody,spring mvc自动帮我们对象转换为JSON数据。而struts2是通过插件的方式来处理。

在springMVC流行起来之前,struts2在MVC框架中占核心地位,随着SpringMVC的出现,SpringMVC慢慢的取代了struts2,但是很多的企业原来搭建的框架都是使用struts2。

492.说一下Spring中的两大核心

Spring是什么?

Spring是J2EE应用程序框架,是轻量级的IOC和AOP的容器框架,主要针对JavaBean的生命周期进行管理的轻量级容器,可以单独使用,也可以和struts框架,ibatis框架等组合使用。

1)IOC(Inversion of Control)

ioc控制反转,又称为“依赖注入”;

IOC的基本概念是:不创建对象,但是描述创建它们的方式。在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务。容器负责将这些联系在一起。   

其原理是基于OO设计原则的The Hollywood Principle:Don't call us, we'll call you(别找我,我会来找你的)。也就是说,所有的组件都是被动的(Passive),所有的组件初始化和调用都由容器负责。组件处在一个容器当中,由容 器负责管理。   

简单的来讲,就是由容器控制程序之间的关系,而非传统实现中,由程序代码直接操控。这也就是所谓“控制反转”的概念所在:控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。

2)AOP 面向切面编程

核心原理:使用动态代理的设计模式在执行方法前后或出现异常常做加入相关逻辑

我们使用AOP来做:

1)事务处理:执行方法前开启事务,执行完成后关闭事务,出现异常后回滚事务

2)权限判断:在执行方法前,判断是否具有权限

3)日志:在执行前进行日志处理

493.讲一下Spring的事务的传播特性

多个事物存在是怎么处理的策略

1)PROPAGATION_REQUIRED:如果存在一个事务,则支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。

2)PROPAGATION_SUPPORTS:如果存在一个事务,支持当前事务,如果当前没有事务,就以非事务方式执行。

3)PROPAGATION_MANDATORY:如果存在一个事务,支持当前事务,如果当前没有事务,就抛出异常。

4)PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。

5)PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

6)PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。

7)PROPAGATION_NESTED:支持当前事务,新增Savepoint点,与当前事务同步提交或回滚。

494.什么是ORM

对象关系映射(Object Relation Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术,简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中,那么到底如何实现持久化呢?一种简单的方案时采用硬编码方式(jdbc操作sql方式),为每一种可能的数据库访问操作提供单独的方法。

这种方案存在以下不足:

1. 持久化层缺乏弹性,一旦出现业务需求变更,就必须修改持久化层的接口

2. 持久化层同时与域模型与关系数据库模型绑定,不管域模型还是关系数据库模型发生变化,都要修改持久化层的相关程序代码,增加软件的维护难度。

ORM提供了实现持久化层的另一种模式,它采用映射元数据来描述对象关系的映射,使得ORM中间件能在任何一个应用的业务逻辑层和数据库层之间充当桥梁,Java典型的ORM框架有:Hibernate,ibatis(mybtis),speedframework。

ORM框架的方法论基于三个核心原则:

简单:以最基本的形式建模数据

传达性:数据库结构被任何人都能理解的语言文档化

精确性:基于数据模型创建正确标准化了结构

对象关系映射(Object Relation Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术,可以简单的方案采用硬编码方式(jdbc操作sql方式),为每一种可能的数据库访问操作提供单独的方法,这种方法存在很多缺陷,使用ORM框架(为了解决面向对象与关系数据库存在互不匹配的现象的框架)来解决。

495.Hibernate对象的状态

临时状态/瞬时状态(transient):刚刚用new语句创建,没有被持久化,无id

不处于session中(没有使用session的方法去操作临时对象),该对象成为临时对象

持久化状态,托管状态(persistent):已经被持久化,加入session的缓存中,session是没有关闭

该状态的对象为持久化对象。

游离状态,脱管状态(detached):已经被持久化,但不处于session中,该状态的对象为游离对象。

删除状态(removed):对象有关联的id,并且在session管理下,但是已经被计划(事务提交的时候,commit)删除,如果没有事务就不能删除

相互转换

496.介绍一下Hibernate的缓存

答:一、why(为什么要用Hibernate缓存?)

Hibernate是一种持久化层框架,经常访问物理数据库。

为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能

缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据。

为了提高访问速度,把磁盘或者数据库访问变成内存访问

二、what(Hibernate缓存原理是怎样的?)Hibernate缓存包括两大类:Hibernate 一级缓存和Hibernate二级缓存

1. Hibernate一级缓存又称为”session的缓存”。

session缓存内置不能被卸载,session的缓存是事务范围的缓存(session对象的生命周期通常对应一个数据库事务或者一个应用事务)。

一级缓存中,持久化类的每个实例都具有唯一的OID

2. Hibernate的二级缓存又称为”sessionFactory的缓存”。

由于sessionFactory对象的生命周期和应用程序的整个过程对应,因此Hibernate二级缓存是进程范围或者集群范围的缓存,有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。

第二级缓存是可选的,是一个可配置的插件,默认下sessionFactory不会启用这个插件。

什么样的数据适合存放到二级缓存中?

1) 很少被修改的数据 (帖子的最后回复时间)

2) 经常被查询的数据 (电商的地点)

3) 不是很重要的数据,允许出现偶尔并发的数据

4) 不会被并发访问的数据

5) 常量数据

扩展:Hibernate的二级缓存默认是不支持分布式缓存的,使用memcache,redis等中央缓存来代替二级缓存。

497.简单讲一下webservice使用的场景

webservice是一个SOA(面向服务的编程)的架构,它是不依赖于语言,不依赖于平台,可以实现不同的语言间的相互调用,通过Internet进行基于http协议的网络应用间的交互。

1、异构系统(不同的开发语言)的整合

2、不同客户端的整合 (浏览器、手机端(android\ios)、微信)

3、实实在在的例子:

天气预报:可以通过实现webservice客户端调用远程天气服务实现的

4、单点登录:一个服务实现所有系统的登录

498.简单介绍一下activity?

Activity是一个业务流程管理(BPM)和工作流系统,适用于开发人员和系统管理员,其核心是超快速,稳定的BPMN2的流程引擎,它易于与Spring集成使用。

主要用在OA中,把线下流程放在线上,把现实生活中一些流程固话定义到系统中,然后通过输入表单数据完成业务。

他可以用在OA系统的流程管理中

请假流程(小于三天,一级主管审批,大于三天二级主管审批)

报销流程(价格区间)

499.什么是MyBatis?

答:MyBatis是一个可以自定义SQL、存储过程和高级映射的持久层框架。

500.Mybatis是如何进行分页的?分页插件的原理是什么?

答:1)Mybatis使用RowBounds对象进行分页,也可以直接编写sql实现分页,也可以使用Mybatis的分页插件。

2)分页插件的原理:实现Mybatis提供的接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql。

举例:select * from student,拦截sql后重写为:select t.* from (select * from student)t limit 0,10

501.MyBatis与Hibernate有哪些不同?

答:1)Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句,不过mybatis可以通过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java对象。

2)Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一但需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。

3)Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。但是Hibernate的缺点是学习门槛高,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行。

总之,按照用户的需求在有限的资源环境下只要能做出维护性、扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。

502.简述Mybatis的Xml映射文件和Mybatis内部数据结构之间的映射关系?

答: Mybatis将所有Xml配置信息都封装到All-In-One重量级对象Configuration内部。在Xml映射文件中,< parameterMap>标签会被解析为ParameterMap对象,其每个子元素会被解析为ParameterMapping对象。< resultMap>标签会被解析为ResultMap对象,其每个子元素会被解析为ResultMapping对象。每一个< select>、< insert>、< update>、< delete>标签均会被解析为MappedStatement对象,标签内的sql会被解析为BoundSql对象。

503.什么是MyBatis的接口绑定,有什么好处?

答:接口映射就是在MyBatis中任意定义接口,然后把接口里面的方法和SQL语句绑定,我们直接调用接口方法就可以,这样比起原来了SqlSession提供的方法我们可以有更加灵活的选择和设置.

504.Mybatis能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别?

答:能,Mybatis不仅可以执行一对一、一对多的关联查询,还可以执行多对一,多对多的关联查询,多对一查询,其实就是一对一查询,只需要把selectOne()修改为selectList()即可;多对多查询,其实就是一对多查询,只需要把selectOne()修改为selectList()即可。

关联对象查询,有两种实现方式,一种是单独发送一个sql去查询关联对象,赋给主对象,然后返回主对象。另一种是使用嵌套查询,嵌套查询的含义为使用join查询,一部分列是A对象的属性值,另外一部分列是关联对象B的属性值,好处是只发一个sql查询,就可以把主对象和其关联对象查出来。

505.MyBatis里面的动态Sql是怎么设定的?用什么语法?

答:MyBatis里面的动态Sql一般是通过if节点来实现,通过OGNL语法来实现,但是如果要写的完整,必须配合where,trim节点,where节点是判断包含节点有内容就插入where,否则不插入,trim节点是用来判断如果动态语句是以and 或or开始,那么会自动把这个and或者or取掉。

506.使用MyBatis的mapper接口调用时有哪些要求?

答:1)Mapper接口方法名和mapper.xml中定义的每个sql的id相同

2)Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同

3)Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

4)Mapper.xml文件中的namespace即是mapper接口的类路径。

507.Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?

答:第一种是使用< resultMap>标签,逐一定义列名和对象属性名之间的映射关系。

第二种是使用sql列的别名功能,将列别名书写为对象属性名,比如T_NAME AS NAME,对象属性名一般是name,小写,但是列名不区分大小写,Mybatis会忽略列名大小写,智能找到与之对应对象属性名,你甚至可以写成T_NAME AS NaMe,Mybatis一样可以正常工作。

有了列名与属性名的映射关系后,Mybatis通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。

508.MyBatis接口绑定有几种实现方式,分别是怎么实现的?

答:接口绑定有两种实现方式,一种是通过注解绑定,就是在接口的方法上面加上@Select@Update等注解里面包含Sql语句来绑定,另外一种就是通过xml里面写SQL来绑定,在这种情况下,要指定xml映射文件里面的namespace必须为接口的全路径名.

509.MyBatis实现一对一有几种方式?具体怎么操作的?

答:有联合查询和嵌套查询,联合查询是几个表联合查询,只查询一次,通过在resultMap里面配置association节点配置一对一的类就可以完成;嵌套查询是先查一个表,根据这个表里面的结果的外键id,去再另外一个表里面查询数据,也是通过association配置,但另外一个表的查询通过select属性配置。

510.什么情况下用注解绑定,什么情况下用xml绑定?

答:当Sql语句比较简单时候,用注解绑定;当SQL语句比较复杂时候,用xml绑定,一般用xml绑定的比较多

511.MyBatis的好处是什么?

答:1) MyBatis把sql语句从Java源程序中独立出来, 放在单独的XML文件中编写,给程序的维护带来了很大便利。

2) MyBatis封装了底层JDBC API的调用细节,并能自动将结果集转换成Java Bean对象,大大简化了Java数据库编程的重复工作。

3) 因为MyBatis需要程序员自己去编写sql语句,程序员可以结合数据库自身的特点灵活控制sql语句, 因此能够实现比Hibernate等全自动orm框架更高的查询效率,能够完成复杂查询。

微服务框架

512.Spring Boot有哪些优点?

答:Spring Boot的优点有:

减少开发,测试时间和努力。

使用JavaConfig有助于避免使用XML。

避免大量的Maven导入和各种版本冲突。

提供意见发展方法。

通过提供默认值快速开始开发。

没有单独的Web服务器需要。这意味着你不再需要启动Tomcat,Glassfish或其他任何东西。

需要更少的配置 因为没有web.xml文件。只需添加用@ Configuration注释的类,然后添加用@Bean注释的方法,Spring将自动加载对象并像以前一样对其进行管理。您甚至可以将@Autowired添加到bean方法中,以使Spring自动装入需要的依赖关系中。

基于环境的配置 使用这些属性,您可以将您正在使用的环境传递到应用程序:-Dspring.profiles.active = {enviornment}。在加载主应用程序属性文件后,Spring将在(application{environment} .properties)中加载后续的应用程序属性文件。

513.如何重新加载Spring Boot上的更改,而无需重新启动服务器?

答:这可以使用DEV工具来实现。通过这种依赖关系,您可以节省任何更改,嵌入式tomcat将重新启动。Spring Boot有一个开发工具(DevTools)模块,它有助于提高开发人员的生产力。Java开发人员面临的一个主要挑战是将文件更改自动部署到服务器并自动重启服务器。开发人员可以重新加载Spring Boot上的更改,而无需重新启动服务器。这将消除每次手动部署更改的需要。Spring Boot在发布它的第一个版本时没有这个功能。这是开发人员最需要的功能。DevTools模块完全满足开发人员的需求。该模块将在生产环境中被禁用。它还提供H2数据库控制台以更好地测试应用程序。

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
514.常见的系统架构风格有哪些?各有什么优缺点?

1、单体架构

单体架构也称之为单体系统或者是单体应用。就是一种把系统中所有的功能、模块耦合在一个应用中的架构方式。

单体架构特点:打包成一个独立的单元(导成一个唯一的jar包或者是war包),会一个进程的方式来运行。

单体架构的优点、缺点

优点:

项目易于管理

部署简单

缺点:

测试成本高

可伸缩性差

可靠性差

迭代困难

跨语言程度差

团队协作难

2、MVC架构

MVC架构特点:

MVC是模型(Model)、视图(View)、控制器(Controller)3个单词的缩写。 下面我们从这3个方面来讲解MVC中的三个要素。

Model是指数据模型,是对客观事物的抽象。 如一篇博客文章,我们可能会以一个Post类来表示,那么,这个Post类就是数据对象。 同时,博客文章还有一些业务逻辑,如发布、回收、评论等,这一般表现为类的方法,这也是model的内容和范畴。 对于Model,主要是数据、业务逻辑和业务规则。相对而言,这是MVC中比较稳定的部分,一般成品后不会改变。 开发初期的最重要任务,主要也是实现Model的部分。这一部分写得好,后面就可以改得少,开发起来就快。

View是指视图,也就是呈现给用户的一个界面,是model的具体表现形式,也是收集用户输入的地方。 如你在某个博客上看到的某一篇文章,就是某个Post类的表现形式。 View的目的在于提供与用户交互的界面。换句话说,对于用户而言,只有View是可见的、可操作的。 事实上也是如此,你不会让用户看到Model,更不会让他直接操作Model。 你只会让用户看到你想让他看的内容。 这就是View要做的事,他往往是MVC中变化频繁的部分,也是客户经常要求改来改去的地方。 今天你可能会以一种形式来展示你的博文,明天可能就变成别的表现形式了。

Contorller指的是控制器,主要负责与model和view打交道。 换句话说,model和view之间一般不直接打交道,他们老死不相往来。view中不会对model作任何操作, model不会输出任何用于表现的东西,如HTML代码等。这俩甩手不干了,那总得有人来干吧,只能Controller上了。 Contorller用于决定使用哪些Model,对Model执行什么操作,为视图准备哪些数据,是MVC中沟通的桥梁。

MVC架构优缺点

优点:

各施其职,互不干涉。

在MVC模式中,三个层各施其职,所以如果一旦哪一层的需求发生了变化,就只需要更改相应的层中的代码而不会影响到其它层中的代码。

有利于开发中的分工。

在MVC模式中,由于按层把系统分开,那么就能更好的实现开发中的分工。网页设计人员可以进行开发视图层中的JSP,对业务熟悉的开发人员可开发业务层,而其它开发人员可开发控制层。

有利于组件的重用。

分层后更有利于组件的重用。如控制层可独立成一个能用的组件,视图层也可做成通用的操作界面。

缺点:

增加了系统结构和实现的复杂性。

视图与控制器间的过于紧密的连接。

视图对模型数据的低效率访问。

3、面向服务架构(SOA)

面向服务的架构(SOA)是一个组件模型,它将应用程序拆分成不同功能单元(称为服务)通过这些服务之间定义良好的接口和契约联系起来。接口是采用中立的方式进行定义的,它应该独立于实现服务的硬件平台、操作系统和编程语言。这使得构建在各种各样的系统中的服务可以以一种统一和通用的方式进行交互。

面向服务架构特点:

系统是由多个服务构成

每个服务可以单独独立部署

每个服务之间是松耦合的。服务内部是高内聚的,外部是低耦合的。高内聚就是每个服务只关注完成一个功能。

服务的优点、缺点

优点:

测试容易

可伸缩性强

可靠性强

跨语言程度会更加灵活

团队协作容易

系统迭代容易

缺点:

运维成本过高,部署数量较多

接口兼容多版本

分布式系统的复杂性

分布式事务

515.什么是AKF拆分原则?

业界对于可扩展的系统架构设计有一个朴素的理念,就是:通过加机器就可以解决容量和可用性问题。(如果一台不行那就两台)。

我是个段子:(世界上没有什么事是一顿烧烤不能解决的。如果有,那就两顿。)

这一理念在“云计算”概念疯狂流行的今天,得到了广泛的认可!对于一个规模迅速增长的系统而言,容量和性能问题当然是首当其冲的。但是随着时间的向前,系统规模的增长,除了面对性能与容量的问题外,还需要面对功能与模块数量上的增长带来的系统复杂性问题以及业务的变化带来的提供差异化服务问题。而许多系统,在架构设计时并未充分考虑到这些问题,导致系统的重构成为常态,从而影响业务交付能力,还浪费人力财力!对此,《可扩展的艺术》一书提出了一个更加系统的可扩展模型—— AKF可扩展立方 (Scalability Cube) 。这个立方体中沿着三个坐标轴设置分别为:X、Y、Z。

Y轴扩展会将庞大的整体应用拆分为多个服务。每个服务实现一组相关的功能,如订单管理、客户管理等。在工程上常见的方案是 服务化架构(SOA) 。比如对于一个电子商务平台,我们可以拆分成不同的服务

X轴扩展与我们前面朴素理念是一致的,通过绝对平等地复制服务与数据,以解决容量和可用性的问题。其实就是将微服务运行多个实例,做集群加负载均衡的模式。

Z轴扩展通常是指基于请求者或用户独特的需求,进行系统划分,并使得划分出来的子系统是相互隔离但又是完整的。以生产汽车的工厂来举例:福特公司为了发展在中国的业务,或者利用中国的廉价劳动力,在中国建立一个完整的子工厂,与美国工厂一样,负责完整的汽车生产。这就是一种Z轴扩展。

516.什么是Spring Cloud?

Spring Cloud是一个微服务框架,相比Dubbo等RPC框架, Spring Cloud提供的全套的分布式系统解决方案。

Spring Cloud对微服务基础框架Netflix的多个开源组件进行了封装,同时又实现了和云端平台以及和Spring Boot开发框架的集成。

Spring Cloud为微服务架构开发涉及的配置管理,服务治理,熔断机制,智能路由,微代理,控制总线,一次性token,全局一致性锁,leader选举,分布式session,集群状态管理等操作提供了一种简单的开发方式。

Spring Cloud 为开发者提供了快速构建分布式系统的工具,开发者可以快速的启动服务或构建应用、同时能够快速和云平台资源进行对接

517.Spring Cloud与Dubbo的区别是什么?
518.什么是Eureka注册中心?

Eureka是Netflix开发的服务发现组件,本身是一个基于REST的服务。Spring Cloud将它集成在其子项目spring-cloud-netflix中,以实现Spring Cloud的服务注册于发现,同时还提供了负载均衡、故障转移等能力。

519.简单谈一下Eureka中的三种角色分别是什么?

1、Eureka Server

通过Register、Get、Renew等接口提供服务的注册和发现。

2、Application Service (Service Provider)

服务提供方

把自身的服务实例注册到Eureka Server中

3、Application Client (Service Consumer)

服务调用方

通过Eureka Server 获取服务列表,消费服务。

520.什么是Ribbon

1.Ribbon 是一个基于Http和TCP的客服端负载均衡工具,它是基于Netflix Ribbon实现的。

2.它不像spring cloud服务注册中心、配置中心、API网关那样独立部署,但是它几乎存在于每个spring cloud 微服务中。包括feign提供的声明式服务调用也是基于该Ribbon实现的。

3.ribbon默认提供很多种负载均衡算法,例如 轮询、随机 等等。甚至包含自定义的负载均衡算法。

521.集中式与进程内负载均衡的区别

目前业界主流的负载均衡方案可分成两类:

第一类:集中式负载均衡, 即在consumer和provider之间使用独立的负载均衡设施(可以是硬件,如F5, 也可以是软件,如nginx), 由该设施负责把 访问请求 通过某种策略转发至provider;

第二类:进程内负载均衡,将负载均衡逻辑集成到consumer,consumer从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的provider。

Ribbon就属于后者,它只是一个类库,集成于consumer进程,consumer通过它来获取到provider的地址。

522.Ribbon的常见负载均衡策略有哪些?
id 策略名称 策略对应的类名 实现原理
1 轮询策略(默认) RoundRobinRule 轮询策略表示每次都顺序取下一个provider,比如一共有5个provider,第1次取第1个,第2次取第2个,第3次取第3个,以此类推
2 权重轮询策略 WeightedResponseTimeRule 1.根据每个provider的响应时间分配一个权重,响应时间越长,权重越小,被选中的可能性越低。 2.原理:一开始为轮询策略,并开启一个计时器,每30秒收集一次每个provider的平均响应时间,当信息足够时,给每个provider附上一个权重,并按权重随机选择provider,高权越重的provider会被高概率选中。
3 随机策略 RandomRule 从provider列表中随机选择一个provider
4 最少并发数策略 BestAvailableRule 选择正在请求中的并发数最小的provider,除非这个provider在熔断中。
5 在“选定的负载均衡策略”基础上进行重试机制 RetryRule 1.“选定的负载均衡策略”这个策略是轮询策略RoundRobinRule 2.该重试策略先设定一个阈值时间段,如果在这个阈值时间段内当选择provider不成功,则一直尝试采用“选定的负载均衡策略:轮询策略”最后选择一个可用的provider
6 可用性敏感策略 AvailabilityFilteringRule 过滤性能差的provider,有2种: 第一种:过滤掉在eureka中处于一直连接失败provider 第二种:过滤掉高并发的provider
7 区域敏感性策略 ZoneAvoidanceRule 1.以一个区域为单位考察可用性,对于不可用的区域整个丢弃,从剩下区域中选可用的provider 2.如果这个ip区域内有一个或多个实例不可达或响应变慢,都会降低该ip区域内其他ip被选中的权重。
523.简单说说什么是Feign?

Feign是一种声明式、模板化的HTTP客户端技术(仅在consumer中使用)。

524.什么是声明式,有什么作用,解决什么问题?

声明式调用就像调用本地方法一样调用远程方法;无感知远程http请求。

1、Spring Cloud的声明式调用, 可以做到使用 HTTP请求远程服务时能就像调用本地方法一样的体验,开发者完全感知不到这是远程方法,更感知不到这是个HTTP请求。

2、它像Dubbo一样,consumer直接调用接口方法调用provider,而不需要通过常规的Http Client构造请求再解析返回数据。

3、它解决了让开发者调用远程接口就跟调用本地方法一样,无需关注与远程的交互细节,更无需关注分布式环境开发。

525.什么是服务的灾难性的雪崩效应?

在微服务架构中,一个请求需要调用多个服务是非常常见的。如客户端访问A服务,而A服务需要调用B服务,B服务需要调用C服务,由于网络原因或者自身的原因,如果B服务或者C服务不能及时响应,A服务将处于阻塞状态,直到B服务C服务响应。此时若有大量的请求涌入,容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故障会传播,造成连锁反应,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的“雪崩”效应

526.如何解决灾难性雪崩效应?

降级

超时降级、资源不足时(线程或信号量)降级,降级后可以配合降级接口返回托底数据。实现一个fallback方法, 当请求后端服务出现异常的时候, 可以使用fallback方法返回的值.

隔离(线程池隔离和信号量隔离)

限制调用分布式服务的资源使用,某一个调用的服务出现问题不会影响其他服务调用。

熔断

当失败率(如因网络故障/超时造成的失败率高)达到阀值自动触发降级,熔断器触发的快速失败会进行快速恢复。

缓存

提供了请求缓存。

请求合并

提供请求合并。

527.线程池隔离和信号量隔离的区别
528.请回答微服务架构的六种常用设计模式是什么?

答:如下这六种
代理设计模式
聚合设计模式
链条设计模式
聚合链条设计模式
数据共享设计模式
异步消息设计模式

529.什么是网关服务?

答:网关服务,通常是外部访问服务的唯一接口,访问内部的所有服务都必须先经过网关服务。网关服务的主要功能是消息解析过滤,路由,转发等。

530.网关服务中,路由器的4种路由规则方法是什么?

答:采用URL指定路由方式

采用服务名称指定路由方式

路由的排除方法

路由的添加前缀方法

531.为什么要使用spring cloud config 配置中心?它解决了什么问题?
532.什么是Spring Cloud Bus
533.消息驱动Stream解决了什么问题?
534.为什么要使用微服务跟踪?它解决了什么问题?
535.什么是ELK(ElasticSearch, Logstash, Kibana)

ELK是三个工具的集合,Elasticsearch + Logstash + Kibana,这三个工具组合形成了一套实用、易用的监控架构,很多公司利用它来搭建可视化的海量日志分析平台。

1. ElasticSearch

ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

2. Logstash

Logstash是一个用于管理日志和事件的工具,你可以用它去收集日志、转换日志、解析日志并将他们作为数据提供给其它模块调用,例如搜索、存储等。

3. Kibana

Kibana是一个优秀的前端日志展示框架,它可以非常详细的将日志转化为各种图表,为用户提供强大的数据可视化支持。

536.为什么要用ELK,它解决了什么问题?
537.什么是分布式跟踪 : Zipki?

数据库

538.下列属于关系型数据库的是()(选择两项)
A. Oracle
B. MySql
C. IMS
D. MongoDB
答案:AB分析: IMS 是IP Mulitimedia Subsystem的缩写,是IP多媒体系统 MongoDB分布式文档存储数据库
539.请列出Java常见的开源数据连接池,并对参数做出简单的说明

答:在Java中开源的常用的数据库连接池有以下几种 :

(1)DBCP

DBCP是一个依赖Jakarta commons-pool对象池机制的数据库连接池.DBCP可以直接的在应用程序中使用,Tomcat的数据源使用的就是DBCP。

(2)c3p0

c3p0是一个开放源代码的JDBC连接池,它在lib目录中与Hibernate一起发布,包括了实现jdbc3和jdbc2扩展规范说明的Connection 和Statement 池的DataSources 对象。

(3)Druid

阿里出品,淘宝和支付宝专用数据库连接池,但它不仅仅是一个数据库连接池,它还包含一个ProxyDriver,一系列内置的JDBC组件库,一个SQL Parser。支持所有JDBC兼容的数据库,包括Oracle、MySql、Derby、Postgresql、SQL Server、H2等等。

540.储蓄所有多个储户,储户在多个储户所存取款,储蓄所与储户之间是()
A. 一对一的联系
B. 多对一的联系
C. 一对多的联系
D. 多对多的联系
答案:D
541.视图是一个“虚表”,视图的构造基于()
A. 基本表或视图
B. 视图
C. 数据字典
D. 基本表
答案:A
542.设有关系R(A,B,C,D)及其上的函数相关性集合F={B→A,BC→D},那么关系R最高是()
A. 第一范式的
B. 第二范式的
C. 第三范式的
D. BCNF范式的
答案:A
分析: 根据数据库三大范式的依赖性要求,从B,BC函数确定A和D这一点上,明显看出B,BC都有可能是主码. 若B是主码的话,仔细看会发现,F中竟然没有谁去函数确定C,这显然是说不通的,(因为C至少会被B这个主码函数确定); 若BC是主码,那么F中存在非主属性对候选码的部分依赖,不满足第二范式的要求,故为第一范式.
543.什么是DAO模式?

答:DAO(DataAccess Object)顾名思义是一个为数据库或其他持久化机制提供了抽象接口的对象,在不暴露数据库实现细节的前提下提供了各种数据操作。为了建立一个健壮的Java EE应用,应该将所有对数据源的访问操作进行抽象化后封装在一个公共API中。用程序设计语言来说,就是建立一个接口,接口中定义了此应用程序中将会用到的所有事务方法。在这个应用程序中,当需要和数据源进行交互的时候则使用这个接口,并且编写一个单独的类来实现这个接口,在逻辑上该类对应一个特定的数据存储。DAO模式实际上包含了两个模式,一是Data Accessor(数据访问器),二是Data Object(数据对象),前者要解决如何访问数据的问题,而后者要解决的是如何用对象封装数据。

544.数据库MySQL,Oracle,SqlServer分页时用的语句

Mysql:使用limit关键字

Select * from 表名 where 条件 limit 开始位置,结束位置。通过动态的改变开始和结束位置的值来实现分页。

Oracle:通过rownum来实现

select * from ( select rownum rn,t.* from addressbook where rownum<= 20 ) where rownum > 10

Sqlserver:

select top 20 * from addressbook where id not in (select top 10 id from addressbook)

545.Oracle完成分页功能的三层子查询语句及其含义?

如:select * from (select t.*,rownum r from (select * from A) t where rownum < 10) where r >5

select * from A:要查询的数据

select t.*,rownum r from (select * from A) t where rownum < 10:取前10行

select * from (select t.*,rownum r from (select * from A) t where rownum < 10) where r >5:取5-10行

546.问SQL怎么优化执行效率更高

答: 1. SQL优化的原则是:将一次操作需要读取的BLOCK数减到最低,即在最短的时间达到最大的数据吞吐量。

调整不良SQL通常可以从以下几点切入:

1) 检查不良的SQL,考虑其写法是否还有可优化内容

2) 检查子查询 考虑SQL子查询是否可以用简单连接的方式进行重新书写

3) 检查优化索引的使用

4) 考虑数据库的优化器

2. 避免出现SELECT * FROM table 语句,要明确查出的字段。

3. 在一个SQL语句中,如果一个where条件过滤的数据库记录越多,定位越准确,则该where条件越应该前移。

4. 查询时尽可能使用索引覆盖。即对SELECT的字段建立复合索引,这样查询时只进行索引扫描,不读取数据块。

5. 在判断有无符合条件的记录时建议不要用SELECT COUNT (*)和select top 1 语句。

6. 使用内层限定原则,在拼写SQL语句时,将查询条件分解、分类,并尽量在SQL语句的最里层进行限定,以减少数据的处理量。

7. 应绝对避免在order by子句中使用表达式。

9. 小心使用 IN 和 OR,需要注意In集合中的数据量。建议集合中的数据不超过200个。

10. <> 用 < 、 > 代替,>用>=代替, < 用< =代替,这样可以有效的利用索引。

11. 在查询时尽量减少对多余数据的读取包括多余的列与多余的行。

12. 对于复合索引要注意,例如在建立复合索引时列的顺序是F1,F2,F3,则在where或order by子句中这些字段出现的顺序要与建立索引时的字段顺序一致,且必须包含第一列。只能是F1或F1,F2或F1,F2,F3。否则不会用到该索引。

547.谈谈数据库去空格的情况

一、表中字符串带空格的原因

1、空格就是空格。

2、控制符 显示为 空格。

二、解决方法

第一种情况,去空格的处理的比较简单,Replace(column,' ','') 就可以解决。
第二种情况,解决方法就比较麻烦点:需要先查出相应的ASCII码,再用Replace(column,char(ascii码),'')解决,以下举个栗子:
CREATE TABLE #temp
(NAME NVARCHAR(50))
INSERT INTO #temp SELECT '明天就是国庆了'+CHAR(10) --换行符
SELECT * FROM #temp --末尾显示为空格
SELECT REPLACE(NAME,' ','') FROM #temp --去不掉这个空格
SELECT REPLACE(NAME,CHAR(10),'') FROM #temp --去掉空格
SELECT REPLACE(NAME,CHAR(ASCII(RIGHT(NAME,1))),'') FROM #temp --在不知道是最后一位是什么字符导致空格的情况下,先转ASCII码,在替换
DROP TABLE #temp
----下面是查询结果:
--'明天就是国庆了 '
--'明天就是国庆了 '
--'明天就是国庆了'
--'明天就是国庆了'

548.根据你以往的经验简单叙述一下MYSQL的优化

答:
1.数据库的设计
尽量把数据库设计的更小的占磁盘空间.
1).尽可能使用更小的整数类型.(mediumint就比int更合适).
2).尽可能的定义字段为not null,除非这个字段需要null.
3).如果没有用到变长字段的话比如varchar,那就采用固定大小的纪录格式比如char.
4).表的主索引应该尽可能的短.这样的话每条纪录都有名字标志且更高效.
5).只创建确实需要的索引。索引有利于检索记录,但是不利于快速保存记录。如果总是要在表的组合字段上做搜索,那么就在这些字段上创建索引。索引的第一部分必须是最常使用的字段.如果总是需要用到很多字段,首先就应该多复制这些字段,使索引更好的压缩。
6).所有数据都得在保存到数据库前进行处理。
7).所有字段都得有默认值。
8).在某些情况下,把一个频繁扫描的表分成两个速度会快好多。在对动态格式表扫描以取得相关记录时,它可能使用更小的静态格式表的情况下更是如此。
2.系统的用途
1).尽量使用长连接.
2).explain 复杂的SQL语句。
3).如果两个关联表要做比较话,做比较的字段必须类型和长度都一致.
4).LIMIT语句尽量要跟order by或者 distinct.这样可以避免做一次full table scan.
5).如果想要清空表的所有记录,建议用truncate table tablename而不是delete from tablename.
6).能使用STORE PROCEDURE 或者 USER FUNCTION的时候.
7).在一条insert语句中采用多重纪录插入格式.而且使用load data infile来导入大量数据,这比单纯的indert快好多.
8).经常OPTIMIZE TABLE 来整理碎片.
9).还有就是date 类型的数据如果频繁要做比较的话尽量保存在unsigned int 类型比较快。
3.系统的瓶颈
1).磁盘搜索.
并行搜索,把数据分开存放到多个磁盘中,这样能加快搜索时间.
2).磁盘读写(IO)
可以从多个媒介中并行的读取数据。
3).CPU周期
数据存放在主内存中.这样就得增加CPU的个数来处理这些数据。
4).内存带宽
当CPU要将更多的数据存放到CPU的缓存中来的话,内存的带宽就成了瓶颈.

549.以Oracle11R为例简述数据库集群部署

命令行工具
–crsctl管理集群相关的操作:
-启动和关闭Oracle集群
-启用和禁用Oracle集群后台进程
-注册集群资源
-srvctl 管理Oracle 资源相关操作
-启动和关闭数据库实例和服务
在Oracle Grid安装的home路径下的命令行工具crsctl和srvctl用来管理Oracle集群。使用crsctl可以监控和管理任何集群节点的集群组件和资源。srvctl工具提供了类似的功能,来监控和管理Oracle相关的资源,例如数据库实例和数据库服务。crsctl命令只能是集群管理者来运行,srvctl命令可以是其他用户,例如数据库管理员来使用。

550.说一下数据库的存储过程?

一、存储过程与函数的区别:

1.一般来说,存储过程实现的功能要复杂一点,而函数的实现的功能针对性比较强。

2.对于存储过程来说可以返回参数(output),而函数只能返回值或者表对象。

3.存储过程一般是作为一个独立的部分来执行,而函数可以作为查询语句的一个部分来调用,由于函数可以返回一个表对象,因此它可以在查询语句中位于FROM关键字的后面。

二、存储过程的优点:

1.执行速度更快 – 在数据库中保存的存储过程语句都是编译过的

2.允许模块化程序设计 – 类似方法的复用

3.提高系统安全性 – 防止SQL注入

4.减少网络流通量 – 只要传输存储过程的名称

系统存储过程一般以sp开头,用户自定义的存储过程一般以usp开头

551.数据库创建索引的缺点?

缺点:

第一,创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。

第二,索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。

第三,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。

552.有两张表;请用SQL查询,所有的客户订单日期最新的前五条订单记录。(分别注明MySQL. Oracle写法)

客户信息表(c CUSTOM)有以下字段:

id、name、mobile

客户订单表(C_ORDER)有以下字段:

id、custom_id、commodity、count、order _date

Mysql:

Select * from c_order order by order_date desc limit 0,5;

Oracle:

Select o.*,rownum n

from c_order order by order_date desc where n<6;

553.关于HQL与SQL,以下哪些说法正确?()
A. HQL与SQL没什么差别
B. HQL面向对象,而SQL操纵关系数据库
C. 在 HQL 与 SQL 中,都包含 select,insert,update,delete 语句
D. HQL仅用于査询数据,不支持insert,update和delete语句
答案:BC
554.下面是学生表(student)的结构说明
字段名称 字段解释 字段类型 字段长度 约束
s_id 学号 字符 10 PK
s_name 学生姓名 字符 50 Not null
s_age 学生年龄 数值 3 Not null
s-sex 学生性别 字符(男:1女:0) 1 Not null

下面是教师表(Teacher )的结构说明

字段名称 字段解释 字段类型 字段长度 约束
t_id 教师编号 字符 10 PK
t_name 教师名字 字符 50 Not null

下面是课程表(Course)的结构说明

字段名称 字段解释 字段类型 字段长度 约束
c_id 课程编号 字符 10 PK
c_name 课程名字 字符 50 Not null
t_id 教师编号 字符 10 Not null

下面是成绩表(SC)的结构说明

字段名称 字段解释 字段类型 字段长度 约束
s_id 学号 字符 10 PK
c_id 课程编号 字符 10 Not null
score 成绩 数值 3 Not null

1、查询“001”课程比“002”课程成绩高的所有学生的学号;

select a.s_id from (select s_id,score from SC where C_ID='001') a,(select s_id,score
from SC where C_ID='002') b
where a.score>b.score and a.s_id=b.s_id;

2、查询平均成绩大于60分的同学的学号和平均成绩;

select S_ID,avg(score)
from sc
group by S_ID having avg(score) >60;

3、查询所有同学的学号、姓名、选课数、总成绩;

select Student.S_ID,Student.Sname,count(SC.C_ID),sum(score)
from Student left Outer join SC on Student.S_ID=SC.S_ID
group by Student.S_ID,Sname

4、查询姓“李”的老师的个数;

select count(distinct(Tname))
from Teacher
where Tname like '李%';

5、查询没学过“叶平”老师课的同学的学号、姓名;

select Student.S_ID,Student.Sname
from Student
where S_ID not in (select distinct( SC.S_ID) from SC,Course,Teacher where SC.C_ID=Course.C_ID and Teacher.T#=Course.T# and Teacher.Tname='叶平');

6、查询学过“001”并且也学过编号“002”课程的同学的学号、姓名;

elect Student.S_ID,Student.Sname from Student,SC where Student.S_ID=SC.S_ID and SC.C_ID='001'and exists( Select * from SC as SC_2 where SC_2.S_ID=SC.S_ID and SC_2.C_ID='002');

7、查询学过“叶平”老师所教的所有课的同学的学号、姓名;

select S_ID,Sname
from Student
where S_ID in (select S_ID from SC ,Course ,Teacher where SC.C_ID=Course.C_ID and Teacher.T#=Course.T# and Teacher.Tname='叶平' group by S_ID having count(SC.C_ID)=(select count(C_ID) from Course,Teacher where Teacher.T#=Course.T# and Tname='叶平'));

8、查询课程编号“002”的成绩比课程编号“001”课程低的所有同学的学号、姓名;

Select S_ID,Sname from (select Student.S_ID,Student.Sname,score ,(select score from SC SC_2 where SC_2.S_ID=Student.S_ID and SC_2.C_ID='002') score2
from Student,SC where Student.S_ID=SC.S_ID and C_ID='001') S_2 where score2 < score;

9、查询所有课程成绩小于60分的同学的学号、姓名;

select S_ID,Sname
from Student
where S_ID not in (select S.S_ID from Student AS S,SC where S.S_ID=SC.S_ID and score>60);

10、查询没有学全所有课的同学的学号、姓名;

select Student.S_ID,Student.Sname
from Student,SC
where Student.S_ID=SC.S_ID group by Student.S_ID,Student.Sname having count(C_ID) <(select count(C_ID) from Course);

11、查询至少有一门课与学号为“1001”的同学所学相同的同学的学号和姓名;

select distinct S_ID,Sname from Student,SC where Student.S_ID=SC.S_ID and SC.C_ID in (select C_ID from SC where S_ID='1001');

12、查询至少学过学号为“001”同学所有一门课的其他同学学号和姓名;

select distinct SC.S_ID,Sname
from Student,SC
where Student.S_ID=SC.S_ID and C_ID in (select C_ID from SC where S_ID='001');

555.为管理岗位业务培训信息,有如下3个表:

S(S#,SN,SD,SA),其中S#,SN,SD,SA分别代表学号、学员姓名、所属单位、学员年龄。 C (C#,CN ),其中C#,CN分别代表课程编号、课程名称
SC(S#,C#,G),其中S#,C#,G分别代表学号、所选修的课程编号、学习成绩
请使用2种标准SQL语句査洵选修课程名称为“税收基础”的学员学号和姓名,并说明其优缺点 。

SQL92标准:

SELECT SN,SD FROM S
WHERE [S#] IN(
SELECT [S#] FROM C,SC
WHERE C.[C#]=SC.[C#]
AND CN=N'税收基础')

SQL99标准:

elect s.s#,s.sn from s
join sc on s.s#=sc.s#
join c on sc.c#=c.c#
where c.cn='税收基础'

优点:

SQL99将连接条件和过滤条件分开,显得代码清晰。
SQL92书写简单易于理解。

缺点:

SQL92连接条件和过滤条件都写在一起,不利于查看。
SQL99书写相对麻烦不易于理解。

556.用Java怎么实现有每天有1亿条记录的DB储存?MySQL上亿记录数据量的数据库如何设计?

1.这么大数据量首先建议 使用大数据的DB,可以用spring batch 来做类似这样的处理。定量向DB存储数据。如果需要定时,可以考虑 quartz。

Mysql数据库设计:

1.读写分离;

2.纵向横向拆分库、表。

MySQL的基本功能中包括replication(复制)功能。所谓replication,就是确定master以及与之同步的slave服务器,再加上slave将master中写入的内容polling过来更新自身内容的功能。这样slave就是master的replica(复制品)。这样就可以准备多台内容相同的服务器。

通过master和salve的replication,准备好多台服务器之后,让应用程序服务器通过负载均衡器去处理查询slave。这样就能将查询分散到多台服务器上。

应用程序实现上应该只把select等读取之类的查询发送给负载均衡器,而更新应当直接发送给master。要是在slave上执行更新操作,slave和master的内容就无法同步。MySQL会检测到master和slave之间内容差异,并停止replication,这回导致系统故障。Slave可以采用LVS(linux系统自带的负载均衡器)实现查询的负载均衡。

使用MySQL的replication是利用的冗余化,实现冗余化需要实现的最小服务器数量是4台,三台slave和一台master,slave为什么是需要三台呢,比如一台slave死机了,现在需要修复再次上线,那么意味着你必须停止一台slave来复制MySQL的数据,如果只有两台slave,一台坏了,你就必须停止服务,如果有三台,坏了一台,你复制数据时停止一台,还有一台可以运维。

对于数据的处理是能放入到内存中就尽量放入到内存中如果不能放入到内存中,可以利用MySQL的Partitioning。

Partitioning就是表分割也就是讲A表和B表放在不同的服务器上。简单来说,Partitioning就是充分利用局部性进行分割,提高缓存利用效率,从而实现Partitioning的效果。其中最重要的一点就是以Partitioning为前提设计的系统将表分割开,用RDBMS的方式的话,对于一对多的关系经常使用JOIN查询将两张表连接起来。但是如果将表分割开了之后,也就是两张表不在同一个数据库,不在同一个服务器上怎样使用JOIN操作,这里需要注意的是如果是用where in操作不是省了一些麻烦了嘛。

557.Mysql的引擎有哪些?支持事物么?DB储存引擎有哪些?

MySQL有多种存储引擎,每种存储引擎有各自的优缺点,可以择优选择使用:

MyISAM、InnoDB、MERGE、MEMORY(HEAP)、BDB(BerkeleyDB)、EXAMPLE、FEDERATED、ARCHIVE、CSV、BLACKHOLE。

MySQL支持数个存储引擎作为对不同表的类型的处理器。MySQL存储引擎包括处理事务安全表的引擎和处理非事务安全表的引擎。

· MyISAM管理非事务表。它提供高速存储和检索,以及全文搜索能力。MyISAM在所有MySQL配置里被支持,它是默认的存储引擎,除非你配置MySQL默认使用另外一个引擎。

· MEMORY存储引擎提供“内存中”表。MERGE存储引擎允许集合将被处理同样的MyISAM表作为一个单独的表。就像MyISAM一样,MEMORY和MERGE存储引擎处理非事务表,这两个引擎也都被默认包含在MySQL中。

注释:MEMORY存储引擎正式地被确定为HEAP引擎。

· InnoDB和BDB存储引擎提供事务安全表。BDB被包含在为支持它的操作系统发布的MySQL-Max二进制分发版里。InnoDB也默认被包括在所 有MySQL 5.1二进制分发版里,你可以按照喜好通过配置MySQL来允许或禁止任一引擎。

· EXAMPLE存储引擎是一个“存根”引擎,它不做什么。你可以用这个引擎创建表,但没有数据被存储于其中或从其中检索。这个引擎的目的是服务,在 MySQL源代码中的一个例子,它演示说明如何开始编写新存储引擎。同样,它的主要兴趣是对开发者。

· NDB Cluster是被MySQL Cluster用来实现分割到多台计算机上的表的存储引擎。它在MySQL-Max 5.1二进制分发版里提供。这个存储引擎当前只被Linux, Solaris, 和Mac OS X 支持。在未来的MySQL分发版中,我们想要添加其它平台对这个引擎的支持,包括Windows。

· ARCHIVE存储引擎被用来无索引地,非常小地覆盖存储的大量数据。

· CSV存储引擎把数据以逗号分隔的格式存储在文本文件中。

· BLACKHOLE存储引擎接受但不存储数据,并且检索总是返回一个空集。

· FEDERATED存储引擎把数据存在远程数据库中。在MySQL 5.1中,它只和MySQL一起工作,使用MySQL C Client API。在未来的分发版中,我们想要让它使用其它驱动器或客户端连接方法连接到另外的数据源。

558.以下是学生考试结果表
fname kecheng fenshu
张三 语文 81
张三 数学 65
李四 语文 76
李四 数学 90
王五 语文 61
王五 数学 100
王五 英语 90

1.请用一条sql语句从t_result表中查询出每门课都大于75分的学生姓名;

select b.fname from
(select fname,count(kecheng) c from t_result group by fname)a,
(Select fname,kecheng,count(fname) c from t_result where fenshu >75 group by fname)b
where a.fname = b.fname and a.c = b.c

2.请用一条sql写出总分排名前三的学生姓名,总分,平均分

select fname,sum(fenshu),avg(fenshu) from t_result GROUP By fname order by SUM(fenshu) desc;

559.库中已经存在雇用表表名:

org_employee;表中字段:雇员编号(emp_id),雇员姓名(em_name),雇员年龄(emp_age),雇员部门(depart_name);请写出执行以下操作的sql语句:

1)向表中增加一条数据:雇员编号(1001),雇员姓名(张三),雇员年龄(24),雇员部门(研发部);

INSERT INTO org_employee

VALUES(‘1001’,’张三’,’24’,’研发部’);

2)查询雇员年龄在55(包含)至60(不包含)岁之间的雇员数据

SELECT * FROM org_employee

WHERE emp_age>=55 and emp_age <60;

3)分部门查询各个部门的雇员数量

SELECT COUNT(*),depart_name group by depart_name;

4)删除姓名为张三的雇员数据

Delete from org_employee where em_name =’张三’;

5)在表中增加一个日期类型的字段雇员出生日期,字段为emp_brithday

Alter table org_employee add(emp_brithday date);

6)将表org_employee删除

drop org_employee;

560.如下表1中的数据,表名为:t_test,记录某场比赛的结果。

请用sql语句实现表2的查询结果

表1

ID matchdate result
1 2015-02-04
2 2015-02-04
3 2015-02-04
4 2015-04-07
5 2015-04-07
6 2015-04-07

表2

比赛日期
2015-02-04 2 1
2015-04-07 1 2

SQL语句:

create table t_second(
 matchdate date,
  win varchar(3),
  lose varchar(3)
);

insert into t_second (matchdate,win) select matchdate,count(result) from t_test where result ='胜' GROUP BY matchdate;

update t_second,(select matchdate,count(result) as lose from t_test where result ='负' GROUP BY matchdate)s set t_second.lose = s.lose where t_second.matchdate = s.matchdate;
561.请将如下数据库语句进行优化,使其执行效率更高(提示:…不需要更改)
SELECT…
FROM EMP
WHERE DEPT_NO NOT IN (SELECT DEPT_NO
FROM DEPT
WHERE DEPT_CAT=’A’);
SELECT…
FROM EMP
WHERE DEPT_NO NOT EXISTS(SELECT DEPT_NO
FROM DEPT
WHERE DEPT_CAT=’A’);

优化的理由:not in 和not exists

如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;

而not extsts 的子查询依然能用到表上的索引。所以无论那个表大,用not exists 都比not in 要快。

562.请简述如何将Oracle中的数据库转至DB2中,需要保证表结构和数据不变

使用ETL工具,如infomatic,datastage,kettle等,可以完成异构数据库的迁移

以kettle为例

表输入选择 oracle库

表输出选择DB库

循环执行可以进行全库迁移

563.学生成绩表
姓名:name 课程:subject 分数:score 学号:stuid
张三 数学 89 1
张三 语文 80 1
张三 英语 70 1
李四 数学 90 2
李四 语文 70 2
李四 英语 80 2

1.计算每个人的总成绩并排名(要求显示字段:姓名,总成绩)

select name,sum(score) s from t_stu GROUP BY name;

2.列出各门课程成绩最好的学生(要求显示字段:学号,姓名,科目,成绩)

select t1.stuid,t1.name,t1.subject,t1.score from t_stu t1,

(select subject,MAX(score) as maxscore from t_stu group by subject)t2

where t1.subject = t2.subject and t1.score = t2.maxscore;

3.列出各个课程的平均成绩(要求显示字段;课程,平均成绩)

select subject,AVG(score)平均成绩 from t_stu

group by subject;

564.Oracl数据库中有两张表Stu(学生表)和Grade(分数表),如下图所示:

Stu表

sid(学生ID) sname(姓名) sage(年龄)
1 张三 23
2 李四 25
3 王五 24

Grade表

gid(分数主键) cid(课程ID) sid(学生主键) grade(分数)
1 2 3 86
2 2 2 79
3 1 2 80
4 1 1 81
5 1 3 70
6 2 1 78

请写sql统计出有两门以上的课的分数在80分以上的学生的姓名和年龄?

Select sname,sage from Stu where Stu.sid in (

Select sid from Grade where grade >80

)

565.下面是学生表(Student)的结构说明:
字段名称 字段解释 字段类型 字段长度 约束
s_id 学号 字符 10 PK
s_name 学生姓名 字符 50 Not null
s_age 学生年龄 数值 3 Not null
s-sex 学生性别 字符(男:1女:0) 1 Not null

下面是教师表(Teacher )的结构说明

字段名称 字段解释 字段类型 字段长度 约束
t_id 教师编号 字符 10 PK
t_name 教师名字 字符 50 Not null

下面是课程表(Course)的结构说明

字段名称 字段解释 字段类型 字段长度 约束
c_id 课程编号 字符 10 PK
c_name 课程名字 字符 50 Not null
t_id 教师编号 字符 10 Not null

下面是成绩表(SC)的结构说明

字段名称 字段解释 字段类型 字段长度 约束
s_id 学号 字符 10 PK
c_id 课程编号 字符 10 Not null
score 成绩 数值 3 Not null

查询同名同姓学生名单,并统计同名人数

select 姓名,count(学号) as num

from 学生表

group by 姓名

having count(学号)>1 --保证查找到的都是存在2个以上(包括2)的同名同姓的姓名及人数。

查询平均成绩大于60分的学生的学号和平均成绩;

Select s_id,avg(score) from sc groupby s_id having avg(score)>60

查询姓“李”的老师的个数;

Select count(*),teacher.t_name from teacher where teacher.t_name like '李%'

566.取出sql表中低31到40的记录(以自动增长ID为主键)

Sql server方案:

select top 10 * from t where id not in

(select top 30 id from t order by id ) orde by id

Mysql方案:select * from t order by id limit 30,10

Oracle方案:

select rownum num,tid from (select rownum num,tid from t_test) where num>=30 and num<=41;

567.下列两个表,需要用一条sql语句把b表中的ID和NAME 字段的数值复制到A表中

A表

ID NAME

B表

ID NAME OTHER
1 Aaa Ddd
2 Bbb Eee

insert into a select id,name from b;

568.什么是基本表,什么是视图,两者的区别和联系是什么?

它是从一个或几个基本表中导出的 表,是从现有基本表中抽取若干子集组成用户的“专用表”。

基本表:基本表的定义指建立基本关系模式,
而变更则是指对数据库中已存在的基本表进行删除与修改。
区别:
1、视图是已经编译好的sql语句。而表不是
2、视图没有实际的物理记录。而表有。
3、表是内容,视图是窗口
4、表只用物理空间而视图不占用物理空间,
视图只是逻辑概念的存在,表可以及时对它进行修改,
但视图只能有创建的语句来修改
5、表是内模式,试图是外模式
6、视图是查看数据表的一种方法,
可以查询数据表中某些字段构成的数据,
只是一些SQL语句的集合。从安全的角度说,
视图可以不给用户接触数据表,从而不知道表结构。
7、表属于全局模式中的表,是实表;视图属于局部模式的表,
是虚表。
8、视图的建立和删除只影响视图本身,不影响对应的基本表。
联系:视图(view)是在基本表之上建立的表,它的结构(
即所定义的列)和内容(即所有数据行)都来自基本表,
它依据基本表存在而存在。一个视图可以对应一个基本表,
也可以对应多个基本表。
视图是基本表的抽象和在逻辑意义上建立的新关系

569.什么是事务?什么是锁?

事务与锁是不同的。事务具有ACID(原子性、一致性、隔离性和持久性),锁是用于解决隔离性的一种机制。事务的隔离级别通过锁的机制来实现。另外锁有不同的粒度,同时事务也是有不同的隔离级别的(一般有四种:读未提交Read uncommitted,
读已提交Read committed,
可重复读Repeatable read,
可串行化Serializable)。
在具体的程序设计中,开启事务其实是要数据库支持才行的,如果数据库本身不支持事务,那么仍然无法确保你在程序中使用的事务是有效的。
锁可以分为乐观锁和悲观锁:
悲观锁:认为在修改数据库数据的这段时间里存在着也想修改此数据的事务;
乐观锁:认为在短暂的时间里不会有事务来修改此数据库的数据;
我们一般意义上讲的锁其实是指悲观锁,在数据处理过程中,将数据置于锁定状态(由数据库实现)
如果开启了事务,在事务没提交之前,别人是无法修改该数据的;如果rollback,你在本次事务中的修改将撤消(不是别人修改的会没有,因为别人此时无法修改)。当然,前提是你使用的数据库支持事务。还有一个要注意的是,部分数据库支持自定义SQL锁覆盖事务隔离级别默认的锁机制,如果使用了自定义的锁,那就另当别论。
重点:一般事务使用的是悲观锁(具有排他性)

570.Student学生表(学号,姓名、性别、年龄、组织部门),Course 课程表(编号,课程名称),Sc选课表(学号,课程编号,成绩)

写一个SQL语句,查询选修了计算机原理的学生学号和姓名
select 学号,姓名 from Student where 学号 in
(select 学号 from Sc where 课程编号 in
(Select 课程编号 from Course where 课程名称 = ‘计算机原理’))
写一个SQL语句,查询“周星驰”同学选修了的课程名字
select 课程名称 from Course where 编号 in (
select Sc.课程编号 from Student,Sc where Student.姓名=’周星驰’ and Student.学号 = Sc.学号)
写一个SQL语句,查询选修了5门课程的学生学号和姓名
Select 学号,姓名 from Student where 学号 in (
Select 学号,count(课程编号) from Sc group by 学号 having count(课程编号)>=5)

571.sql查询

Student(S#,Sname,Sage,Ssex)学生表
S#:学号
Sname:学生姓名
Sage:学生年龄
Ssex: 学生性别
Course(C#,Cname,T#)课程表
C#,课程编号;
Cname:课程名字;
T#:教师编号;
SC(S#,C#,score)成绩表
S#:学号;
C#,课程编号;
Score:成绩;
Teacher(T#,Tname)教师表
T#:教师编号;
Tname:教师名字
查询“001”课程比“002”课程成绩高的所有学生学号
select SC1.S#
from SC SC1 JOIN SC SC2 ON SC1.S#=SC2.S#
WHERE SC1.C#='001' AND SC2.C#='002' AND SC1.score>SC2.score
查询平均成绩大于60分的同学的学号和平均成绩
select S#,AVG(score) 平均成绩
from SC
group by S#
having AVG(score)>60
查询所有同学的学号、姓名、选课数、总成绩
select Student.S#,Sname,COUNT(*) 选课数,SUM(score) 总成绩
from Student JOIN SC on Student.S#=SC.S#
group by Student.S#,Sname
查询姓“李”的老师的个数
Select count(*) from Teacher where Tname like ‘李%’;
查询没学过“叶平”老师课的同学的学号、姓名
SELECT stu2.s#,stu2.stuname FROM Student stu2 WHERE stu2.s# NOT IN
(SELECT DISTINCT stu.s# FROM student stu, course c,teacher tea,score score
WHERE stu.s#= score.s# AND course.c#= score.c#
AND tea.t#= course.t#AND tea.tname= '叶平' )

JVM

572.简述Java内存管理机制,以及垃圾回收的原理和使用过Java调优工具

内存管理的职责为分配内存,回收内存。 没有自动内存管理的语言/平台容易发生错误。

典型的问题包括悬挂指针问题,一个指针引用了一个已经被回收的内存地址,导致程序的运行完全不可知。

另一个典型问题为内存泄露,内存已经分配,但是已经没有了指向该内存的指针,导致内存泄露。 程序员要花费大量时间在调试该类问题上。

573.描述JVM加载class文件的原理机制

JVM中类的装载是由类加载器(ClassLoader)和它的子类来实现的,Java中的类加载器是一个重要的Java运行时系统组件,它负责在运行时查找和装入类文件中的类。

由于Java的跨平台性,经过编译的Java源程序并不是一个可执行程序,而是一个或多个类文件。当Java程序需要使用某个类时,JVM会确保这个类已经被加载、连接(验证、准备和解析)和初始化。类的加载是指把类的.class文件中的数据读入到内存中,通常是创建一个字节数组读入.class文件,然后产生与所加载类对应的Class对象。加载完成后,Class对象还不完整,所以此时的类还不可用。当类被加载后就进入连接阶段,这一阶段包括验证、准备(为静态变量分配内存并设置默认的初始值)和解析(将符号引用替换为直接引用)三个步骤。最后JVM对类进行初始化,包括:1)如果类存在直接的父类并且这个类还没有被初始化,那么就先初始化父类;2)如果类中存在初始化语句,就依次执行这些初始化语句。

 类的加载是由类加载器完成的,类加载器包括:根加载器(BootStrap)、扩展加载器(Extension)、系统加载器(System)和用户自定义类加载器(java.lang.ClassLoader的子类)。从Java 2(JDK 1.2)开始,类加载过程采取了父亲委托机制(PDM)。PDM更好的保证了Java平台的安全性,在该机制中,JVM自带的Bootstrap是根加载器,其他的加载器都有且仅有一个父类加载器。类的加载首先请求父类加载器加载,父类加载器无能为力时才由其子类加载器自行加载。JVM不会向Java程序提供对Bootstrap的引用。下面是关于几个类加载器的说明:

Bootstrap:一般用本地代码实现,负责加载JVM基础核心类库(rt.jar);

Extension:从java.ext.dirs系统属性所指定的目录中加载类库,它的父加载器是Bootstrap;

System:又叫应用类加载器,其父类是Extension。它是应用最广泛的类加载器。它从环境变量classpath或者系统属性java.class.path所指定的目录中记载类,是用户自定义加载器的默认父加载器。

574.说说JVM原理?内存泄漏与溢出的区别?何时产生内存泄漏?

答:JVM原理:

JVM是Java Virtual Machine(Java虚拟机)的缩写,它是整个java实现跨平台的最核心的部分,所有的Java程序会首先被编译为.class的类文件,这种类文件可以在虚拟机上执行,也就是说class并不直接与机器的操作系统相对应,而是经过虚拟机间接与操作系统交互,由虚拟机将程序解释给本地系统执行。JVM是Java平台的基础,和实际的机器一样,它也有自己的指令集,并且在运行时操作不同的内存区域。JVM通过抽象操作系统和CPU结构,提供了一种与平台无关的代码执行方法,即与特殊的实现方法、主机硬件、主机操作系统无关。JVM的主要工作是解释自己的指令集(即字节码)到CPU的指令集或对应的系统调用,保护用户免被恶意程序骚扰。JVM对上层的Java源文件是不关心的,它关注的只是由源文件生成的类文件(.class文件)。

内存泄漏与溢出的区别:

1) 内存泄漏是指分配出去的内存无法回收了。

2) 内存溢出是指程序要求的内存,超出了系统所能分配的范围,从而发生溢出。比如用byte类型的变量存储10000这个数据,就属于内存溢出。

3) 内存溢出是提供的内存不够;内存泄漏是无法再提供内存资源。

何时产生内存泄漏:

1) 静态集合类:在使用Set、Vector、HashMap等集合类的时候需要特别注意,有可能会发生内存泄漏。当这些集合被定义成静态的时候,由于它们的生命周期跟应用程序一样长,这时候,就有可能会发生内存泄漏。

2) 监听器:在Java中,我们经常会使用到监听器,如对某个控件添加单击监听器addOnClickListener(),但往往释放对象的时候会忘记删除监听器,这就有可能造成内存泄漏。好的方法就是,在释放对象的时候,应该记住释放所有监听器,这就能避免了因为监听器而导致的内存泄漏。

3) 各种连接:Java中的连接包括数据库连接、网络连接和io连接,如果没有显式调用其close()方法,是不会自动关闭的,这些连接就不能被GC回收而导致内存泄漏。一般情况下,在try代码块里创建连接,在finally里释放连接,就能够避免此类内存泄漏。

4) 外部模块的引用:调用外部模块的时候,也应该注意防止内存泄漏。如模块A调用了外部模块B的一个方法,如:public void register(Object o)。这个方法有可能就使得A模块持有传入对象的引用,这时候需要查看B模块是否提供了去除引用的方法,如unregister()。这种情况容易忽略,而且发生了内存泄漏的话,比较难察觉,应该在编写代码过程中就应该注意此类问题。

5) 单例模式:使用单例模式的时候也有可能导致内存泄漏。因为单例对象初始化后将在JVM的整个生命周期内存在,如果它持有一个外部对象(生命周期比较短)的引用,那么这个外部对象就不能被回收,而导致内存泄漏。如果这个外部对象还持有其它对象的引用,那么内存泄漏会更严重,因此需要特别注意此类情况。这种情况就需要考虑下单例模式的设计会不会有问题,应该怎样保证不会产生内存泄漏问题。

575.GC线程是否为守护线程?

GC线程是守护线程。线程分为守护线程和非守护线程(即用户线程)。只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作。

576.Java的类加载器都有哪些,每个类加载器都有加载那些类,什么是双亲委派模型,是做什么的?

类加载器按照层次,从顶层到底层,分为以下三种:

(1)启动类加载器(Bootstrap ClassLoader)

这个类加载器负责将存放在JAVA_HOME/lib下的,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别的类库加载到虚拟机内存中。启动类加载器无法被Java程序直接引用。

(2)扩展类加载器(Extension ClassLoader)

这个加载器负责加载JAVA_HOME/lib/ext目录中的,或者被java.ext.dirs系统变量所指定的路径中的所有类库,开发者可以直接使用扩展类加载器

(3)应用程序类加载器(Application ClassLoader)

这个加载器是ClassLoader中getSystemClassLoader()方法的返回值,所以一般也称它为系统类加载器。它负责加载用户类路径(Classpath)上所指定的类库,可直接使用这个加载器,如果应用程序没有自定义自己的类加载器,一般情况下这个就是程序中默认的类加载器

双亲委派模型:

双亲委派模型要求除了顶层的启动类加载器外,其他的类加载器都应当有自己的父类加载器。这里类加载器之间的父子关系一般不会以继承关系来实现,而是都使用组合关系来复用父加载器的代码

工作过程:

如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传递到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。

好处:

Java类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类Object,它放在rt.jar中,无论哪一个类加载器要加载这个类,最终都是委派给启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类,判断两个类是否相同是通过classloader.class这种方式进行的,所以哪怕是同一个class文件如果被两个classloader加载,那么他们也是不同的类。

577.垃圾回收器(GC)的基本原理是什么?垃圾回收器可以马上回收内存吗?如何通知虚拟机进行垃圾回收?

1、对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是"可达的",哪些对象是"不可达的"。当GC确定一些对象为"不可达”时,GC就有责任回收这些内存空间。

2、可以。程序员可以手动执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。

3. System.gc();或者Runtime.getRuntime().gc();

578.Java 中会存在内存泄漏吗,请简单描述。

答:理论上Java因为有垃圾回收机制(GC)不会存在内存泄露问题(这也是Java被广泛使用于服务器端编程的一个重要原因);然而在实际开发中,可能会存在无用但可达的对象,这些对象不能被GC回收也会发生内存泄露。一个例子就是hibernate的Session(一级缓存)中的对象属于持久态,垃圾回收器是不会回收这些对象的,然而这些对象中可能存在无用的垃圾对象。下面的例子也展示了Java中发生内存泄露的情况:

package com.bjsxt;
import java.util.Arrays;
import java.util.EmptyStackException;

public class MyStack<T> {
    private T[] elements;
    private int size = 0;
private static final int INIT_CAPACITY = 16;
    public MyStack() {
        elements = (T[]) new Object[INIT_CAPACITY];
    }
    public void push(T elem) {
        ensureCapacity();
        elements[size++] = elem;
    }
    public T pop() {
        if(size == 0)
            throw new EmptyStackException();
        return elements[--size];
    }
    private void ensureCapacity() {
        if(elements.length == size) {
            elements = Arrays.copyOf(elements, 2 * size + 1);
        }
    }
}

上面的代码实现了一个栈(先进后出(FILO))结构,乍看之下似乎没有什么明显的问题,它甚至可以通过你编写的各种单元测试。然而其中的pop方法却存在内存泄露的问题,当我们用pop方法弹出栈中的对象时,该对象不会被当作垃圾回收,即使使用栈的程序不再引用这些对象,因为栈内部维护着对这些对象的过期引用(obsolete reference)。在支持垃圾回收的语言中,内存泄露是很隐蔽的,这种内存泄露其实就是无意识的对象保持。如果一个对象引用被无意识的保留起来了,那么垃圾回收器不会处理这个对象,也不会处理该对象引用的其他对象,即使这样的对象只有少数几个,也可能会导致很多的对象被排除在垃圾回收之外,从而对性能造成重大影响,极端情况下会引发Disk Paging(物理内存与硬盘的虚拟内存交换数据),甚至造成OutOfMemoryError。 

579.GC 是什么?为什么要有GC?

答:GC是垃圾收集的意思,内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。Java程序员不用担心内存管理,因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方法之一:System.gc() 或Runtime.getRuntime().gc() ,但JVM可以屏蔽掉显示的垃圾回收调用。

垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低优先级的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。在Java诞生初期,垃圾回收是Java最大的亮点之一,因为服务器端的编程需要有效的防止内存泄露问题,然而时过境迁,如今Java的垃圾回收机制已经成为被诟病的东西。移动智能终端用户通常觉得iOS的系统比Android系统有更好的用户体验,其中一个深层次的原因就在于Android系统中垃圾回收的不可预知性。

补充:垃圾回收机制有很多种,包括:分代复制垃圾回收、标记垃圾回收、增量垃圾回收等方式。标准的Java进程既有栈又有堆。栈保存了原始型局部变量,堆保存了要创建的对象。Java平台对堆内存回收和再利用的基本算法被称为标记和清除,但是Java对其进行了改进,采用“分代式垃圾收集”。这种方法会跟Java对象的生命周期将堆内存划分为不同的区域,在垃圾收集过程中,可能会将对象移动到不同区域:

伊甸园(Eden):这是对象最初诞生的区域,并且对大多数对象来说,这里是它们唯一存在过的区域。

幸存者乐园(Survivor):从伊甸园幸存下来的对象会被挪到这里。

终身颐养园(Tenured):这是足够老的幸存对象的归宿。年轻代收集(Minor-GC)过程是不会触及这个地方的。当年轻代收集不能把对象放进终身颐养园时,就会触发一次完全收集(Major-GC),这里可能还会牵扯到压缩,以便为大对象腾出足够的空间。

与垃圾回收相关的JVM参数:

-Xms / -Xmx --- 堆的初始大小 / 堆的最大大小

-Xmn --- 堆中年轻代的大小

-XX:-DisableExplicitGC --- 让System.gc()不产生任何作用

-XX:+PrintGCDetail --- 打印GC的细节

-XX:+PrintGCDateStamps --- 打印GC操作的时间戳 

Linux操作

580.请写出常用的linux指令不低于10个,请写出linux tomcat启动。

答:linux指令
arch 显示机器的处理器架构(1)
uname -m 显示机器的处理器架构(2)
shutdown -h now 关闭系统(1)
shutdown -r now 重启(1)
cd /home 进入 '/ home' 目录'
cd .. 返回上一级目录
cd ../.. 返回上两级目录
mkdir dir1 创建一个叫做 'dir1' 的目录'
mkdir dir1 dir2 同时创建两个目录
find / -name file1 从 '/' 开始进入根文件系统搜索文件和目录
find / -user user1 搜索属于用户 'user1' 的文件和目录
linuxtomcat启动
进入tomcat下的bin目录执行 ./catalina.sh start直接启动即可,然后使用tail -f /usr/local/tomcat6/logs/catalina.out查看tomcat启动日志。

581.当使用RMI技术实现远程方法调用时,能为远程对象生成Sub和Skeleton命令的是()
A. Mic
B. mid
C. mitegistry
D. policytool
答案:A
582.以下哪个是服务()
A. kill
B. tar
C. rsyne
D. policytool
答案:c
分析:
A:kill命令,常用于杀死进程;
B:tar命令,tar命令是Unix/Linux系统中备份文件的可靠方法,几乎可以工作于任何环境中,它的使用权限是所有用户
C:类unix系统下的数据镜像备份工具
D:在终端下输入lsof即可显示系统打开的文件,因为 lsof 需要访问核心内存和各种文件,所以必须以 root 用户的身份运行它才能够充分地发挥其功能
583.下面的网络协议中,面向连接的的协议是: ()
A. 传输控制协议
B. 用户数据报协议
C. 网际协议
D. 网际控制报文协议
答案:A
584.在/etc/fstab 文件中指定的文件系统加载参数中, () 参数一般用于CD-ROM 等移动设备。
A. defaults
B. sw
C. rw 和 ro
D. noauto
答案:D
585.Linux 文件权限一共10 位长度,分成四段,第三段表示的内容是 ()
A. 文件类型
B. 文件所有者的权限
C. 文件所有者所在组的权限
D. 其他用户的权限
答案:C
586.终止一个前台进程可能用到的命令和操作 ()
A. kill
B. < CTRL >;+C
C. shut down
D. halt
答案:B
587.在使用mkdir 命令创建新的目录时,在其父目录不存在时先创建父目录的选项是 ()
A. -m
B. -d
C. -d
D. -p
答案:D
588.下面关于i 节点描述错误的是 ()
A. i 节点和文件是一一对应的(每个文件都有唯一一个索引结点号与之对应,而对于一个索引结点号,却可以有多个文件名与之对应)
B. i 节点能描述文件占用的块数
C. i 节点描述了文件大小和指向数据块的指针
D. 通过i 节点实现文件的逻辑结构和物理结构的转换
答案:A
589.一个文件名字为rr.Z,可以用来解压缩的命令是: ()
A. tar
B. gzip
C. compress
D. uncompress
答案:D
590.具有很多C 语言的功能,又称过滤器的是 ()
A. csh
B. tcsh
C. awk
D. sed
答案:C
591.一台主机要实现通过局域网与另一个局域网通信,需要做的工作是 ()
A. 配置域名服务器
B. 定义一条本机指向所在网络的路由
C. 定义一条本机指向所在网络网关的路由
D. 定义一条本机指向目标网络网关的路由
答案:C
592.建立动态路由需要用到的文件有 ()
A. /etc/hosts
B. /etc/HOSTNAME
C. /etc/resolv.conf
D. /etc/gateways
答案:D
593.局域网的网络地址192.168.1.0/24,局域网络连接其它网络的网关地址是192.168.1.1。主机192.168.1.20 访问172.16.1.0/24 网络时,其路由设置正确的是 ()
A. route add –net 192.168.1.0 gw 192.168.1.1 netmask 255.255.255.0 metric 1
B. route add –net 172.16.1.0 gw 192.168.1.1 netmask 255.255.255.0 metric 1
C. route add –net 172.16.1.0 gw 172.16.1.1 netmask 255.255.255.0 metric 1
D. route add default 192.168.1.0 netmask 172.168.1.1 metric 1
答案:B
594.下列提法中,不属于ifconfig 命令作用范围的是 ()
A. 配置本地回环地址
B. 配置网卡的IP地址
C. 激活网络适配器
D. 加载网卡到内核中
答案:D
595.下列关于链接描述,错误的是()
A. 硬链接就是让链接文件的i 节点号指向被链接文件的i 节点
B. 硬链接和符号连接都是产生一个新的i 节点
C 链接分为硬链接和符号链接
D. 硬连接不能链接目录文件
答案:B
596.在局域网络内的某台主机用ping 命令测试网络连接时发现网络内部的主机都可以连同,而不能与公网连通,问题可能是()
A. 主机IP设置有误
B. 没有设置连接局域网的网关
C. 局域网的网关或主机的网关设置有误
D. 局域网DNS服务器设置有误
答案:C
597.下列文件中,包含了主机名到IP 地址的映射关系的文件是:
A. /etc/HOSTNAME
B. /etc/hosts
C. /etc/resolv.conf
D. /etc/networks
答案:B
598.不需要编译内核的情况是()
A. 删除系统不用的设备驱动程序时
B. 升级内核时
C. 添加新硬件时
D. 将网卡激活
答案:D
599.在shell 中变量的赋值有四种方法,其中,采用name=12 的方法称 ()
A. 直接赋值
B. 使用read命令
C. 使用命令行参数
D. 使用命令的输出
答案:A
600.()命令可以从文本文件的每一行中截取指定内容的数据。
A. cp
B. dd
C. fmt
D. cut
答案:D
601.下列不是Linux 系统进程类型的是()
A. 交互进程
B. 批处理进程
C. 守护进程
D. 就绪进程
答案:D
602.在日常管理中,通常CPU 会影响系统性能的情况是: ()
A. CPU 已满负荷地运转
B. CPU 的运行效率为30%
C. CPU 的运行效率为50%
D. CPU 的运行效率为80%
答案:A
603.若一台计算机的内存为128MB,则交换分区的大小通常是
A. 64MB
B. 128MB
C. 256MB
D. 512MB
答案:C
604.在安装Linux 的过程中的第五步是让用户选择安装方式,如果用户希望安装部分组件(软件程序),并在选择好后让系统自动安装,应该选择的选项是()
A. full
B. expert
C. newbie
D. menu
答案:D
605.Linux 有三个查看文件的命令,若希望在查看文件内容过程中可以用光标上下移动来查看文件内容,应使用()命令
A. cat
B. more
C. less
D. menu
答案:C
606.下列信息是某系统用ps –ef 命令列出的正在运行的进程 ()进程是运行Internet 超级服务器,它负责监听Internet sockets 上的连接,并调用合适的服务器来处理接收的信息。
A. root 1 4.0 0.0 344 204? S 17:09 0:00 init
B. root 2 0.0 0.1 2916 1520? S 17:09 0:00 /sbin/getty
C. root 3 0.0 0.2 1364 632? S 17:09 0:00 /usr/sbin/syslogd
D. root 4 0.0 1344 1204? S 17:09 0:10 /usr/sbin/inetd
答案:D
607.在TCP/IP 模型中,应用层包含了所有的高层协议,在下列的一些应用协议中, ()是能够实现本地与远程主机之间的文件传输工作
A. telnet
B. FTP
C. SNMP
D. NFS
答案:B
608.当我们与某远程网络连接不上时,就需要跟踪路由查看,以便了解在网络的什么位置出现了问题,满足该目的的命令是()
A. ping
B. ifconfig
C. traceroute
D. netstat
答案:C
609.对名为fido 的文件用chmod 551 fido 进行了修改,则它的许可权是()
A. -rwxr-xr-x
B. -rwxr--r--
C. -r--r--r--
D. -r-xr-x—x
答案:C
610.用ls –al 命令列出下面的文件列表,()文件是符号连接文件
A. -rw-rw-rw- 2 hel-s users 56 Sep 09 11:05 hello
B. -rwxrwxrwx 2 hel-s users 56 Sep 09 11:05 goodbey
C. drwxr--r-- 1 hel users 1024 Sep 10 08:10 zhang
D. lrwxr--r-- 1 hel users 2024 Sep 12 08:12 cheng
答案:D
611.DNS 域名系统主要负责主机名和()之间的解析。
A. IP地址
B. MAC地址
C. 网络地址
D. 主机别名
答案:A
612.WWW 服务器是在Internet 上使用最为广泛,它采用的是()结构
A. 服务器/工作站
B. B/S
C. 集中式
D. 分布式
答案:B
613.Linux 系统通过()命令给其他用户发消息。
A. less
B. mesg
C. write
D. echo to
答案:C
614.NFS 是()系统。
A. 文件
B. 磁盘
C. 网络文件
D. 操作
答案:C
615.()命令可以在Linux 的安全系统中完成文件向磁带备份的工作
A. cp
B. tr
C. dir
D. cpio
答案:D
616.Linux 文件系统的文件都按其作用分门别类地放在相关的目录中,对于外部设备文件,一般应将其放在()目录中
A. /bin
B. /etc
C. /dev
D. /lib
答案:C
617.在重新启动Linux 系统的同时把内存中的信息写入硬盘,应使用()命令实现
A. # reboot
B. # halt
C. # reboot
D. # shutdown –r now
答案:D
618.网络管理具备以下几大功能:配置管理、()、性能管理、安全管理和计费管理等
A. 故障管理
B. 日常备份管理
C. 升级管理
D. 发送
答案:A
619.关闭linux 系统(不重新启动)可使用命令()
A. Ctrl+Alt+Del
B. halt
C. shutdown -r now
D. reboot
答案:B
620.实现从IP 地址到以太网MAC 地址转换的命令为: ()
A. ping
B. ifconfig
C. arp
D. traceroute
答案:C
621.在vi 编辑器中的命令模式下,键入()可在光标当前所在行下添加一新行
A. < a>;
B. < o>;
C. < I>;
D. A
答案:B
622.在vi 编辑器中的命令模式下,删除当前光标处的字符使用()命令
A. < x>;
B. < d>;< w>;
C. < D>;
D. < d>;< d>;
答案:A
623.在vi 编辑器中的命令模式下,重复上一次对编辑的文本进行的操作,可使用()命令
A. 上箭头
B. 下箭头
C. < .>;
D. < *>;
答案:C
624.删除文件命令为: ()
A. mkdir
B. rmdir
C. mv
D. traceroute
答案:D
625.退出交互模式的shell,应键入()
A. < Esc>;
B. ^q
C. exit
D. quit__
答案:C

算法分析及手写代码

626.判断身份证:要么是15位,要么是18位,最后一位可以为字母,并写出程序提出其中年月日。要求:

写出合格的身份证的正则表达式,

^(\d{15}|\d{17}[\dx])$

写程序提取身份证中的年月日

public class IdCard
{
    private String idCard;//私有变量
    public IdCard(){}//构造方法
   //构造方法
   public IdCard(String idCard){
       this.idCard=idCard;
     }

    public void setIdCard(String idCard)
    {
        this.idCard=idCard;
    }

    public String getIdCard()
    {
        return idCard;
    }

    //从身份证号码中截取生日
    public String getBirthday()
    {
      return this.getIdCard().substring(6, 14);
    }

    public static void main(String args[])
    {
        ShenFenZheng sfz = new ShenFenZheng("420154199908157841");
         //调用getBirthday()方法获取生日
        System.out.println("生日:" + sfz.getBirthday());
    }
}
627.对于一个字符串,请设计一个高效算法,找到第一次重复出现的字符保证字符串中有重复的字符,字符串的长度小于等于500.
package com.bjsxt;
import java.util.ArrayList;
import java.util.List;
public class FirstRepeat {

public static void main(String[] args) {
System.out.println(findFirstRepeat("pmedmitjtckhxwhvpwemznhmhzhpueainchqrftkmbjlradhmjekcqzansyzkvqhwnrdgzdbzewdmxkzrscikdaugbvygntrifnolehdtrqjlasofuvzeijbmzehkxknmjekcxswqldknysfsxrqaqzp",152));
}
//返回:y
    public static char findFirstRepeat(String A, int n) {
     String[] str=A.split("");
     for(int x=0;x<n;x++){
      int index=0;
      int num=0;
      //对于每一个值,都需要从前开始遍历
      while(index<=x){
       if(str[index].equals(str[x])){
        num++;
       }
       index++;
      }
      //该值出现了两次,说明重复了
      if(num>1){
       char flag='x';
       flag=str[x].toCharArray()[0];
       return flag;
      }
     }
     //返回该值说明已经没有重复的
     return 'p';
    }
}
628.写一个完整函数,实现拷贝数组
public class test {

public static void main(String[] args) {
int [] arr1 = {10,20,30,40,50};
int [] arr2 = CopyArray(arr1);

System.out.println(Arrays.toString(arr2));
}

private static int[] CopyArray(int[] arr) {
int [] arr2 = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
arr2[i] = arr[i];
}
return null;
}
}
629.写一排序算法,输入10个数字,以逗号分开,可根据参数选择升序或者降序排序,须注明是何种排序算法。
package cn.bjsxt.demo;

import java.util.Scanner;

public class SortDemo {
/**
 * 给定的字符串使用,号分隔
 * @param strNumber
 * @return
 */
public static String [] split(String strNumber){
String [] strSplit=strNumber.split(",");
return strSplit;
}
/**
 * 将String类型的数组转换成int类型的数组
 * @param strSplit
 * @return
 */
public static int [] getInt(String [] strSplit){
int arr[]=new int[strSplit.length];
for (int i = 0; i < strSplit.length; i++) {
arr[i]=Integer.parseInt(strSplit[i]);
}
return arr;
}
/**
 * 冒泡排序
 * @param arr
 */
public static void sort(int [] arr){
for (int i = 0; i < arr.length-1; i++) {
for (int j = 0; j < arr.length-1-i; j++) {
if (arr[j]>arr[j+1]) {
change(arr,j,j+1);
}
}
}
}
/**
 * 两数交换的方法
 * @param arr 数组
 * @param x 数组中元素的下标
 * @param y 数组中元素的下标
 */
public static void change(int [] arr,int x,int y){
int temp=arr[x];
arr[x]=arr[y];
arr[y]=temp;
}
/**
 * 测试类
 * @param args
 */
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
System.out.println("请输入一个数字串,每个数字以逗号分隔");
String str=input.next();

//调用方法
String [] s=split(str);//使用逗号分隔
int [] arr=getInt(s);//调有获得整型数组的方法
sort(arr);//调用排序的方法
for (int i : arr) {
System.out.print(i+"\t");
}
}
}
630.判断字符串是否是这样的组成的,第一个字母,后面可以是字母、数字、下划线、总长度为5-20。
package cn.bjsxt.demo;

import java.util.Scanner;

public class StringDemo {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
System.out.println("请输入一个字符串,第一个字符必须是字母:");
String str=input.next();
if (str.length()<5||str.length()>20) {
System.out.println("对不起,字符串的长度必须在5-20之间!");
}else{
char []ch=str.toCharArray();
if (Character.isLetter(ch[0])) {//判断第一个字符是否是字母
for (int i = 1; i < ch.length; i++) {
if (!Character.isLetterOrDigit(ch[i])&&ch[i]!='_') {
System.out.println("字符串不符合要求");
break;
}
}
}
}
}
}
631.已排好序的数组A,一般来说可用二分查找可以很快找到,现有一特殊数组A,它是循环递增的,如a[]={17, 19 ,20, 25, 1, 4, 7, 9},在这样的数组中找一元素,看看是否存在。请写出你的算法,必要时可写伪代码,并分析其空间,时间复杂度。

思路说明:循环递增数组有这么一个性质:以数组中间元素将循环递增数组划分为两部分,则一部分为一个严格递增数组,而另一部分为一个更小的循环递增数组。当中间元素大于首元素时,前半部分为严格递增数组,后半部分为循环递增数组;当中间元素小于首元素时,前半部分为循环递增数组;后半部分为严格递增数组。

记要检索的元素为e,数组的首元素为a[low],中间元素为a[mid],末尾元素为a[high]。则当e等于a[mid] 时,直接返回mid的值即可;当e不等于a[mid] 时:

1) a[mid] > a[low],即数组前半部分为严格递增数组,后半部分为循环递增数组时,若key小于a[mid]并且不小于a[low]时,则key落在数组前半部分;否则,key落在数组后半部分。

2) a[mid] < a[high],即数组前半部分为循环递增数组,后半部分为严格递增数组时,若key大于a[mid]并且不大于a[high]时,则key落在数组后半部分;否则,key落在数组前半部分。

这种方式的时间复杂度为:O(log(n)),空间复杂度为O(1)。

public class TestBinarySearch {
public static void main(String[] args) {
// 定义数组
int[] a = { 17, 19, 20, 21, 25, 1, 4, 7 };
// 调用改进后的二分查找法求索引
int pos = search(a, 7);
System.out.println("要查找的元素的索引为:" + pos);
}

/** 改进后的二分查找法:e为要查找的元素 */
public static int search(int[] a, int e) {
int low = 0;
int high = a.length - 1;
int mid = 0;
int pos = -1; // 返回-1,表示查找失败
// 如果low < high,说明循环查找结束,直接返回-1;否则循环查找
while (low <= high) {
// mid为中间值索引
mid = (low + high) / 2;
// 如果中间值刚好是e,则查找成功,终止查找,e的索引为mid
if (a[mid] == e) {
pos = mid;
break;
}
// 如果a[low] <= a[mid],说明原数组的前半部分是严格递增的,后半部分是一个更小的循环递增数组
if (a[low] <= a[mid]) {
// 如果要查找的元素e小于a[mid]并且不小于a[low]时,则说明e落在数组前半部分
if (a[low] <= e && e < a[mid]) {
high = mid - 1;
} else {// 否则的话,需要在数组的后半部分继续查找
low = mid + 1;
}
} else {// 否则,后半部分是严格递增的,前半部分是一个更小的循环递增数组
// 如果要查找的元素e大于a[mid]并且不大于a[high]时,则说明e落在数组后半部分
if (a[mid] < e && e <= a[high]) {
low = mid + 1;
} else {// 否则的话,需要在数组的前半部分继续查找
high = mid - 1;
}
}
}
return pos;
}
}
632.请编写一个完整的程序,实现如下功能:从键盘输入数字n,程序自动计算n!并输出。(注1:n!=1*2*3...*n, 注2:请使用递归实现)

思路说明:因为n! = (n-1)! * n,所以要求n!首先要求出(n-1)!,而(n-1)! = (n-1-1)! * (n-1),以此类推,直到n = 1为止。

import java.util.Scanner;
public class TestFactorial {
public static void main(String[] args) {
System.out.print("请输入一个整数:");
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
System.out.println(n + "的阶乘是:" + factorial(n));
}
/**求阶乘的方法*/
public static int factorial(int n) {
if(n == 1){
return 1;
}
return factorial(n - 1) * n;
}
}
633.请用递归的方法计算斐波那契数列的同项F(n),已知F0=0,F1=1,F(n)=F(n-1)+F(n-2)(n>=2,n∈N*).

思路说明:斐波那契数列的排列是:0,1,1,2,3,5,8,13,21,34,55,89,144……,特别指出的是0不是第一项而是第0项;因为F(n)=F(n-1)+F(n-2),所以要求F(n)首先要求出F(n-1)和F(n-2),而F(n-1)=F(n-1-1)+F(n-1-2),以此类推,直到,F(2)=F(1)+F(0)为止,已知F(1) = 1,F(0) = 0。

import java.util.Scanner;
public class TestFibo {
public static void main(String[] args) {
System.out.print("请输要求斐波那契数列的第几项:");
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
System.out.println("斐波那契数列的第"+ n + "是:" + fibo(n));
}
public static int fibo(int n) {
if(n == 0){
return 0;
} else if(n == 1){
return 1;
}
return fibo(n -1) + fibo(n - 2);
}
}
634.现在有整数数组{11,66,22,0,55,32},请任意选择一种排序算法,用Java程序实现

冒泡思路说明:
(1) 最开始将数组看做一个无序数列(个数是数组的长度)与一个有序数列(0个)的组合;
(2) 每一趟比较完后, 找到了无序数列的最大值, 将其放到有序数列中(有序数列个数+1);
(3) N个数, 比较N-1趟;
(4) 每一趟挨个进行比较:从数组的第一个元素开始, 到无序数列的最后一个为止;
(5) 如果前边一个大于后边一个, 那么交换位置;
(6) 每趟比较的次数与趟数有关;
(7) 根据每趟比较是否发生了交换判断数据是否已经有序,从而进行优化。

public class TestSort {
public static void main(String[] args) {
int[] arr = {11, 66, 22, 0, 55, 32};
// 调用排序方法
sort(arr);
// 输出排除后的数组
for (int num : arr) {
System.out.print(num + "\t");
}
}

public static void sort(int[] arr) {
// 定义标记
boolean flag = false;
int temp;
// 排序
// 外层循环控制的是比较的趟数
for (int i = 0; i < arr.length - 1; i++) {
// 每一趟比较之前初始化, 否则会保留上一堂比较的结果
flag = false;
// 内层循环控制的是每趟比较的次数
for (int j = 0; j < arr.length - 1 - i; j++) {
// 挨个进行比较: 从数组的第一个元素开始, 到无序数列的最后一个
if (arr[j] > arr[j + 1]) {
// 交换
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
//如果发生交换,改变flag的值
flag = true;
}
}
if (!flag) {
break;
}
}
}
}
635.请根据注释,编码实现下面类的方法
// 这个类用于存取一组权限,每个权限用非负整数表示的.这组枳限存储在
// righiString属性中。如果权限N权限存在,rightString第N个字符为“1”,否则, 为空格。
class RightStore {
public String righString = "";

// 如果传入的权限right存在,该方法返回true.否期,为false.,
// right为传入的权限的整数值.
public boolean getRight(int right) {

return true;
}

// 该方法存储或消除传入的权限.如果value为true,存储传入的权限,
// 否则淸除该权限.
// right为传入的权限的整数值.
public void setRight(int right, boolean value) {
}
}

思路说明:我们首先要读懂这道题的意思:righString这个字符串是用来存储一系列权限的,并且权限的取值只有两种:有和没有;在righString中使用字符‘1’表示有权限,字符空格‘ ’表示没有权限。举个例子:如果righString的长度为3,第一位表示对订单系统是否有权限,第二位表示对人员管理系统是否有权限,第三位表示对库存系统是否有权限。而方法中的int right参数则表示的是字符串的第几位。

上边这些搞明白之后,方法的编写就简单多了。

public class RightStore {
public String righString = "";

public boolean getRight(int right) {
//先求得第right个字符
char ch = righString.charAt(right - 1);
//如果ch为'1',返回true,否则返回false
return ch == '1';
}

public void setRight(int right, boolean value) {
//如果value为true,存储传入的权限,否则消除权限(改为空格)
righString.replace(righString.charAt(right - 1), value ? '1' : ' ');
}
}
636.二分法查询(递归实现)

思路说明:假设在一个已经排好序的有序序列(N个元素,升序排列),首先让序列中的中间的元素与需要查找的关键字进行比较,如果相等,则查找成功,否则利用中间位置将序列分成两个子序列,如果待查找的关键字小于中间的元素,则在前一个子序列中同样的方法进一步查找,如果待查找的关键字大于中间的元素,则在后一个子序列中同样的方法进一步查找,重复以上过程一直到查找结束!

import java.util.Scanner;
public class TestBinarySearchRecursion {
public static void main(String[] args) {
int[] a = { 1, 3, 5, 7, 9, 11, 13 };
System.out.print("请输入要查找的元素:");
int e = new Scanner(System.in).nextInt();
int index = binarySearch(a, 0, a.length - 1, e);
System.out.println(index != -1 ? "元素索引为" + index : "没有该元素");
}

private static int binarySearch(int[] a, int low, int high, int e) {
int mid = 0;
if (low <= high) {
mid = (low + high) / 2;
if (a[mid] == e) {
return mid;
} else if (a[mid] > e) {
return binarySearch(a, low, mid - 1, e);
} else {
return binarySearch(a, mid + 1, high, e);
}
}
return -1;
}
}
637.编写一段Java程序,把一句英语中的每个单词中的字母次序倒转,单词次序保持不变,例入输入为“There is a dog.”,输出结果应该是“erehT si a god.”要求不使用Java的库函数,例如String类的split,reverse方法。

函数形如:

public static String reverseWords(String input) {
String str = "";

return str;
}

思路说明:将字符串转化成字符数组,然后根据数组中空格的位置判断每个单词所占的索引范围,根据得到的索引将数组中的每个单词逆序后拼接到新的字符串中。

public class TestStringReverse{
public static void main(String[] args) {
String input = "There is a dog";
System.out.println("逆转后的字符串为:" + reverseWords(input));
}
public static String reverseWords(String input) {
String str = "";
//将字符串转化成字符数组
char[] arr = input.toCharArray();
//index用来记录每个单词的起始索引
int index = 0;
//遍历字符数组,将空格前边的单词挨个拼接到str中
for (int i = 0; i < arr.length; i++) {
if(arr[i] == ' '){
//根据空格的位置将空格前边一个单词密续追加到str中
for(int j = i - 1; j >= index; j--){
str += arr[j];
}
//单词拼接完成后,拼接一个空格
str += ' ';
//让index指向下一个单词的起始位置
index = i + 1;
}
}
//将最后一个单词拼接上
for(int i = arr.length - 1; i >= index; i--){
str += arr[i];
}
return str;
}
}
638.手写9x9乘法表,冒泡排序

9x9乘法表:

class Demo {
    public static void main(String[] args) {
        for(int x = 0;x <= 9; x++) {
            for(int y = 1;y <= x; y++) {
                System.out.print(y+"*"+x+"="+x*y+"\t");
            }
            System.out.println();
        }
    }
}

冒泡排序:

public class BubbleSort{
     public static void main(String[] args){
         int score[] = {67, 69, 75, 87, 89, 90, 99, 100};
         for (int i = 0; i < score.length -1; i++){//最多做n-1趟排序
             for(int j = 0 ;j < score.length - i - 1; j++){//对当前无序区间score[0......length-i-1]进行排序(j的范围很关键,这个范围是在逐步缩小的)
                 if(score[j] < score[j + 1]){ //把小的值交换到后面
                     int temp = score[j];
                     score[j] = score[j + 1];
                     score[j + 1] = temp;
                 }
             }
             System.out.print("第" + (i + 1) + "次排序结果:");
             for(int a = 0; a < score.length; a++){
                 System.out.print(score[a] + "\t");
             }
             System.out.println("");
         }
         System.out.print("最终排序结果:");
         for(int a = 0; a < score.length; a++){
             System.out.print(score[a] + "\t");
         }
}
}
639.题目: 给定一个整数数组,找到是否该数组包含任何重复数字。你的函数应该返回true只要有任何数字 在该数组中重复出现,否则返回false。
public class Solution {
    public boolean containsDuplicate(int[] nums) {
        Set<Integer> numSet = new HashSet<Integer>();
        for(int i=0;i<nums.length;i++){·
            if(numSet.contains(nums[i]))
                return true;
            else
                numSet.add(nums[i]);
        }
        return false;
    }
}
640.给定一个数组nums, 写一个函数来移动所有0元素到数组末尾,同时维持数组中非0元素的相对顺序不变。要求不能申请额外的内存空间,并且最小化操作次数。
public void moveZeroes(int[] nums) {
        int size = nums.length;
        int startIndex = 0;
// 0元素开始的位置
        int endIndex = 0;
// 0元素结束的位置
        int currentNum;
        int i= 0;
        // 第一步:找到第一个0元素开始的位置
        // 并将第一个0元素的游标赋值给startIndex&endIndex
        while(i < size){
            currentNum = nums[i];
            if (currentNum == 0) {
                startIndex = i;
                endIndex = i;
                break;
            }
            ++i;
        }
        // 如果当前数组中没有找到0元素,则推出
        if (nums[endIndex] != 0)
            return;

        // 将当前i的值加1;直接从刚才0元素位置的后一位置开始循环
        ++i;
        while (i < size) {
            currentNum = nums[i];
            if (currentNum == 0){//如果当前元素等于0,则将i值赋值给endIndex
                    endIndex = i;
            } else {
                // 如果不为0
                //则将当前元素赋值给nums[startIndex]
                // 并将当前位置的元素赋值为0
                // startIndex和endIndex都加1;
                nums[startIndex] = currentNum;
                nums[i] = 0;
                ++startIndex;
                ++endIndex;
            }
            ++i;
        }
    }
641.给定一颗二叉树,返回节点值得先序遍历,请使用迭代(非递归)方式实现。
public class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
        if(root == null)
            return result;
        Stack<TreeNode> stack = new Stack<TreeNode>();
        stack.push(root);
        while(!stack.isEmpty()) {
            TreeNode node = stack.pop();
            result.add(node.val);
            if(node.right != null)
                stack.push(node.right);
            if(node.left != null)
                stack.push(node.left);
        }
        return result;
    }
}
642.验证一棵树是否为有效的二叉搜索树BST
public class Solution {
    private static int lastVisit = Integer.MIN_VALUE;
public boolean isValidBST(TreeNode root) {
    if(root == null) return true;
        boolean judgeLeft = isValidBST(root.left); // 先判断左子树

        if(root.data >= lastVisit && judgeLeft) { // 当前节点比上次访问的数值要大
            lastVisit = root.data;
        } else {
            return false;
        }
        boolean judgeRight = isValidBST(root.right); // 后判断右子树
        return judgeRight;
}
}
643.从一个链表中删除节点

题目: 写一个函数用于在一个单向链表中删除一个节点(⾮非尾节点),前提是仅仅能够访问要删除的那个节点。

比如给定链表1 -> 3 -> 5 -> 7 -> 9 -> 16,给定你值为3的那个节点, 调⽤用你的函数后,链表变为

1 -> 5 -> 7 -> 9 -> 16。

/**
Definition for singly-linked list.
public class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
* }
*/
public class Solution {
public void deleteNode(ListNode node) {
if(node==null||node.next==null) {
System.out.println("节点不存在或者是尾节点");

}else{
node.val=node.next.val;
node.next=node.next.next;
}
}
}
644.二叉搜索树BST中第Kth小的元素 题目:给定⼀个BST,写一个函数kthSmallest来找到第kth小的元素
/**
Definition for a binary tree node.
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
* }
*/
public class Solution2  {
public int kthSmallest(TreeNode root, int k) {
    Stack<TreeNode> store = new Stack<TreeNode>();
    if (root == null) {
        return -1;
    }
    store.push(root);
    while (root.left != null) {
        store.push(root.left);
        root = root.left;
    }
    while (!store.empty()) {
        TreeNode cur = store.pop();
        k--;
        if (k == 0) {
            return cur.val;
        }
        if (cur.right != null) {
            root = cur.right;// let cur.right be the current node
            store.push(root);
            while (root.left != null) {
                store.push(root.left);
                root = root.left;
            }
        }
    }
    return -1;
}
}
645.题目:给定含有n个整数的数组S,S中是否存在三个元素a,b,c使得a + b + c = 0? 找到所有这样的三元 组,并且结果集中不包含重复的三元组。

比如,
S = [-1, 0, 1, 2, -1, -4],,
结果集为: [
[-1, 0, 1],
[-1, -1, 2]
]

/**
 * 给定一个n个元素的数组,是否存在a,b,c三个元素,使用得a+b+c=0,找出所有符合这个条件的三元组
 * 注意: - 三元组中的元素必须是非递减的  - 结果不能包含重复元素
 */
public class Solution {

    public static void main(String[] args) {
        int[] S = {-1, 0, 1, 2, -1, -4,-3,-4,4,3};
        new Solution().get3Sum(S);
    }

    public Set<String> get3Sum(int[] S){

        if(S.length<3 || S==null){
            return null;
        }

        //接收拼接的字符串
        StringBuffer sb = new StringBuffer();
        for(int i=0; i<S.length; i++){
            for(int j=0; j<S.length; j++){
                for(int z=0; z<S.length; z++){
                    //筛选出不是递减的一组元素
                    if(S[i]<=S[j] && S[j]<=S[z]){
                        int sum = S[i] + S[j] + S[z];
                        if(sum==0){
                            String str = "("+S[i]+","+S[j]+","+S[z]+")";
                            sb.append(str+";");
                        }
                    }
                }
            }
        }

        String s = sb.toString();
        s = s.substring(0, sb.length()-1);
        String[] arr = s.split(";");

        Set<String> set = new HashSet<String>();
        //将所筛选出来的元素放入Set集合中,去重
        for (int k = 0; k < arr.length; k++) {
            set.add(arr[k]);
        }
        System.out.println(set);
        return set;
    }

    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result = new LinkedList<>();

        if (nums != null && nums.length > 2) {
            // 先对数组进行排序
            Arrays.sort(nums);
            // i表示假设取第i个数作为结果
            for (int i = 0; i < nums.length - 2; ) {
                // 第二个数可能的起始位置
                int j = i + 1;
                // 第三个数可能是结束位置
                int k = nums.length - 1;
                while (j < k) {
                    // 如果找到满足条件的解
                    if (nums[j] + nums[k] == -nums[i]) {
                        // 将结果添加到结果含集中
                        List<Integer> list = new ArrayList<>(3);
                        list.add(nums[i]);
                        list.add(nums[j]);
                        list.add(nums[k]);
                        result.add(list);
                        // 移动到下一个位置,找下一组解
                        k--;
                        j++;

                        // 从左向右找第一个与之前处理的数不同的数的下标
                        while (j < k && nums[j] == nums[j - 1]) {
                            j++;
                        }
                        // 从右向左找第一个与之前处理的数不同的数的下标
                        while (j < k && nums[k] == nums[k + 1]) {
                            k--;
                        }
                    }
                    // 和大于0
                    else if (nums[j] + nums[k] > -nums[i]) {
                        k--;
                        // 从右向左找第一个与之前处理的数不同的数的下标
                        while (j < k && nums[k] == nums[k + 1]) {
                            k--;
                        }
                    }
                    // 和小于0
                    else {
                        j++;
                        // 从左向右找第一个与之前处理的数不同的数的下标
                        while (j < k && nums[j] == nums[j - 1]) {
                            j++;
                        }
                    }
                }
                // 指向下一个要处理的数
                i++;
                // 从左向右找第一个与之前处理的数不同的数的下标
                while (i < nums.length - 2 && nums[i] == nums[i - 1]) {
                    i++;
                }
            }
        }
 return result;
    }
}
646.子集问题

题目: 给定一个不包含相同元素的整数集合,nums,返回所有可能的子集集合。解答中集合不能包含重 复的子集。
比如,
nums = [1, 2, 3], ⼀一种解答为:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2], []
]

/**
 * 不重复集合求子集
解答采用的是深度优先遍历,先取原数组一个元素,再构造包括这个元素的两个,三个……n个元素的集合。dfs中的start就指向这个元素的,它在不断地后移(i+1)。
 * @param S: A set of numbers.
 * @return: A list of lists. All valid subsets.
 */
public class Solution1 {
    public static void main(String[] args) {
        int[] first = new int[]{1, 2, 3};
        ArrayList<ArrayList<Integer>> res = subsets(first);
        for(int i = 0; i < res.size(); i ++){
            System.out.println(res.get(i));
        }
    }
    public static ArrayList<ArrayList<Integer>> subsets(int[] nums) {
        ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
        ArrayList<Integer> item = new ArrayList<Integer>();
        if(nums.length == 0 || nums == null)
            return res;
        Arrays.sort(nums); //排序
        dfs(nums, 0, item, res);  //递归调用
        res.add(new ArrayList<Integer>());  //最后加上一个空集
        return res;
    }
    public static void dfs(int[] nums, int start, ArrayList<Integer>item, ArrayList<ArrayList<Integer>>res){
        for(int i = start; i < nums.length; i ++){
            item.add(nums[i]);
            //item是以整数为元素的动态数组,而res是以数组为元素的数组,在这一步,当item增加完元素后,item所有元素构成一个完整的子串,再由res纳入
            res.add(new ArrayList<Integer>(item));
            dfs(nums, i + 1, item, res);
            item.remove(item.size() - 1);
        }
    }
}
647.迭代方法实现二叉树的先序遍历:题目: 给定一颗⼆叉树,返回节点值得先序遍历,请使用迭代(非递归)方式实现。

比如, 给定二叉树{1,#,2,3}, 返回 [1,2,3]

/**
Definition for a binary tree node.
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
* }
*/
public class Solution {

    List<Integer> result = new ArrayList<Integer>();

    /**
     * 迭代实现,维护一个栈,因为入栈顺序按照根右左进行入栈,因此首先将根出栈,然后出栈左子节点,
     * 最后出栈右子节点。
     * @param root
     * @return
     */
    public List<Integer> preorderTraversal(TreeNode root) {
        if(root == null)
            return result;
        Stack<TreeNode> stack = new Stack<TreeNode>();
        stack.push(root);
        while(!stack.isEmpty()) {
            TreeNode node = stack.pop();
            result.add(node.val);
            if(node.right != null)
                stack.push(node.right);
            if(node.left != null)
                stack.push(node.left);
        }
        return result;
    }
}
648.验证二叉搜索树BST:题目: 验证一棵树是否为有效的二叉搜索树BST比如,二叉树[2, 1, 3],返回true二叉树[1, 2, 3], 返回false
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
TreeNode(int x) { val = x; }
}
public class BSTChecker {
    private static int lastVisit = Integer.MIN_VALUE;

    public static boolean isBST(TreeNode root) {
        if(root == null) return true;

        boolean judgeLeft = isBST(root.left); // 先判断左子树

        if(root.val >= lastVisit && judgeLeft) { // 当前节点比上次访问的数值要大
            lastVisit = root.val;
        } else {
            return false;
        }

        boolean judgeRight = isBST(root.right); // 后判断右子树

        return judgeRight;
    }
}
649.编辑距离题目: 给定两个单词word1和word2,找到最小的操作步骤使得word1转换成word2,每次操作算作一 步。你可以对单词进行以下三种操作:1)插入一个字符2)删除一个字符3)替换一个字符

参考地址:http://www.cnblogs.com/masterlibin/p/5785092.html

650.买卖股票问题:题目: 你有一个数组,第i个元素表示第i天某个股票的价格,设计一个算法找到最大的利润,并且你只能最多完成两次交易。

参考地址:没有完全理解的

http://www.mamicode.com/info-detail-1087177.html

http://www.mamicode.com/info-detail-1087177.html

/**
 * 解题思路:
 * 比如给定一组数组,[1,2,3,6,9,3,10]
 * 最多可以2次去获取最大的利益,可以用2分的思想,分成2部分,
 * 从0元素开始遍历分别求出左右2边的最大利益,求出的左右2边最大的利益即为解
 */
class Solution {

    public static int maxProfit(int[] prices) {
        // write your code here
        if(null==prices||0==prices.length) return 0;
         int sumProfit = 0;
         for(int i=1;i<prices.length;i++){
              int tmpsum = maxProfit(prices, 0, i)
                + maxProfit(prices, i+1, prices.length-1);
              sumProfit = Math.max(sumProfit, tmpsum);
         }
         return sumProfit;
    }
    public static int maxProfit(int[] prices,int s,int e){
         if(e<=s) return 0;
         int min = prices[s];
         int maxProfit = 0;
         for(int i=s+1;i<=e;i++){
              maxProfit = Math.max(maxProfit, prices[i]-min);
              min = Math.min(min, prices[i]);
         }
         return maxProfit;
    }
    public static void main(String[] args) {
     int arr [] =  {4,4,6,1,1,4,2,5};
     System.out.println(maxProfit(arr));
}
}
651.[编程]任给n个整数和一个整数x。请计算n个整数中有多少对整数之和等于x。
public class Test8 {
public static void main(String[] args) {
//输入n个整数和一个整数
Scanner input = new Scanner(System.in);
System.out.println("请输入n个整数,数量任意,以逗号分隔");
String str = input.next();
System.out.println("请输入一个整数:");
int x = input.nextInt();
//将n个整数的字符串转换为数组
String arr1[] = str.split(",");
int [] arr2 = new int[arr1.length];
for(int i=0;i<arr1.length;i++){
arr2[i] = Integer.parseInt(arr1[i]);
}
System.out.println(Arrays.toString(arr2));
//判断并输出n个整数中有几对的和等于x
int count = 0;
for(int i=0;i<arr2.length-1;i++){
for(int j = i+1;j<arr2.length;j++){
if(arr2[i]+arr2[j]==x){
count++;
}
}
}
System.out.println(count);
}
}
652.[编程]请说明快速排序算法的设计思想和时间复杂度,并用高级语言写出对整数数组进行一趟快排的函数实现。

快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。

一趟快速排序的算法是:
1、设置两个变量i、j,排序开始的时候:i=0,j=N-1;
2、以第一个数组元素作为关键数据,赋值给key,即key=A[0];
3、从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]和A[i]互换;
4、从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;
5、重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。

public class Quick {
public static void main(String[] args) {
int arr [] = {90,60,70,50,40,80,20,100,10};
sort(arr,0,arr.length-1);
System.out.println(Arrays.toString(arr));
}
public static void sort(int arr[], int low, int high) {
//设置两个变量l、h,排序开始的时候:l=0,h=N-1
int l = low;
int h = high;
//以第一个数组元素作为关键数据,赋值给key,即key=A[0]
int key = arr[low];
//重复操作,直到i=j
while (l < h) {
//从h开始向前搜索,即由后开始向前搜索(h--),找到第一个小于key的值arr[h],将arr[h]和arr[l]互换
while (l < h && arr[h] >= key)
h--;
if (l < h) {
int temp = arr[h];
arr[h] = arr[l];
arr[l] = temp;
l++;
}
//从l开始向后搜索,即由前开始向后搜索(l++),找到第一个大于key的arr[l],将arr[l]和arr[h]互换;
while (l < h && arr[l] <= key)
l++;

if (l < h) {
int temp = arr[h];
arr[h] = arr[l];
arr[l] = temp;
h--;
}
}
//对前一部分进行快速排序
if (l > low)
sort(arr, low, l - 1);
//对前一部分进行快速排序
if (h < high)
sort(arr, l + 1, high);
}
}
653.对于一段形如:1,-1~3,1~15×3的输入

输入会依照以下规则:
1、所有输入为整数、
2、“,”为分隔符
3、“~”表示一个区间,比如“-1~3”表示-1到3总共5个整数,同时“~”前的数小于“~”后的数:
4、“x”表示步长,“x3”指每3个整数一个,比如“1~15×3”表示1,4,7,10,13;
根据以上得到的结果进行打印,打印的规则为:
1、所有得到的整数按从小到大排列,以“,”分隔,不计重复;
2、每行最多显示3个整数;
3、如果两个整数是连续的,可以放在同一行,否则自动换行。
例如对于输入“1,-1~3,1~15×3”的输出结果为:
-1,0,1,
2,3,4,
7,
10,
13

public class Test {
public static void main(String[] args) {
Map<Integer, Integer> map = new TreeMap<Integer, Integer>();
String str = "5~20x3,1,-1~3,1~15x3";
String[] s = str.split(",");
for (int i = 0; i < s.length; i++) {
if (s[i].contains("~")) {
String ss[] = s[i].split("~");
int first = Integer.parseInt(ss[0]);
if (s[i].contains("x")) {
String sss[] = ss[1].split("x");
int end = Integer.parseInt(sss[0]);
int l = Integer.parseInt(sss[1]);
for (int j = first; j < end;) {
map.put(j, j);
j += l;
}
} else {
int end = Integer.parseInt(ss[ss.length - 1]);
for (int j = first; j <= end; j++) {
map.put(j, j);
}
}
} else {
int j = Integer.parseInt(s[i]);
map.put(j, j);
}
}
List<Integer> list = new ArrayList<Integer>();
Set<Integer> set = map.keySet();
Iterator<Integer> ite = set.iterator();
while (ite.hasNext()) {
int key = ite.next();
int value = map.get(key);
list.add(value);
System.out.println("v :" + value);
}
System.out.println("=================");
for (int i = 0; i < list.size();) {
int value = list.get(i);
List<Integer> co = new ArrayList<Integer>();
co.add(value + 1);
co.add(value + 2);
if (list.containsAll(co)) {
System.out.println(value + "," + (value + 1) + ","
+ (value + 2));
i += 3;
} else {
System.out.println(value);
i++;
}
}
}
}
654.有两个字符串:目标串S=“s1s2.......sn”,模式串T="t1t2.......tm"。若存在T的每个字符一次和S中的一个连续字符序列相等,则匹配成功,返回T中第一个字符在S中的位置。否则匹配不成功,返回0。写出你的算法,要求线性时间复杂度

答:
字符串匹配操作定义:
目标串S="S0S1S2...Sn-1" , 模式串T=“T0T1T2...Tm-1”
对合法位置 0<= i <= n-m (i称为位移)依次将目标串的字串 S[i ... i+m-1] 和模式串T[0 ... m-1] 进行比较,若:
1、S[i ... i+m-1] = T[0 ... m-1] , 则从位置i开始匹配成功,称模式串 T 在目标串 S 中出现。
2、S[i ... i+m-1] != T[0 ... m-1] ,则从位置i开始匹配失败。
字符串匹配算法 —— Brute-Force 算法
字符串匹配过程中,对于位移i (i在目标串中的某个位置),当第一次 Sk != Tj 时,i 向后移动1位 , 及 i = i+1,此时k退回到i+1位置 ;模式串要退回到第一个字符。该算法时间复杂度O(M*N),但是实际情况中时间复杂度接近于O(M + N),以下为Brute-Force算法的Java实现版本:

public static int bruteForce(String target, String pattern, int pos) {
        if (target == null || pattern == null) {
            return -1;
        }
        int k = pos - 1, j = 0, tLen = target.length(), pLen = pattern.length();
        while (k < tLen && j < pLen) {
            if (target.charAt(k) == pattern.charAt(j)) {
                j++;
                k++;
            } else {
                k = k - j + 1;
                j = 0;
            }
        }
        if (j == pLen) {
            return k - j + 1;
        }
        return -1;
    }
655.如何生成一个0-100的随机整数?
public class Test {
public static void main(String[] args) {
int num=(int)(Math.random()*101);
System.out.println(num);
}
}
656.请编写一段Java程序将两个有序数组合并成一个有序数组
import java.util.Arrays;

publicclass Demo1 {

publicstaticvoid main(String[] args) {

int[] a = { 1, 2, 3, 4, 5, 7, 8, 9, 10 };
int[] b = { 3, 5, 7, 9, 10 };
int[] target = newint[a.length + b.length];

for (inti = 0; i<a.length; i++)
target[i] = a[i];
for (intj = 0; j<b.length; j++)
target[a.length + j] = b[j];

Arrays.sort(target);
for (inti = 0; i<target.length; i++)
System.out.println(target[i]);

}
}
657.在最佳情况下,以下哪个时间复杂度最高(D)
A. 直接插入排序
B. 直接选择排序
C. 冒泡排序
D. 归并排序
分析:答案: D
排序方法 最坏时间复杂度 最好时间复杂度 平均时间复杂度
直接插入 O(n2) O(n) O(n2)
简单选择 O(n2) O(n2) O(n2)
冒泡排序 O(n2) O(n) O(n2)
快速排序 O(n2) O(nlog2n) O(nlog2n)
堆排序 O(nlog2n) O(nlog2n) O(nlog2n)
归并排序 O(nlog2n) O(nlog2n) O(nlog2n)
658.一个数组,元素为从0到m的整数,判断其中是否有重复元素,使用java语言编写一个方法
publicstaticboolean demo(int[] arr){
for (inti = 0; i<arr.length; i++) {
for (intj = i + 1; j<arr.length; j++) {
if (arr[i] == arr[j]) {
returntrue;
}
}
}
returnfalse;
}
659.某二叉树的先序遍历是12453,中序遍历是42513,那么其后序遍历是(A)
A. 45231
B. 42351
C. 12345
D. 54321
660.设一颗二叉树中有3个叶子节点,有八个度为1的节点,则该二叉树中总的节点数为()
A. 12
B. 13
C. 14
D. 15
分析:选b 子叶节点是度为零的节点,而二叉树的性质可知,度是0的节点比度是2的节点数多1个,所以度是2的节点为2个,所以共有3+8+2=13
661.给出下面的二叉树先序、中序、后序遍历的序列?

答:先序序列:ABDEGHCF;中序序列:DBGEHACF;后序序列:DGHEBFCA。

补充:二叉树也称为二分树,它是树形结构的一种,其特点是每个结点至多有二棵子树,并且二叉树的子树有左右之分,其次序不能任意颠倒。二叉树的遍历序列按照访问根节点的顺序分为先序(先访问根节点,接下来先序访问左子树,再先序访问右子树)、中序(先中序访问左子树,然后访问根节点,最后中序访问右子树)和后序(先后序访问左子树,再后序访问右子树,最后访问根节点)。如果知道一棵二叉树的先序和中序序列或者中序和后序序列,那么也可以还原出该二叉树。

例如,已知二叉树的先序序列为:xefdzmhqsk,中序序列为:fezdmxqhks,那么还原出该二叉树应该如下图所示:

662.你知道的排序算法都哪些?用Java写一个排序系统

答:稳定的排序算法有:插入排序、选择排序、冒泡排序、鸡尾酒排序、归并排序、二叉树排序、基数排序等;不稳定排序算法包括:希尔排序、堆排序、快速排序等。

下面是关于排序算法的一个列表:

下面按照策略模式给出一个排序系统,实现了冒泡、归并和快速排序。

package com.bjsxt;

import java.util.Comparator;

/**
 * 排序器接口(策略模式: 将算法封装到具有共同接口的独立的类中使得它们可以相互替换)
 * @author SXT李端阳
 *
 */
public interface Sorter {

   /**
    * 排序
    * @param list 待排序的数组
    */
   public <T extends Comparable<T>> void sort(T[] list);

   /**
    * 排序
    * @param list 待排序的数组
    * @param comp 比较两个对象的比较器
    */
   public <T> void sort(T[] list, Comparator<T> comp);
}

BubbleSorter.java

package com.bjsxt;

import java.util.Comparator;

/**
 * 冒泡排序
 * @author SXT李端阳
 *
 */
public class BubbleSorter implements Sorter {

   @Override
   public <T extends Comparable<T>> void sort(T[] list) {
      boolean swapped = true;
      for(int i = 1; i < list.length && swapped;i++) {
        swapped= false;
        for(int j = 0; j < list.length - i; j++) {
           if(list[j].compareTo(list[j+ 1]) > 0 ) {
              T temp = list[j];
              list[j]= list[j + 1];
              list[j+ 1] = temp;
              swapped= true;
           }
        }
      }
   }

   public <T> void sort(T[] list,Comparator<T> comp) {
      boolean swapped = true;
      for(int i = 1; i < list.length && swapped; i++) {
        swapped = false;
        for(int j = 0; j < list.length - i; j++) {
           if(comp.compare(list[j], list[j + 1]) > 0 ) {
              T temp = list[j];
              list[j]= list[j + 1];
              list[j+ 1] = temp;
              swapped= true;
           }
        }
      }
   }
}
package com.bjsxt;

import java.util.Comparator;
/**
 * 归并排序
 * 归并排序是建立在归并操作上的一种有效的排序算法。
 * 该算法是采用分治法(divide-and-conquer)的一个非常典型的应用,
 * 先将待排序的序列划分成一个一个的元素,再进行两两归并,
 * 在归并的过程中保持归并之后的序列仍然有序。
 * @author SXT李端阳
 *
 */
public class MergeSorter implements Sorter {

   @Override
   public <T extends Comparable<T>> void sort(T[] list) {
      T[] temp = (T[]) new Comparable[list.length];
      mSort(list,temp, 0, list.length- 1);
   }

   private <T extends Comparable<T>> void mSort(T[] list, T[] temp, int low, int high) {
      if(low == high) {
        return ;
      }
      else {
        int mid = low + ((high -low) >> 1);
        mSort(list,temp, low, mid);
        mSort(list,temp, mid + 1, high);
        merge(list,temp, low, mid + 1, high);
      }
   }

   private <T extends Comparable<T>> void merge(T[] list, T[] temp, int left, int right, int last) {
        int j = 0;
        int lowIndex = left;
        int mid = right - 1;
        int n = last - lowIndex + 1;
        while (left <= mid && right <= last){
            if (list[left].compareTo(list[right]) < 0){
                temp[j++] = list[left++];
            } else {
                temp[j++] = list[right++];
            }
        }
        while (left <= mid) {
            temp[j++] = list[left++];
        }
        while (right <= last) {
            temp[j++] = list[right++];
        }
        for (j = 0; j < n; j++) {
            list[lowIndex + j] = temp[j];
        }
   }

   @Override
   public <T> void sort(T[] list, Comparator<T> comp) {
      T[]temp = (T[])new Comparable[list.length];
      mSort(list,temp, 0, list.length- 1, comp);
   }

   private <T> void mSort(T[] list, T[] temp, int low, int high, Comparator<T> comp) {
      if(low == high) {
        return ;
      }
      else {
        int mid = low + ((high -low) >> 1);
        mSort(list,temp, low, mid, comp);
        mSort(list,temp, mid + 1, high, comp);
        merge(list,temp, low, mid + 1, high, comp);
      }
   }

   private <T> void merge(T[] list, T[]temp, int left, int right, int last, Comparator<T> comp) {
        int j = 0;
        int lowIndex = left;
        int mid = right - 1;
        int n = last - lowIndex + 1;
        while (left <= mid && right <= last){
            if (comp.compare(list[left], list[right]) <0) {
                temp[j++] = list[left++];
            } else {
                temp[j++] = list[right++];
            }
        }
        while (left <= mid) {
            temp[j++] = list[left++];
        }
        while (right <= last) {
            temp[j++] = list[right++];
        }
        for (j = 0; j < n; j++) {
            list[lowIndex + j] = temp[j];
        }
   }

}

QuickSorter.java

package com.bjsxt;

import java.util.Comparator;

/**
 * 快速排序
 * 快速排序是使用分治法(divide-and-conquer)依选定的枢轴
 * 将待排序序列划分成两个子序列,其中一个子序列的元素都小于枢轴,
 * 另一个子序列的元素都大于或等于枢轴,然后对子序列重复上面的方法,
 * 直到子序列中只有一个元素为止
 * @author Hao
 *
 */
public class QuickSorter implements Sorter {

   @Override
   public <T extends Comparable<T>> void sort(T[] list) {
      quickSort(list, 0, list.length- 1);
   }

   @Override
   public <T> void sort(T[] list, Comparator<T> comp) {
      quickSort(list, 0, list.length- 1, comp);
   }

   private <T extends Comparable<T>> void quickSort(T[] list, int first, int last) {
      if (last > first) {
        int pivotIndex = partition(list, first, last);
        quickSort(list, first, pivotIndex - 1);
        quickSort(list, pivotIndex, last);
      }
   }

   private <T> void quickSort(T[] list, int first, int last,Comparator<T> comp) {
      if (last > first) {
        int pivotIndex = partition(list, first, last, comp);
        quickSort(list, first, pivotIndex - 1, comp);
        quickSort(list, pivotIndex, last, comp);
      }
   }

   private <T extends Comparable<T>> int partition(T[] list, int first, int last) {
      T pivot = list[first];
      int low = first + 1;
      int high = last;

      while (high > low) {
        while (low <= high && list[low].compareTo(pivot) <= 0) {
           low++;
        }
        while (low <= high && list[high].compareTo(pivot) >= 0) {
           high--;
        }
        if (high > low) {
           T temp = list[high];
           list[high]= list[low];
           list[low]= temp;
        }
      }

      while (high > first&& list[high].compareTo(pivot) >= 0) {
        high--;
      }
      if (pivot.compareTo(list[high])> 0) {
        list[first]= list[high];
        list[high]= pivot;
        return high;
      }
      else {
        return low;
      }
   }

   private <T> int partition(T[] list, int first, int last, Comparator<T> comp) {
      T pivot = list[first];
      int low = first + 1;
      int high = last;

      while (high > low) {
        while (low <= high&& comp.compare(list[low], pivot) <= 0) {
           low++;
        }
        while (low <= high&& comp.compare(list[high], pivot) >= 0) {
           high--;
        }
        if (high > low) {
           T temp = list[high];
           list[high] = list[low];
           list[low]= temp;
        }
      }

      while (high > first&& comp.compare(list[high], pivot) >= 0) {
        high--;
      }
      if (comp.compare(pivot,list[high]) > 0) {
        list[first]= list[high];
        list[high]= pivot;
        return high;
      }
      else {
        return low;
      }
   }

}
663.写一个二分查找(折半搜索)的算法。

答:折半搜索,也称二分查找算法、二分搜索,是一种在有序数组中查找某一特定元素的搜索算法。搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。

package com.bjsxt;
import java.util.Comparator;

public class MyUtil1 {

   public static <T extends Comparable<T>> int binarySearch(T[] x, T key) {
      return binarySearch(x, 0, x.length- 1, key);
   }

   public static <T> int binarySearch(T[] x, T key, Comparator<T> comp) {
      int low = 0;
      int high = x.length - 1;
      while (low <= high) {
          int mid = (low + high) >>> 1;
          int cmp = comp.compare(x[mid], key);
          if (cmp < 0) {
            low = mid + 1;
          }
          else if (cmp > 0) {
            high = mid - 1;
          }
          else {
            return mid;
          }
      }
      return -1;
   }

   private static <T extends Comparable<T>> int binarySearch(T[] x, int low, int high, T key) {
      if(low <= high) {
          int mid = low + ((high -low) >> 1);
          if(key.compareTo(x[mid]) == 0) {
              return mid;
          }
          else if(key.compareTo(x[mid])< 0) {
              return binarySearch(x,low, mid - 1, key);
          }
          else {
              return binarySearch(x, mid + 1, high, key);
          }
      }
      return -1;
   }
}

说明:两个版本一个用递归实现,一个用循环实现。需要注意的是计算中间位置时不应该使用(high+ low) / 2的方式,因为加法运算可能导致整数越界,这里应该使用一下三种方式之一:low+ (high – low) / 2或low + (high – low) >> 1或(low + high) >>> 1(注:>>>是逻辑右移,不带符号位的右移)

664.统计一篇英文文章单词个数。
package com.bjsxt;

import java.io.FileReader;

public class WordCounting {
   public static void main(String[] args) {
     try(FileReader fr = new FileReader("a.txt")) {
        int counter = 0;
        boolean state = false;
        int currentChar;
        while((currentChar= fr.read()) != -1) {
          if(currentChar== ' ' || currentChar == '\n'
             || currentChar == '\t' || currentChar == '\r') {
             state = false;
          }
          else if(!state) {
             state = true;
             counter++;
          }
        }
        System.out.println(counter);
     }
     catch(Exception e) {
        e.printStackTrace();
     }
   }
}

补充:这个程序可能有很多种写法,这里选择的是Dennis M. Ritchie和Brian W. Kernighan老师在他们不朽的著作《The C Programming Language》中给出的代码,向两位老师致敬。下面的代码也是如此。

665.输入年月日,计算该日期是这一年的第几天。
package com.bjsxt;

import java.util.Scanner;

public class DayCounting {

   public static void main(String[] args) {
      int[][] data = {
           {31,28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
           {31,29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
      };
      Scanner sc = new Scanner(System.in);
      System.out.print("请输入年月日(1980 11 28): ");
      int year = sc.nextInt();
      int month = sc.nextInt();
      int date = sc.nextInt();
      int[] daysOfMonth = data[(year % 4 == 0 && year % 100 != 0 || year % 400 == 0)?1 : 0];
      int sum = 0;
      for(int i = 0; i < month -1; i++) {
        sum += daysOfMonth[i];
      }
      sum += date;
      System.out.println(sum);
      sc.close();
  }
}
666.回文素数:所谓回文数就是顺着读和倒着读一样的数(例如:11,121,1991…),回文素数就是既是回文数又是素数(只能被1和自身整除的数)的数。编程找出11~9999之间的回文素数。
package com.bjsxt;

public class PalindromicPrimeNumber {

   public static void main(String[] args) {
      for(int i = 11; i <= 9999; i++) {
        if(isPrime(i) && isPalindromic(i)) {
           System.out.println(i);
        }
      }
   }

   public static boolean isPrime(int n) {
      for(int i = 2; i <= Math.sqrt(n); i++) {
         if(n % i == 0) {
           return false;
        }
      }
      return true;
   }

   public static boolean isPalindromic(int n) {
      int temp = n;
      int sum = 0;
      while(temp > 0) {
        sum= sum * 10 + temp % 10;
        temp/= 10;
      }
      return sum == n;
   }
}
667.全排列:给出五个数字12345的所有排列。
package com.bjsxt;

public class FullPermutation {

   public static void perm(int[] list) {
      perm(list,0);
   }

   private static void perm(int[] list, int k) {
      if (k == list.length) {
        for (int i = 0; i < list.length; i++) {
           System.out.print(list[i]);
        }
         System.out.println();
      }else{
        for (int i = k; i < list.length; i++) {
           swap(list, k, i);
           perm(list, k + 1);
           swap(list, k, i);
        }
      }
   }

   private static void swap(int[] list, int pos1, int pos2) {
      int temp = list[pos1];
      list[pos1] = list[pos2];
      list[pos2] = temp;
   }

   public static void main(String[] args) {
      int[] x = {1, 2, 3, 4, 5};
      perm(x);
   }
}
668.对于一个有N个整数元素的一维数组,找出它的子数组(数组中下标连续的元素组成的数组)之和的最大值。

答:下面给出几个例子(最大子数组用粗体表示):
数组:{ 1, -2, 3,5, -3, 2 },结果是:8
2) 数组:{ 0, -2, 3, 5, -1, 2 },结果是:9
3) 数组:{ -9, -2,-3, -5, -3 },结果是:-2
可以使用动态规划的思想求解:

package com.bjsxt;

public class MaxSum {

   private static int max(int x, int y) {
      return x > y? x: y;
   }

   public static int maxSum(int[] array) {
      int n = array.length;
      int[] start = new int[n];
      int[] all = new int[n];
      all[n - 1] = start[n - 1] = array[n - 1];
      for(int i = n - 2; i >= 0;i--) {
        start[i] = max(array[i], array[i] + start[i + 1]);
        all[i] = max(start[i], all[i + 1]);
      }
      return all[0];
   }

   public static void main(String[] args) {
      int[] x1 = { 1, -2, 3, 5,-3, 2 };
      int[] x2 = { 0, -2, 3, 5,-1, 2 };
      int[] x3 = { -9, -2, -3,-5, -3 };
      System.out.println(maxSum(x1));   // 8
      System.out.println(maxSum(x2));   // 9
      System.out.println(maxSum(x3));   //-2
   }
}
669.用递归实现字符串倒转
package com.bjsxt;

public class StringReverse {

   public static String reverse(String originStr) {
      if(originStr == null || originStr.length()== 1) {
          return originStr;
      }
      return reverse(originStr.substring(1))+ originStr.charAt(0);
   }

   public static void main(String[] args) {
      System.out.println(reverse("hello"));
   }
}
670.输入一个正整数,将其分解为素数的乘积。
package com.bjsxt;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class DecomposeInteger {

   private static List<Integer> list = new ArrayList<Integer>();

   public static void main(String[] args) {
       System.out.print("请输入一个数: ");
       Scanner sc = new Scanner(System.in);
       int n = sc.nextInt();
       decomposeNumber(n);
       System.out.print(n + " = ");
       for(int i = 0; i < list.size() - 1; i++) {
           System.out.print(list.get(i) + " * ");
       }
      System.out.println(list.get(list.size() - 1));
   }

   public static void decomposeNumber(int n) {
      if(isPrime(n)) {
        list.add(n);
        list.add(1);
      }
      else {
        doIt(n, (int)Math.sqrt(n));
      }
   }

   public static void doIt(int n, int div) {
      if(isPrime(div) && n % div == 0) {
        list.add(div);
        decomposeNumber(n / div);
      }
      else {
        doIt(n, div - 1);
      }
   }

   public static boolean isPrime(int n) {
      for(int i = 2; i <= Math.sqrt(n);i++) {
        if(n % i == 0) {
           return false;
        }
      }
      return true;
   }
}
一个有n级的台阶,一次可以走1级、2级或3级,问走完n级台阶有多少种走法。
package com.bjsxt;

public class GoSteps {

   public static int countWays(int n) {
        if(n < 0) {
            return 0;
        }
        else if(n == 0) {
            return 1;
        }
        else {
            return countWays(n - 1) + countWays(n - 2) + countWays(n -3);
        }
   }

   public static void main(String[] args) {
        System.out.println(countWays(5));   // 13
   }
}
672.写一个算法判断一个英文单词的所有字母是否全都不同(不区分大小写)
package com.bjsxt;

public class AllNotTheSame {

   public static boolean judge(String str) {
      String temp = str.toLowerCase();
      int[] letterCounter = new int[26];
      for(int i = 0; i <temp.length(); i++) {
        int index = temp.charAt(i)- 'a';
        letterCounter[index]++;
        if(letterCounter[index] > 1) {
           return false;
        }
      }
      return true;
   }

   public static void main(String[] args) {
      System.out.println(judge("hello"));
      System.out.print(judge("smile"));
   }
}
673.有一个已经排好序的整数数组,其中存在重复元素,请将重复元素删除掉,例如,A= [1, 1, 2, 2, 3],处理之后的数组应当为A= [1, 2, 3]。
package com.bjsxt;

import java.util.Arrays;

public class RemoveDuplication {

   public static int[] removeDuplicates(int a[]) {
        if(a.length <= 1) {
            return a;
        }
        int index = 0;
        for(int i = 1; i < a.length; i++) {
            if(a[index] != a[i]) {
                a[++index] = a[i];
            }
        }
        int[] b = new int[index + 1];
        System.arraycopy(a, 0, b, 0, b.length);
        return b;
   }

   public static void main(String[] args) {
        int[] a = {1, 1, 2, 2, 3};
        a = removeDuplicates(a);
        System.out.println(Arrays.toString(a));
   }
}
674.给一个数组,其中有一个重复元素占半数以上,找出这个元素。
package com.bjsxt;

public class FindMost {

   public static <T> T find(T[] x){
      T temp = null;
      for(int i = 0, nTimes = 0; i< x.length;i++) {
          if(nTimes == 0) {
              temp= x[i];
              nTimes= 1;
          }
          else {
              if(x[i].equals(temp)) {
                  nTimes++;
              }
              else {
                  nTimes--;
              }
          }
      }
      return temp;
   }

   public static void main(String[] args) {
      String[]strs = {"hello","kiss","hello","hello","maybe"};
      System.out.println(find(strs));
   }
}
675.编写一个方法求一个字符串的字节长度?
 public int getWordCount(String s)
    {
        int length = 0;
        for(int i = 0; i < s.length(); i++)
        {
            int ascii = Character.codePointAt(s, i);
            if(ascii >= 0 && ascii <=255)
                length++;
            else
                length += 2;

        }
        return length;
    }
第二篇:就业实战

一:招聘程序员的内幕

1.面试和相亲

面试其实本质上是一个交流的过程,它跟你去相亲本质完全一样。那么,把握面试官的心理状态,从面试官的角度出发思考问题,将是你可以顺利收到offer的关键。

如果你知道面试官的动机,就可以建立共通点,很容易就能恰当地回应问题。从而为你的面试加分、添彩。

相亲时,你期望碰到美女的渴望和美女期望碰到白马王子的渴望,二者的“渴望程度”完全是一样的。 那么,你如果是男方,你需要做的事情就是“包装”自己,让自己显得比实际上“更高,更富,更帅”,接近女方的心中白马王子的高度,越接近越容易成功。这个过程也存在“心理博弈”的过程,双方聊过去、聊现在、聊未来。 有辉煌过去的喜欢聊过去来证明自己的未来;现在就辉煌的就喜欢聊当下;过去不行,现在不行的就喜欢聊未来,展现自己的雄心。

同上面相亲的案例,面试中,面试官需要人才的热烈程度等于你求职的热烈程度。 我们首先要明白面试官需要什么样的人才,然后展示自己,告诉他,我就是这样的人才!

明白上面的道理,我们就需要针对整个招聘的过程进行详细的分析,让大家心里更有底,更容易把握面试官的心理状态。

2.为什么要招聘程序员?为什么绝大部分总能找到工作?

一般公司招聘员工有三大类原因:

1.公司计划性扩张

2.特定项目

3.有员工离职

因此,招聘者也是“求贤若渴”,他也面临公司给他的绩效压力。 如何能尽快、低成本的招聘到合适的人到岗,而不耽误业务的进展,这是招聘者最大的工作。

通常如果受到高层压力,感觉招聘进度已经限制了公司业务的发展、已经阻碍了业务推广的时间,招聘者就会变“急”。 就跟开发人员迫于项目时间的压力,凑合完成一段不合格的代码一样。招聘者也会由于这些压力,有可能降低招聘的岗位标准(这种降低不是明面上通知降低标准,而是各个环节把控较松)。 这也就是为什么很多人技术并不太好,也能找到工作的原因。 公司最大的成本有时候不是金钱、而是时间。 这也就像很多优秀的男生女生30岁之后,迫于时间压力,降低标准找对象的道理一样。

虽然学习编程的人员很多,但是各行各业都需要信息化,人员需求也非常巨大,缺口仍然很大。 如果某个公司招聘并不顺利,连续面试很多人都不合格,那么可能就在面试你的时候降低“标准”。 这也是为什么很多技术很水的人也能找到工作的原因。 对于招聘者来说,如果你心态好,很踏实,即使现在技术不行,花一点时间培养你,也没什么大不了。

当然,这不能成为你不好好学习技术的理由。”技术强、心态好、踏实”将会让你面临更多的人生机会。

3.为什么有人会找不到工作?

任何一个行业都有失败者,这就是规律。 就像婚姻、恋爱市场,总会有打光棍的问题(100%是男同胞,男女比例严重失调啊)。 为什么会有人找不到工作?为什么会有人找不到老婆?这是个大课题。想明白了,你将会走向人生巅峰。

我们先以婚姻、恋爱市场为例。研究研究为什么会有人找不到老婆? 有人说,打光棍是因为这个人没钱。 但你总会发现比他还没钱的人娶了老婆,有的还很漂亮。老婆还很贤惠,出去打工养老公。 有人说,打光棍是因为这个人没能力。 但你总会发现很多没能力的人也娶了老婆,有的也很漂亮。 这时候,你只能仰天长叹,“好白菜都让猪拱了”。有人说,打光棍是因为这个人长得丑,个子矮、家里穷等等。但你总会找到层出不穷的反例。这时候,你可能就会迷茫了。 到底什么才是关键、才是问题的核心?

好吧,我告诉你, 是心态!心态!心态!重要的问题说三遍! 心态积极,勤奋努力什么事情都能干成。 心态消极,懒惰不努力,什么条件都没戏! 很多“懒屌丝”宁愿天天宅在家里睡懒觉、玩游戏,也不愿意走出去。宁愿窝在家里练习右手臂力,也不愿意出去多跟异性接触。 这些人,不管什么条件都将被淘汰。

大家如果看过电影《夏洛特烦恼》,里面的“大傻”,智商低,但是人实在。就是靠死缠烂打硬泡的方式,竟然也追上了自己的女神。 追女神也是概率问题,努力去追,提高成功率,女神总有空虚、心理没底的时候,这时候可能就会有机会了。 某天,女神忽然微信呼你:“忙吗?”,这时候机会就来了。 但是,如果你不努力,你连女神的候选名单都上不去,怎么可能有机会?

在招聘市场,应聘者面临的是同样的问题。 即使你技术水平差,只要多面试、多总结、多努力,没有不成功的。 你想想,面试是个概率事件,技术差你的成功率即使只有1%,面试100家也上去了。 技术好你的成功率是10%,不去面试,面试的少,你可能也没戏。 因此,我们要千方百计提高自己“面试的机会”,至少可以让自己进入企业“眼里”,一旦有机会,即可成功。

我们曾经碰到一个学员,大学学的是文科,学历是专科, 毕业后做了一名“光荣的水手”,环球航行了两年,决定回归陆地。 开始学习编程,学了1个多月后,仍然在纠结什么是变量的问题。 但是,这个同学心态好,积极向上,毕业后,积极主动的去面试,结果很快搞定了工作,刚开始工资并不高。 工作两年后,成了项目经理,年薪30万。风风光光的回尚学堂招聘学弟学妹了。 积极努力,一天当两天用,起点再低也会成功。

我们也碰到过一个奇葩的学员,在尚学堂学完后,就纠结于你们不是“推荐就业”吗?窝在宿舍等着。 企业来了,老师通知也不来参加面试,偶尔来了,结果窝在宿舍根本没有锻炼出能力,也无法面试成功,这是极其个别的案例。即使你是千里马,不出去跑,天天窝在家里,消极等待,最终你也会成为一匹“废马”。

所以,无论你是什么条件,高富帅还是矮矬穷,心态不对,恋爱和工作都不可能成功。 希望大家积极起来,大着胆子冲向社会,千方百计进入企业招聘环节,即使不成功,就当做一次锻炼机会,锻炼多了,一旦机会来了,是不是成功率就大大提高了? 做“屌丝”可以,自嘲一下也不错,但千万不要做“懒屌丝”,那样你就完蛋了。

4. 公司最喜欢什么样的程序员?

公司喜欢什么样的程序员?特别简单,三个特点:

第一、态度好

态度永远是第一要素,面试者通常都是你以后的直接上级。如果跟你交流顺畅,看你态度也不错,这样对他来说,领导起来就容易一些。 因此,态度通常是面试官看人的第一要素。 态度不端正,一切免谈。能力强我也驾驭不了,要你何用? 能力差态度好也勉强能接受,能力差态度还差那就分分钟被灭掉。

如果你知道面试官的动机,就可以建立共通点,很容易就能恰当地回应问题。从而为你的面试加分、添彩。

第二、技术能力较强

企业招聘人员毕竟是来做事的,技术能力是考察的重点。技术能力能胜任目前的工作,是面试官主要看重的。

第三、热爱技术工作,学习能力强

通过跟面试官的交流,能让别人觉得你热爱技术工作,会让你具备极大的优势。即使感觉你现在水平较差,也没有关系。兴趣是最好的老师,喜欢技术,把加班当成玩游戏一样的态度,面试官显然会大大的给你点个赞。

PS:这里顺便给个技巧,可以让你身价立刻增加30%以上(本来你值8000,可以拿到1万,一下子让你一年多挣3万),那就是学习本专业的一些新的技术、高级一点的技术。不需要多么精通,了解即可。可以在面试的时候说出来。这样就会令面试官对你刮目相看,薪水标准也会立刻增加。因为你说的这些技术,可能是面试官也不会的,这种对你的好感度和惊诧的眼神立刻就会让你身价暴增。 很多java学员学完后再学大数据或者架构师班,都有这样的误解,觉得一定要学到多么多么好。其实,没必要,了解大数据或者架构师班某些技术能交流即可,面试时优势已经极大了; 而且,即使上了班,用到这些技术,查查资料加加班能弄出来就OK了。

如上三点决定了你是否能被录用。大家掌握这三点,也可以互相补充。比如,你技术差,可以通过展现态度好,爱技术,爱学习来获得加分。 当然,如果技术好,也要通过展现态度好,爱技术,爱学习获得更多的分。

面试官经常会碰到技术非常合适,但是态度较差,计较是否加班的面试者,基本都被pass。毕竟,技术再强也不是地球上只有你会,对不对? 如果态度差,加入团队变成团队的负能量,那就损失大了。

5.我到底值多少钱?

第一、态度好

“我是谁?”这是人生最大的命题,找工作最大的命题是什么呢?显然,就是“我到底值多少钱?”。给自己确定了合适的定位,才能找到合适的工作。 如果你能力只值5000,一定要找3万的工作,那怎么可能找得到?

一般情况,面试官评价你的薪资标准通常从下面几项:

1.个人素质和口才(占比:20%)

这其实是个印象分,所以要被别人认可的其实就是上一个话题《公司最喜欢什么样的程序员》中表示的第一特点:“态度好”。

如果你向面试官充分表达了良好的个人素质、对工作积极的态度,整个面试过程中让面试官都觉得非常的顺畅、很投缘,即使你技术较差,也可以让你顺利拿到offer。

“个人素质和口才”是你拿到offer的最关键因素。

2.基础技术(占比:40%)

基础编程能力、理论知识是否扎实、知识体系是否系统是面试官比较看重的。老师讲课过程中的基本知识点要尽力吃透,良好的知识体系对于后期面试极其有利。

如果面试官感觉你项目经验不丰富,但是基础扎实,也可以完全的弥补项目经验欠缺的问题。这也是很多应届毕业生能顺利就业的法宝。 当然,如果项目经验欠缺的话,高薪的概率就降低了, 需要降低薪资要求,保持较普通的薪水来实现就业。

“基础技术”是你能否就业的基础因素。

3.项目经验(占比:40%)

项目经验显然是面试官极其看重的一项。从项目经验的描述中可以体现你的个人素质、基础技术等等。尽量多的积累项目案例,尽量多的敲代码,可以完成基本的项目模块,会成为你以后面试的杀手锏。

在培训期间,老师讲的项目案例大家要学会举一反三,毕竟这些案例对着几十人、几百人讲过,你在面试时直接写到简历上并不是特别好的做法。最好的做法是,做一个有心人,多留意和查找适合自己的项目案例。

项目案例是你的,里面的项目流程和开发中遇到的问题是老师课上讲过的。说白了,就是将你的项目案例换了个衣服,“换汤不换药”,这样就可以在面试中起到更好的效果。

“项目经验”是你能否实现高薪的关键因素。

4.最新和高级技术了解程度(额外,增值30%--50%)前面3项如果做好了就可以完全保证就业了。“最新和高级技术了解度”是能否争取到合理范围内更高薪水的关键,也就是让你实现更高“溢价”,“超额把你自己卖出去“。

面试官通常由于平时工作忙,无暇学习新的技术和知识,除非是项目用到的技术。但是,作为一个“技术控“,通常会关注最新技术的信息,拥有学习这些技术的渴望,但是没有时间和精力。 这个时候,应聘者简历上写的新技术、面试时聊的新技术,都会成为让”面试官欣赏你的理由“。

但是,注意千万不要有心理负担,这种”欣赏的眼神“是上级发现一个得力下属的”喜欢的眼神“,而不是好基友。 面试官也知道你基础一般、项目经验一般,但是这些新技术你都在学,证明你是个”技术好胚子“,很像曾经的”他自己“而已。

如果前三项决定了你的薪水是8000,那么有了第四项,你的薪水标准通常会提高至少30%,最高50%。也就是实现了”你的溢价”, 每个月可以多赚:4000元左右。 而且,你会发现拿8000和溢价拿1万,1万2, 最后干的活其实差别不大。

这里有个经过我们统计的”1.5倍定律”: 就是经过”最新和高级技术”的助力,你的薪水会在原定值上增加50%,薪水是原来的1.5倍。

6.找工作最重要的是什么?薪水?机会?

什么最重要,因人而异。一般分为如下几类:

这种情况,我也不多说。缺钱就看薪水,不缺就看机会。个人建议,看机会。

第二种情况:offer少,没得挑

这种情况,当然,就是”别挑了。先进入行业,再寻找机会”。时间浪费不起,如果因为薪水纠结,两个月不上班,损失两个月薪水不说,还浪费了两个月时间。

第三种情况:没offer

这种情况,就是降低标准,千方百计就业,不管什么企业,先进去再说。进去行业后,再学习,再进步,再找更大的机会。

我们始终强调”机会成本”,差不多的前提下,尽快就业,不要纠结于薪水多500少1000的问题,进入行业后,还需要再学习再提高。 现在就业不是你的终点,而是你的起点。

7.学习很多技术,现在的公司不用,不是亏了吗?

很多朋友还是跟小孩一样, 感觉学习了东西后如果考试不考,公司暂时不用就没有价值,不想学习。 感觉学习好累啊,是给老师学的,给尚学堂交了学费,是给尚学堂学的。别不承认,很多人潜意识里面就是这种”应试教育”思维。

多学东西到底是为什么?其实,很简单。掌握更多的技术,意味着更多的机会,有更多选择的机会。 人和人之间本质的差距就是“选择权“的差距。 农民自家种蔬菜、养猪吃,很干净很有机;千万富翁可能还要吃着普通的猪肉和蔬菜;他们之间的差距在于:千万富翁可以随便选择,可以随时过农民的生活;而农民却没有选择过千万富翁生活的权利。 多学技术,就意味着有更多选择的机会,发展的机会,就会造成工作和生活的差距。

同时,在IT行业多学东西,除了这些“机会和选择权“之外,更直接的就是能带来金钱的收益。 举例来说,同样招聘一个java程序员。小A只会java已经合格了。 小B除了会java,还会一点大数据和架构知识,要价比小A高20%。 关键是,我们公司现在也不需要大数据和架构技术,小A和小B来了以后还是写java代码。 你猜,面试官会选择小A还是小B? 绝大多数面试官会选择小B。 有了小B,一旦后期有大数据和架构的需求,技术经理就多了一个选择。 而且,小B显然更好学,成长性更好,虽然薪水高20%,但是几个月时间就能把这20%的薪水赚回来。

掌握或了解更多的技术知识,抛开企业用和不用的角度,单纯看应聘者就是一个态度的问题、成长潜力的问题。 面试官显然会要态度更好、成长力更大的员工。

另外,你的企业现在不用,以后可能会用呀,这个时候你可能就具备强大的话语权和机会了。 我们一个大数据的学员毕业后,他还是应届生,去了一家公司做java开发,没多久老板成立大数据业务的公司,结果公司就他会,直接就被任命为大数据业务的技术负责人。 你可以说,这个学员还年轻,技术不行什么的,但是他有这个技术负责人的平台,还要学习和提高,现在不行,一年后呢?

多学习,意味着更多的机会和选择;更多的机会,意味着完全不同的人生。

二:找工作前需要准备的杀手锏

高考前,我们要练兵考试和集训。”临阵磨枪不快也光 ”,找工作前,我们也必须要花很多精力去完成一些必要的准备。 “不打无准备之仗”, 精心准备和训练会对你有相当正面的作用。

有人认为“找工作要靠能力”。这话没错,我要说的是,“临阵磨枪准备的内容也是能力的一部分”。 找工作其实是结果导向的一个事情,而不是过程导向。

小A和小B技术实力差不多, 小A经过精心的准备和策划,获得的机会显然要远远多于小B。也许一个机会,就能完全将小A的命运改变了。

1.职场的十大基本素质

大家进入职场前,非常有必要明白职场的一些基本要领。其实,道理都非常简单,甚至可以说是常识, 关键是我们能否执行下去。很多人不明白这些基本的道理,几年下来,坏的行为固化成习惯,习惯进一步融入到命运,最后很悲惨的成为人人鄙视的loser。所以,我希望大家从看到这篇文章起,就遵守这样的行为准则,你将会在职场中很快迎来自己的好运。

①着装整洁、个人卫生合格

这个都不能算作职场素质,应该是做人的素质。每天逢头垢面出门、指甲里面都是污垢、身体有异味,如何让别人觉得你是个靠谱的人?千万不要跟我说,你不拘小节。不拘小节是谦词,别人可以给你面子这么说你,但你不能这么说自己。每天出门前,男士花十分钟打理一下自己,穿一身干净的衣服。你可以没有阿玛尼,穿地摊货都可以,关键是干净整洁。干净整洁、形象良好,马上可以让人对你的印象提高N个档次。

记得几年前,一个学员过来找我,说:“老师,我面试了好多家了。为什么都是几分钟就被人打发了”。我极其惊讶地看着他,N天没有洗澡,乱糟糟的头发,满脸油腻,“逢头垢面”就是形容他的。那时候是夏天,估计N天没洗澡,一股异味。基本上我可以断定,这个哥们的处境。第一、没朋友,无论男女。没有人会愿意跟他呆的距离在1米以内,那真是一种折磨。第二、没前途。不知道哪个瞎眼的面试官会要他?于是,我很残忍的告诉他现在的处境。

我问他:“你个人卫生是不是太差了。这个仪表,人家跟你说十分钟都是给你天大的面子了”。他说:“我知道卫生有点差。但我觉得别人不会那么庸俗的,应该更多的关注我的技术和我的人品”。

我说:”大家时间都很有限,都很忙。第一、跟你技术水平相当的人多得是,没必要花时间透过你这个外表去琢磨你的内在。第二、你太自我为中心了。别人应该关注你的内在,你怎么不说,你应该改改你的外在?连基本外在卫生都没有,你还能做什么?“。

他仍然固执:”讲卫生很简单,我每天花点时间整理一下就行了。但是…“。

我打断他的话:”先回去洗个澡,换身干净的衣服。你这样的仪表,第一、不尊重你自己。第二。不尊重别人。不说工作了,你这样怎么找女朋友?想改变你的处境,先改变你的仪表,改变你的行为。以后,每天早上花十分钟整理一下自己,不然,你完蛋了“

后来,就没再来找我。一年后,我收到一个短信:“高老师,感谢你的醍醐灌顶。以前,太自以为是,以为世界都是围绕我的。那天回去后,我就真的“洗心革面”了,每天早上整理一下外表,都不用十分钟,五分钟就够了。后来,我再面试只花了一周时间就上班了。这一年里,收获很大,也有了女朋友,也有了很多男性朋友,整个人生都感觉改变了。再次谢谢您的直言不讳”。

②有正常的交流习惯

一个正常的交流习惯也是及其重要的。正常的交流习惯有如下五点:

1.不打断对方说话

这是对别人最基本的尊重,把话让别人讲完,也是最基本的礼貌。

2. 说话时,盯着对方的眼睛。眼神坚定,不飘忽

眼睛是心灵的窗户。跟人交流时,千万不要边说话,眼睛边四处看。要紧盯着对方的眼睛,如果你实在不好意思,可以盯着鼻梁看。盯着鼻梁,在对方看来也是盯着眼睛的,效果差不多。

3. 说话时,语气不拖拉。

说话语气肯定,有自信,千万不要嗯嗯啊啊。

4. 没有小动作,但可以适当增加手势

抖腿、搓手、动手碰别人这都是不礼貌的习惯。交流时,不要有这些不良动作,但是可以适当增加手势,让你的交流更顺畅。

5. 表情放松,多一些微笑

不要将跟别人的交流搞得太过正式,放松一些,多一些微笑。

③准时,不迟到

一个没有时间观念的人,怎么可能做好事情?因此,面试不迟到、约会不迟到,这都是最基本的礼仪。而且,所有的面试、约会最好保证提前十分钟到达。

但是,万一发生了迟到的状况,怎么办?万一由于堵车等原因迟到,要立刻打电话联系对方,告知对方原因,并表示抱歉。

领导不下班,你也不走

对于初入职场的你来说,非常有必要让领导看到你的工作态度。你可以工作做的慢,但是态度必须端正,至少要让领导觉得你是可造之材而不是烂泥。

如果你的直接上级仍然在加班工作,你非常有必要保持同步。如果能帮上忙,可以上前问问有没有需要你做的事情。如果暂时帮不上忙,可以坐在电脑前学习一些专业性的知识。能做到这一点的人,其实真的不多。做到了,也基本就可以奠定你工作认真、愿意付出的形象,为以后创造更多的机会打下基础。

⑤和周围的同事打成一片

多跟同事交流、打成一片,是职场最基本的规矩。这在平时工作和休息时,一定要多注意不能落单。最典型的:中午午餐时间,一定跟同事们一起吃饭,不要落单。

⑥有困难,就马上寻求帮助

工作中遇到问题,自己通过查资料无法解决。立刻寻求同事帮忙,千万不要因为不好意思开口而耽误工作时间,影响公司整体的工作进度。

⑦有责任心、事情到我这里结束

基本的责任心及其重要!千万不要以分工清楚、不是我的事情作为推脱的借口。在大公司,分工过细是事实,但是你也经常需要参与工作之外的事情。在中小企业就更不用说了。事情到你这里,你能把他解决掉,本身就是能力的锻炼和提升,是让自己升值的机会。如果,你把它推脱开,不仅丧失了锻炼的机会,也让别人看到了你的态度,看清了你的前途。

以前遇到过一个“搬椅子”的小事情。一次开会,会议室少五把椅子,老板已经坐下,说:“多了5个人,少5把椅子”。负责安排会议的人竟然问:“让我去搬吗?”他也许是想说,我是个女孩哎,搬不动。也许是想说,我是个经理哎,让我去搬椅子,多没面子。总之,他说了这5个字。老板一脸错愕,没说什么。一周后,这个女孩辞职走人。

工作中,你碰到了就是你的事情。解决的事情越多,你得到的锻炼机会越多,你的能力就越强,还怕没有升职和发展的机会吗?

很遗憾的是,工作中很大一部分都是责任心缺失的人。这也很幸运,这些无责任心的人会让出很多的机会给你。一定要相信,你有没有责任心,你的上级、你的女朋友一定能第一时间知道。

⑧学习的心态对待同事和上级、包容的心态对待同事和下级

“懂得配合才能有领导力、才能有协作力”,对待你的上级一定要抱着学习的态度。他能做到这个位置,肯定有过人之处、肯定有比你强的地方。把他这些优点学习到位,再进行改进,青出于蓝,你不就有机会了吗?

工作中,很多同事都会私下议论上级,觉得这个决定好傻、那个决定好呆。往往是由于下级和上级看问题的角度不一样导致的,“屁股决定脑袋”。那么,为什么不尝试配合一下领导的决定看看到底行不行呢?或者,你觉得确实有问题,完全可以私下跟领导说说你的感想。在企业中的人事关系要比政府关系简单的多,你私下有礼貌的提出来你的意见,往往还能博得上级的好感。

⑨忠诚

如果你不忠于你的公司,私下贪污公款、私下为其他公司牟利。一旦有这些行为,基本上你就为人所不齿了。在公司你肯定不会有好的前途,其他公司看你这样,无非就是利用一下你,但绝对不可能重用你。

永远不要以自己的小聪明耍弄你的上级和你的同事,这个世界,智商都差不多,谁比谁笨呀?你可以蒙他一次,两次,不可能蒙他三次、四次。就像你考试作弊一样,自以为很聪明,但如果你坐在讲台上监考,你就明白,下面的动作一览无余,更多的时候,只是老师不愿意去把你拎出来而已。

所以,职场上,忠诚是人的最基本的素养。

⑩办法总比问题多,积极的心态面对问题

工作中遇到问题,不要害怕。工作就是解决一个个问题呀!既然是问题,就有应对的办法。想尽办法,总能解决。不要遇到问题就牢骚满腹:“完蛋了。这绝对不能解决”。发牢骚的人,在公司里面不仅毫无价值,而且是负价值。

2.公司调研

对于你即将要面试的公司,一定要做到“知己知彼”,在面试前做充分的调研。这样既能让你在面试的时候与HR有充分的互动机会,也可以避免很多无良公司的“坑”。

做公司调研需要做到如下几个关键点:

1. 公司发展的历程

2. 公司的产品或者项目以及周期

3. 公司下一步的发展规划

4. 公司开发使用的技术架构

5. 公司跟开发有关的组织结构(开发部、测试部、运维部、产品部等)

3.项目调研

对于企业来说,会关注你大学期间成绩单呢,还是关注你的项目经验?答案显然是:项目经验。甚至在很多研究生复试时候,导师看到你的简历上写了很多项目经验,也会极大的增加你的分数。五年前,我的一个学生在尚学堂培训时的项目写在研究生复试简历上,被导师问了又问,最终被中科院计算所录取。这就是项目的力量。

因此,前期的项目准备会让你的简历更加丰富,赢得更多的机会。一个小小的机会也许就能完全改变你的命运。

对于项目调研,大家要避免误区。不是说,一定要将项目的商业源码搞到手,通读一遍才算是完成调研;也不是说,一定要把这个项目代码写一遍;其实,项目调研的本质是让你开阔眼界,增加和“面试官”的谈资。

项目调研最重要目的是要让你明白某个项目开发的流程、某个项目的内在逻辑,此类项目常见的问题,开阔眼界,最终真正理解项目开发的整体流程。

项目调研关键是要做到有心!现代互联网这么发达,任何资料都可以在网络上找到。我可以给大家提供各种项目调研的思路:

A. 打开各种网站,其实就是一个个项目。

B. 打开相关软件公司,下载他们软件的试用版,就可以去研究他的内在逻辑。

C. 下载各种app,也是一个个完整的项目。

D. 各种开源网站下载的项目,也可以作为研究的对象。

E. 大胆出去,参加一些创业、创意相关的活动。比如:中关村创业一条街的各种会议。

4.基础技术准备

就业前,大家需要将自己平时培训期间学习的技术捋一遍,全面复习一遍。临阵磨枪仍然是最重要的应急手段,面试前的准备就像高考前一样,越充分越好。

但是,需要记住如下两点:

1. 对于一些常见的面试和笔试问题,一定要反复练习,最好能背下来。

2. 对于一些工作和面试不常见的问题,记住结论即可,不要纠结。不要因为一些小概率的问题而浪费太多的时间。毕竟,任何人都没有必要有能力可以应对所有的问题,只要能应对常见的问题足以实现就业。

5.热门技术准备

软件行业技术更新较快,经常会出现新的技术。但是,这些技术通常不会马上应用于企业中,企业一般都会使用稳定和大众化的技术。所以,企业应用技术通常都有2-3年的滞后期。

身处软件开发第一线的人往往对新技术学习也会滞后,毕竟企业不用,大家还是不愿意多花时间和精力去学习。但是,作为程序猿往往对这些技术保留了极大的好奇心。绝大部分程序猿会心想:“等我有时间,我一定要学习一下”。

这种滞后性,就是刚进入软件行业的新人的机会。如果你是做IOS开发的,简历上写明会使用swift语言开发,就会引起一直使用Object-C开发项目的面试官极大的兴趣。如果你是做JAVA开发的,会使用微服务架构,了解大数据相关的技术,也会引起面试官较大的兴趣。而且,更有意思的是,你不需要精通这些新技术,只要了解即可。就能很快的引起面试官的兴趣,毕竟“好奇心”是程序猿最大的特点。

对于热门新技术的了解,可以明明白白的告诉对方,你就是一个喜欢技术、喜欢钻研的典型的程序猿。这会给你起到加薪加分的效果。” 1.5倍薪水定律”就会起到作用。

6.更高端技术准备

技术行业是一个非常干净的行业,付出和得到基本是正比关系,你不需要靠关系靠背景。作为程序猿,学习就是本能,学习跟你的薪水是成正比的!学习越多,薪水越高。作为一个专业的程序猿,必须做好进一步提升的准备。千万不能有已经到头的想法!一个二三十岁,刚入行的年轻人,如果产生了已经学够的想法,那说明你的前途也到尽头了!”观念决定行动,最终决定命运”。

对于本专业更加高端的技术,一定要保持学习的心态。即使,这些技术暂时用不到。对于开阔眼界,提高思维境界,应对面试都是极好的。掌握或了解本专业更高端的技术,加薪加分效果也很明显。“1.5倍薪水定律”效用也非常明显。

7.本专业之外的技术准备

很多人会以:“专业贵精不贵多”,“一招鲜吃遍天”,作为不学习其他技术的借口。这些话没有错,我也赞成这些话。但是,这些话不能作为不学习的理由。

一个学习安卓、IOS开发的程序猿当然最重要的就是掌握本专业的开发技能,但是如果你还了解后台服务器程序的开发,这就是你不同于普通程序猿的优势。

一个学习JAVAEE开发的程序猿,学好JAVAEE是最重要的,再了解大数据开发的知识、人工智能开发的知识, 也可以触类旁通, 让自己获得更多技巧。同时,在面试JAVAEE的时候,你竟然也懂大数据、懂人工智能(也许只是皮毛)?但也一定可以给你的面试加分。

知识面宽往往意味着好学,潜力巨大。经过两三年的磨练后,熟悉各种技术的你,必将迎来一次发展的机遇。为什么机遇一定会给你?显然,一般人是做不到这一点的。

我们有一个学员学完JAVAEE后,又学习了大数据开发,很多人说他:“好傻,你去公司只是做一份工作。学那么多干什么?“。但是,这些嘲笑他的人错了。这位学员三个月后,就成了公司项目的负责人,很简单,就是因为他JAVAEE会,大数据也会,公司正好需要两方面都懂的人。

“如果因为学习,别人说你傻”,我们只能回应:“别人笑我太疯癫,我笑他人看不穿”。这个社会,如果不能跟别人拼爹,那就只能跟别人拼头脑拼血汗了。

8.共同话题准备

面试你的人基本都是程序员,或者程序员出身,因此你们在对话中都可以找到很多共同话题。那么,为了让我们的面试充满各种“亮点”,对于共同话题的准备就相当有必要了。“用心去准备的面试,连面试官都会被你认真的态度打动;反过来说,如果连面试都不重视的人,我怎么相信你会对工作更有责任?”。

我们可以准备以下这些问题:

1. 是否曾经耗费几个小时甚至几天的时间来追踪一个顽固的bug?

2. 你有没有因为某个问题加班到半夜的经历?

3. 你喜欢某种编程语言的哪一点?

4. 经常访问哪个程序员的网站?

5. 你最喜欢看的编程类的书籍是什么?

6. 关于IDE,什么事最让你抓狂?

7. 精心准备几个能说明你技术能力的专业问题,在面试时尽量发挥出来。

9.自我模拟面试和对练

开始投递简历前,可以五人一组互相对练,进行角色扮演。分组练习的好处非常明显,可以让我们在非常短的时间里得到提升。分组练习的角色有:面试官、应聘者、旁观者。

分组练习的好处有:

1. 面试官面试别人可以体会如何设问,对方回答是否得体

2. 应聘者可以身临其境体验被面的过程。

3. 旁观者可以清晰的看到面试官的优缺点、应聘者的优缺点。加强学习,避免自己发生这些问题。

但是,也不能过多的训练。以每人各扮演两次角色(两次面试官、两次应聘者)为宜。然后,马上投递简历,开始实战!!

三:面试准备

1. 简历的作用

一份格式规范、要点突出的简历是你找工作的“敲门砖”,值得你花上一周、甚至两周时间精心打磨。这样你会获得更多的机会。当然,简历仅仅是敲门砖,任何一个面试官都不可能仅凭简历就雇佣一个人。

2.简历两个灵魂

第一要点:必须自己亲自写简历。

简历必须每个字都自己写,绝对不能抄!自己亲自写一次简历,相当于把技术复习一遍,把项目捋一遍,对于其中的关键点可以做到心中有数。 面试中的很多问题都是根据简历问出来的,只有自己亲自写一遍才能灵活应对。

第二要点:简历要突出自己的核心竞争力。

一个职位会有几十、几百份简历的投递!投递简历显然是存在竞争关系的,一定要对简历作出适当的包装,就像去相亲要化妆一样。 不包装的简历如同没有穿衣服逛街一样,虽然显得本真,但是也很神经病,很傻。在面试官看来,没有包装的简历会显得你这个人不识时务,不灵活,而不会觉得你这个人本真(其实就是天真)。 处在世俗社会里面,我们要随“社会大流”,别人化妆我们也要跟进,不求占别人便宜,但是也不能吃亏。但是,包装不能欺骗企业,掌握好“度”。

3.一份完美的简历(6大要素)

1.囊括相关技术关键词,注意上下文

公司每天会收到几十份简历,筛选这些简历往往是不懂技术的招聘人员,因此尽量写上你会的技术的关键词。

2.文笔要好,要点突出,简明扼要

如果你不知道如何组织文字,可以先尝试将想表达的内容讲给朋友听,这非常有效。第一、可以起到互动、交流的作用,让你的朋友给你指正。第二、可以捋思路。第三、为面试时的回答打下坚实基础。

3.对工作经验、项目经验、实习经验作出解释

如果你声称具备某种工作经验、项目经验,那么就必须说明是如何获得的。如果简历上写了“3年java开发经验”、“3年ios开发经验”,不进行进一步的说明,就显得太虚假了。 不说明倒也没关系,但是面试官收到的简历可不止你这一份,毕竟还是有很多人进行了详细的说明。你不说明就意味着白白丢失了很多机会。 就像去相亲见面,但是你不化妆、不打扮,穿着拖鞋去了,那我想你太吃亏了。 我们不想占别人便宜,但绝不能吃亏。

4.工作经历不要留有情况不明的空白期

简历中,不要留下特别长的空白期,这会让人觉得你心中有鬼。

5.个人爱好和特殊证书

很多人会写上自己的个人爱好:“卡拉ok,听音乐,看电影”。这些不能体现个人素质的内容不如不写。但是,如果你是篮球校队、乒乒球学校冠军、厨艺大赛冠军这些倒是可以写在自己的简历上。

6.简历结构明了,条理清晰

简历结构一定要清晰明了,便于招聘者快速阅读。不过,现在的招聘网站都有标准的模板,应聘者往里填数据即可。

如下是一份比较规范的简历,该学员当时年薪为30万(税前,北京)。 大家可以作为奋斗的参考。当然,写简历简单,掌握简历上的内容难。可以说,简历上的每个字都代表“一段血泪史”。

4.简历的常见错误

“千里之堤,溃于蚁穴”, 简历可以让招聘者对你形成第一印象。如果简历中存在细小的错误,也会被视为不认真的体现,可能会让你失去很多机会。

通常有如下错误:

1.手机号、qq号错误、电子邮箱格式不正确

真的有傻瓜竟然会把自己手机号码写错,或者写了已经停机的旧手机号码。然后,坐等招聘电话。 这些基本联系方式,一定要核准无误。

2.技术词汇拼写错误

这也是常见的错误,技术词汇单词错误、大小写不对等等,这会直接降低你的第一印象。连自己的简历都不认真,还能做什么? 就像出门不洗脸的人,还能期望他做什么?

3.排版混乱

排版必须清晰,大方,结构整齐。

4.抄袭别人的简历

这是对自己和他人最大的不负责任。想找工作连个简历都懒得写,这种态度如何处人处事?面试中,针对简历提出的问题,你如何能回答?

所以,抄简历,一定是死路一条。

5.注册招聘网站和简历投递

简历准备好以后,必须尽快的进入投递环节。不要等待,不要老琢磨“我要把各个环节搞明白再投简历和面试”,这是错误的想法。我们必须在战场中提高自己,实战中提高自己是最快的。

首先,注册著名招聘网站或者地方类招聘网站,并在这些网站上完善简历。智联招聘、51job、中华英才、拉勾网等这些网站是必须要注册的,一个都不能少。如果在地方城市找工作,地方类招聘网站也可以注册,比如:长沙的芙蓉人才网、太原人才网等。

简历投递一般采用海投的方式,并且要隔两三天海投一次。 海投会给企业招聘者带来一定的麻烦,但是对于应聘者是最高效的方式。对于应聘者来说,时间很宝贵。千万不要把时间花在一个个筛选企业上面,对于刚入行的新人,还没有资格筛选企业。至于有善良的应聘者害怕企业的HR麻烦,我只能说: “你想多了”。

一份合格的简历海投完后,你就会接到一些面试电话。下面就应该学习怎么应对面试电话了。

6.接面试电话如何应对

接到面试电话的时候,一些基本的电话礼仪你需要知道。通过如下的场景模拟,让你对接电话后的流程有一个基本的了解。

流程如下:

1. 接听电话第一句通常是: “喂(二声),你好”。

2. 对方通常会说:“我是xxx公司,我们这里收到你的简历。你明天上午10点有时间来我公司面试吗?”

3. 你通常会说:“可以,没有问题。贵公司的地址在哪里?”。注意,如果时间上不允许,比如跟你已经约好的一家公司冲突了。你也可以大方的告诉别人,明天上午有面试了,能不能换一个时间。

4. 对方会说: “我们公司在海淀区xx大厦12层1201”。

5. 你可以说: “那我到了以后,跟您联系吗?您怎么称呼?”

6. 对方会说: “我姓高。到了,你跟前台说找高七七就行”。

7. 如果你对自己查询交通路线不太放心,可以问一下对方,如何到他们公司。如果有信心,就不用问了。

8. 最后,你一定要这样说,“好的。谢谢你。我跟您确认一下。您的公司名字是:xxx公司。明天上午10点,在海淀区xx大厦12层1201。对吗?”

9. 对方回答: “是的。没有问题。还有其他问题吗?”

10.你回答: “没有了。谢谢。我明天准时到贵公司”。

11.对方回答: “好的。再见”。

12.你回答:“OK。再见”。等对方挂掉电话后,你再挂掉电话。即可结束本次电话邀约。通过一次交流,将公司名称、地址、面试时间、联系人问清楚即可。

然后,立刻马上,使用手机或者电脑查询这个公司相关的信息,越详细越好。直到能够回答如下问题为止:

1. 公司发展的历程

2. 公司的产品或者项目(该公司同类型公司的产品和项目,各自的优劣势分析)

3. 公司下一步的发展规划

这些问题,将会让你在后续的面试中获得意向不到的收获。

7.去公司之前的准备

去公司面试前,做到如下五点:

1. 查询和调研该公司的基本情况

2. 个人卫生整洁,着装干净

3. 提前10-15分钟到达,不迟到(万一迟到,一定电话通知对方,告知实情)

4. 将以前面试遇到的问题再预演一遍

5. 将笔试题再复习一遍

8.笔试

去企业笔试,通常都会做一份该企业的笔试题目,作为基本的考核。通常,企业笔试题目都大同小异,都是一些常见工作问题,不会出现偏题难题怪题。如果你之前,已经做过常见笔试题目,绝大部分题目都可以囊括。所以,只要好好准备,笔试不会构成特别大的问题。笔试过后,通常都会带你进入面试环节。面试官通常都是你以后的直接上级,这时候就需要你好好表现了。

四: 面试

1.面试时,为什么没必要紧张?

第一、从心态上你要把这次面试看做一次练习,成败都可。毕竟,说实话,面试成功是小概率事件,按照一个人面试十家公司成功一家来看,每家成功的概率只有10%。所以,完全没有必要紧张。

第二、面试官在跟你交流的时候,并不会将你说的每个字都记在心里。毕竟,他也有工作压力,他可能在想:“下午开会,怎么跟老板交代的问题”。面试官多数时候,是处于一个完全放松的状态,听你回答只是听个流程和大概,并不会全身心投入。所以,你尽可以放轻松的交流。你的若干小问题,对方通常都不会注意到。

第三、面试完你以后,面试官还要再面试N个人。最后留到脑子里的就是你当时表现的打分结果,不会对你们这些应聘者每个都留下特别多的回忆。如果你觉得你说的做的每个细节,面试官都看到了。通常,是你想多了。

第四、失败又有何惧?此地不留爷,自有留爷处!天下公司那么多,只要我多面试,多总结问题。即使只有1%的机会,面试100家不是也能面上吗?

当然,上面是给大家做“失败并不可怕的心态调整”,并不意味着你就可以浪费大把面试机会而不珍惜。

2.面试中的礼仪

面试中,遵循正常的职场礼仪即可。这是“最基本要求”,如果你有任何一点问题,都可以让你的成功率立马降低50%以上。

所以,一定要遵守基本原则:

1. 微笑、礼貌、大方

2. 有正常的交流习惯,没有小动作(抖腿、搓手等)

3. 绝对不能争论

4. 卫生干净,衣冠整洁即可(没必要西装领带)

面试开始时:

1.面试官进入、求职者从座位起立,微笑说:“你好”。

2.如果对方是男士,可以主动伸手握手。如果是女士,不要主动,看对方示意即可。

面试结束时:

1.结束时,一定要对面试官表示感谢。

2.将座位放回原位,帮助收拾一下桌面卫生,所有物品物归原位。

3.常见技术面试场景分析

无论面试官是否是技术人员出身,我们一定要给出充分准备的回答,发音准确的技术名称,不要有所保留,尽可能仔细地回答问题。一定要在面试前,准备本专业至少20个常见的专业技术问题,能对答如流,可以变成自己的话说出来。当然,再完美的准备也会碰到不会的问题,那么如何应对呢?

1. 面试官提出的某个技术,你不会。

第一,绝对不能就说“不会”两个字。太傻,太二,无法继续交流,典型直男癌。

第二,态度上正视差距,如实回答。“这个技术我确实不会。之前的项目没用到,只是用了xxx技术。面试完后,我也想学习一下”。

这样,既说明了实际情况和自己的学习态度,也引向了你会的xxx技术,从而可能会小小的带一波节奏。

2. 你对这个技术有一定的认知,但没有把握。

对策:可以告诉面试官去年项目不太忙的时候,我学习过几天,后来项目忙了就没继续看。然后,简单说说对这个技术的理解。最后,问一下,我们公司是否在使用这个技术?我也正想捡起来再学习一下。

3. 面试官提出尖锐的问题,质疑你的简历或者技术能力。

面试官:“我在你的简历中没有看到对我们有用的项目经验,你的技术能力也不符合我们的要求。”

面试者:“可能是我的经历还是太浅。对咱们公司这块业务确实没涉及过。您这块还有什么技术要求,我可以推荐我的朋友过来试试”。

当碰到直接质疑的情况,面试成功的概率就非常低了。但也不能紧张,天下公司这么多,此处不留人,自有留我处。但要尽量多的跟面试官交流,获得更多的行业知识,为下一次面试做准备。

4. 问到自己特别了解的技术

好吧,发挥吧,少年!还不眉飞色舞好好表现表现。

4.十大非技术面试问题及策略

社会竞争很残酷、面试其实就是一场表演,企业永远喜欢可以随机应变、聪明的求职者。而不喜欢看似老实、实则笨拙不懂变通的求职者。所以,大家也要按套路出牌,出面试官喜欢的牌才能有更多的胜算。

面试官也知道求职者肯定是经过精心准备的表演,但是仍然会认可。如果你连面试都懒得用心准备、你肯定也不会为了工作而用心。这是面试官内在的逻辑。

1.自我介绍

这个问题是面试的时候最常被问到的问题。很多人回答这些问题会陷入一个误区,以为简单介绍一下自己的名字、多少岁、哪里工作过、什么大学什么专业、有什么爱好就好了。如果这样回答,你的自我介绍只能算是30分。

“面试官最想听他想知道的内容”,换位思考一下,假如你是面试官最想知道什么?显然,就是”应聘者能不能胜任现在的岗位”。所以,应聘者应该更多的从这个角度出发思考问题。

所以,我们一般建议应聘者在自我介绍中侧重于自己“实战经验”的介绍。比如:在xxx公司从事过什么工作、做过什么项目、我为什么可以胜任贵公司的岗位。这些才是面试官最想听到的内容。

好的自我介绍应该分如下几个部分:

a.实战经验描述

实战经验可以是在公司的工作经验、实习经验、甚至是参与大学老师的项目都可以。你需要告诉面试官实战经验的公司名称、时间多长、做了什么项目、有什么收获。说到此处,你这个问题就可以拿到60分了。

b.为什么来应聘贵公司

根据自己网上查到的该公司的基本信息,可以说一下对公司的了解情况:看好公司未来发展前景、想进来以后多多学习。说到此处,你这个问题可以拿到80分。

c.我可以胜任贵公司这个岗位的原因

前面两点说完后。结合自己的实战经历和应聘公司的情况,告诉面试官我可以胜任目前的岗位、并且有决心干好。说到此处,你这个问题可以拿到100分。静等面试官欣赏的、色眯眯的眼神吧。

2.你的优点是什么?

优缺点的描述是想看看应聘者对自己的了解程度。求职者关于优点的描述一定要跟工作相关,并且有具体的案例描述你的优点。

面试官通常喜欢具备如下优点的程序猿:

1. 态度好

2. 技术实力强

3. 热爱技术、学习能力强

大家描述的自己的优点可以围绕这三点展开。可以参考:《公司喜欢什么样的程序猿》。

3.你的缺点是什么?

求职者面对这个问题一定要把握一个原则:“缺点不能跟工作相关”。你不能说“我的缺点就是不喜欢技术、不喜欢加班”,那你完蛋了。缺点尽量不跟工作相关。比如:我觉得我的缺点是比较内向、比较宅。周末我可以一个人在家闷头钻研技术、但是就是不想走出去跟别人去玩。这方面我觉得应该改一改。

缺点也不能说的太假。比如:我觉得我的缺点就是工作太拼命了,不注意身体。这么一说,面试官立马就喷了。

4.对我们公司了解吗?

我一直强调,面试前一定要查询该公司相关的信息。所以,这个问题是必须要回答的。如果面试官没问你这个问题。你也要在其他问题中说出你对他们公司的了解。

5.为什么从上一家公司离职?

公司都希望稳定、有培养价值的员工。因此,都会特别关注你的离职理由。离职理由尽量正能量、客观,绝对不能表示对上一家公司和上级的不满。比如:我觉得上一个公司太抠了,加班还没有加班费。好了,你这么负能量的回答,等于判了自己死刑。哪个公司都是抠门的、IT行业加班普遍是没有加班费的。

6.如何看待加班?

面试官问这个问题显然是他们公司经常加班的。如果你确实接受不了也可以说出来。但是,对于刚入行的年轻人一定要了解,加班是非常正常的一件事。

回答这个问题,一定要客观的说。你说你喜欢加班,这有点太扯了。你可以说:“项目紧的时候,加班也很正常。现在行业情况就是这样的,没有问题。而且,我还年轻,能扛的住”。

7.如何看待出差?

出差在有的人眼里看是辛苦,在有的人眼里看是经历。有的年轻人就特喜欢出差,感觉可以去不同的城市、有不同的体验。对于求职者来说,可以根据自己实际情况说出自己的真实感受。如果你确实无法接受、也可以明确拒绝。

8.你的职业规划是什么?

这个问题是想了解求职者的规划能力、对于自己是否有规划?求职者可以根据自己的情况正常的说出自己的职业规划,不能太低人一等、也不能好高骛远。

一般较好的回答如下:

“这三年,我还是想脚踏实地的钻研技术。希望通过三年的努力成为我们这个行业比较牛的人。三年后,我想学着做管理。再用两年时间,一共五年,最终可以独当一面”。

三年钻研技术、显得你很踏实。五年进入管理,这是一个有心人的正常的晋升流程。

9.你对跳槽怎么看?

公司非常不喜欢频繁跳槽的人,所以你对这个问题的回答一定要谨慎对待。

经典回答如下:

“现在这个行业大家都很浮躁,跳槽频繁。但是,我并不喜欢频繁的换环境。我想,我只要在一个公司扎扎实实做下去,不可能没有机会。做好了,薪水不可能比跳槽的低”。

10.你还有什么问题要问我吗?

这是通常面试要结束的时候的问题。求职者一定不能说:“我没有问题”。一下子就把你搞得很low,最后一定要问一个问题问回去,即使面试官没有这个问题。结束时,也一定要问个问题。

求职者也不能太过于急功近利的问:“今天我能面试上吗?你能给我多少钱?”。虽然你很想知道,但这么一问,你的档次立马降低。通常的问题应该是跟工作相关。

技术人员可以这样问:

1. 今天我们聊到的某个技术,我想回去好好研究一下,您这里有什么资料吗?

2. XX新技术,您怎么看他的发展?我想趁这几天时间宽裕,学习一下。

3. XXX技术,我感觉您好像有比较深的研究。我也想学学,您能推荐些资料吗?

类似这样的问题,可以让你喜爱技术的特点,立马暴露的一览无余。本来面试70分的你,立刻加到80分。而你,只是问了个问题而已,回答的竟然是面试官。这么好的无本生意,不做是不是有点可惜?

5.面试后一定要总结

很多人面试后,就开始等公司的消息,焦躁不安,这绝对是错误的做法。面试后,大局已定,战争已经打完了,还需要再纠结吗?我们应该做的事是为下一场面试做准备,立刻做面试的总结,没有总结就没有进步。

必须总结如下内容:

1. 列出问了哪些问题?

2. 列出自己回答较好的问题

3. 列出自己回答交差的问题,并进行改进

心态上不要等待,”谋事在人,成事在天”,成了好,不成也无所谓,就当面试失败了。立刻,投入紧张的复习和下一次面试中。

第三篇:热门专业学习之路

一:JAVA学习知识点明细以及配套视频

这是JAVA工程师的完整学习路径,我们也会公布大部分的学习视频,这些视频来自于我们的线下培训课程,大多数直接录制于课堂,欢迎大家下载或者在线观看。

我们每个月都会更新相应的视频,大家可以持续关注下载地址:

http://www.bjsxt.com/javashipin.html (java视频的拼音,方便记忆)

1.JAVASE

首先要学JavaSE,这是毋庸置疑的。与此同时,和JavaSE的学习同步,建议大家研究一下数据结构与算法。

在JavaSE完成之后,可以试着完成一些小项目,同时关注一下设计模式的内容,不必强求自己能够完全掌握各种细节,往前走吧。

掌握一种编程工具,比如说Eclipse。当然,工具掌握很简单,大约只需要30分钟。

建议大家读北京尚学堂的《实战JAVA程序设计》,同时可以配合《java300集视频教程》(好吧,书是我写的,视频也是我录的。个人认为还是很不错的)。这里有JAVASE讲解、有项目实战、有数据结构、有算法、有JDK源码解读、有底层内存分析、有设计模式,从一开始就植入了“高手思维和高手习惯”, 可以说是非常适合大学生和入门学习的人使用。

学习列表和学习说明如下:

  • 知识块
  • 1.JAVA入门
  • 2.面向对象基础
  • 3.飞机小项目(前两个阶段练习)
  • 4.面向对象深入
  • 5.常用类
  • 6.异常机制
  • 7.容器和数据结构
  • 8.IO流技术
  • 9.多线程
  • 10.网络编程
  • 11.手写服务器(java基础集大成者)
  • 12.注解、反射机制、字节码
  • 13.GOF23种设计模式
  • 14.正则表达式和文本操作
  • 15.JDBC数据库操作(可在学完数据库后学习)
  • 16.手写SORM框架(学有余力的同学学习)

对于基础的同学,建议大家学习一下预科阶段(大约2小时)。对于整个行业、JAVA技术体系、就业流程、职业发展都会有个基本的认识和了解。

2.数据库

数据库是程序员必学的技术,大家可以选择Oracle或者MySQL开始。学数据库时,重点掌握SQL语言、熟悉各种查询、数据库设计范式。这也是以后工作中常用、面试和笔试中常考的内容

再学习JDBC技术,这样就可以用Java操作数据库了。

大家可以按照如下顺序学习:

  • 知识块
  • 1.Oracle数据库安装和配置、客户端使用
  • 2.Mysql数据库的安装和配置、客户端使用
  • 3.SQL语言
  • 4.SQL语言强化(查询深入)
  • 5.数据库设计范式
  • 6.项目数据库表设计核心
  • 7.PL/SQL

3.网页设计和开发

互联网时代,不学习网页知识的程序员不是好司机。HTML、CSS、JavaScript、ajax,这些东西是做web项目必需内容。当然,作为java程序员不需要学的很深入,熟悉即可。毕竟,前端工程师也是一个需要学习4-5个月的专门岗位。

4.Servlet/ JSP和企业级项目开发

Servlet/JSP是JAVAEE的核心内容,必须作为重点掌握。学完基本知识后,做一些项目吧。比如:BBS、留言系统、学籍管理、商城、客户关系管理等。刚开始找一些业务逻辑比较简单的做一做。只有通过开发项目、调试项目才能真正的掌握学到的知识,真正的开启自己的“JAVA腾飞之路”。

5.SSM框架(Spring、Spring MVC、Mybatis)

Spring 是java程序员必须掌握的一个框架,已经形成了事实上的行业标准。 刚开始学习一下“IOC + AOP”。 依赖注入 + 面向切面,嗯,完善的旅程

Spring MVC是典型的MVC框架,企业非常流行。已经超过struts2成为行业第一。

Mybatis是经典的ORM框架,让我们可以用面向对象的方式从容操作数据库。已经超过Hibernate成为第一的ORM框架。

学完三个经典框架后,整合他们吧。然后,开始做一些商业项目加深自己的功力。这里可以找一些相对复杂的商业项目,加上复杂的业务逻辑。这样,才能在你的简历中加入浓重的一笔。

6.各种JAVA新技术和大型项目的整合

其他一些工作中可能会用到的技术,也需要大家学习: Maven、Shiro、Nginx、Lucene、Solr、Redis、Dubbo、Zookeeper 等。

这些技术的学习,不需要特别深入,毕竟一个企业并不是使用所有的技术。但是,为了搭建“java技术体系”,必须学习这些内容。这样,你就形成了完完整整的“系统”。工作中,就可以从容应对各种各样的问题。

记住:搭建体系,要比钻研某个知识点的细节重要的多。不要因为某个细节而耽误搭建体系!不要因为看不懂某个单词就停止阅读整篇文章!

7.微服务架构

企业和服务提供商正在寻找更好的方法将应用程序部署在云环境中,微服务被认为是未来的方向。通过将应用和服务分解成更小的、松散耦合的组件,它们可以更加容易升级和扩展。

目前,越来越流行的微服务技术是需要大家重视的。SpringBoot、SpringData、Springcloud相关的技能已经成为JAVA程序员必备的技能了。在后面的面试中也越来越重要,企业用的也越来越多。

8.一定要做一个大项目!

学了这么多,也做了一些小项目。最后,一定要做一个大的项目整合一下自己的所学。就像高考时候的综合题一样,这才是拉开差距的关键。

经历一个大项目的锤炼,就能“百炼成钢”。可以将几个月所有的知识成体系的应用起来,这是成为“高手”的起步!也是你腾飞的起点。

二:JAVA基础如何学习,才能又快又稳?

学java编程,一般有两种情况。一种是已经掌握了其他语言,那学习java比较简单,语言只是工具,编程能力才是根本。另一种是基础,对于编程未入门或者懵懵懂懂。本文针对第二种情况。

作为初学者,在一开始学习就要培养良好的习惯和思维方式。因此,在入门的时候除了学着写代码,更重要的是这种习惯的培养。

企业要求:程序员既有实战技能可以快速上手,也内功扎实熟悉底层原理后劲十足。因此,在笔试和面试考察时候也是结合 “底层原理、数据结构、实战应用、设计思维” 四方面进行考察。

因此,作为初学者,需要掌握下面五个核心:

1.JAVA本身内容的应用。比如:一些类的字面用法。

2.需要掌握面向对象的思维模式。

3.掌握程序基于内存底层的运行方式。这可以让你对于编程理解的更加深刻。

4.掌握基本的数据结构和算法。

5.开始会写项目,将学到的知识融会贯通。

所以我们可以根据上面的理论,开始JAVA基础课程的学习了。

第一步:学习JAVA的开发环境配置、开发第一个Java程序。也建议大家开始使用eclipse等IDE,不必纠结是不是一定要从记事本开始。

第二步:学习数据类型、运算符、变量。这是编程的基础,是程序的“砖块”。这些内容大多数编程语言都有,而且非常类似。

第三步:学习控制语句。这是编程的基础,是程序的“混凝土”。有了控制语句+变量,理论上你就可以写任意的程序了。因此,这是进入程序的门槛,需要大量的练习。

第四步:学习面向对象基础。通过类、对象、包等基本概念讲解。学习的时候,一定要在此处介入内存分析,这样可以对于对象等知识有非常深刻的理解。

第五步:继续面向对象,主要包含三大特征:继承、封装,以及接口、抽象类、内部类等概念。这些概念需要掌握。但是对于初学者来说,先熟悉语法。通过后面的学习再深入。不要期待初学时候就能深刻领会这些概念。

第六步:异常机制。Java程序的安全需要异常机制,这是必学内容。当然,也非常简单。学习过程中,先不要揪着什么自定义异常不放,学会基本用法即可。

第七步:数组和算法。学习数组时,注重结合循环管理数组。也要从底层内存理解数组,这既是学数组也是复习面向对象;再结合一些算法,比如排序和搜索算法,既练习数组的用法,也学习了算法知识,为应对企业笔试和面试做好准备。

第八步:常用类和JDK源码阅读。学习常用类的用法:包装类、字符串相关类、实践类、Math类、File类等。学习过程中,只学怎么用这些API就及格了。要优秀,要培养高手思维,一定要结合JDK源码,一开始就培养阅读源码的习惯(虽然,可能大多数看不懂)。

第九步:容器和数据结构。容器有:List、Set、Map。学习这三种容器用法只需要一两个小时。但,此时你要结合数据结构,再结合JDK源码讲解。这就是“高手习惯”,让大家既学习容器,也学习了数据结构,打深了内功,应对企业面试绰绰有余。

第十步:IO流技术。学会各种常用流即可,掌握一些工具类的用法,比如:Apache IOUtil这样会让你在以后使用时效率大增。

第十一步:多线程技术。这也是笔试和面试中常见的内容。我们要学习多线程基本使用、生命周期、状态转化。如果学有余力,学习一下生产者消费者模式,让你一开始就具备架构的思维;既然学,就按照“高标准”要求自己。

第十二步:网络编程。工作中直接用到的不多,而且socket编程范式差不多,了解即可。毕竟直接让你编写基于socket底层代码的情况比较少见。

第十三步:做个项目吧。 学了这么多,不做个东西怎么对得起自己?不管是小游戏项目也好,还是基于swing的项目,还是其他控制台项目。

大家也可以下载我录制的《尚学堂JAVA300集视频教程》,已经上百万人在学习了。基本上贯穿了我上面的思想,有知识、有底层、有数据结构、有算法、还有项目,从一开始就培养你的“高手思维”。

三:Python学习知识点以及配套视频

这是Python工程师的完整学习路径,我们会公布大部分的学习视频,这些视频来自于我们线下培训课程,大多数直接录制于课堂,欢迎大家免费下载或者在线观看。

我们每个月都会更新相应的视频,大家可以持续关注下载地址:

http://www.bjsxt.com/pythonshipin.html (python视频的拼音)

1.Python基础

“人生苦短,我用Python”, 随着人工智能的发展,Python无疑是现在热度最高的语言。从“小白”到成为一个合格的Python程序员首先要先迈过Python基础这个门槛。

第一步:需要学习编程最基本的知识:变量、数据类型、控制语句、容器、函数和文件操作。同时,我们也深入数组结构的组织,打扎实大家的基本功。

第二步:学习python的面向对象机制,并学习一些常用的设计模式,这些都是成为Python编程高手必经的磨练。并通过一个项目实际体会面向对象开发的优势。

第三步:还需要了解python是如何管理内存的以及很多高级特性;学习内存管理会让我们更深入掌握python的运行机制; 很多函数式编程的特性,比如闭包、装饰器和生成器,这些都是一些比较难掌握的概念,但面试和工作中会经常遇到,所以大家也必须掌握。

第四步: 网络编程中的高并发问题是大型互联网企业必须面对的核心问题,解决高并发可以用多进程、多线程,python中还有协程。高并发和网络是相关的,最后我们会利用学到的并发编程的知识来编写不同的服务器模型。

上面四大块学习完后,你已经具备了比较强的python基础,但是离工作要求还有差距。还需要继续学习其他内容。

2.Linux环境编程基础

现在企业中不管是Web项目,还是数据库,以及部署的爬虫,更不要说大数据处理,甚至是人工智能,绝大多数都运行在Linux系统内,所以打好一个Linux基础可谓是必备技能。

我们将学习如何在虚拟机中安装Linux系统,在Linux系统中安装各种常用的软件。学习如何配置Linux系统的网络。学习使用Linux系统的常用基本命令。最后成为一个Linux系统的熟练管理员。

当然,我们的目标是会用Linux,熟悉相关常用命令即可。不需要掌握很多运维方面的知识,毕竟运维也是一个专业的岗位。

3.数据库编程基础

任何企业级项目都离不开数据库,数据库知识是程序员的必备技能。大家主要学习现在各大互联网公司最常用的数据库:Mysql

当然,不管学习哪一个数据库。SQL语言是必须要深入掌握的,包含:数据库设计思想、三大范式以及SQL语言实现增、删、改、查最基本的操作。然后,也需要掌握Mysql一些基本的操作。

4.网页编程基础

目前软件行业大多数的项目都是基于B/S架构,即在浏览器端实现效果展示。网页编程也是每个程序员必懂的技能

本阶段课程主要讲解Web开发的三大基础:HTML5、CSS3和JavaScript语言,并学习前端项目中经常使用的Jquery和Ajax。

对于python程序员来说,不需要像前端程序员那样精通这部分内容,但是也需要做到熟悉。

5.Django Web开发框架

python也越来越多的被用在开发WEB应用上,这得益于Django这个强大的WEB框架。

学习Django的使用,要深入了解Django中MVT的开发模式,掌握模型的设计、视图路由的设置和模板。并在最后带领大家用Django开发一个博客项目,贯穿所有Django的常用特性。

python在WEB应用开发方向的需求在近段时间逐步增长, 薪水范围在10k-25k之间,是大家学完python后的一个重要就业方向。

6.做一个项目

学完Django,必须做一个项目。将前面学习的Python基础、数据库、网页开发等等技能整合起来,这样才能学以致用。让自己快速成长起来。

7.Tornado 异步编程框架

Tornado也是一个常用的python WEB开发框架,但Tornado更强大的地方是它的异步IO处理能力。在真正的项目中,经常会混合使用Django和Torndao这两大框架,充分利用Django的方便快捷和Tornado的高负载来解决项目中的实际问题。

8.Python爬虫开发

由于近年大数据分析、人工智能都需要大量的数据做支持,所以爬虫工程师的需求量也越来越多,有经验的爬虫工程师经常能拿到15k-25k的工资,有兴趣的同学可以向这个方向发展。

首先,大家要理解网络爬虫编写的基本套路,了解网络爬虫编写的各种坑,能够应对一些常用的反爬虫技术,能够应对动态网站爬取,能够应对带有验证码的网站。我们还要学习一些做爬虫的常用框架:request,bs4,scrapy等。并利用scrapy结合redis实现分布式爬虫的开发。

学习了这些技术,我们就可以在互联网的汪洋大海中获取到任何想要的数据。

四:人工智能学习知识点和配套视频

人工智能成为了IT行业未来几十年极其重要的学科。尚学堂·百战程序员开设了完整的人工智能课程,由从欧美留学归国的陈博老师领衔主讲。

为了让更多人受益, 我们会陆续公布大部分的学习视频,这些视频来自于我们线下培训精品课程,大多数直接录制于课堂,欢迎大家免费下载或者在线观看。

我们每个月都会更新相应的视频,大家可以关注下载地址(人工智能视频的拼音):

http://www.bjsxt.com/rengongzhinengshipin.html

1. 机器学习

首先要学习机器学习算法,这是人工智能的核心,也是重中之重。

在学习机器学习算法理论同时,建议大家使用scikit-learn这个python机器学习的库,试着完成一些小项目。同时关注一下能否各种算法结合使用来提高预测结果准确率。在学习的过程中不必强求自己能够完全掌握各种算法推导,抓住重点理解算法,然后把算法用起来才是王道。

掌握一种编程工具,比如说PyCharm或者Jupyter Notebook,当然工具掌握不难,大约只需要30分钟。

建议大家不要盲目的去看各种市面上的书籍和博客,有的对于大家来说过于理论,推导太多还有些跳步显得过于深奥,有的又太浮于表面了不涉及算法原理细节,还是以北京尚学堂的视频作为学习材料,这里有算法的理解,算法的推导,算法的应用,非常适合大学生和入门学习的人使用,从一开始就即有算法的逐步深入,又有算法的实战。给自己成为一个数据挖掘工程师,算法工程师打好基础。

上面提到的机器学习算法譬如有监督学习回归算法中多元线性回归,Lasso回归,岭回归。分类算法中逻辑回归,支持向量机,决策树,随机森林,GBDT,Adaboost,XGBOOST。无监督学习聚类算法中K均值聚类,密度聚类,谱聚类。降维算法中PCA降维,FM因式分解,SVD奇异值分解。推荐算法中协调过滤,ALS交替最小二乘。还有机器学习里面的大招多层感知机,神经网络。关联分析的算法Apriori,FP-Growth。最后研究朴素贝叶斯,贝叶斯网络,隐含马尔科夫模型,条件随机场。

对于人工智能专业不了解的同学,建议大家学习一下预科阶段,对于整个行业,技术体系,就业方向,未来职业发展都会有个基本的认识和了解。

2.深度学习

深度学习是当今非常热门的一个领域,是机器学习算法神经网络的延申,是把机器学习的拟人更加发扬光大的领域。深度学习工程师也是各大公司需要的人才。

学习深度学习可以从Google开源的tensorflow框架开始学习如何完成DNN(深度神经网络)的构建以及应用。然后还是使用tensorflow框架来学习如何完成CNN(卷积神经网络)的构建以及应用。最后来使用tensorflow框架来学习如何完成RNN(循环神经网络)的构建以及应用。

学习建议:大家在学习过程中可以试着利用构建的DNN来完成机器学习算法做的分类和回归的案例,对比看看结果是否有提升,从而体会深度学习的奥妙。也可以利用CNN来完成一些图像识别任务,和利用RNN来完成一些NLP(自然语言处理)任务。CNN和RNN不仅限于这两个领域,但是目前来看它们在这两个领域各有优势。

Tensorflow框架是深度学习框架之一,但不是唯一,Keras框架也是一个非常优秀的框架,大家有兴趣也可继续学习Keras框架。代码量会比TensorFlow更少一些,更适合去做一些实验。

3.Python数据分析模块

Python当今作为数据科学的第一语言,熟练掌握numpy、scipy、pandas、matplotlib等数据分析的模块不光是作为数据分析师必须的,也是作为人工智能工程师所必须的, 如果大家认为自己的python语言掌握的不够熟练,可以从学习这些基础的模块开始,来锻炼自己。因为scikit-learn机器学习算法库是基于numpy、scipy、matplotlib开发的,所以大家掌握好了这些基础库,对于分析别人封装的算法源代码,甚至日后自己开发一些算法也有了可能性。

学习建议:在学习这些数据分析模块的同时,可以补补python语言的基础语法,重复一遍基础语法即可,不要跑偏到python其他比如什么web开发,爬虫等领域里面去。

4.Spark MLlib机器学习库

如果说当今有什么是算法工程师的加分项,那么分布式计算框架Spark中算法库MLlib就是一个,如果想掌握Spark MLlib,首先需要会使用spark计算框架,建议大家还是使用python语言通过pyspark来学习,在掌握了前面的机器学习部分后,这里再来学习里面的算法使用将变得异常容易。

学习建议:大家要抓住重点,千万不要钻到集群搭建里面,甚至是大数据各种框架里面,因为对于我们来说,spark计算框架只是一个工具,帮助我们来更好的做数据预处理,和帮助我们将算法使用分布式集群来完成海量数据场景下结果的计算。在公司里面,有运维的人员管理集群,在一些大公司,有专门给算法工程师配备数据预处理的工程师。

5.做一个人工智能项目

学了这么多,也做了一些小项目,最后一定要做一些个大项目整合一下自己的知识。做一些个人工智能领域的譬如医疗图像识别、人脸识别、自动聊天机器人、推荐系统、用户画像等的大项目才是企业很需要的经验。可以将理论结合实际的运用也是成为高手的必经之路,也是在企业工作所需要的能力。

6.数学

数学是一个误区,很多人说自己的数学不够好,是不是做不了算法工程师?面对这样的问题,公司里面的算法工程师谁又敢说自己的数学真的好?数学是在学习机器学习阶段算法推导用的到的,但是这里的推导你又不需要非要一步步扣数学计算过程,举个例子,2+2=4,那么数据基础是1+1=2,但是咱们需要证明1+1=2吗?不需要,对吧,所以在机器学习阶段算法推导这里更重要的还是理解算法证明的思想,能够把讲的算法推导理清楚足够了,而这在讲的过程中如何有好的引导,又何须非自己没头绪的补数学然后走那个弯路呢?

学习建议:很多数学符号只是一种表达而已,在学习过程中稍微补一下即可,不需要花大量时间前期准备数学知识,最重要的是,企业中人工智能工程师没人天天抱着数学公式推导。所以同学们在大学期间数学学的不错的同学恭喜你,你在机器学习算法学习时会稍微轻松一些,相反,在大学期间数学学的不行的同学也恭喜你,因为数学不是决定能否成为一个企业所需算法工程师的鸿沟!

五:H5前端和移动APP开发知识点和配套视频

随着互联网、移动互联网的发展,HTML5成为了客户端软件开发的主流技术,HTML5实际上是由:HTML5语言、CSS3、JAVASCRIPT语言组成。

尚学堂的HTML5前端课程由国内知名技术专家刘兴宇老师领衔,已经培训就业数千人,取得了非常好的社会影响。

为了让更多人受益, 我们会陆续公布大部分的学习视频,这些视频来自于我们线下培训精品课程,大多数直接录制于课堂,欢迎大家免费下载或者在线观看。

我们每个月都会更新相应的视频,大家可以持续关注下载地址(前端视频的拼音):

http://www.bjsxt.com/qianduanshipin.html

1.WEB前端快速入门

在本阶段,我们需要掌握HTML与CSS基础,当然,也包含H5和C3的新特性。这个部分内容非常简单,而且非常容易掌握。相信你也更愿意学习这个部分,毕竟他可以让你最直观的感受到前端的魅力。为了锻炼大家写代码,可以根据你喜欢的站点去实现效果。

这一阶段是非常重要的基础阶段,所谓基础就是可能这个阶段我们的学习的内容,可以让我们开发出来绚丽网站站点,但是功能丰富却暂时做不到。 为了完成更绚丽的站点,我们需要掌握常见特效的实现,利用css3和h5的新特性实现动画,布局,雪碧图,滑动门,tab切换等特效。并且掌握基础的站点优化内容。例如sprite等。虽然我们还不能完成更多交互内容,但是我们会学习到很多的知识模型和理论,而这些知识模型和理论是我们后期工作和学习的基石。扎实的基础有了,我们才能走的更稳更快。

注:本阶段不涉及到编程,主要是熟悉HTML5各种标签用法、CSS3各种属性的用法。

2.JavaScript基础与深入解析

JavaScript语言非常重要,可以说学习前端本质就是学习“JavaScript”编程。后面学的很多高级技术,全部都是基于JavaScript的。

JavaScript语言可以让网页元素具备动态效果,让体验度更加流畅。这在目前流行的B/S架构体系下,是极端重要的事情。这也是为什么前端工程师大行其道,被广泛需求的根本原因。

在本阶段中,我们主要学习基础JavaScript语法与深入解析JavaScript,包含DOM操作同时也涵盖了面向对象和设计模式,课程也涵盖了兼容性处理和数据解析。希望大家在本阶段可以熟练掌握这些知识点。

3.jQuery应用与项目开发

jQuery是一个快速、简洁的JavaScript框架,jQuery设计的宗旨是“write Less,Do More”,即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作、事件处理、动画设计和Ajax交互。在本阶段,我们注重讲解如何更好的应用jQuery以及他的设计方式,同时也包含jQuery扩展内容。

4.PHP、数据库编程与设计

后端服务器工程师需要了解前端的基本知识,同样,前端工程师也必须了解服务器端编程的基本内容。我们可以不精通,但必须知道整体的流程。

作为一名前端开发工程师,会一门后端语言是必然的。在我们的课程中,为您选择的是PHP,因为PHP环境搭建简单,语言与JavaScript相似性比较大,并且容易上手,连接数据库也非常方便。希望本阶段的内容能帮助你快速掌握前后端交互数据。

通过学习PHP,前端工程师也能称为“全栈工程师”。既能做前端开发,也能做后端服务器开发。

5. Http服务于Ajax编程

Ajax真的是一个非常古老的技术了,但是到现在为止,这门技术仍然被大量使用,可以看出来,他是多么的优秀。在本阶段,我们将带你了解Ajax,并且掌握它的应用。也包含了解Http相关的知识。对于站点来说,除了页面效果能看到的就是数据了。所以,数据的获取合理适配尤为重要。与Ajax相关的也包含跨域处理,希望大家可以掌握这些核心知识点。

6. 做一个阶段项目

本阶段为纯项目实战,可以将前面学到的知识融会贯通,不实战就相当于没有学习;主要练习网络请求、站点布局、网站优化等内容,同时我们需要对项目有一定的而了解。 所以,在老师的带领下,可以更快的了解项目如何搭建,如何更优雅的实现代码。老师会将整个项目的开发流程完整的罗列出来。本阶段也锻炼BootStrap的应用,也包含一些常用的第三方插件。在实战中展示具体应用。

7. H5新特性与移动端开发

H5新特性在现在来说已经不再是新内容了,项目中随处可见,毕竟移动端不会存在兼容性问题,而且这些新特性在移动端的体现也是非常好的。例如定位,语义化等。利用Canvas实现更多的效果等。

在移动端中,我们主要注重移动端布局和资源加载,布局方向,我们主要讲解百分比、flex、REM、栅格系统来实现。资源加载采用(SPA)单页面加载,也是目前比较火的形式。在页面跳转时可以非常节省资源。混合开发也同样是移动端的一大特点,在我们的课程中都会详细讲解。

8.高级框架

随着项目的需求越来越多。传统的开发方式已经不能满足我们的需求了,所以我们需要更多的支持。在本阶段中,我们讲解模块化,将程序分解为模块化开发。我们需要Nodejs做支撑,无论是作为构建工具中的服务器存在,还是为我们提供数据模拟测试,都是必不可少的。

随着ES5开发者体会在开发中的难言之隐,ES6的到来解决了各种头痛的问题。也是我们必须要掌握的一个重点。还有更多,例如多人协同开发(git或者svn),利用Less和Sass完成更好的CSS的编写

接下来我们介绍一下目前前端三大框架:

Angular:Angular是一个开发平台,他能帮我们轻松的构建Web应用,我们将在这部分课程中讲解Angular的声明式模板,依赖注入,端到端的工具和一些最佳实践于一身。我们通过完整项目配合实例讲解课程,以便于大家更容易去理解Angular的应用。

React:作为前端三大框架之一,React拥有声明式和组件化两大特点,React可以轻松创建交互式用户界面。为应用程序中的每个状态设计简单的视图,当数据更改时,React将高效地更新和正确的渲染组件。声明式视图使您的代码更具可预测性,更易于调试。创建好拥有各自State(状态) 的组件,再将其组合构成更加复杂的UI界面。由于组件逻辑是用JavaScript而不是模板编写的,因此可以通过应用程序轻松传递丰富的数据,并将State(状态) 保留在DOM之外。我们将会从零开发讲解,讲解过程中个,我们也带领大家从环境的构建开始学习,这样可以让你更好更快的对接企业级项目的环境架构。

VUE:在借鉴了Angular和React两个优秀框架的基础上,Vue无疑是非常受欢迎的,它使用简单,强大的生态系统,高效的运行速度也是我们在开发中的选择之一。Vue是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue被设计为可以自底向上逐层应用。Vue的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。

另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue也完全能够为复杂的单页应用提供驱动。在学习真个Vue的过程中,我们会通过两个企业级项目来讲解他的使用,以便于大家更好的掌握使用Vue熟练开发。

9.微信小程序

作为微信推出的一种新的项目展示形式,微信小程序必然是非常受到人们重视的,而且,目前为止,大部分推广为主的公司都存在了微信小程序,也催生了一个岗位,微信小程序开发工程师。可想而知,微信小程序是非常火的。我们课程是在小程序正式发布后就已经加入到课程了,通过近1年的实战演练,在我们的课程中,通过项目直接入手,在项目中掌握API知识点的应用。这样可以更快适应项目开发。

六:大数据和云计算学习知识点和配套视频

IT时代,最重要的特征就是:“数据越来越多”。每天产生的数据源源不断,成为了现代社会的“石油”。大数据的存储、分析都成了非常重要的技术。

尚学堂从2014年国内第一批开设大数据专业,由国内知名专家夏中云、肖斌、周智雷创建。我们培训的大数据学员绝大多数成为了目前各大数据企业的骨干,深刻的影响了国内大数据行业。

为了让更多人受益, 我们会陆续公布大部分的大数据课程视频,这些视频来自于我们线下培训精品课程,大多数直接录制于课堂,欢迎大家免费下载或者在线观看。

我们每个月都会更新相应的视频,大家可以持续关注下载地址(大数据视频的拼音):

http://www.bjsxt.com/dashujushipin.html

1.大数据学习之前“必看”

大数据是现在这个时代非常流行的概念,并且随着人工智能的崛起,大数据也越来越有价值。人工智能算法其实在三十年前就有了,但是没有用。原因是:第一、计算机不够快;第二、数据量不够大,训练出来的模型太差。

IT时代,其实也是大数据时代。我们产生的数据越来越多,这些数据反过来就像“石油”一样,为我们提供了进一步的价值。人工智能等算法就像“吞食数据的怪兽”,数据越多人工智能也越强大。

因此,在学习大数据之前,一定要先搞明白几个问题:

1.什么大数据?

2.什么是云计算?

3.什么是数据挖掘?

4.什么是人工智能?

5.什么条件才能学习大数据?

了解之后你才能有的放矢,以及想一想自己是否适合学习。同时,也至少不会被人骗,因为了解这些问题之后,一看课程大纲里面有“遥控机器人技术,android技术”等。这些技术肯定和大数据是没有关系的。

由于篇幅的问题,这个几个问题的解答已经录制成一套视频。视频列表如下:

  • 知识块
  • 1、什么大数据?
  • 2、什么是人工智能?
  • 3、什么是机器学习和深度学习?
  • 4、数据挖掘到底挖什么?
  • 5、大数据技术体系介绍
  • 6、基础可以学习大数据吗?
  • 7、大数据工作职务多吗?薪水怎么样?
  • 8、大数据简历怎么写?
  • 9、大数据的学习方法
  • 10、哪些技术才是大数据的重点内容?

建议:在学习大数据之前最好花2个小时,认真看一下,所有人都能看懂。就算不想学习大数据,也可以增加大家的知识面。

2.Hadoop框架

Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供了存储,则MapReduce为海量的数据提供了计算。

HDFS是一个高度容错性的系统,适合部署在廉价的机器上。HDFS能提供高吞吐量的数据访问,非常适合大规模数据集上的程序计算。HDFS技术是整个大数据的“入门”。只要从事大数据方面工作的程序员,不管你后面用什么样的分析技术都必须要学会HDFS。

MapReduce是用于大规模数据集(大于1TB)的并行运算。它极大地方便了编程人员在不会分布式并行编程的情况下,将自己的程序运行在分布式系统上。因为只有分布式计算才能解决“海量数据”的分析问题。

学好HDFS,就能知道为什么它可以存储海量数据,知道“百度网盘”本身是什么?能否自己也能实现一个网盘。让大家一开始就进入大数据实战状态。

Hadoop是大数据中必学的一个技术,也是大数据职位要求必有的一个技术。Hadoop也是后面其他技术的基础,学好了Hadoop才能更好的学好Hive,Hbase,Spark,Storm等。

3.数据仓库技术

大数据的数据仓库技术主要包括:Hive,Hbase,Sqoop,Flume等。其中Hive在企业中使用最为广泛。对于同学们来说,Hive最容易入门,因为不用写代码;只需要有sql基础就能很好的学习Hive。

Hbase是一个分布式、列式数据库。它解决的问题是:在海量数据的情况下还能做到秒级的增、删、改、查操作。

4.Spark内存计算框架

Spark是当前最为流行的基于内存计算的分布式框架,在Spark的生态圈中的框架几乎能够解决所有的大数据的应用场景,如果基于内存计算,计算速度比Hadoop生态圈中的MapReduce快100倍,如果是基于磁盘的计算,那么速度快10倍以上,所以Spark是当前大数据开发人员必备的。

Spark是有Scala语言开发的,包括:Spark-Core(离线计算)、Spark-SQL、Spark-Streaming(流式计算)、Spark-MLlib(机器学习)。

Spark是整个大数据技术中的“重中之重”。因为在面试过程中,笔试题和面试题有60%的可能性会涉及到Spark知识点。所以,Spark的学习要求是:了解Spark源码,能够优化Spark、能够用Java,Scala,Python三种计算机语言开发任何的Spark程序。

5.机器学习和数据挖掘

机器学习(Machine Learning, ML)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。它是人工智能的核心,是使计算机具有智能的根本途径,其应用遍及人工智能的各个领域。

在公司项目应用过程中,重点强调的分布式的机器学习,因为基于海量的数据必须采用分布式的机器学习库。否则根本就是“扯淡”。所以根据企业的需求,同学们也要分辨出哪些是分布式的机器学习库,比如:M ahout,Spark-Mllib等。

6.Storm流式计算框架

目前有两种比较流行的计算方式:离线计算和流式计算。

流计算方式:它可以很好地对大规模流动数据在不断变化的运动过程中实时地进行分析,捕捉到可能有用的信息,并把结果发送到下一计算节点。

Storm是流式计算中的技术之一,Storm集群由一个主节点和多个工作节点组成。主节点运行了一个名为“Nimbus”的守护进程,用于分配代码、布置任务及故障检测。每个工作节 点都运行了一个名为“Supervisor”的守护进程,用于监听工作,开始并终止工作进程。Nimbus和Supervisor都能快速失败,而且是无 状态的,这样一来它们就变得十分健壮。

一般来说只要用到了流式计算,还得用到Kafka。所以大数据里面需要掌握一套Kafka+Storm流式解决方案。

7.云计算之Openstack和docker

云计算从服务角度分为三层:

同学们需要重点掌握:Iaas层的云计算技术。目前比较流行的云平台都是基于Iaas层的云计算,包括:阿里云(https://www.aliyun.com/)、腾讯云、百度云等。 而Openstack 和Docker就是属于Iaas层的云计算技术。

Openstack和Docker在找工作的过程中,对应的职位比较少,但是有很好的发展前景。建议大家先在入个门。等工作之后或者有剩余的时间再深入研究。

8.做一个大数据项目

“实战学习,最重要的就是参与项目”。大数据的技术学完之后,需要参与一个企业级的大项目,这样才能真正的出山,拿到高薪、获得更多的好机会。

七:区块链学习知识点和配套视频

区块链已经成为近年非常热门的技术,并且正在飞速的发展。各大公司都成立了区块链相关部门, 大量职位空缺等待区块链专业人才加入,而目前区块链专业人才少之又少,所以抓住机会就是成功了一大步。

区块链中涉及的面比较广,技术又相对”底层”,学好区块链后我们可以很快学习其他方向,因为区块链可以给学习者打下很牢固的基础。

在尚学堂的区块链课程中,囊括了目前企业绝大多数区块链相关知识,又配套大量企业级项目,可以说是广且深。

区块链课程适用于各种人群,即使是行业小白,也可以在由浅入深的课程中逐渐学会区块链。技术不是遥不可及的,都是扎扎实实学出来的。不要对某个技术有过度崇拜的冲动,一层窗户纸而已,大胆捅破它。

我们将公布区块链课程中的大部分视频,大家可以通过下面网址免费下载或者在线观看:

http://www.bjsxt.com/qukuanlianshipin.html (区块链视频的拼音)

1.区块链行业介绍

本阶段主要是为了让学习者对区块链有总体的认识,从宏观角度阐述了区块链相关内容.本阶段是一个纯理论阶段,不需要编程, 所以学习本阶段重点在听而不是写。区块链也将作为像人工智能那样的一个基础技术,改造现在的很多行业。让很多行业去中心化,极大的提升行业效率。

2.Golang从入门到高级

本阶段主要是为了让学习者对区块链有总体的认识,从宏观角度阐述了区块链相关内容.本阶段是一个纯理论阶段,不需要编程, 所以学习本阶段重点在听而不是写。区块链也将作为像人工智能那样的一个基础技术,改造现在的很多行业。让很多行业去中心化,极大的提升行业效率

3.数据库操作和Golang Web

Go语言可以当作服务端语言,使用Go语言可以完成Web项目开发。本阶段需要Go语言的数据库操作和网络操作,其中数据库操作是以MySQL举例。学习完本阶段后就可以使用Go开发项目了。如果以后是找Go语言相关工作,这阶段也很重要。

4. Golang 实战项目

在学习完前几个阶段后,本阶段是要对前面几个阶段的实际应用。单独学习每个语法可能都不难,但是要把学习的内容融入到实际项目中就需要一个转化的过程。这个阶段重点在敲代码, 一定要按照视频中顺序把每个功能都认真完成。

密码学

密码学是区块链中几个核心部分之一,是实现数据按照的重要手段。在本阶段中介绍了大部分区块链成名项目中应用频率比较高的密码学知识。每个密码学都有单独的讲解,这部分要重点学习,是后面学习比特币、以太坊、超级账本源码的基础。

6. 共识算法

所谓“共识机制”,是通过特殊节点的投票,在很短的时间内完成对交易的验证和确认;对一笔交易,如果利益不相干的若干个节点能够达成共识,我们就可以认为全网对此也能够达成共识。再通俗一点来讲,如果中国一名微博大V、美国一名虚拟币玩家、一名非洲留学生和一名欧洲旅行者互不相识,但他们都一致认为你是个好人,那么基本上就可以断定你这人还不坏。

区块链作为一种按时间顺序存储数据的数据结构,可支持不同的共识机制。共识机制是区块链技术的重要组件。

共识算法和密码学都是区块链核心部分, 学习完共识后就可以准备开始学习具体的区块链项目了。

7. Solidity

Solidity是以太坊中专门描述智能合约的语言,学习Solidity的同时也在讲述什么是智能合约。 学习完Solidity就可以学习以太坊相关内容.所以本段内容是专门给以太坊打基础。

8. 以太坊原理

以太坊和比特币都是学习区块链中经典的例子。 这个阶段,包含了以太坊原理架构流程和一些区块链中专业概念。这一阶段讲解比较全面,重点学习后就可以对区块链有了较深的认识。

9.以太坊客户端

本阶段继续学习以太坊,主要讲解以太坊客户端配置和原理。为后面讲解以太坊DApp打基础。主要讲解:geth客户端配置和运行、geth源代码解读。

10.去中心换拍卖系统DApp

本阶段是对以太坊的巩固学习,属于一个编码阶段,所有编码阶段的重点都是在动手,实战。所有内容都编写完成后就完成了对区块第一次完整认识。

最终我们可以利用:区块链、星际文件系统、Node.js、MongoDB构建一个“去中心化”革命性的电商平台。

11.超级账本和DApp实战

超级账本是一个大体系。 在这个阶段中会使用Linux的一些命令和使用,同时这一阶段中使用Go作为源码语言。学习完这个阶段后会更加加深对区块链的认识。

12.C++编程快速入门

C++语言是比特币项目的编写语言, 学习C++主要目的是为了读懂比特币中关键代码。所以这阶段不是非常详细的把C++所有知识点都讲解到,只是一个快速入门,能够读懂比特币的核心代码即可。

大家没有必要对C++做过分深入的研究,毕竟应用范围越来越小了。

13.比特币

比特币作为区块链的起源,也是区块链行业中的标杆。学习区块链,也一定要学习比特币相关内容。 之前已经学习了区块链的两大部分,这阶段学习起来将会比较轻松。

14.EOS

除了几个经典的比特币项目以外,在本套课程引入了其他的项目讲解,目前讲解的是EOS,在以后的课程中还会陆续引入小蚁、星云、量子等其他项目。

EOS:可以理解为Enterprise Operation System,即为商用分布式应用设计的一款区块链操作系统。EOS是引入的一种新的区块链架构,旨在实现分布式应用的性能扩展。注意,它并不是像比特币和以太坊那样的货币,而是基于EOS软件项目之上发布的代币,被称为区块链3.0。

EOS有点类似于微软的windows平台,通过创建一个对开发者友好的区块链底层平台,支持多个应用同时运行,为开发dAPP提供底层的模板。

当你拥有了EOS的话,就相当于拥有了计算机资源,随着DAPP的开发,你可以将手里的EOS租赁给别人使用,单从这一点来说EOS也具有广泛的价值。简单来说,就是你拥有了EOS,就相当于拥有了一套房租给别人收房租,或者说拥有了一块地租给别人建房。

八:100套毕业设计和课程设计项目案例和配套视频

本套100个完整项目源码是由【北京尚学堂·百战程序员】学员做毕设时提供,老师提供了相应的毕设辅导服务。

一共分为5季,每季约20套项目,希望大家持续关注。

很多大四同学苦于没有参考的毕设资料,或者下载的资料不全、代码有问题、数据有问题等等,造成毕设出现问题影响大学毕业。现在,我们提供了经过审核的100个项目源码和对应的辅导视频,让大家在短时间内可以完成自己的毕业设计。

同时,我们也录制了更多的项目视频,2018年计划100套,后续将会有更多。大家可以到www.itbaizhan.cn在线观看和学习,也可以到北京尚学堂官网免费下载。

关于版权的声明,源码由北京尚学堂学员做项目时提供,非北京尚学堂原创。北京尚学堂讲师只提供了项目的部署和使用说明的视频,如果侵犯了原作者的版权,请联系我们。

未来,我们将发布H5前端毕设项目、Python毕设项目、大数据毕设项目、人工智能毕设项目等。让我们的大学生朋友再也不用为毕设发愁。请大家随时关注尚学堂bjsxt.com或者百战程序员(itbaizhan.cn)的官网。

大家可以在:

http://www.bjsxt.com/biyeshejishipin.html (毕业视频视频的拼音)

1.关于各种开发软件的使用说明和配套视频

由于很多大学生对于开发软件不是很熟悉,我们将常见的开发软件使用方式集中进行了录制。大家项目中用到哪些软件,自行对比学习即可。

为了方便大家的学习,我们提供了常用开发软件的安装包,大家可以根据需要直接从网盘下载:

软件的使用方式都特别简单,大家不要有畏惧心理,这里讲解了软件在开发中最常用的使用方式。包含了常见数据库软件的使用(oracle、mysql、sqlserver)、数据库客户端操作软件、eclipse、Myeclipse、Tomcat服务器等的使用。包含如下视频:

1.Eclipse的使用1_开发环境使用原因

2.Eclipse的使用2_下载楼基本选择和使用

3.Eclipse的使用3_建立JAVA项目_项目的结构说明

4.Eclipse的使用4_开发和运行JAVA程序

5.Eclipse(JEE)的使用_Tomcat整合_项目部署

6.JDK安装1_下载和安装_JDK目录介绍

7.JDK安装2_环境变量PATH设置_classpath问题

8.JDK安装3_控制台测试JDK安装和配置成功

9.Myeclipse2014的安装和使用_web项目创建和发布

10.Myeclipse和Tomcat整合_web项目部署

11.Mysql数据库1_安装和配置_命令行简单使用

12.Mysql数据库2_navicat客户端软件的使用_加载SQL文件到库

13.Oracle数据库1_安装

14.Oracle数据库2_客户端plsql安装并连接

15.SqlServer数据库1_安装

16.SqlServer数据库2_连接并回复数据库

17.SqlServer数据库3_客户端操作

18.SqlServer数据库4_卸载

19.Tomcat服务器安装_使用介绍

2.第一季20套项目源代码和配套视频

第一季20套源代码覆盖范围较广,有比较基础的JAVA初级项目,也有比较大的WEB项目。每个项目我们都提供了完整的内容,涵盖:论文、PPT、源代码、数据库文件、配套讲解视频。我们以“土地局档案管理系统”为例:

打开“论文等资料”文件夹,就发现有完整的论文和答辩内容,供大家参考:

打开“项目辅导视频”,就发现有详细的项目讲解视频,帮助大家解决项目部署、项目模块讲解的问题:

为了快速查看这个项目是否符合你的需求,可以打开“项目截图”文件夹:

报表图.png

捕获.png

档案修改.png

登录.png

功能.png

注册.png

第一季视频涵盖如下图所示项目,范围比较广泛。有电子政务项目、也有医疗项目、也有供应链管理项目、互联网项目也有若干。同时,也有几个java基础项目,大家可以用于做JAVA的课程设计。

九:7U职场软实力课程和配套视频

1.职场软实力是什么?

“每一个人都要训练软实力”。成功职场和成功人生不仅需要硬实力,更需要软实力。两种实力就像人的双腿,缺一即“残”。中国传媒大学老师王雪和北京尚学堂总裁高淇发明了7U软实力理论,让人的软实力有可测量的七种维度和提升的标准。已经有上百位学员受益,短时间极速提升自己的软实力,让自己的工作、爱情、生活都极大受益。

程序员往往关注“编码能力”等硬实力的提升,而忽视了“口才”、“沟通”等软实力的提升,造成发展的困境、职位升迁的困境、甚至恋爱婚姻的困境。所以,对于软实力不太好的朋友,非常有必要学习软实力。

更重要的是,软实力是一个相对的概念。而且大多数人对认为“软实力”是天生的,无法通过训练改变。而实际上,软实力可以通过训练快速提升。大家都不学习的情况下,你是很容易脱颖而出的。

职场软实力不等于技能,但可以让你的技能得到更好的发挥。它是你个人发展的“催化剂”,可以让你发展更快、走的更稳。

2.形象气质和社交礼仪

好的形象气质和职场礼仪是你成功的“助跑器”。除了你父母,没有人有义务通过你邋遢的外表和不专业的礼仪深入了解你的内在。

本阶段将详细介绍在各种场合的实用技巧。包括:服装搭配、言谈举止、社交礼仪、生活礼仪、宴会礼仪。

让你完全掌握职场上的基本礼仪,商务接待和谈判的礼仪;掌握生活中待人接物的礼仪,成为一个落落大方的人;掌握宴会礼仪,明白如何讲话,如何根据自己的身份说恰当的话术。

3.声音素质

声音不是天生的,可以通过专业的发声技巧来改变。如果声音不好听,在人际交往中的效果就要大打折扣。本阶段旨在培养大家如何在沟通中发出好听的声音,让我们的声音更有磁性,更有力量,更有感染力。

学会掌握自己的声音,在卡拉OK的场合,再也不惧了。在公众发言的场合,心里也会更加有底气。

声音是人的第二张名片。我们可以通过掌握胸腹式联合呼吸法、共鸣训练,正确的用气技巧,很快就能成为一个再也不惧“发言”场合的人。

4.情商

人际关系有多重要,情商就有多重要。情商是我们所有软实力的基础,也是最后的一个升华,所以掌握情商能够让我们的人际关系更加的和谐,同时在处理困难挫折的时候又不至于焦头烂额。本阶段将告诉大家我们紧张的原因以及克服的技巧,从微表情中看出对方没有用语言表达出来的想法,学会如何面对各种“失意”的情绪,以及在朋友圈中,在职场中如何利用情商处理人际关系。

通过学习情绪控制的基本原理:紧张的原理、条件反射原理。让自己明白,情商的基础物理知识。再进一步学习,微表情、自身情商的激励,成为一个“高情商”的人。

再进一步学习,“朋友中的情商”让自己成为一个善解人意的人;学习“职场情商”,让自己成为一个懂领导、懂同事、懂下属的“高情商”的合作伙伴;

5.沟通力

好的沟通力是人际交往的基础,可以极大降低生活和工作成本。坏的沟通力能把好事也办成坏事。本阶段将详细介绍如何更好的打开对方的心扉快速对接,以及赞美和批评的20多种技巧,还会讲到如何讲好故事,方便我们的沟通,以及酒宴场合的一些应对技巧。

我们需要学习:

1.如何介绍自己、商务场合介绍他人、八卦场合介绍他人

2.人性的特点

3.如何寻找合适的话题

4.掌握赞美的艺术

5.掌握批评他人的技巧

6.各种酒宴场合的演讲技巧

7.掌握讲好一件事的技术

6.说服力

生活是由一个个说服和被说服构成的,不是被别人说服,就是在说服别人。说服力是职场成功的关键。本阶段讲解提升说服力的技巧方法,让我们快速的说服领导、同事以及家人。

好的说服力,在你谈恋爱、找工作中能发挥极致作用。我们需要学习如下内容:

1.如何破冰,破冰的八大策略

2.如何增加筹码说服别人

3.十大说服技巧

4.条理公式(说服需要条理和逻辑)

7.说服力之销售

不管你的职业是什么,每个人都是销售。有人销售产品,有人销售思想,有人销售自己。本阶段主要针对销售的技巧进行提升,对于没有经验的学员能够快速提升销售技巧,对于有经验的销售人员极大提高转化效率。

做任何职业,掌握销售技巧都是非常有帮助的。毕竟,本质上“人人都是销售员”。我们需要学习如下内容:

成功销售三部曲(问、听、看)

销售十大步骤

绝对成交七个技巧

8.演讲力

“能面对多少人讲话,就能有多大的成就”。本阶段从演讲的三个关键点入手,进行细节分析和技巧把握,以及如何应对演讲过程中的尴尬,如何在舞台上进行即兴演讲,让我们站在舞台上更加从容。

我们需要学习演讲训练的如下关键点:

1.如何写出漂亮的演讲稿

2.如何克服恐惧

3.演讲自我介绍和互动技巧

4.万能开场白

5.把握演讲节奏和内容

6.眼神、形体、语气如何运用

7.演讲的小策略

①.如何营造互动氛围

②.如何赢取掌声

③.忘词怎么办

④.如何面对刁钻古怪的问题

9.领导力

“不想当将军的士兵不是好士兵”,领导力培养需要从娃娃抓起,是先有领导力才能成为领导,而不是成为领导再锻炼领导力(除非有个好爸爸给你大量练手机会)。本阶段围绕领导力的的九种特质及快速提升领导力的方法,以及怎样创建一个优秀的适合企业发展的团队。

学好领导力,需要学习如下课程,并开始实战训练:

1.理解领导力的九大特质

2.领导的创新心态调整

组织管理的核心秘诀

4.如何制定合理的战略决策

5.正确的沟通协调下属方式

就业班
1.JAVA专业,1000课 3.大数据专业,500课
2.Python专业,500课    4.人工智能专业,500课

四个专业都要学,从零开始2000小时,成为高端人才,打下一生技术基础,不再是低端码农。

2.扫一扫,咨询详情:

访问官网 www.itbaizhan.cn