Java面试题
1、Java基本数据类型有哪些?
(1)Java有8种基本数据类型: byte、short、 int、 long、float、double、boolean、 char。
(2)基本数据类型对应的包装类型:Byte、Short、Integer、Long、Float、Double、Boolean、Character['kærəktə(r)]。
(4)基本数据类型详细介绍:
1)byte是8位、占1个字节、最小值是-128(-2^7)、最大值是127(2^7-1)、默认值是0
2)short是16位、占2个字节、最小值是-32768(-2^15)、最大值是32767(2^15-1)、默认值是0
3)int是32位、占4个字节、最小值是-2^31、最大值是2^31-1、默认值是0
4)long是64位、占8个字节、最小值是-2^63、最大值是2^63-1、默认值是0L
5)float是单精度、32位、占4个字节、默认值是0.0f
6)double是双精度、64位、占8个字节、默认值是 0.0d
7)boolean有两个取值:true和false、默认值是 false、1和0表示、占1个字节
8)char是16位、占2个字节、最小值是u0000(即0)、最大值是uffff(即65535)
9)自动装箱是将基本数据类型转换为包装数据类型,自动拆箱是将包装类型转换为基本数据类型。
2、Integer和int的区别?
(1)Integer是int的包装类,int是java的基本数据类型。
(2)Integer需实例化才能使用,而int不需实例化。
(3)Integer是对象的引用,当new一个Integer时生成一个指针指向此对象,而int是直接存储数据值。
(4)Integer默认值是null,int默认值是0。
3、抽象类(abstract class)和接口(interface)的区别?(JDK8接口有哪些变化?)
(1)抽象类和接口都不能被实例化。
(2)抽象类有构造函数,接口有方法声明无具体实现。
(3)抽象类可以继承一个类或实现多个接口,接口可以继承一个或多个接口。
(4)子类使用extends继承抽象类,子类使用implements实现接口。
(5)抽象方法可以使用protected修饰符,接口方法不能使用protected修饰符。
(6)抽象类可以包含非final的变量,接口中声明的变量默认都是final的修饰。
(7)抽象类可以包含非抽象和抽象的方法,接口中所有的方法隐含的都是抽象的。
(8)子类覆盖抽象类中所有的方法,该子类才可以实例化,否则该子类还是抽象类。
(9)JDK8新特性:
<1>Lambda[ˈlæmdə]表达式:允许把函数作为一个方法的参数传递进方法中。
<2>方法引用:方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
<3>默认方法:是一个在接口里面有了一个实现的方法。
<4>新编译工具:Nashorn取代Rhino(JDK 1.6、1.7)成为Java的嵌入式JavaScript引擎,将JavaScript编译成Java字节码在JVM上运行。
<5>Stream API:新添加的Stream API(java.util.stream)。
<6>Date Time API:加强对日期与时间的处理。
<7>Optional类:Optional类已经成为Java8类库的一部分,用来解决空指针异常。
4、包与包之间的类进行访问,被访问的包中的类必须是public的,被访问的包中的类的方法也必须是public的。
|
public |
protected |
default |
private |
同一类 |
ok |
ok |
ok |
ok |
同一包 |
ok |
ok |
ok |
|
子类 |
ok |
ok |
|
|
不同包 |
ok |
|
|
|
5、重写重载(Overload)和(Override)的区别?
(1)重载是在同一个类中,允许存在一个以上的同名函数,只要它们的参数个数或者参数类型不同即可,构造函数也可以重载。
(2)重写是子类对父类允许访问的方法进行重新编写,返回值和形参不能变。
6、Java对象的生命周期?
(1)创建:分配内存构造对象并初始化。
(2)应用:对象至少被一个强引用持有着。
(3)不可见:程序本身不再持有该对象的任何强引用,虽然该引用仍然是存在的。
(4)不可达:无任何引用指向。
(5)收集:执行该对象的finalized方法进行垃圾回收。
(6)终结:回收该对象的内存。
(7)对象空间重分配:对该对象的内存进行再分配,对象彻底消失。
7、servlet的生命周期有哪些?servlet是线程安全的吗?为什么?
(1)Servlet是具有独立于平台和协议的特性,主要功能在于交互地浏览和生成数据,生成动态web内容。
(2)Servlet实现过程:
1)客户端发送请求至服务端;
2)服务器将请求信息发送至Servlet;
3)Servlet生成响应内容并传给服务器,响应内容动态生成,通常取决于客户端的请求;
4)服务器将响应返回给客户端。
(3)Servlet生命周期:
1)Servlet调用init()方法进行初始化。
2)Servlet调用service()方法来处理客户端的请求(根据请求方法调用doGet()或者doPost())。
3)Servlet调用destroy()方法终止(结束)。
4)最后,Servlet是由JVM垃圾回收器进行垃圾回收的。
(4)Servlet是线程不安全,避免使用全局变量,而使用局部变量,用synchronized同步对共享数据操作,实现SingleThreadModel接口。
8、线程生命周期?
(1)新建状态(2)就绪状态(3)运行状态(4)阻塞状态(5)死亡状态
9、面向对象四大特征:抽象、封装、继承、多态。
(1)抽象是从具体事物抽出、概括出它们共同的方面、本质属性与关系等,将个别的、非本质的方面、属性与关系舍弃,这种思维过程称为抽象。
(2)封装是将接口实现细节包装、隐藏、禁止被外部类随意访问,必须通过接口控制才能访问。
(3)继承是子类继承父类特征和行为,使子类具有父类的实例域和方法,使子类具有父类相同的行为。
(4)多态是同一个行为具有多种不同表现形式的能力,多态是同一个接口使用不同实例而执行不同操作。
多态的优点:<1>扩充性<2>灵活性<3>简化性<4>接口性<5>替换性<6>消除类型之间耦合关系。
面向对象(OOP)和面向过程都是一种思想,面向对象强调是对象实例,面向过程强调是动作,面向对象特点是复杂变简单,执行者变指挥者。
10、多态时成员的特点?
(1)成员变量。
编译时:参考引用型变量所属的类中的是否有调用的成员变量,有,编译通过,没有,编译失败。
运行时:参考引用型变量所属的类中的是否有调用的成员变量,并运行该所属类中的成员变量。
简单说,编译和运行都参考等号的左边。
(2)成员函数(非静态)。
编译时:参考引用型变量所属的类中的是否有调用的函数,有,编译通过,没有,编译失败。
运行时:参考的是对象所属的类中是否有调用的函数。
简单说,编译看左边,运行看右边。因为成员函数存在覆盖特性。
(3)静态函数。
编译时:参考引用型变量所属的类中的是否有调用的静态方法。
运行时:参考引用型变量所属的类中的是否有调用的静态方法。
简单说,编译和运行都看左边。
11、String、StringBuffer与StringBuilder的区别?
(1)String类是不可变的(final),而StringBuffer与StringBuilder是一个可变的字符序列。
(2)StringBuffer线程安全,StringBuilder线程不安全。
(3)StringBuffer比StringBuilder运行速度要慢。
12、cookie与session的区别?
(1)cookie数据存放在客户端,session数据存放在服务器端。
(2)cookie安全性低,session安全性高。
(3)cookie使用在网站登录,session使用在网站购物车。
13、Session特点?
(1)Session是线程不安全,应该避免多个线程共享同一个Session实例。
(2)Session实例是轻量级的,它的创建和删除不需要消耗太多资源。
(3)Session对象内部有一个缓存,被称为Hibernate第一缓存,每个Session实例都有自己的缓存。
14、Hibernate中SessionFactory是线程安全的吗?Session是线程安全的吗(两个线程能够共享一个Session吗)?
(1)SessionFactory接口负责初始化Hibernate,是线程安全的,可以被多个线程并发访问,并负责创建Session对象。
(2)Session对象存储特定用户会话所需的属性及配置信息,是非线程安全的。
15、final、finally与finalize区别?
(1)final用于修饰变量、属性、方法和类,分别表示变量变为常量只能赋值一次,属性不可变、方法不可覆盖和类不可继承。
(2)finally是异常处理结构的一部分,表示总是执行。
(3)finalize方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。
16、Error和Exception的区别?
(1)Error表示系统级的错误和程序不必处理的异常,是恢复不是不可能,但很困难的情况下的一种严重问题,如内存溢出。
(2)Exception 表示需要捕捉或需要程序进行处理的异常,是一种设计或实现问题,它表示如果程序运行正常从不会发生的情况。
17、try{}里有一个return语句,那么紧跟在这个try后的finally{}里的code会不会被执行,什么时候被执行,在return前还是后?
会执行,在return前执行。
18、什么是Java序列化,如何实现Java序列化?
(1)序列化是一种用来处理对象流的机制,对象流是将对象的内容进行流化,可以对流化后的对象进行读写操作或传输于网络之间。
(2)将需要被序列化的类实现Serializable[sɪərɪəlaɪ'zəbl]接口,该接口无方法的实现。
19、成员变量和局部变量的区别?
(1)成员变量定义在类中,整个类中都可以访问,局部变量定义在函数、语句、局部代码块中,只在所属的区域有效。
(2)成员变量存储在堆内存的对象中,局部变量存储在栈内存的方法中。
(3)成员变量随着对象的创建而存在,随着对象的消失而消失,局部变量随着所属区域的执行而存在,随着所属区域的结束而释放。
(4)成员变量都有默认初始化值,局部变量没有默认初始化值。
20、成员变量和静态变量的区别?
(1)成员变量随着对象的创建而存在,随着对象的被回收而释放,静态变量随着类的加载而存在,随着类的消失而消失。
(2)成员变量只能被对象调用,静态变量可以被对象调用,还可以被类名调用。
(3)成员变量也称为实例变量,静态变量称为类变量。
(4)成员变量数据存储在堆内存的对象中,也称对象的特有数据,静态变量数据存储在方法区(共享数据区)的静态区,也称对象的共享数据。
(5)静态使用的注意事项:
<1>静态方法只能访问静态成员,非静态既可以访问静态,又可以访问非静态。
<2>静态方法中不可以使用this或者super关键字。
<3>主函数是静态的。
(6)static的特点:
<1>static修饰成员被所有的对象所共享。
<2>static优先于对象存在随着类加载而存在。
<3>static修饰数据是共享数据,对象中的存储的是特有数据。
21、常见异常类有哪些?
(1)NullPointerException 空指针异常
(2)IOException IO流异常
(3)IndexOutOfBoundsException下标越界异常
(4)NumberFormatException字符串转换为数字异常
(5)FileNotFoundException文件未找到异常
22、throw 和throws的区别?
(1)throw使用在函数内,throws使用在函数上。
(2)throw抛出的是异常对象,throws抛出的是异常的声明(用在方法上),可以抛出多个,用逗号隔开。
23、Collection与Collections区别?
(1)Collection是集合类的上级接口,继承它的接口主要有Set和List。
(2)Collections是针对集合类的一个辅助类,它提供一系列静态方法实现对各种集合的搜索、排序、线程安全等操作。
24、请画出collection的族谱关系,并指出各数据结构的特点。
(1)Collection 一次添加一个元素,称为单列集合,Map一次添加一对元素,称为双列集合Key唯一无序value不唯一无序。
(2)List存储一组不唯一有序对象。
(3)Set存储一组唯一无序的对象。
(4)Vector是数组数据结构同步的增删查慢。
(5)ArrayList是数组数据结构不同步替代了Vector查询速度快。
(6)LinkedList是链表数据结构不同步增删速度快。
(7) HashSet实现Set接口,哈希表,不同步的,存储不重复的对象,无序的,允许使用null元素。
(8)TreeSet是有序不同步的。
(9)TreeMap是二叉树不同步可以对Map集合中的键进行排序。
(10)Hashtable是哈希表同步(线程安全),null不能作为键和值。
(11)HashMap是哈希表不同步(非线程安全),null可以作为键和值。
25、list、set、map的区别?
(1)List存储一组不唯一有序对象,查询效率高,添加删除效率低,因为会引起其它元素位置改变。
(2)Set存储一组唯一无序的对象,查询效率低下,添加和删除效率高。
(3)Map存储键值对象Key无序不重复value无序可重复,HashMap是哈希表不同步(非线程安全),null可以作为键和值。
26、Vector、ArrayList、LinkedList区别?
(1)Vector是数组数据结构同步的增删查速度慢。
(2)ArrayList和LinkedList实现了List接口。
(3)ArrayList是数组数据结构不同步替代了Vector查询快增删慢,因为增删时所有的元素都会被移动。
(4)LinkedList是链表数据结构不同步的,增删速度快。
27、Hashtable、HashMap、TreeMap区别?
(1)Hashtable、HashMap、TreeMap都实现了Map接口。
(2)Hashtable是哈希表同步(线程安全),null不能作为键和值。
(3)HashMap是哈希表不同步(非线程安全),null可以作为键和值。
(4)TreeMap是二叉树不同步可以对Map集合中的键进行排序。
(5)HashMap用于单线程,而Hashtable用于多线程。
28、Web Services有哪些优点?
(1)Web Services是应用程序组件,使用开放协议进行通信,XML是Web Services的基础。
(2)Web Services优点是开放性、跨平台性,开放性正是Web Services的基础。
29、Struts2拦截器与过滤器区别?
(1)拦截器是基于java的反射机制,过滤器是基于函数回调。
(2)拦截器不依赖于Servlet容器,过滤器依赖于Servlet容器。
(3)拦截器只能对Action请求起作用,过滤器则对所有请求起作用。
(4)拦截器可以访问Action上下文(ActionContext)和值栈里对象(ValueStack),过滤器不能。
(5)拦截器在Action生命周期中可以多次被调用,过滤器只能在容器初始化时被调用一次。
30、MyBaits理解?
(1)MyBaits是持久层框架,支持普通或定制化SQL查询、存储过程以及高级映射,使用XML或注解来配置和映射信息。
(2)SQL写在XML文件便于统一管理和优化,解除SQL与程序代码的耦合,通过提供DAL层,将业务逻辑和数据访问逻辑分离,使系统设计更清晰,更易维护,更易单元测试,提高了可维护性。
(3)MyBatis功能架构分为三层:
<1>API接口层:提供给外部使用接口API,接口层接收到调用请求后调用数据处理层来完成具体的数据处理。
<2>数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等,目的是根据调用请求完成一次数据库操作。
<3>基础支撑层:负责最基础功能支撑,包括连接管理、事务管理、配置加载和缓存处理。
31、Hibernate理解?
(1)Hibernate是对象关系映射框架,对JDBC进行非常轻量级的对象封装,是全自动的ORM框架,自动生成SQL且执行。
(2)封装JDBC简化重复性代码,简化DAO层编码使开发更对象化,移植性好支持各种数据库,支持透明持久化,没有实现任何接口,没有侵入性。
(3)核心API为:Session、SessionFactory、Transaction [træn'zækʃn]、Query、Criteria[kraɪ'tɪəriə]和Configuration[kənˌfɪɡə'reɪʃn]。
<1>Session接口负责执行被持久化对象CRUD操作,是非线程安全的。
<2>SessionFactory接口负责初始化Hibernate。
<3>Query负责查询。
<4>Configuration作用是对Hibernate进行配置以及对它进行启动。
32、Hibernate与MyBaits的区别?
(1)Hibernate是全自动,myBatis是半自动。
(2)Hibernate数据库移植性比myBatis容易。
(3)Hibernate拥有完整的日志系统,myBatis则欠缺一些。
(4)Hibernate强大、方便、高效、复杂、全自动,myBatis小巧、方便、高效、简单、半自动。
33、Struts2理解?
(1)Struts2是一个基于MVC设计模式的WEB应用框架,作为控制器来建立模型与视图的数据交互。
(2)Struts 2以WEBWork为核心,采用拦截器的机制来处理用户的请求,使业务逻辑控制器与Servlet API完全脱离开。
(3)Struts2运行原理如下:
<1>当WEB容器收到一个请求时,它将请求传递给一个标准的过滤器链。
<2>FilterDispatcher被调用,它调用ActionMapper确定请求调用哪个Action,ActionMapper返回收集了Action信息的ActionMapping对象。
<3>FilterDispatcher将控制权委派给ActionProxy,ActionProxy调用配置管理器从配置文件中读取配置信息,然后创建ActionInvocation对象,被创建同时填充了需要的所有的对象和信息,它在调用Action之前会依次调用所有配置的拦截器。
<4>Action执行返回结果字符串,ActionInvocation负责根据struts.xml中的配置查找结果字符串对应Result且执行。
<5>之后拦截器会被再次执行且顺序相反,最后响应被返回给在web.xml中配置的过滤器。
34、Spring理解?
(1)Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架,是轻量的、非侵入的、面向接口编程。
(2)控制反转(IoC):控制反转促进了松耦合,当应用了IoC一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。
(3)面向切面(AOP):Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务和事务管理进行内聚性的开发。应用对象只实现它们应该做的业务逻辑。它们并不负责其它的系统级关注点,如日志记录、性能统计、安全控制、事务处理、异常处理等。
AOP使用两种代理机制:一种是基于JDK的动态代理,另一种是基于CGLib(Code Generation[ˌdʒenə'reɪʃn] Library['laɪbrəri])的动态代理。
(4)AOP的好处:<1>每个事务逻辑位于一个位置,代码不分散,便于维护和升级。<2>业务模块更简洁,只包含核心业务代码。
35、SpringMVC理解?
(1)MVC(Model View Controller)中M是指模型,V是指视图,C是指控制器,MVC将模型与视图实现代码分离,使同一个程序可以使用不同的表现形式。控制器确保模型与视图同步,模型改变视图应同步更新。
(2)模型是处理应用程序数据逻辑部分,模型对象负责数据存取。
(3)视图是处理应用程序数据展示部分,视图是依据模型数据创建。
(4)控制器是处理用户交互部分,控制器从视图读取数据,控制用户输入向模型发送数据。
(5)MVC分层有助于管理复杂的应用程序、简化了分组开发,不同开发人员可同时开发视图、控制器逻辑和业务逻辑。
(6)SpringMVC运行原理:如果在web.xml中设置DispatcherServlet的<url-pattern>为/时,当用户发起请求,请求一个控制器,首先会执行DispatcherServlet。由DispatcherServlet调用HandlerMapping的DefaultAnnotationHandlerMapping解析URL,解析后调用HandlerAdatper组件的AnnotationMethodHandlerAdapter调用Controller中的HandlerMethod。当HandlerMethod执行完成后会返回View,会被ViewResovler进行视图解析,解析后调用jsp对应的.class文件并运行,最终把运行.class文件的结果响应给客户端。
36、Struts1与Struts2区别?
(1)Struts1执行过程:
<1>WEB容器启动ActionServlet被初始化且加载struts-config.xml配置文件。
<2>浏览器发送请求到ActionServlet时且对请求进行处理,根据请求路劲和配置信息找到对应的Action和ActionForm。
<3>确定将要调用的Action和对应的ActionForm后,将请求中包含的值填充到ActionForm中。在调用execute方法前ActionServlet需要准备ActionMapping参数。
<4>Action调用业务逻辑方法得到返回值,并返回ActionForward对象。
<5>控制权重新回到ActionServlet,根据Action返回的ActionForward对象转发到相应页面,把处理结果返回给浏览器。
(2)Struts2执行过程:
<1>当WEB容器收到一个请求时,它将请求传递给一个标准的过滤器链。
<2>FilterDispatcher被调用,它调用ActionMapper确定请求调用哪个Action,ActionMapper返回收集了Action信息的ActionMapping对象。
<3>FilterDispatcher将控制权委派给ActionProxy,ActionProxy调用配置管理器从配置文件中读取配置信息,然后创建ActionInvocation对象,被创建同时填充了需要的所有的对象和信息,它在调用Acton之前会依次调用所有配置的拦截器。
<4>Action执行返回结果字符串,ActionInvocation负责根据struts.xml中的配置查找结果字符串对应Result且执行。
<5>之后拦截器会被再次执行且顺序相反,最后响应被返回给在web.xml中配置的过滤器。
(3)Struts1与Struts2区别:
<1>struts1的Action继承抽象基类,struts2的actio实现action接口。
<2>sturts1 的action是单例模式,线程是不安全的,struts2的action线程是安全的。
<3>sturts1依赖Serlet API,struts2不依赖于容器。
<4>struts1使用ActionForm对象捕获输入,struts2使用Action属性作为输入属性。
<5>struts1绑定JSTL,struts2整合ONGL。
37、SSH理解?
(1)SSH是Struts+Spring+Hibernate的一个集成框架,是目前比较流行的一种Web应用程序开源框架。
(2)SSH框架的系统从职责上分为四层:表示层、业务逻辑层、数据持久层和域模块层,Struts作为系统的整体基础架构,负责MVC的分离,控制业务跳转,Hibernate框架对持久层提供支持,Spring做管理,管理Struts和Hibernate。具体做法是:用面向对象的分析方法根据需求提出一些模型,将这些模型实现为基本的Java对象,然后编写基本的DAO接口,并给出Hibernate的DAO实现,采用Hibernate架构实现的DAO类来实现Java类与数据库之间的转换和访问,最后由Spring做管理,管理Struts和Hibernate。
(3)系统的基本业务流程是:在表示层中,首先通过JSP页面实现交互界面,负责接收请求(request)和传送响应(response),然后Struts根据配置文件(struts-config.xml)将ActionServlet接收到的request委派给相应的Action处理。在业务层中,管理服务组件的Spring IoC容器负责向Action提供业务模型(Model)组件和该组件的协作对象数据处理(DAO)组件完成业务逻辑,并提供事务处理、缓冲池等容器组件以提升系统性能和保证数据的完整性。而在持久层中,则依赖于Hibernate的对象化映射和数据库交互,处理DAO组件请求的数据,并返回处理结果。
(4)SSH不仅实现了视图、控制器与模型的彻底分离,而且还实现了业务逻辑层与持久层的分离。无论前端如何变化,模型层只需很少的改动,并且数据库的变化也不会对前端有所影响,大大提高了系统的可复用性。而且由于不同层之间耦合度小,有利于团队成员并行工作,大大提高了开发效率。
38、在SSH项目中Struts2、Spring、Hibernate分别起什么作用?优点和缺点?
(1)Struts2是一个基于MVC设计模式的WEB应用框架,作为控制器来建立模型与视图的数据交互。
(2)Spring是控制反转(IoC)和面向切面(AOP)容器框架,是轻量的、非侵入的、面向接口编程。
(3)Hibernate是对象关系映射框架,对JDBC进行非常轻量级的对象封装,是全自动的ORM框架,自动生成SQL且执行。
(4)MyBaits是持久层框架,支持普通或定制化SQL查询、存储过程以及高级映射,使用XML或注解来配置和映射信息。
(5)Struts2主要起控制作用,Spring主要起解耦作用,Hibernate主要起持久化操作。
(6)优点:
(7)缺点:
39、SSM理解?
(Spring+SpringMVC+MyBatis)框架集由Spring、MyBatis两个开源框架整合而成(SpringMVC是Spring中的部分内容)。
(1)Spring是整个项目中装配bean的大工厂,在配置文件中可以指定使用特定的参数去调用实体类的构造方法来实例化对象。Spring的核心思想是IoC(控制反转),即不在需要开发人员显式地new一个对象,而是让Spring框架帮助来完成这一切。
(2)SpringMVC在项目中拦截用户请求,它的核心Servlet即DispatcherServlet承担中介或者前台这样的职责,将用户请求通过HandlerMapping去匹配Controller,Controller就是具体对应请求所执行的操作。SpringMVC相当于SSH框架中struts。
(3)MyBatis是对JDBC的封装,它让数据库底层操作变透明,MyBatis的操作都是围绕一个SQLSessionFactory实例展开的。MyBatis通过配置文件关联到各实体类的Mapping文件,Mapper文件中配置了每个类对数据库所需进行的sql语句映射。在每次数据库交互时,通sqlSessionFactory获取一个sqlSession,再执行sql命令。
(4)页面发送请求给控制器,控制器调用业务层处理逻辑,逻辑层向持久层发送请求,持久层与数据库交互,后将结果返回给业务层,业务层将处理逻辑发送给控制器,控制器再调用视图展示数据。
40、SpringMVC的控制器是不是单例模式,如果是,有什么问题,怎么解决?
(1)SpringMVC的控制器是单例模式,在多线程访问时有线程安全问题。
(2)不能使用同步,在控制器里面不能写字段。
42、SpringMVC如何传递数组参数?
(1)index.jsp
<script type="text/javascript">
var param = {
cityName : [ "BeiJing", "XiAn", "ShangHai" ]
};
$.ajax({
url : "saveCity",
type : "post",
data : param,
async : false,
dataType : "json",
success : function(data) {
alert(data);
}
});
</script>
(2)IndexController.java
@RequestMapping(value = "/saveCity", method = RequestMethod.POST)
public ModelAndView saveCity(@RequestParam(value = "cityName[]") String[] cityName) {
ModelAndView mv = new ModelAndView();
List<String> listCity = new ArrayList<String>();
for (int i = 0; i < cityName.length; i++) {
listCity.add(cityName[i]);
}
mv.addObject("listCity", listCity);
mv.setViewName("index/index");
return mv;
}
43、BeanFactory的作用是什么?
(1)BeanFactory是最顶层接口类定义IOC容器的基本功能规范。
(2)BeanFactory配置和管理众多bean容器。
44、Spring中自动装配的方式有哪些?
(1)<bean autowire="no"></bean>
(默认)无自动装配, bean引用必须由ref元素定义。对于较大的部署,不建议更改默认设置,因为显式指定合作者可以提供更大的控制和清晰性。在某种程度上,它记录了系统的结构。
(2)<bean autowire="byName"></bean>
按属性名称自动装配,Spring查找与需要自动装配的属性同名的bean。例如,如果bean定义按名称设置为autowire并且它包含一个master属性(即,它有一个setMaster(..)方法),则Spring会查找名为bean的定义master并使用它来设置属性。
(3)<bean autowire="byType"></bean>
如果容器中只存在一个属性类型的bean,则允许属性自动装配。如果存在多个,则抛出致命异常,这表示您可能不会byType对该bean使用自动装配。如果没有匹配的bean,则不会发生任何事情(该属性未设置)。
(4)<bean autowire="constructor"></bean>
类似byType但适用于构造函数参数,如果容器中没有构造函数参数类型的一个bean,则会引发致命错误。
45、Spring中Bean的作用域有哪些?
(1)<bean scope="singleton"></bean>
(默认)将单个bean定义范围限定为每个Spring IoC容器的单个对象实例。
(2)<bean scope="prototype"></bean>
将单个bean定义范围限定为任意数量的对象实例。
(3)<bean scope="request"></bean>
将单个bean定义范围限定为单个HTTP请求的生命周期。也就是说,每个HTTP请求都有自己的bean实例,它是在单个bean定义的后面创建的。仅在具有Web感知功能的Spring环境中有效ApplicationContext。
(4)<bean scope="session"></bean>
将单个bean定义范围限定为HTTP的生命周期Session。仅在具有Web感知功能的Spring环境中有效ApplicationContext。
(5)<bean scope="application"></bean>
将单个bean定义范围限定为a的生命周期ServletContext。仅在具有Web感知功能的Spring环境中有效ApplicationContext。
(6)<bean scope="websocket"></bean>
将单个bean定义范围限定为一个的生命周期WebSocket。仅在具有Web感知功能的Spring环境中有效ApplicationContext。
44、Spring配置文件中的ref元素的作用是什么?它的两个基本属性是什么?
ref指定属性值为Spring容器中其它bean,它的两个基本属性是local和bean。
45、框架注解?
(1)Spring
<1>@Controller
<2>@Service
<3>@Resource
<4>@Autowired 注释应用于“传统”setter方法、字段、构造函数等
<5>@Bean
<6>@Required 注释适用于bean属性setter方法
<7>@Primary
<8>@Configuration
<9>@Component
<10>@SessionScope
@Autowired 与@Resource的区别:
1)@Autowired与@Resource都用来装配bean,都可以写在字段上或写在setter方法上。
2)@Autowired默认按类型装配(Spring注解),默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false如:@Autowired(required=false)如果使用名称装配可以结合@Qualifier注解进行使用,如:
@Autowired()@Qualifier("baseDao")
private BaseDao baseDao;
3)@Resource(J2EE注解)默认按照名称进行装配,通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名进行安装名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。如果name属性一旦指定,就只会按照名称进行装配。
@Resource(name="baseDao")
privateBaseDao baseDao;
推荐使用:@Resource注解在字段上,不用写setter方法了并且这个注解是属于J2EE的,减少了与Spring的耦合。
(2)Struts2
<1>@Action 注释组,将多个URL映射到同一个操作
<2>@Result
<3>@ExceptionMapping 异常映射
<4>@ResultPath
<5>@ParentPackage 应用于包(和子包)
<6>@Namespace 命名空间
(3)SpringMVC
<1>@Controller该注解表明该类扮演控制器的角色。
<2>@Service("userService")
<3>@Repository("userDao")
<4>@Resource(name = "userService")
<5>@RequestMapping(value = "/login")来映射Request请求与处理器,用在类或方法上。
<6>@ResponseBody
<7>@RequestParam(value = "cityName[]") String[] cityName
(3)Hibernate
<1>@Entity
<2>@Id
<3>@GeneratedValue(generator="increment")
<4>@GenericGenerator(name="increment", strategy = "increment")
<5>@Temporal(TemporalType.TIMESTAMP)
<6>@Column(name = "EVENT_DATE")
(4)SpringBoot
<1>@RestController 表示修饰该Controller所有的方法返回JSON格式
<2>@EnableAutoConfiguration
<3>@RequestMapping("/")
<4>@Controller
<5>@SpringBootApplication
<6>@ComponentScan
<7>@EntityScan
<8>@SpringBootApplication
<9>@ImportResource
<10>@Configuration
<11>@ExceptionHandler 表示拦截异常
<12>@ControllerAdvice
46、线程(thread)与进程(process)的区别?
(1)进程是程序的一次执行过程,有动态、独立、异步、并发的特征。
(2)线程是进程中的实体,一个进程可以拥有多个线程,每条线程并行执行不同的任务。
(3)线程比进程更快的处理单元,而且所占的资源也小。
(4)线程的存在离不开进程,进程如果消失后线程一定会消失,反之如果线程消失了进程未必消失。
(5)线程是程序执行流的最小单元,线程是独立调度和分派的基本单位。
(6)线程的生命周期:线程是一个动态执行的过程,它也有一个从产生到死亡的过程。
<1>新建状态:使用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就 处于新建状态。它保持这个状态直到程序start()这个线程。
<2>就绪状态:当线程对象调用start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。
<3>运行状态:如果就绪状态的线程获取CPU资源,就可以执行run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
<4>阻塞状态:如果一个线程执行了sleep(睡眠)、suspend[səˈspend](挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:
a、等待阻塞:运行状态中的线程执行wait()方法,使线程进入到等待阻塞状态。
b、同步阻塞:线程在获取synchronized同步锁失败(因为同步锁被其他线程占用)。
c、其他阻塞:通过调用线程的sleep()或join()发出了I/O请求时,线程就会进入到阻塞状态。当sleep()状态超时,join()等待线程终止或超时,或者I/O处理完毕,线程重新转入就绪状态。
<5>死亡状态:一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。
(7)线程与进程的主要区别:
<1>进程间相互独立,同一进程的各线程间共享,某进程内的线程在其它进程不可见。
<2>进程间通信IPC,线程间可以直接读写进程数据段(全局变量)来进行通信,需要进程同步和互斥手段的辅助,以保证数据的一致性。
<3>线程上下文切换比进程上下文切换要快得多。
<4>在多线程OS中,线程不是一个可执行的实体。
47、什么是线程及线程的基本状态?
(1)线程是程序执行流的最小单元。
(2)线程状态分别是创建状态、就绪状态、运行状态、阻塞状态和终止状态。
48、Thread类中的start()和run()方法区别?
(1)start方法用来启动新创建的线程且内部调用了run方法。
(2)run方法只会是在原来的线程中调用,没有新的线程启动。
49、线程中sleep()和wait()的区别?
(1)sleep不释放同步锁,wait释放同步锁。
(2)sleep必须指定时间,wait可以指定时间也可以不指定。
(3)sleep是Thread类的方法,wait是Object类的方法。
50、SOA(面向服务的架构)?
(1)面向服务的架构(SOA)是一个组件模型,它将应用程序的不同功能单元(称为服务)通过这些服务之间定义良好的接口和契约联系起来。接口是采用中立的方式进行定义的,它应该独立于实现服务的硬件平台、操作系统和编程语言。这使得构建在各种各样的系统中的服务可以以一种统一和通用的方式进行交互。
(2)面向于服务架构优点:代码服务、解耦、适合于大公司,人多。
缺点:网络延迟、维护复杂、不好整合、编写复杂、小公司传统项目。
51、RPC远程调用框架有哪些?
(1)SpringCloud
Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring Cloud并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。
(2)HttpClient
HttpClient是Apache Jakarta Common下的子项目,可以用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。
(3)Hessian['hesiən]
Hessian是一个轻量级的remoting onhttp工具,使用简单的方法提供了RMI的功能。相比WebService,Hessian更简单、快捷。采用的是二进制RPC协议,因为采用的是二进制协议,所以它很适合于发送二进制数据。
(4)Dubbo
(开源分布式服务框架)是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的RPC实现服务的输出和输入功能,可以和Spring框架无缝集成。
(5)Web Service
Web Service是一个平台独立的,低耦合的,自包含的、基于可编程的Web的应用程序,可使用开放的XML标准来描述、发布、发现、协调和配置这些应用程序,用于开发分布式的互操作的应用程序。Web Service能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件,就可相互交换数据或集成。依据Web Service规范实施的应用之间,无论它们所使用的语言、平台或内部协议是什么,都可以相互交换数据。Web Service是自描述、自包含的可用网络模块,可以执行具体的业务功能。Web Service也很容易部署,因为它们基于一些常规的产业标准以及已有的一些技术,诸如标准通用标记语言下的子集XML、HTTP。Web Service减少了应用接口的花费。Web Service为整个企业甚至多个组织之间的业务流程的集成提供了一个通用机制。
52、Tomcat的调优思路?
(1)Tomcat的自身调优
①采用Nginx+Tomcat动静分离节约Tomcat的性能
Tomcat处理静态资源性能会被损耗,采用Nginx+Tomcat实现动静分离,Nginx实现静态资源访问,Tomcat负责jsp解析。
Nginx是一个高性能的Web(HTTP)和反向代理服务,因它的稳定性、丰富的功能集、示例配置文件和低系统资源消耗而闻名,特点是占有内存少,并发能力强,优点是可以在Unix、Linux、OS上编译运行,并有Windows移植版。
②调整Tomcat的线程池
<1>打开Tomcat的serve.xml文件,配置Executor[ɪɡ'zekjətə(r)]。
<2><Executor name="tomcatThreadPool"
namePrefix="catalina-exec-"
maxThreads="500"
minSpareThreads="20"
maxIdleTime="60000"
/>
name:给线程池起一个名字
namePrefix:指定线程池中的每一线程的name前缀
maxThreads:线程池中最大的线程数量
minSpareThreads:线程池中允许空闲的线程数量
maxIdleTime:一个线程空闲多久算是一个空闲线程
③调整Tomcat的连接器
<1>打开Tomcat的serve.xml文件,配置Connector[kə'nektə(r)]。
<2><Connector executor="tomcatThreadPool"
port="8080"
protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
enableLookups="false"
minProcessors="10"
maxProcessors="30"
acceptCount="1000"
/>
enableLookups:关闭DNS解析,减少性能损耗
minProcessors:服务启动时创建的最少线程数
maxProcessors:服务启动时创建的最多线程数
acceptCount:接收的队列数
④修改Tomcat的运行模式
<1>Tomcat8以下版本默认是BIO(阻塞式IO)模式,对于每一个请求都要创建一个线程来进行处理,不适合高并发。
<2>Tomcat8以上版本默认是NIO(非阻塞式IO)
⑤禁用AJP的连接器
<1>使用Nginx+Tomcat实现动静分离,所以把AJP协议连接器禁用。
<2><!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> -->
(2)调优JVM内存
<1>在tomcat的bin目录下找到catalina.sh,添加如下内容(添加在cygwin=false之前110行)。
<2>JAVA_OPTS="-Xms256m -Xmx512m -Xss1024k -XX:PermSize=128m -XX:MaxPermSize=256m"
53、synchronized修饰同步方法和同步代码块有什么区别?
(1)synchronized用来给对象和方法或者代码块加锁。
(2)synchronized后面括号里是对象或类,线程获得的是对象锁,在对象上使用锁通常是一种比较粗糙。当两个并发线程访问同一个对象object中synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行,另一个线程必须等待当前线程执行完以后才能执行该代码块,一个线程访问其它线程访问将被阻塞。
public class MyThread implements Runnable {
public static void main(String[] args) {
MyThread mt = new MyThread();
Thread t1 = new Thread(mt, "t1");
Thread t2 = new Thread(mt, "t2");
t1.start();
t2.start();
}
public void run() {
synchronized (this) {
System.out.println(Thread.currentThread().getName());
}
}
}
(3)synchronized方法声明时使用线程获得的是成员锁,一次只能有一个线程进入该方法,其它线程要想在此时调用该方法,只能排队等待,当前线程执行完该方法后,别的线程才能进入。
public synchronized void synMethod(){//方法体}
(4)synchronized后括号里是变量,代码块使用线程获得的是成员锁,一次只有一个线程进入该代码块。
public Object synMethod(Object a1) {
synchronized (a1) {// 一次只能有一个线程进入}
}
(5)锁和对象是相关联的每个对象只有一把锁,被一个线程获得之后它就不再拥有此锁,线程执行完synchronized语句后,将获得锁交还给对象。
(6)在方法前面加上synchronized即可以将一个方法声明为同步化方法,在执行之前获得一个锁,如果这是一个类方法,此锁和声明方法的类相关的Class类对象的锁,如果这是一个实例方法,此锁是this对象的锁。
54、怎么处理OutOfMemoryError异常,JVM中堆和栈分别存放何种数据或对象?
(1)产生OutOfMemoryError异常原因:JVM内存过小、程序不严密产生了过多的垃圾。['meməri]存储
(2)因为内存溢出或没有可用的内存提供给垃圾回收器时,java虚拟机无法分配一个对象,这时抛出该异常。
(3)解决此异常方法:
<1>增加jvm的内存大小
a、MyEclipse设置JVM:-Xmx1024m -Xms1024m -Xmn256m -Xss16m
b、Tomcat设置JVM:set JAVA_OPTS=-Xmx512m -Xms512m -Xmn64m -Xss2m
<2>优化程序,释放垃圾,主要包括避免死循环,应该及时释放种资源,数据库的各种连接,防止一次加载太多的数据至内存。
55、struts2里面跳转模式常用有以下四种:
(1)转发:type="dispatcher",默认的跳转形式,表示使用服务器端跳转,没写表示默认跳转(路径不变)。
<result name="addM" type="dispatcher">/WEB-INF/resource/since/lztj/addMember.jsp</result>
(2)重定向:type="redirect",跳转到另一个Action中表示使用客户端跳转(路径改变)。
<result name="addsucc" type="redirect">active_SearchPage.action</result><!-- action 跳action 加type属性 -->
(3)重定向到Action:type="redirectAction"。
<result name="saveok" type="redirectAction">research_ressearch.action</result>
(4)转发到Action:type="chain"
<result name="updateGroup" type="chain">treeAction</result>
56、Java实现多线程的方式有哪些?
(1)继承Thread类创建线程
(2)实现Runnable接口创建线程
(3)使用Callable['kɔːləbl]和Future['fjuːtʃə(r)]创建线程
(4)继承Thread类来创建并启动多线程的步骤:
(1)定义Thread类的子类,并重写该类的run()方法,该方法是线程需要完成的任务称为线程执行体。
(2)创建Thread子类的实例即线程对象。
(3)启动线程即调用线程的start()方法。
(5)实现Runnable接口创建并启动线程的步骤:
(1)定义Runnable接口的实现类,并重写该类的run()方法,此方法是线程的执行体。
(2)创建Runnable实现类的实例,此实例作为Thread的target来创建Thread对象,这个Thread对象才是线程对象。
(3)启动线程即调用线程的start()方法。
(6)使用Callable和Future创建线程步骤:
(1)创建Callable接口的实现类,并实现call()方法,然后创建该实现类的实例。
(2)使用FutureTask类来包装Callable对象,该FutureTask对象封装了Callable对象的call()方法的返回值。
(3)使用FutureTask对象作为Thread对象的target创建并启动线程。
(4)调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。
(7)Thread类是Runnable接口的子类,使用Runnable接口实现多线程可以避免单继承的局限性。
(8)Runnable接口实现的多线程比Thread类实现的多线程更加清楚的描述数据共享的概念。
(9) Callable和Future创建线程示例
public class CallableThreadTest implements Callable<Integer> {
public Integer call() throws Exception {
int i = 0;
for (; i < 50; i++) {
System.out.println(Thread.currentThread().getName() + "--" + i);
}
return i;
}
public static void main(String[] args) throws Exception {
CallableThreadTest ctt = new CallableThreadTest();
FutureTask<Integer> ft = new FutureTask<Integer>(ctt);
for (int i = 0; i < 50; i++) {
System.out.println(Thread.currentThread().getName() + "-的循环变量i的值-" + i);
if (i == 10) {
new Thread(ft, "有返回值的线程").start();
}
}
System.out.println("子线程的返回值:" + ft.get());
}
}
57、HashSet和TreeSet有什么区别?
(1)HashSet实现Set接口,哈希表,不同步的,存储不重复的对象,无序的,允许使用null元素。
(2)TreeSet是有序的,不同步的。
58、事务的ACID是指什么?
(1)事务的ACID是指原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
(2)原子性:整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
(3)一致性:一个事务可以封装状态改变(除非它是一个只读的)。事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少。
(4)隔离性:隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相同的时间内,执行相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。这种属性有时称为串行化,为了防止事务操作间的混淆,必须串行化或序列化请求,使得在同一时间仅有一个请求用于同一数据。
(5)持久性:在事务完成以后,该事务对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
59、实现多态有哪几种方式?
(1)重写:Java重写(Override)与重载(Overload)。
(2)接口:Java中的接口类似于生活中的接口,就是一些方法特征的集合,但没有方法的实现。
(3)抽象类和抽象方法
60、对线程池的理解?
线程池(thread pool):一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。
61、JVM的常量区都放什么?
(1)JVM有两类存储区:常量缓冲池和方法区。
(2)常量缓冲池用于存储类名称、方法和字段名称以及串常量。
(3)方法区则用于存储Java方法的字节码。
62、JVM执行程序的过程是什么?
(1)加载.class文件
(2)管理并分配内存
(3)执行垃圾收集
63、JVM的堆主要是做什么的?
(1)内存划分为:栈内存、堆内存、寄存器、方法区。
(2)栈内存存储的都是局部变量,而且变量所属的作用域一旦结束,该变量就自动释放。
(3)堆内存存储是数组和对象(其实数组就是对象),凡是new建立在堆中。
(4)堆内存特点:
①每一个实体都有首地址值。
②堆内存中的每一个变量都有默认初始化值,根据类型的不同而不同。
整数是0,小数是0.0或0.0f,boolean false char ‘u0000’
③垃圾回收机制
64、JRE和JVM的区别?
(1)JRE(JavaRuntimeEnvironment,Java运行环境),也就是Java平台。所有的Java程序都要在JRE下才能运行。JDK的工具也是Java程序,也需要JRE才能运行。为了保持JDK的独立性和完整性,在JDK的安装过程中,JRE也是安装的一部分。所以,在JDK的安装目录下有一个名为jre的目录,用于存放JRE文件。
(2)JVM(JavaVirtualMachine,Java虚拟机)是JRE的一部分。它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。JVM有自己完善的硬件架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。Java语言最重要的特点就是跨平台运行。使用JVM就是为了支持与操作系统无关,实现跨平台。
65、怎样会导致内存溢出,内存溢出有几种?
(1)内存溢出是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于虚拟机能提供的最大内存。
(2)Java的内存管理是对象的分配和释放问题,内存分配是由程序完成,内存释放是由垃圾收集器(GarbageCollection,GC)完成,GC只能回收无用并且不再被其它对象引用对象所占用的空间。
(3)Java的内存垃圾回收机制是从程序的主要运行对象开始检查引用链,当遍历一遍后发现没有被引用的孤立对象就作为垃圾回收。
(4)内存溢出原因:
<1>内存中加载的数据量过多,如一次从数据库取出过多数据。
<2>集合类中有对象的引用,使用完后未清空,使得JVM不能回收。
<3>代码中存在死循环或循环产生过多重复的实体对象。
<4>使用的第三方软件中的BUG。
<5>启动参数设定的过小。
(5)内存溢出解决方法:
<1>修改JVM启动参数,直接增加内存。JVM默认内存为64MB,Tomcat默认内存为128MB,经常报"OutOfMemory"错误,因此修改,-Xms,-Xmx参数。
<2>检查错误日志,查看"OutOfMemory"错误前是否有其它异常或错误。
<3>对代码进行分析找出可能发生内存溢出的位置。
①检查代码中是否有死循环或递归调用。
②检查是否有循环重复产生新对象实体。
③检查对数据库查询中是否有一次获得全部数据的查询,对于数据库查询尽量采用分页的方式查询。
④检查List、Map等集合对象是否有使用完后未清除的问题。
<4>使用内存查看工具动态查看内存使用情况,内存查看工具:Optimizeit Profiler、JProbeProfiler、JinSight和Java1.5的Jconsole等。
66、Java中会出现内存泄露吗?
(1)内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
(2)内存泄露分类:
<1>常发性内存泄漏
<2>偶发性内存泄漏
<3>一次性内存泄漏
<4>隐式内存泄漏
(2)内存泄漏原因是长生命周期的对象持有短生命周期对象的引用,尽管短生命周期对象已经不再需要,但是因为长生命周期持有它的引用而导致不能被回收,如:
<1>静态集合类引起内存泄漏
<2>当集合里面的对象属性被修改后,再调用remove()方法时不起作用。
<3>在释放对象的时候没有去删除监听器
<4>各种连接没有关闭,如数据库连接、io连接等
<5>内部类和外部模块的引用
<6>单例模式中对象在初始化后将在JVM的整个生命周期中存在,如果单例对象持有外部的引用,此对象将不能被JVM正常回收。
67、GC是什么? 为什么要有GC?
(1)垃圾回收机制(Garbage Collection,GC):当需要分配的内存空间不再使用的时候,JVM将调用垃圾回收机制来回收内存空间(2)Garbage-Collect定时器,RIP路由协议用来维护路由信息的,它定义了一条路由从度量值变为16开始,直到它从路由表里被删除所经过的时 间。如果Garbage-Collect超时,该路由仍没有得到更新,则该路由将被彻底删除,默认值为120秒。
(3)回收不再使用的内存空间。
(4)系统级线程跟踪存储空间的分配情况,并在JVM的空闲时,检查并释放那些可被释放的存储空间。
(5)垃圾回收在Java程序运行过程中自动运行,程序员无法精确控制和干预。
68、静态内部类(Static Nested Class)和内部类(Inner Class)有什么不同?
(1)静态内部类分为:常规内部类、局部内部类、匿名内部类和静态嵌套类四种。
(2)静态内部类只能访问外部类的静态成员,静态内部类的对象可以直接生成。
(3)生成(new)一个静态内部类不需要外部类成员,静态内部类的对象可以直接生成:Outer.Inner in=new Outer.Inner();
不需要通过生成外部类对象来生成,使静态内部类成为了一个顶级类。
(4)内部类分为:静态内部类、成员内部类、局部内部类、匿名内部类。
(5)内部类优点:
<1>内部类对象可以访问创建它的对象的实现,包括私有数据。
<2>内部类不为同一包的其它类所见,具有很好的封装性。
<3>使用内部类可以很方便的编写事件驱动程序。
<4>匿名内部类可以方便的定义运行时回调。
69、BigDecimal与Double的区别?
(1)BigDecimallei类用来对超过16位有效位的数进行精确的运算。
(2)双精度浮点型变量double可以处理16位有效数。
(3)在实际应用中需要对更大或者更小的数进行运算和处理。float和double只能用来做科学计算或者是工程计算,在商业计算中要用java.math.BigDecimal。
(4)BigDecimal所创建的是对象不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法,方法中的参数也必须是BigDecimal的对象。
70、Java中WeakReference与SoftReference的区别?
(1)WeakReference与SoftReference都继承Reference类,Reference['refrəns]类是引用对象的抽象基类。
(1)WeakReference弱引用对象,它们并不禁止其指示对象变得可终结,并被终结,然后被回收,弱引用最常用于实现规范化的映射。
(2)SoftReference软引用对象,在响应内存需要时,由垃圾回收器决定是否清除此对象,软引用对象最常用于实现内存敏感的缓存。
71、实例方法与静态方法区别?
(1)
(2)静态方法只能访问静态成员,静态方法中不可以使用this或者super关键字。
71、GET和POST提交乱码?
(1)HttpServletResponse response = ServletActionContext.getResponse();
HttpServletRequest request = ServletActionContext.getRequest();
request.setCharacterEncoding("utf-8");
request.getParameter("name").getBytes("utf-8")
response.setCharacterEncoding("UTF-8");
response.setContentType("application/octet-stream;charset=utf-8");
response.encodeURL(new String(name.getBytes(),"utf-8"));
response.setContentType("text/json;charset=utf-8");
String name = java.net.URLDecoder.decode(name, "UTF-8");
(2) web.xml文件filter配置
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
72、Anonymous Inner Class(匿名内部类)是否可以extends(继承)其它类,是implements(实现)interface(接口)?
(1)匿名内部类可以继承其它类,可以实现接口。
(2)匿名内部类的声明格式如下:
new ParentName(){
// 内部类的定义
}
(3)使用匿名内部类场景:
<1>只用到类的一个实例
<2>类在定义后马上用到
<3>类非常小(SUN推荐是在4行代码以下)
<4>给类命名并不会导致你的代码更容易被理解。
<5>在使用匿名内部类时,要记住以下几个原则:
[1]匿名内部类不能有构造方法。
[2]匿名内部类不能定义任何静态成员、静态方法。
[3]匿名内部类不能是public,protected,private,static。
[4]只能创建匿名内部类的一个实例。
[5]一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
[6]因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。
(4)继承式的匿名内部类
public class Car {
public void drive() {
System.out.println("Driving a car!");
}
public static void main(String[] args) {
Car car = new Car() {
public void drive() {
System.out.println("Driving another car!");
}
};
car.drive();
}
}
运行结果: Driving another car!
(5)接口式的匿名内部类
public interface Car {
public void drive();
}
public class BMWCar {
public static void main(String[] args) {
Car vchile = new Car(){
public void drive() {
System.out.println("This is a car.");
}
};
vchile.drive();
}
}
运行结果:This is a car.
(6)参数式的匿名内部类
public interface Car {
public void carRun();
}
public class BMWCar {
public void doBMWCar(Car car) {
car.carRun();
}
}
public class BMWCarTest {
public static void main(String[] args) {
BMWCar bmw = new BMWCar();
bmw.doBMWCar(new Car() {
public void carRun() {
System.out.println("This is a BMW limousine.");
}
});
}
}
运行结果: This is a BMW limousine.
5、面向对象中接口有什么作用?一般在什么情况下使用?
6、分别举一个泛型类和泛型方法的例子?
7、系统设计中有两个实体类:部门(Department)和用户(User),它们之间是一对多的关系时,如何设计?如果是多对多呢?请写出关键部分接口。
8、Spring和Struts怎么集成的?
71、编写Shell脚本时,经常需要引用到命令行参数,$1,$#,$*分别表示什么含义?(C)
A.调用命令自身,命令行参数个数,所有的命令行参数
B.调用命令自身,所有的命令行参数,命令行参数个数
C.第一个命令行参数(非命令自身),命令行参数个数,所有的命令行参数
D.第一个命令行参数(非命令自身),所有的命令行参数,命令行参数个数
72、linux的基本命令?
(1)ls显示指定工作目录下之内容
(2)pwd显示出当前工作目录的绝对路径
(3)cd进入目录
(4)mkdir创建目录
(5)rmdir命令删除空的目录
(6)rm删除目录或文件 rm -r homework
(7)cp复制文件或目录
(8)mv用来为文件或目录改名、或将文件或目录移入其它位置
(9)ps显示当前进程的状态
ps -ef 显示所有进程信息
(10)ping用于检测主机
(11)su切换用户
(12)exit 退出终端
(13)df显示磁盘可用空间数目信息及空间结点信息
(14)du统计目录(或文件)所占磁盘空间的大小
(15)ifconfig命令用于显示或设置网络设备
(16)uname用于显示系统信息
(17)telnet用于远端登入
(18)zip命令用于压缩文件
(19)tar命令用于备份文件
(20)env显示当前用户的环境变量
(21)ftp设置文件系统相关功能
(22)more以一页一页的形式显示
(23)echo用于字符串的输出
(24)tail +20 notes.log显示文件notes.log的内容,从第20行至文件末尾
73、构造函数何时被调用(B)
A.类定义时 B.创建对象时 C.调用对象方法时 D.使用对象的变量时
74、short s1 = 1;s1 += 1;和short s1 = 1;s1 = s1 + 1;是否都能正确运行?为什么?
(1)short s1 = 1;s1 += 1;编译成功,short s1 = 1;s1 = s1 + 1;编译失败。
(2)s1 = s1 + 1编译失败原因是它已经进行了自动类型的提升,类型已经不能再赋给低值类型或低空间类型,因为精度丢失。
(3)s1 += 1编译成功是因为底层做了强制类型转换动作。
75、用Java正则表达式,验证由26个英文字母组成的字符串。
(1)boolean b1 = Pattern.compile("^+[a-zA-Z]+$").matcher("a").matches();
(2)boolean b2 = Pattern.matches("^+[a-zA-Z]+$", "a");
注:Pattern模式 matches()方法编译表达式并在单个调用中将输入序列与其匹配
76、Math.ceil(-6.8)的值等于多少(A)
A.-6.0 B.-7.0 C.-6.5 D.-5.0
【解析1】ceil函数返回最小的(最接近负无穷大)double 值,该值大于等于参数,并等于某个整数。
double b1=Math.ceil(6.8);结果:7.0
【解析2】floor函数返回最大的(最接近正无穷大)double 值,该值小于等于参数,并等于某个整数。
double b2=Math.floor(6.8);结果:6.0
77、Math.round(11.5)等于多少?Math.round(-11.5)等于多少?
long a = Math.round(11.5);
long b = Math.round(-11.5);
a = 12 b = -11 注:round(double a)返回最接近参数的long。
78、float f=3.4是否正确?
(1)不正确,精度不准确应该用强制类型转换。
(2)正确声明方式是float f =(float)3.4。
79、多态的表现形式有(A)
A.重写 B.抽象 C.继承 D.封装
80、下列哪个选项不是Collection接口的子接口?(C)
A.List B.Set C.Map D.Vector
81、计算题
(1)int n = 7
int a = 2 * ++n;
int b = 2 * n++;
a、b、c的值分别是多少
a = 16 b = 16 n = 9
(2)int answerA = 5 & 7;
int answerB = 5 | 2;
answerA = 5 answerB = 7
82、&(与)运算特点?
true & true = true
true & false = false
false & true = false
false & false = false
(1)&两边有一个是false,结果肯定是false。
(2)&两边都是true,结果才是true。
83、|(或)运算特点?
true | true = true
true | false = true
false | true = true
false | false = false
(1)|两边有一个是true,结果肯定是true。
(2)|两边都是false,结果才是false。
84、^(异或)运算特点?
true ^ true = false
true ^ false = true
false ^ true = true
false ^ false = false
(1)^两边如果相同,结果是false。
(2)^两边如果不同,结果是true。
85、!(非运算)运算特点?
!true = false
!false = true
!!true = true
86、&和&&区别?
(1)运算结果是一样的,但是运算过程有点小区别。
(2)&无论左边结果是什么,右边都参与运算。
(3)&&左边为false时,右边不参与运算。
87、|和||区别?
(1)运算结果是一样的,但是运算过程有点小区别。
(2)|无论左边结果是什么,右边都参与运算。
(3)||左边为true时,右边不参与运算。
88、Java符号含义?
(1) 回车:
(2) 制表符。
(3) 退格。
(4) 按下回车键。
(5)windows系统中回车符其实是由两个符号组成的 ,linux中回车符是 。
(6)获取换行符:private static final String LINE_SEPARATOR = System.getProperty("line.separator");
89、当出现在如下错误时,你会最先选择调整JVM的哪一个参数?(ABF)
Exception in thread “main”java.lang.OutOfMemoryError:Java heap space.
A.-Xms B.-Xmx C.Xmem D.-XX:HeapSize E.XX:PermSize F.XX:MaxPermSize
【设置MyEclipse中Tomcat使用的Jdk的VM arguments:-Xms512m -Xmx1024m -XX:MaxNewSize=512m -XX:MaxPermSize=512m】
90、AssertionError是下面哪个类的子类(D)?
A.RuntimeException B.VirtualMachineError C.Exception D.Throwable
注:AssertionErroràErroràThrowableàObject
ExceptionàThrowableàObject
注:AssertionError:抛出该异常指示某个断言失败
91、在Servlet的生命周期中,容器只调用一次的方法是(C)
A.service B.getServletConfig C.init D.destroy
92、下面哪个方法不属于HttpServlet的基本方法(C)?
A.doGet B.doPut C.doQuery D.doDelete E.doPost
93、以下模式中属于行为模式的是(E)?
A.Abstract Factory(抽象工厂模式—创建型模式) B.Facade(外观模式—结构型模式)
C.Proxy(代理模式—结构型模式) D.Singleton(单例模式—创建型模式) E.Observer(观察者模式—行为型模式)
94、下面关于变量及其范围的陈述哪些是不正确的(B)?
A、实例变量是类的成员变量(√) B、实例变量用关键字static声明(静态成员,也叫类变量需要static)
C、在方法中定义的局部变量在该方法被执行时创建(√) D、局部变量在使用前必须初始化(√)
95、下面能让线程停止执行的有(多选)(ABCEG)
A、sleep(); // 在指定的毫秒数加指定的纳秒数内让当前正在执行的线程休眠(暂停执行)
B、stop(); //具有不安全性(已过时),强制停止线程。
C、notify(); //在其它线程调用此对象的notify()或notifyAll()前导致当前线程等待。
D、synchronzied();
E、yield(); //暂停当前正在执行的线程对象,并执行其他线程
F、wait();
G、notifyAll()//唤醒在此对象监视器上等待的所有线程。
96、int类型可以强制转为byte类型吗?为什么?
int类型可以强制转为byte类型,超过byte取值范围就会丢失精度。
70、char型变量中能不能存储一个中文汉字?为什么?
char型变量能存储一个中文,因为Java采用的unicode编码,一个char占16字节,而一个中文汉字占两个字节。
97、switch的表达式可以是哪些数据类型?
switch的表达式是int、short、char、byte;
98、String str = new String(“xyz”)创建了几个字符串对象?
创建两个对象,一个new字符串对象在堆内存中。
99、下面哪个流类属于面向字符的输入流(D)
A.BufferedWriter B.FileInputStream C.ObjectInputStream D.InputStreamReader
100、ArrayList list = new ArrayList(30);中的list扩充了几次(A)。
A、0 B、1 C、2 D、3
注:ArrayList默认10数组
101、项目中关联到金额,用什么数据类型?
(1)项目中关联到金额使用BigDecimal类型
(2)public class BigDecimalDemo {
public static void main(String[] args) {
BigDecimal a = new BigDecimal("4.5");
BigDecimal b = new BigDecimal("1.5");
System.out.println("a + b =" + a.add(b));
System.out.println("a - b =" + a.subtract(b));
System.out.println("a * b =" + a.multiply(b));
System.out.println("a / b =" + a.divide(b));
BigDecimal a1 = new BigDecimal("4.5634");
BigDecimal a2 = a1.setScale(3, RoundingMode.HALF_UP);//保留3位小数,且四舍五入
System.out.println(a2);
}
}
a + b =6.0
a - b =3.0
a * b =6.75
a / b =3
a2 = 4.563
102、软件工程?
软件工程是研究和应用如何以系统性的、规范性的、可定量的过程化方法去开发和维护软件,以及如何把经过时间考验而证明正确的管理技术和当前能够得到的最好的技术方法结合起来的学科。它涉及到程序设计语言、数据库、软件开发工具、系统平台、标准、设计模式等方面。
103、CMMI?
(1)CMMI(Capability Maturity Model Integration),软件能力成熟度集成模型。
(2)CMMI目的是帮助软件企业对软件工程过程进行管理和改进,增强开发与改进能力,从而能按时地、不超预算地开发出高质量的软件。其想法是:只要集中精力持续努力去建立有效的软件工程过程的基础结构,不断进行管理的实践和过程的改进,就可以克服软件开发中的困难。
(3)CMMI主要关注点是成本效益、明确重点、过程集中和灵活性四个方面。
(4)CMMI过程域:过程管理、项目管理、工程管理、支持管理。
103、问题:烧一根均匀的绳,从头烧到尾总共需要1小时。现在有若干材质相同的绳子,问如何用烧绳的方法来计时一个小时十五分钟呢?
(1)需要准备三根绳子。
(2)第一根绳子和第二根绳子同时点燃,第一根绳子点燃一头,第二根绳子点燃两头。
(2)在第二根绳子燃完后(30分钟),点燃第一根绳子的另一头。
(3)前两根绳子燃完后(15分钟),点燃第三根绳子的两头。
(4)全部燃完后(30分钟),一共就是1小时15分钟。
171、下面程序的运行结果是(false)
public static void main(String[] args) {
String str1 = "hello";
String str2 = "he" + new String("llo");
System.out.println(str1 == str2);
}
96、有一个整数类型的数组arr,写出从小到大进行排列的算法(冒泡排序)。
public static void main(String[] args) {
int[] arr = { 6, 3, 8, 2, 9, 1 };
for (int x = arr.length - 1; x > 0; --x) {
for (int y = 0; y < x; ++y) {
if (arr[y + 1] < arr[y]) {
int temp = arr[y];
arr[y] = arr[y + 1];
arr[y + 1] = temp;
}
}
}
}
97、用java实现数组的反转
public static void main(String[] args) {
int[] arr = { 6, 3, 8, 2, 9, 1 };
for (int s = 0, e = arr.length - 1; s < e; s++, e--) {
int t = arr[s];
arr[s] = arr[e];
arr[e] = t;
}
}
98、用Java递归实现1,1,2,3,5,8,,,,第30个数是多少?请写出算法。
public static int recursion(int i) {// i = 30
if (i <= 0) {
return 0;
} else if (i > 0 && i <= 2) {
return 1;
}
return recursion(i - 1) + recursion(i - 2);
}
运行结果:832040
99、已知源目录路径sourceFilePath,此目录下还有多级子目录和多个文本文件(*.txt)。尝试编写一个方法,将此目录下所有的文件拷贝至另一个目录targetFilePath,并其中的文本文件修改成SQL文件(*.sql)。
public void copyFile(String oldPath, String newPath) throws IOException {
(new File(newPath)).mkdirs();
String[] file = new File(oldPath).list();
File fileTemp = null;
String separator = File.separator;
for (int i = 0; i < file.length; i++) {
if (oldPath.endsWith(separator)) {
fileTemp = new File(oldPath + file[i]);
} else {
fileTemp = new File(oldPath + separator + file[i]);
}
if (fileTemp.isFile()) {
FileInputStream fis = new FileInputStream(fileTemp);
if (file[i].endsWith(".txt")) {
fileTemp = new File(oldPath + separator + file[i].substring(0, file[i].length() - 4) + ".sql");
}
FileOutputStream fos = new FileOutputStream(newPath + "/" + fileTemp.getName());
byte[] b = new byte[1024 * 5];
int len;
while ((len = fis.read(b)) != -1) {
fos.write(b, 0, len);
}
fos.flush();
fos.close();
fis.close();
}
if (fileTemp.isDirectory()) {
this.copyFile(oldPath + "/" + file[i], newPath + "/" + file[i]);
}
}
}
100、手写一个线程安全的生产者与消费者。
public class Resource {// 资源
private String name;
private int count = 1;
private boolean flag = false;
Lock lock = new ReentrantLock();// 创建一个对象锁
private Condition producer_con = lock.newCondition();//通过已有的锁获取两组监视器,一组监视生产者,一组监视消费者
private Condition consumer_con = lock.newCondition();
public void set(String name) {
lock.lock();
try {
while (flag) {
try {
producer_con.await();
} catch (InterruptedException e) {}
}
this.name = name + count;
count++;
System.out.println(Thread.currentThread().getName() + "...生产者..." + this.name);
flag = true;
consumer_con.signal();
} finally {
lock.unlock();
}
}
public void out() {
lock.lock();
try {
while (!flag) {
try {
consumer_con.await();
} catch (InterruptedException e) {}
}
System.out.println(Thread.currentThread().getName() + "...消费者..." + this.name);
flag = false;
producer_con.signal();
} finally {
lock.unlock();
}
}
}
public class Producer implements Runnable {// 生产者
private Resource resource;
public Producer(Resource resource) {
this.resource = resource;
}
public void run() {
while (true) {
resource.set("烤鸭");
}
}
}
public class Consumer implements Runnable {// 消费者
private Resource resource;
public Consumer(Resource resource) {
this.resource = resource;
}
public void run() {
while (true) {
resource.out();
}
}
}
public class ProducerConsumerDemo {
public static void main(String[] args){
Resource resource = new Resource();
Producer producer = new Producer(resource);
Consumer consumer = new Consumer(resource);
Thread t0 = new Thread(producer);
Thread t1 = new Thread(producer);
Thread t2 = new Thread(consumer);
Thread t3 = new Thread(consumer);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
运行结果:
Thread-0...生产者...烤鸭1
Thread-2...消费者...烤鸭2
Thread-0...生产者...烤鸭2
Thread-3...消费者...烤鸭2
Thread-0...生产者...烤鸭3
Thread-2...消费者...烤鸭3
101、设计模式 ?
(1)设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。
(2)设计模式总共有23种分为三大类:创建型模式(Creational Patterns)、结构型模式(Structural Patterns)、行为型模式(Behavioral)。
<1>创建型模式:单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式。
[1]单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
[2]抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
[3]建造者模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
[4]工厂模式:定义一个用于创建对象的接口,让子类决定将哪一个类实例化。
[5]原型模式:用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象。
<2>结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
[6]适配器模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
[7]桥接模式:将抽象部分与它的实现部分分离,使它们都可以独立地变化。
[8]装饰模式:动态地给一个对象添加一些额外的职责。
[9]组合模式:将对象组合成树形结构以表示“部分-整体”的层次结构。它使得客户对单个对象和复合对象的使用具有一致性。
[10]外观模式:为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
[11]享元模式:运用共享技术有效地支持大量细粒度的对象。
[12]代理模式:为其他对象提供一个代理以控制对这个对象的访问。
<3>行为型模式:模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式(责任链模式)、访问者模式。
[13]模板方法模式:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
[14]命令模式:将一个请求封装为一个对象,可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可取消的操作。
[15]迭代器模式:提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示。
[16]观察者模式:定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。
[17]中介模式:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
[18]备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
[19]解释器模式:给定一个语言, 定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。
[20]状态模式:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它所属的类。
[21]策略模式:定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法的变化可独立于使用它的客户。
[22]责任链模式:为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它。
[23]访问者模式:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
(4)设计模式的六大原则
<1>开闭原则<2>里氏代换原则<3>依赖倒转原则<4>接口隔离原则<5>迪米特法则<6>合成复用原则
(5)创建型模式
①单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
主要解决:一个全局使用的类频繁地创建与销毁。
public class SingleLazy {
private static SingleLazy sl = null;// sl是共享数据
public SingleLazy() {}
public static SingleLazy getInstance() {
if (sl == null) {// 加判断解决线程效率问题
synchronized (SingleLazy.class) {// 加锁解决线程安全问题
if (sl == null) {
sl = new SingleLazy();
}
}
}
return sl;
}
}
public class SingleHungry {
private static final SingleHungry sh = new SingleHungry();
public SingleHungry() {}
public static SingleHungry getInstance() {
return sh;
} // 不存在安全问题,无论谁来都返回同一地址,而且sh已经是final,值固定不变。
}
②工厂模式:定义一个用于创建对象的接口,让子类决定将哪一个类实例化。
主要解决:主要解决接口选择的问题。
public interface Shape {//形状
public void draw();
}
public class Circle implements Shape {//圆形
public void draw() {//绘制(图形)
System.out.println("Inside Circle::draw() method.");
}
}
public class Rectangle implements Shape {//长方形
public void draw() {//绘制(图形)
System.out.println("Inside Rectangle::draw() method.");
}
}
public class ShapeFactory {
public Shape getShape(String shapeType) {//使用getShape方法获取形状类型的对象
if (shapeType == null) {
return null;
}
if (shapeType.equalsIgnoreCase("CIRCLE")) {
return new Circle();//生产圆形
} else if (shapeType.equalsIgnoreCase("RECTANGLE")) {
return new Rectangle();//生产长方形
}
return null;
}
}
public class FactoryPatternDemo {
public static void main(String[] args) {
ShapeFactory shapeFactory = new ShapeFactory();
Shape shapeCircle = shapeFactory.getShape("CIRCLE");//获取Circle的对象,并调用它的draw方法
shapeCircle.draw();//调用圆形的draw方法
Shape shapeRectangle = shapeFactory.getShape("RECTANGLE");//获取Rectangle的对象,并调用它的draw方法
shapeRectangle.draw();//调用长方形的draw方法
}
}
运行结果:
Inside Circle::draw() method.
Inside Rectangle::draw() method.
③抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
主要解决:主要解决接口选择的问题。
public interface Shape {//形状:为形状创建一个接口
public void draw();//绘制(图形)
}
public class Circle implements Shape {//圆形:创建实现接口的实体类
public void draw() {//绘制(圆形)
System.out.println("Inside Circle::draw() method.");
}
}
public class Rectangle implements Shape {//长方形:创建实现接口的实体类
public void draw() {//绘制(长方形)
System.out.println("Inside Rectangle::draw() method.");
}
}
public abstract class AbstractFactory {//为Shape对象创建抽象类来获取工厂
public abstract Shape getShape(String shape);//获取形状
}
public class ShapeFactory extends AbstractFactory {//创建扩展了AbstractFactory
public Shape getShape(String shapeType) {//获取形状
if (shapeType == null) {
return null;
}
if (shapeType.equalsIgnoreCase("CIRCLE")) {//圆形
return new Circle();//生产圆形
} else if (shapeType.equalsIgnoreCase("RECTANGLE")) {//长方形
return new Rectangle();//生产长方形
}
return null;
}
}
public class FactoryProducer {//创建一个工厂创造器/生成器类,通过传递形状信息来获取工厂。
public static AbstractFactory getFactory(String choice) {
if (choice.equalsIgnoreCase("SHAPE")) {//形状
return new ShapeFactory();//形状工厂
}
return null;
}
}
public class AbstractFactoryPatternDemo{//使用FactoryProducer获取AbstractFactory通过传递类型信息来获取实体类的对象。
public static void main(String[] args) {
AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");//获取形状工厂
Shape shapeCircle = shapeFactory.getShape("CIRCLE");//获取形状为圆形的对象
shapeCircle.draw();//调用圆形的draw方法
Shape shapeRectangle = shapeFactory.getShape("RECTANGLE");//获取形状为长方形的对象
shapeRectangle.draw();//调用长方形的draw方法
}
}
运行结果:
Inside Circle::draw() method.
Inside Rectangle::draw() method.
(6)观察者模式:定义对象间的一种一对多依赖关系,当一个对象的状态发生改变时,所以依赖于它的对象得到通知并被自动更新。
主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
public abstract class Observer {//observer[əbˈzɜ:və(r)]观察者
protected Subject subject;
public abstract void update();
}
public class Subject {//subject[ˈsʌbdʒɪkt]主题
private List<Observer> observers = new ArrayList<Observer>();
private int state;
public int getState() {
return state;
}
public void setSate(int state) {
this.state = state;//19 30 33
notifyAllObservers();//20 31 34
}
public void notifyAllObservers() {
for (Observer observer : observers) {//21 24 26 27 30 35 38 41 44
observer.update();//22 25 28 36 39 42
}
}
public void attach(Observer observer) {
observers.add(observer);//6 11 16
}
}
public class BinaryObserver extends Observer {//二进制
public BinaryObserver(Subject subject) {//3
this.subject = subject;//4
this.subject.attach(this);//5
}
public void update() {
System.out.println("Binary String:" + Integer.toBinaryString(subject.getState()));//23 37
}
}
public class OctalObserver extends Observer {// 八进制
public OctalObserver(Subject subject) {// 8
this.subject = subject;// 9
this.subject.attach(this);// 10
}
public void update() {
System.out.println("Octal String:" + Integer.toOctalString(subject.getState()));// 26 40
}
}
public class HexObserver extends Observer {// 十六进制
public HexObserver(Subject subject) {// 13
this.subject = subject;// 14
this.subject.attach(this);// 15
}
public void update() {
System.out.println("Hex String:" + Integer.toHexString(subject.getState()).toUpperCase());// 29
}
}
public class ObserverPatternDemo {
public static void main(String[] args) {
Subject subject = new Subject();// 1
new BinaryObserver(subject);// 2
new OctalObserver(subject);// 7
new HexObserver(subject);// 12
System.out.println("First state chang:15");// 17
subject.setSate(15);// 18
System.out.println("Second state change:10");// 31
subject.setSate(10);// 32
}// 45
}
运行结果:
First state chang:15
Binary String:1111
Octal String:17
Hex String:F
Second state change:10
Binary String:1010
Octal String:12
Hex String:A
102、(1)写出下段程序的运行结果
public static void main(String[] args) {
int x = 3, y = 1;
if (x == y) {
System.out.println("Equal");
} else {
System.out.println("Not equal");
}
}
运行结果:Not equal
(2)写出下段程序的运行结果
public static void main(String[] args) {
int i = 0;
switch (i) {
case 0:
case 1:
System.out.print("one");
case 2:
System.out.print("two");
break;
case 3:
System.out.print("three");
}
}
运行结果:one two
(3)写出下段程序的运行结果
public class Parent {// 3
public void method() {
System.out.println("parent_method");
}
public static void smethod() {// 11
System.out.println("parent_smethod");// 12
}
}
public class Child extends Parent {// 2 4
public void method() {// 8
System.out.println("child_method");// 9
}
public static void smethod() {
System.out.println("child_smethod");
}
}
public class Test {
public static void main(String[] args) {
Child c = new Child();// 1 5
Parent p = (Parent) c;// 6
p.method();// 7[子类]
p.smethod();// 10[父类]
}
}
运行结果:child_method parent_smethod
103、下列程序段的结果是(A)
public static void main(String[] args) {
int x = 20, y = 30;
boolean n;
n = x > 50 && y > 40 || x > 30 && y < -10 || x < -50 && y > 35 || x < -10 && y < -15;
System.out.println(n);
}
A.false B. true C. 1 D. 0
104、以下程序的运行结果(C)
public static void main(String[] args) {
Integer a = 34556;
Integer b = 34556;
if (a == b) {
System.out.println("Equal");
} else {
System.out.println("Not equal");
}
}
A.Equal B.无出 C.Not equal D.编译错误
(1)[-128~127]从对象池取,超了后新建对象。
(2)比较基本类型时,==用来比较二进制的值。
(3)比较引用类型时,==用来比较对象的虚地址。
(4)Integer值在[-128~127]之间值相同则相等(包括-128及127),否则不等。
注:a=b=-129或a=b=128时结果输出Not equal。
105、以下程序的运行结果是(B)
public static void main(String[] args) {
System.out.print(100 % 3);
System.out.print(",");
System.out.print(100 % 3.0);
}
A. 1,1 B. 1,1.0 C.1.0,1 D. 1.0,1.0
106、代码段如下,选项中描述正确的是(A)
public static int ternary(int s) {
int i = s;
return i < 10 ? i * 10 : i * 100;
}
A.这是静态方法,不需要实例化就可以被调用 B.返回值是方法临时变量的值 C.返回值等于i*10 D.返回值等于i*100
107、下面的java程序编译运行结果是(C)
public interface Animal {
int x = 0;
}
public class FlyAnimal {// 3
int x = 1;// 4
}
public class Bird extends FlyAnimal implements Animal {// 2 5
public void getbirdInfo() {// 7
System.out.println(super.x);// 8
}
public static void main(String[] args) {
new Bird().getbirdInfo();// 1 6
}
}
A.产运行期错误 B.产编译期错误 C.程序运行,出结果1 D.程序运行,出结果0
108、写出下面代码的输出结果(B)
public class OuterClass {
private class InterClass {
public InterClass() {// 4
System.out.println("InterClass Create");// 5
}
}
public OuterClass() {// 2
InterClass ic = new InterClass();// 3 6
System.out.println("OuterClass Create");// 7
}
public static void main(String[] args) {
OuterClass oc = new OuterClass();// 1 8
}
}
A.interClass create B.InterClass Create OuterClass Create C.OuterClass create interClass create D.OuterClass create
109、以下程序运行结果是(1)
public class Demo {
public static void modify(int[] arr) {// [0]=0[引用类型]
arr[0]++;// [0]=0(前)-->[0]=1(后)
}
public static void main(String[] args) {
int[] arr = new int[1];// [0]=0
modify(arr);// [0]=0(前)-->[0]=1(后)[引用类型]
System.out.println(arr[0]);// [0]=1
}
}
110、以下程序运行结果是(0 1 0 1 1)
public class Demo {
int i;
public void changeA(int i) {// i=0[基本类型]
i++;// i=0-->i=1
System.out.println(i);// i=1
}
public void changeB(Demo d) {// i=0[引用类型]
d.i++;// d.i=0(前)-->d.i=1(后)
System.out.println(d.i);// d.i=1
}
public static void main(String[] args) {
Demo d = new Demo();// d.i=0
System.out.println(d.i);// d.i=0
d.changeA(d.i);// d.i=0(前)-->d.i=0(后)[基本类型]
System.out.println(d.i);// d.i=0
d.changeB(d);// i=0(前)-->i=1(后)[引用类型]
System.out.println(d.i);// d.i=1
}
}
111、以下程序运行结果是(15 0 20)
public class Demo {
public void first() {
int i = 5;
Student s = new Student();//s.i=15
s.i = 25;//s.i=25
second(s, i);//s.i=25(前)-->s.i=20(后)[引用类型],i=5(前)-->i=5(后)[基本类型]
System.out.println(s.i);//s.i=20
}
public void second(Student s, int i) {//s.i=25[引用类型],i=5[基本类型]
i = 0;
s.i = 20;//s.i=20
Student stu = new Student();//stu.i=15
s = stu;//i=20(左)<--i=15(右)(右15覆盖左20)
System.out.println(s.i + " " + i);//s.i=15,i=0
}
public static void main(String argv[]) {
Demo d = new Demo();
d.first();
}
}
112、以下程序运行结果是(10 10 5 6)
public class Demo {
public void methodA(int i) {//i=10
System.out.println(i++);//i=10-->i=11(输出后)[基本类型]
}
public void methodB(Person p) {//i=5
System.out.println(p.i++);//i=5-->i=6(输出后)[引用类型]
}
public static void main(String[] args) {
int i = 10;
Demo d = new Demo();
d.methodA(i);//i=10(前)-->i=10(后)[基本数据类型]
System.out.println(i);
Person p = new Person();//p.i=5
d.methodB(p);//p.i=5(前)-->i=6(后)[引用数据类型]
System.out.println(p.i);//p.i=6
}
}
113、以下程序运行结果是(2 14)
public class Demo {
public static void main(String[] args) {
show(0);//(1)0
show(1);//(7)1
}
public static void show(int i) {//(2)0 //(8)1
switch (i) {//(3)0 //(9)1
case 1: i += 1;//(10)i=2
case 2: i += 4;//(11)i=6
case 4: i += 8;//(12)i=14
break;//(13)i=14
default://(4)
i += 2;//(5)i=0(前)-->i=2
}
System.out.println("i=" + i);//(6)i=2 //(14)i=14
}
}
114、以下程序运行结果是(AB D CB D CB)
public class Demo {
public static boolean show(char ch) {//3)ch=A 7)ch=B 12)ch=D 18)ch=C 22)ch=B 27)ch=D 33)ch=C 37)ch=B
System.out.println(ch); //4)ch=A 8)ch=B 13)ch=D 19)ch=C 23)ch=B 28)ch=D 34)ch=C 38)ch=B
return true; // 5 9 14 20 24 29 35 39
}
public static void main(String[] args) {
int x = 1;//1)x=1
for (show('A'); show('B') && x < 3; show('C')) {//2 6 10 17 21 25 32 36 40
show('D');//11 15 26 30
x++;// (16)x=1-->x=2 //(31)x=2-->x=3
}// 41
}// 42
}
115、以下运行结果是(4 30 71)
public class Demo {
public static void main(String[] args) {
short a = 10;
byte b = 5;
char c = 'A';
int n = 6;
System.out.println("a-n=" + (a - n));//10-6=4
System.out.println("b*n=" + (b * n));//5*6=30
System.out.println("c+n=" + (c + n));//A+6(A=65)->65+6=71
}
}
116、以下语句输出结果(Hello World 1 tom)?
public class Demo {
public static void pass(StringBuffer s1,int i,String str) {
s1.append(" World");
i = 8;
str += "cat";
}
public static void main(String[] args) {
int i = 1;
StringBuffer s1 = new StringBuffer("Hello");
String str = "tom";
pass(s1, i, str);//i[基本类型]
System.out.println(s1);
System.out.println(i);
System.out.println(str);
}
}
117、程序运行结果(编译失败)?
public interface DemoA {}
public class DemoB implements DemoA {
public String func(){
return "func";
}
}
public class DemoTest {
public static void main(String[] args) {
DemoA a = new DemoB();
System.out.println(a.func());// 编译失败,因为a所属的A接口中没有定义func方法(编译看左边,运行看右边)。
}
}
118、程序运行结果(A B)?
public class Parent {//3
public boolean show(char a) {
System.out.println(a);
return true;
}
}
public class Child extends Parent {//2 4 7
public boolean show(char a){
System.out.println(a);//10) a=A 12)a=B
return false;
}
public static void main(String[] args) {
int i = 0;
Parent p = new Child();//1 5
Child c = new Child();//6 8
for(p.show('A');p.show('B') && (i<2);p.show('C')){//9 11 13
i++;
c.show('D');
}
}//14
}
注意:f.show('B')结果是false,双&&短路则后不读。
119、程序运行结果(B C 7)
public class Parent {
int i = 0;//(5)
public Parent(String a) {
System.out.println("A");
i = 1;
}
public Parent() {//(4)
System.out.println("B");//(6)—>//B
i += 2;//(7)i=0(前)-->i=2(后)
}
}
public class Child extends Parent {
public Child(String a) {//(3)
//super();//默认super-->(4)
System.out.println("C");//(8)—>//C
i += 5;//(9)i=2(前)-->i=7(后)
}
public static void main(String[] args) {
int i = 4;//(1)
Parent p = new Child("A");//(2)//(10)
System.out.println(p.i);//(11)—>//7
}
}
121、下面程序是对还是错,如果错请说明原因!
abstract class Name {
private String name;
public abstract boolean isStupidName(String name){};
}
答:isStupidName函数错误,抽象方法不应该有具体的实现,应修改为public abstract boolean isStupidName(String name);
122、指出下面程序片段中是否存在问题,并说明原因。
public static void main(String[] args) {
double num = 5;
String val = num.toString();
System.out.print(num);
}
答:上面程序num.toString错误,double类型没有toString方法,需类型转换,应修改为String val = String.valueOf(num).toString();
138、程序运行结果(pong ping)
public static void main(String[] args) {
Thread t = new Thread() {//1
public void run() {
pong();//3
}
};
t.run();//2
System.out.println("ping");//5
}
static void pong() {
System.out.println("pong");//4
}
144、下面哪两个可以在Test的子类中使用(AC)?
class Test {
protected int m1(int a, int b) {
return 0;
}
}
A、public int m1(int a,int b){return 0;} 注:重写是子类对父类允许访问的方法进行重新编写,返回值和形参不能变。
B、private int m1(int a,int b){return 0;}
C、private int m1(int a,long b){return 0;} 注:子类特有方法
D、public short m1(int a,int b){return 0;}
145、编译运行以下程序后,关于输出结果的说明的是(C)。
public class Conditional {
public static void main(String[] args) {
int x = 4;
System.out.print("value is" + ((x > 4) ? 99.9 : 9));
}
}
A、输出结果为:value is 99.99 B、输出结果为:value is 9
C、输出结果为: value is 9.0 (三元运算符中:前后结果类型保持一致) D、编译错误
147、关于以下列对该类的说明,正确的是(C)
public class StaticSteff {
static int x = 10;
static {
x += 5;
}
public static void main(String[] args) {
System.out.println("x=" + x);
}
static {
x /= 3;
}
}
A、4行与9行不能通过编译,因为缺少方法名和返回类型
B、9行不能通过编译,因为只能有一个静态初始化器
C、编译通过,执行结果为:x = 5
D、编译通过,执行结果为:x = 3
148、写出下列的程序运行结果(1a2b2b)
class A {//3
static {
System.out.print("1");//2
}
public A() {//8 16
System.out.print("2");//9 17
}//10 18
}
class B extends A {//5
static {
System.out.print("a");//4
}
public B() {//7 15
System.out.print("b");//11 19
}//12 20
}
public class Hello {
public static void main(String[] args) {
A ab = new B();//1 6 13
ab = new B();//14 21
}//22
}
150、在Web 应用开发过程中经常遇到输出某种编码的字符,如 iso8859-1等,如何输出一个某种编码的字符串?
public String translate(String str) {
String tempStr = "";
try {
tempStr = new String(str.getBytes("ISO-8859-1"), "GBK");
tempStr = tempStr.trim();
} catch (Exception e) {
System.err.println(e.getMessage());
}
return tempStr;
}
151、定义类A和类B如下:
public class A {
int a = 1;
double d = 2.0;
void show() {
System.out.println("Class A: a=" + a + " d=" + d);
}
}
public class B extends A {
float a = 3.0f;
String d = "Java program.";
void show() {
super.show();
System.out.println("Class B: a=" + a + " d=" + d);
}
}
(1)若在应用程序的 main 方法中有以下语句:
A a = new A();
a.show();
则输出的结果如何?
结果:Class A: a=1 d=2.0
(2)若在应用程序的main方法中定义类B的对象b:
A b=new B();
b.show();
则输出的结果如何?
结果:
Class A: a=1 d=2.0
Class B: a=3.0 d=Java program.
152、运行如下程序
public class FatherClass {
public FatherClass() {
System.out.println("FatherClass Create");
}
}
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();
}
}
结果:
FatherClass Create
FatherClass Create
ChildClass Create
153、运行如下程序
public class OuterClass {
private class InterClass {
public InterClass() {
System.out.println("InterClass Create");
}
}
public OuterClass() {
InterClass ic = new InterClass();
System.out.println("OuterClass Create");
}
public static void main(String[] args) {
OuterClass oc = new OuterClass();
}
}
结果:
InterClass Create
OuterClass Create
154、java 编程打印昨天的当前时刻。
public class YesterdayCurrent {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, -1);
System.out.println(cal.getTime());
}
}
158、求一个字符串中连续出现次数最多的子符?
public class CheckChar {
public static void main(String[] args) throws Exception {
String str = "I Love Beijing Tiananmen";
char[] strArr = str.toCharArray();// 把字符串转为字符数组toCharArray
Map<Character, Integer> map = MapFunction(strArr);
FindMapMaxValue(map);
}
// MapFunction:实现将字符数组转存到Map中,其中Map中的key为出现的字符,value对应该字符出现的次数
public static Map<Character, Integer> MapFunction(char[] strArr) {
Map<Character, Integer> map = new HashMap<Character, Integer>();
if (!(strArr == null || strArr.length == 0)) {// 先判断字符数组是否为空
for (int i = 0; i < strArr.length; i++) {
if (null != map.get(strArr[i])) {//若不为空,说明已经存在相同字符,则Value值在原来的基础上加1
map.put(strArr[i], map.get(strArr[i]) + 1);
} else {
map.put(strArr[i], 1);
}
}
}
return map;
}
public static char FindMapMaxValue(Map<Character, Integer> map) {
Iterator iter = map.entrySet().iterator();
Map.Entry entry = (Map.Entry) iter.next();// 将第一个entry定义为最大次数的
char maxKey = (char) entry.getKey();// 获得K
int maxValue = (int) entry.getValue();// 获得V
while (iter.hasNext()) {
entry = (Map.Entry) iter.next();// 第二个entry
char tempK = (char) entry.getKey();
int tempV = (int) entry.getValue();
if (maxValue < tempV) {
maxKey = tempK;
maxValue = tempV;
}
}
System.out.println("出现次数最多的字符:" + maxKey);
System.out.println("字符出现的次数:" + maxValue);
return maxKey;
}
}
159、有一篇英文有单词、标点、空格计算出每个单词出现的次数。再找出次数最多的十个,请用代码写出?
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CountsWord {
public static void main(String[] args) throws Exception {
// 首先将文件的内容读取到缓冲区bufferedreader中,利用的是BufferedReader中的readline()
//读取文件中的每一个文本行,readline()并不是一行一行读取的,而是一个文本行一个文本行读取。
BufferedReader readfile = new BufferedReader(new FileReader("h:\test.txt"));
StringBuffer sb = new StringBuffer();
String text = null;
while ((text = readfile.readLine()) != null) {
sb.append(text);// 将从文件中读出来的字符串追加,形成一个字符串
}
readfile.close();
//用Pattern类中的complie()方法, 将正则表达式编译到模式中
Pattern patten = Pattern.compile("[a-zA-Z]+");
String sbstring = sb.toString();
//用Pattern类中的matcher()方法,生成一个匹配器对象,Matcher类是匹配器类
Matcher matcher = patten.matcher(sbstring);
Map<String, Integer> tp = new TreeMap<String, Integer>();
//用Matcher类中的find()方法,查找与模式匹配的下一个子序列
while (matcher.find()) {
//用Matcher类中的group()方法, 返回匹配的子序列
String word = matcher.group();
if (tp.containsKey(word)) {// 统计每个单词出现的次数
Integer wordfrequency = tp.get(word);
tp.put(word, wordfrequency + 1);
} else {
tp.put(word, 1);
}
}
//将treemap中的键值对的set视图存入ArrayList中,其中的类型必须是Map.Entry,因为TreeMap中的entrySet()
//方法的返回类型就是Map.Entry类型,其实Map.Entry就是个接口。将treemap存入ArrayList的目的就是用Collections
//类中的sort()方法进行排序,其中的sort(List<T> list,Comparator)是按照指定的比较器进行排序
List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(tp.entrySet());
//重写Comparator比较器,目的是让TreeMap按照value进行降序排列,这里的重写比较器用的是匿名类,也就是
//是先创建实现Comparator接口的类,并重写其中的compare方法,并不是接口实例化了。如果觉得用匿名
//类这种方式实现比较器重写,你还可以单独写个类MyComparator实现接口Comparator,并重写compare()
//方法,在sort(List<T>list,new MyComparator())作用一样
Comparator<Map.Entry<String, Integer>> comparator = new Comparator<Map.Entry<String, Integer>>() {
public int compare(Map.Entry<String, Integer> param1, Map.Entry<String, Integer> param2) {
//如果是实现升序就是return(param1.getValue().compareTo(param2.getValue());
return (param2.getValue().compareTo(param1.getValue()));
}
};
Collections.sort(list, comparator);// 按照指定的比较器,对list列表进行升序或者降序排序
for (int i = 0; i < 10; i++) {
String key = list.get(i).getKey();
Integer value = list.get(i).getValue();
System.out.println(key + ":" + value);
}
}
}
161、截取一个字符串的第3个到第9个字符串是否等于“beijing”,用代码表示。
public boolean getStr(String str) {
String newStr = str.substring(3, 10);
if (newStr.equals("beijing")) {
return true;
}
return false;
}
176、设计程序,返回21-25的整型随机数。
public int getRandom() {
Random random = new Random();
return random.nextInt(25-21 + 1) + 21;//nextInt(i):在0(包括)和指定值(不包括)之间均匀分布的int值
}
176、看程序写输出答案并陈述理由。
public static void main(String[] args) {
Integer num = new Integer(1999);
change(num);
System.out.println(num);
}
public static void change(Integer num) {
num = new Integer(2000);
}
结果:1999
177、任意小于10000的正整数转化为4位字符串,不够4位的前面加0,例:22转化为“0022”。
public static void main(String[] args) {
int num = 22;
if (num > 0 && num < 10000) {
String numStr = String.valueOf(num);
if (numStr.length() == 3) {
numStr = "0" + numStr;
} else if (numStr.length() == 2) {
numStr = "00" + numStr;
} else if (numStr.length() == 1) {
numStr = "000" + numStr;
}
System.out.println(numStr);
} else {
System.out.println("数据不在0至10000之间");
}
}
160、写一个com.act.interview.Test类,输出“Hello World!”,并手动编译test类,并将其打包为Test.jar,并运行此Test.jar输出字符串。
(1)定义com.act.interview.Test类
package com.act.interview;
public class Test {
public static void main(String[] args){
System.out.println("Hello World!");
}
}
DOS运行步骤:
①cmd->java文件目录下
②javac -d . Test.java
③java com.act.interview.Test
④输出结果 Hello World!
注:javac编译包下类必须在javac后加-d再加·,·前后必须有空一格,再写类名.java,如javac -d . Test.java
java运行包下class必须在java后加包名,层级包用·,再写类名,如java com.act.interview.Test
(2)手动编译此类命令
javac -d . Test.java
(3)将此类打包为Test.jar的命令
①javac -d . Test.java
②cd com/act/interview
③jar cvf Test.jar Test.class
④首先把java文件编译为class文件,其次cd进入到class文件位置,最后jar cvf 文件名称.jar class文件名称
(4)运行Test.jar中com.act.interview.Test类
1、JSP内置对象及作用?
(1)request:用户端请求,此请求会包含来自get/post请求的参数
(2)response:网页传回用户端的回应
(3)page:jsp网页本身
(4)pageContext:网页的属性是在这里管理
(5)session:与请求有关的会话期
(6)application:Servlet正在执行的内容
(7)out:用来传送回应的输出
(8)config:servlet的构架部件
(9)exception:针对错误网页,未捕捉的例外
2、jsp生命周期有哪些阶段
(1)编译阶段(2)初始化阶段(3)执行阶段(4)销毁阶段 注:jsp->java文件->class文件
3、页面间对象传递的方法?
request,session,application,cookie 等。
4、HTTP状态码分类?
(1)1** 信息(100-继续发送请求),服务器收到请求需请求者继续执行操作。
(2)2** 成功(200-请求成功),操作被成功接收并处理。
(3)3** 重定向(301-资源被永久转移到其它URL),需进一步操作以完成请求。
(4)4** 客户端错误(404-请求资源不存在),请求包含语法错误或无法完成请求。
(5)5** 服务器错误(500-内部服务器错误),服务器在处理请求的过程中发生了错误。
5、get和post区别?
(1)get提交对于敏感数据不安全,post提交对于敏感数据安全。
(2)get提交数据显示在地址栏,post提交数据不显示在地址栏。
(3)get提交的数据量小,post提交的数据量大。
(4)get将数据封装到请求行中,post将数据封装到了请求体中。
6、forward(转发)和redirect(重定向)的区别?
(1)转发是服务器行为地址不变,重定向是客户端行为地址发生变化。
(2)转发页面可以共享request数据,重定向不能共享数据。
(3)转发效率高,重定向效率低。
7、jQuery中常用的选择器有哪几种,请举例列举示意。
(1)基本选择器 ①$("#id")//ID选择器 ②$("div")//元素选择器
(2)层次选择器 ①$("#id > .classname")//子元素选择器 ②$("#id .classname")//后代元素选择器
(3)过滤选择器 ①$("li:first")//第一个li ②$("li:last")//最后一个li
(4)属性过滤选择器①$("div[id]")//所有含有id 属性的div元素 ②$("div[id='123']")// id属性值为123的div 元素
(5)状态过滤选择器①$("input:checked")// 匹配选中的
(6)表单选择器 ①$(":password")//所有密码框 ②$(":button")//所有button按钮
8、请选择会产生运行错误的语句(A)
A、var obj = (); B、var obj = []; C、var obj = {}; D、var obj = / /; 注:中间有空格(对),中间没空格(错)
9、页面重定向有哪些什么方法?有什么区别?
(1)页面重定向有:301 redirect、302 redirect与meta fresh。
(2)301 redirect代表永久性转移
(3)302 redirect代表暂时性转移
(4)meta fresh是通过网页中的meta指令在特定时间后重定向到新的网页。
10、jsp中<% %>、<%! %>、<%= %>的区别?
(1)<% %>Java的代码片段
(2)<%! %>用于声明变量和方法
(3)<%= %>获取值
11、在JavaScript中如何验证一个数据是否是数字(B)
A.如果用Integer.parseInt(value)有误就不是数字 B.利用isNaN[næn](value)返回的boolean进行判断
C.没有方法验证 D.int I = value 若报错就不是数字
解析:Integer.parseInt(String)就是将String字符类型数据转换为Integer整型数据。
12、HTML5主要标签?
(1)视频:<video><source src="/i/movie.mp4" type="video/mp4"></video>
(2)声音:<audio src="/i/song.ogg" controls="controls"></audio>
(3)画布:<canvas>
(4)拖放:<img draggable="true" />
(5)获取地理位置:getCurrentPosition()
13、jsp中静态包含和动态包含区别?
(1)静态包含<%@ include file="index.jsp" %>,动态包含<jsp:include page="index.jsp" />。
(2)静态包含将所有要包含文件作为一个整体编译生成一个class文件,动态包含将所有要包含文件分别编译生成多个class文件。
(3)经常修改的文件使用动态包含且未修改文件不会重新编译。
14、jQuery中如何将数组转化json字符串,然后再转化回来?
(1)JSON.stringify()方法用于将对象或数组转换为JSON字符串。
(2)JSON.parse[pɑ:z]()方法用于将一个JSON字符串转换为对象或数组。
15、编写一个ajax方法?
<div id="div1"><h2>使用jQuery AJAX修改文本内容</h2></div>
<button>获取其他内容</button>
<script type="text/javascript">
$(document).ready(function() {
$("button").click(function() {
$.ajax({
url : "demo.txt",
success : function(data) {
$("#div1").html(data);
}
});
});
});
</script>
97、数据库里面的索引和约束是什么?
(1)索引是为了加速对表中数据行的检索而创建的一种分散的存储结构。
(2)索引作用:
<1>快速取数据
<2>保证数据记录的唯一性
<3>实现表与表之间的参照完整性
<4>在使用order by、group by子句进行数据检索时,利用索引可以减少排序和分组的时间。
(3)索引优点:
<1>加快数据的检索速度
<2>创建唯一性索引,保证数据库表中每一行数据的唯一性
<3>加速表和表之间的连接
<4>在使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间
(4)索引缺点:
<1>索引需要占物理空间
<2>当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,降低了数据的维护速度。
(5)索引分为:普通索引、唯一索引、主键索引和聚集索引。
<1>普通索引:create index emp_index on emp(empno,ename,mgr)
<2>唯一索引:不允许其中任何两行具有相同索引值的索引,create unique index emp_index on emp(empno,ename,mgr)
<3>主键索引:数据库表中一列或列组合(字段)的值唯一标识表中的每一行
(6)SQL约束用于限制加入表的数据的类型。
(7)not null约束强制字段始终包含值。
(8)unique约束唯一标识数据库表中的每条记录。
(9)primary key约束唯一标识数据库表中的每条记录,主键必须包含唯一的值、不能包含null值。
(10)foreign key约束一个表中的foreign key指向另一个表中的primary key。
(11)check约束用于限制列中的值的范围
(12)default约束用于向列中插入默认值
124、存储过程?
(1)存储过程是大型数据库系统中一组为了完成特定功能的SQL语句集,第一次编译后再次调用不需要重新编译。
(2)存储过程有系统存储过程、本地存储过程、临时存储过程、远程存储过程、扩展存储过程。
(3)创建存储过程
create procedure 名称
@[参数名] [类型],@[参数名] [类型]
as
begin
……
end
(4)调用存储过程:exec 名称 [参数名]
(5)删除存储过程:drop procedure[prəˈsi:dʒə(r)] 名称
(6)存储过程优点①重复使用②减少网络流量③安全性高
(7)存储过程缺点①调试麻烦②移植问题③重新编译问题
125、SQL注入?
(1)SQL注入是将恶意的SQL语句注入到数据库,而不是按照设计者意图去执行SQL语句。
(2)对用户输入信息进行校验,不要使用动态拼接SQL,不要使用管理员权限连接数据库,对敏感信息加密存储。
167、数据库优化有哪些?
(1)索引优化、查询优化、表优化、事务优化、SQL优化。
(2)调整数据库结构设计。
(3)调整应用程序结构设计。
(4)对数据库服务器内存分配的调整。
63、请简述项目中优化SQL语句执行效率的方法,从哪些方面,SQL语句性能如何分析?(MySql)
(1)where子句中的连接顺序
(2)select中避免使用*
(3)where子句替换HAVING子句
(4)通过内部函数提高SQL效率
(5)where中用的比较频繁的字段建立索引
(6)避免在索引列上使用计算、not in和<>等操作
180、打印html中全部a标签的href的属性。(js后jquery)
181、打印出下面select标签中选中option的文本内容。(js或jquery)
<select>
<option value=“1”>北京</option>
<option value=“2”>上海</option>
<option value=“3” selected=“selected”>重庆</option>
<option value=“4”>天津</option>
</select>
95、下面一个车辆记录表Car和一个车型表Car_type
Car |
||
name |
type |
num |
张三 |
1 |
3 |
张三 |
2 |
4 |
李四 |
3 |
2 |
王五 |
1 |
2 |
王五 |
4 |
6 |
Car_type |
||
id |
name |
price |
1 |
宝马 |
300 |
2 |
奔驰 |
400 |
3 |
奥迪 |
350 |
4 |
马自达 |
200 |
更新Car表车辆数,如车辆估值小于300加2辆,车辆估值大于350加3辆,剩下的加1辆。
UPDATE Car a
SET num = (
SELECT
CASE
WHEN b.price > 350 THEN
a.num + 3
WHEN b.price < 300 THEN
a.num + 2
ELSE
a.num + 1
END
FROM
Car_type b
WHERE
a.type = b.id
)
126、有一张学生表有班级id、学号、数学成绩。
drop table if exists student;
create table student (
classID varchar(5) not null, -- 班级ID
studentNumber varchar(10) not null, -- 学号(年号(4位)+学生类别编号(2位)+顺序号(4位))
mathScore double(10,2) not null -- 数学成绩
) engine = innodb default charset = utf8;
insert into student(classID,studentNumber,mathScore)values('10001','2018010001',65);
insert into student(classID,studentNumber,mathScore)values('10001','2018010002',85);
insert into student(classID,studentNumber,mathScore)values('10001','2018010003',74);
insert into student(classID,studentNumber,mathScore)values('10002','2018010004',45);
insert into student(classID,studentNumber,mathScore)values('10002','2018010005',95);
insert into student(classID,studentNumber,mathScore)values('10002','2018010005',78);
(1)数学平均成绩:select classID,avg(mathScore) as mathScore from student group by classID
(2)比平均成绩高的学生的所有信息:select * from student where mathScore > (select avg(mathScore) from student)
127、有一张成绩表如下,请写出成绩全部合格的学生信息(包含姓名、课程、分数)。(注:分数在60以上评为合格)
姓名 |
课程 |
分数 |
张三 |
语文 |
81 |
张三 |
数学 |
75 |
李四 |
语文 |
56 |
李四 |
数学 |
90 |
王五 |
语文 |
81 |
王五 |
数学 |
100 |
王五 |
英语 |
49 |
drop table if exists score;
create table score(
name varchar(10) not null, -- 姓名
course varchar(10) not null, -- 课程
score double(10,2) not null -- 成绩
) engine = innodb default charset = utf8;
insert into score(name,course,score)values('张三','语文',81);
insert into score(name,course,score)values('张三','数学',75);
insert into score(name,course,score)values('李四','语文',56);
insert into score(name,course,score)values('李四','数学',90);
insert into score(name,course,score)values('王五','语文',81);
insert into score(name,course,score)values('王五','数学',100);
insert into score(name,course,score)values('王五','英语',49);
成绩全部合格的学生信息:select * from score where score >= 60
128、有两个字段完全一样的学生表A、B,主键为学生ID,请写出将A表中的学生ID为A001的学生信息插入到B表中的SQL语句。
drop table if exists studentA;
create table studentA(
id varchar(10) primary key not null, -- 学生ID
name varchar(10) not null, -- 课程
score double(10,2) not null -- 成绩
) engine = innodb default charset = utf8;
drop table if exists studentB;
create table studentB(
id varchar(10) primary key not null, -- 学生ID
name varchar(10) not null, -- 课程
score double(10,2) not null -- 成绩
) engine = innodb default charset = utf8;
insert into studentA(id,name,score)values('A001','王国强',81);
insert into studentA(id,name,score)values('A002','张小碗',78);
insert into studentA(id,name,score)values('A003','苏家强',66);
insert into studentA(id,name,score)values('A004','张国胜',96);
insert into studentA(id,name,score)values('A005','王洪亮',100);
将A表中的学生ID为A001的学生信息插入到B表:insert into studentB (select * from studentA where id = 'A001')
129、student(id,className,score)用最高效最简单的SQL列出各班成绩最高的列表,显示班级、成绩两个字段
drop table if exists student;
create table student(
id varchar(5) not null, -- ID
className varchar(8) not null, -- 班级
score double(10,2) not null -- 成绩
) engine = innodb default charset = utf8;
insert into student(id,className,score)values('10001','A0001',65);
insert into student(id,className,score)values('10002','A0001',45);
insert into student(id,className,score)values('10003','A0001',88);
insert into student(id,className,score)values('10004','B0001',84.5);
insert into student(id,className,score)values('10005','B0001',91);
insert into student(id,className,score)values('10006','B0001',49);
各班成绩最高的列表,显示班级、成绩两个字段:select className,max(score) score from student group by className
130、如何只显示重复数据,或不显示重复数据?
drop table if exists student;
create table student(
id varchar(10) not null, -- 学生ID
name varchar(10) not null, -- 课程
score double(10,2) not null -- 成绩
) engine = innodb default charset = utf8;
insert into student(id,name,score)values('1001','王宏涛',95);
insert into student(id,name,score)values('1002','彭新闻',88);
insert into student(id,name,score)values('1003','张海英',80);
insert into student(id,name,score)values('1001','王宏涛',95);
insert into student(id,name,score)values('1004','彭俊涛',65);
insert into student(id,name,score)values('1005','王海洋',85);
insert into student(id,name,score)values('1003','张海英',80);
(1)显示重复数据:select * from student group by id,name,score having count(*)>1
(2)不显示重复数据:select distinct * from student
131、select count(*) from student和select count(id) from student区别?
drop table if exists student;
create table student(
id varchar(10), -- 学生ID
name varchar(10), -- 课程
score double(10,2) -- 成绩
) engine = innodb default charset = utf8;
insert into student(id,name,score)values('1001','将国庆',95);
insert into student(id,name,score)values('1002','将军庆',95);
insert into student(id,name,score)values(null,'王卫东',60);
insert into student(id,name,score)values('1004','将昌盛',73);
insert into student(id,name,score)values(null,'蒋伟民',59);
(1)select count(*) from student:count(*)包括空(Null)记录。
(2)select count(Id) from student:count(id)不包括空(Null)记录。
132、rowid和rownum的区别?
create table city(
id varchar(10), -- ID
city varchar(10), -- 城市
areaNumber varchar(10) -- 区号
);
insert into city(id,city,areaNumber)values('1001','北京市','110');
insert into city(id,city,areaNumber)values('1002','上海市','021');
insert into city(id,city,areaNumber)values('1003','西安市','029');
insert into city(id,city,areaNumber)values('1004','广州市','058');
insert into city(id,city,areaNumber)values('1005','南京市','271');
insert into city(id,city,areaNumber)values('1006','成都市','480');
insert into city(id,city,areaNumber)values('1007','天津市','553');
select rowid,id,city,areaNumber from city;
select rownum,id,city,areaNumber from city;
(1)rowid是插入数据时生成,rownum是查询数据时生成。
(2)rowid是行的物理地址,rownum是查询结果中行的次序。
(3)rowid 用于定位数据表中某条数据的位置且唯一不会改变。
133、Oracle中字符串用什么符号链接?
create table employee(
id varchar(10), -- ID
num varchar(10), -- 工号
name varchar(10) -- 姓名
);
insert into employee(id,num,name)values('1001','101','张春霞');
insert into employee(id,num,name)values('1002','102','王芳芳');
insert into employee(id,num,name)values('1003','103','王洪涛');
(1)Oracle使用“||”字符串链接。
(2)select '工号为'||num||'的员工姓名为'||name from employee
134、Oracle与MySQL的分页
create table employee(
id varchar(10), -- ID
num varchar(10), -- 工号
name varchar(10) -- 姓名
);
insert into employee(id,num,name)values('1001','101','张春霞');
insert into employee(id,num,name)values('1002','102','王芳芳');
insert into employee(id,num,name)values('1003','103','王洪涛');
insert into employee(id,num,name)values('1004','104','周桃红');
insert into employee(id,num,name)values('1005','105','王海文');
insert into employee(id,num,name)values('1006','106','苦咖啡');
insert into employee(id,num,name)values('1007','107','尚飞文');
insert into employee(id,num,name)values('1008','108','刘连飞');
insert into employee(id,num,name)values('1009','109','李婷婷');
insert into employee(id,num,name)values('1010','110','张彤彤');
(1)Oracle分页:
①select * from (select employee.*, rownum r from employee) where r between 2 and 5
②select * from (select employee.*, rownum r from employee where rownum <= 5) where r >= 2
③select * from (select e.*, rownum r from (select * from employee) e where rownum <= 5) where r >= 2
(2)MySQL分页:select * from employee limit 1,4
135、使用Oracle删除表中重复记录
删除重复数据:delete from employee e1 where rowid != (select max(rowid) from employee e2 where e1.id = e2.id)
136、bid表(项目表)
id |
title |
amount |
periods |
rate |
1 |
X01 |
5000 |
12 |
10 |
2 |
X02 |
6000 |
3 |
8 |
说明:title-标题 amount-总额 periods-借款期限 rate-年利率
invest_log(投资记录表)
id |
bid_id |
user_id |
invest |
Time |
1 |
1 |
1001 |
50 |
2015-12-22 14:49:14 |
2 |
1 |
1002 |
1000 |
2015-12-22 13:49:33 |
3 |
2 |
1001 |
1500 |
2015-12-22 17:51:06 |
4 |
2 |
1002 |
800 |
2015-12-22 18:29:33 |
5 |
1 |
1003 |
900 |
2015-12-22 22:18:09 |
说明:bid_id-项目id,user_id-用户id,invest-用户投资金额,time-投资时间
(1)分页查询项目信息,按项目id倒序.
select * from bid order by id desc limit 0,1
查询结果:
说明:0表示开始页数,1表示每页显示条数
(2)查询每个用户的投资总额.
select user_id,sum(invest) from invest_log group by user_id
查询结果:
(3)查询每个用户关于项目投资信息,要求包括项目标题、用户id、投资总金额、时间。
select bid.title,invest_log.user_id,invest_log.invest,invest_log.time from bid join invest_log on bid.id=invest_log.bid_id
查询结果:
137、(1)有三张表,表结构如下:
表一:班级表(class表)
classID |
className |
100000001 |
甲班 |
100000002 |
乙班 |
表二:学生表(Student表)
SID |
Name |
Score |
ClassID |
1 |
张某某 |
70 |
100000001 |
2 |
李某某 |
82 |
100000002 |
表三:成绩级别表(score表)
minScore |
maxScore |
Level |
0 |
60 |
不及格 |
60 |
80 |
及格 |
80 |
90 |
良 |
90 |
100 |
优 |
(2)简单描述以上表之间的关系(文字描述,或E-R图描述)。
班级与学生是一对多关系,学生与成绩是一对多关系。
drop table if exists class;
create table class (
classid int primary key,
classname varchar (15) not null
) engine = innodb default charset = utf8;
insert into class(classid,classname)values(100000001,'甲班');
insert into class(classid,classname)values(100000002,'乙班');
drop table if exists student;
create table student (
sid int primary key,
name varchar (15) not null,
score double (10,2) not null,
classid int not null
) engine = innodb default charset = utf8;
insert into student(sid,name,score,classid)values(1,'秦婷婷',70,100000001);
insert into student(sid,name,score,classid)values(2,'马海娟',95,100000001);
insert into student(sid,name,score,classid)values(3,'陈宏子',91,100000001);
insert into student(sid,name,score,classid)values(4,'曹丽娜',60,100000001);
insert into student(sid,name,score,classid)values(5,'王红梅',50,100000001);
insert into student(sid,name,score,classid)values(6,'任娟娟',82,100000002);
insert into student(sid,name,score,classid)values(7,'胡书琴',95,100000002);
insert into student(sid,name,score,classid)values(8,'安瑞娟',91,100000002);
insert into student(sid,name,score,classid)values(9,'王艳红',60,100000002);
insert into student(sid,name,score,classid)values(10,'姚志奋',90,100000002);
insert into student(sid,name,score,classid)values(11,'毛春华',82,100000002);
insert into student(sid,name,score,classid)values(12,'王丽婧',92,100000002);
drop table if exists score;
create table score(
minscore int not null,
maxscore int not null,
level varchar (15) not null
) engine = innodb default charset = utf8;
insert into score(minscore,maxscore,level)values(0,60,'不及格');
insert into score(minscore,maxscore,level)values(60,80,'及格');
insert into score(minscore,maxscore,level)values(80,90,'良');
insert into score(minscore,maxscore,level)values(90,100,'优');
(3)请查询出学生SID为“1”的成绩级别。
select level from score where minScore <= (select score from student where sid = '1') and maxScore >= (select score from student where sid = '1')
查询结果:
(4)统计各个班中成绩级别为优的学生人数。
select classId,count(sid) from student where classId in(select classid from class) and score >= 90 and score <= 100 group by classId
查询结果:
155、有 3张表如下:
Student(sno,sname,sex,age,department)—学生表(学号,姓名,性别,年龄,组织部门)
Sc(sno,cno,score)-选课表(学号,课程编号,成绩)
Course(cno,cname)-课程表(课程编号,课程名称)
(1)查询选修了’计算机原理’的学生学号和姓名。
select stu.sno,stu.sname from Student stu
where (select count(*) from sc where sno=stu.sno and cno=(select cno from Course where cname='计算机原理')) != 0
(2)查询’张华’同学选修了的课程名字。
select cname from Course
where cno in ( select cno from sc where sno = (select sno from Student where sname='张华'))
(3)查询选修了 5 门课程的学生学号和姓名。
select stu.sno, stu.sname from student stu
where (select count(*) from sc where sno=stu.sno) = 5
MyBatis映射文件中#和$的区别
什么是数据库死锁。哪种情况会导致MySQL死锁,怎么查看、处理和避免MySQL死锁。
179、假设Books表如下:
类编号 |
图书名 |
出版社 |
价格 |
2 |
C#高级开发 |
盛通出版 |
23.00 |
2 |
JSP开发应用 |
机械出版社 |
45.00 |
3 |
高等数学 |
济南出版社 |
25.00 |
3 |
疯狂英语 |
清华大学出版社 |
32.00 |
1、Oracle中索引的类型及作用?
2、存储过程的优缺点?