Java基础面试题集锦

1.什么是序列化以及用途,什么时候使用序列化?

序列化是指把对象转换为字节序列的过程称为对象的序列化;而反序列化是指把字节序列恢复为对象的过程称为对象的反序列化。

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

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

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

什么时候使用序列化:

1)对象序列化可以实现分布式对象。主要应用例如:RMI要利用对象序列化运行远程主机上的服务,就像在本地机上运行对象时一样。

2)java对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每个对象的数据。可以将整个对象层次写入字节流中,可以保存在文件中或在网络连接上传递。利用对象序列化可以进行对象的"深复制",即复制对象本身及引用的对象本身。序列化一个对象可能得到整个对象序列。

-----------------------------------------------------------------------------

2.编程题: 写一个Singleton单例模式

Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在,一般Singleton模式通常有几种种形式:

第一种形式: 定义一个类,它的构造函数为private的,它有一个static的private的该类变量,

在类初始化时实例话,通过一个public的getInstance方法获取对它的引用,继而调用其中的方法。

public class Singleton {

private Singleton(){}

   //在自己内部定义自己一个实例,是不是很奇怪?

//注意这是private 只供内部调用

private static Singleton instance = new Singleton();

//这里提供了一个供外部访问本class的静态方法,可以直接访问

public static Singleton getInstance() {

return instance;

  } 

第二种形式: 

public class Singleton { 

private static Singleton instance = null;

public static synchronized Singleton getInstance() {

//这个方法比上面有所改进,不用每次都进行生成对象,只是第一次

//使用时生成实例,提高了效率!

if (instance==null)

instance=new Singleton();

return instance;

其他形式:

定义一个类,它的构造函数为private的,所有方法为static的,一般认为第一种形式要更加安全些。

-----------------------------------------------------------------------------

3.用简洁的话描述一下关于Spring的IOC与AOP

IoC就是对象的创建,依赖都由Spring及配置文件控制;而AOP就是统一的给一些类似的方法加上同样的功能,比如日志,事务。

IOC:控制反转,是一种设计模式。一层含义是控制权的转移:由传统的在程序中控制依赖转移到由容器来控制;

第二层是依赖注入:将相互依赖的对象分离,在spring配置文件中描述他们的依赖关系。他们的依赖关系只在使用的时候才建立。

AOP:面向切面,是一种编程思想,OOP的延续。将系统中非核心的业务提取出来,进行单独处理。比如事务、日志和安全等。

-----------------------------------------------------------------------------

4.cookie和session的的区别有哪些?

COOKIE数据存放在客户的浏览器上,而session数据放在服务器上;COOKIE分发是通过扩展HTTP协议来实现的,服务器通过在HTTP的响应头中加上一行特殊的指示以提示浏览器按照指示生成相应的COOKIE

COOKIE不是很安全,可以分析存放在本地的COOKIE并进行COOKIE欺骗,出于安全考虑应当使用session;

session会在一定时间内保存在服务器上,当访问增多时会比较影响服务器的性能,出于考虑减轻服务器性能方面,应当使用COOKIE;

单个COOKIE保存的数据不能超过4K,大多说浏览器都限制了一个站点最多保存20个COOKIE

个人观点认为将一些登录信息(重要信息)存放在session中,而其他信息如果需要保留,可以放在COOKIE中

-----------------------------------------------------------------------------

5.乐观锁和悲观锁的区别

悲观锁(Pessimistic Lock), 锁如其名,字面上理解就是很悲观的意思,每次获取数据时都会认为可能造成数据变动,所以每次获取数据都会上锁,这样别人想获取时就会block直到它拿到锁。传统的关系型数据库中就使用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

乐观锁(Optimistic Lock), 顾名思义,字面上理解就是很乐观的意思,每次获取数据的时候都认为不可能造成数据变动,因此不会上锁,但是在更新的时候会判断一下,其他人有没有去更新这个数据,可以采用版本号等类似的机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实就是提供的乐观锁。

悲观锁会造成访问数据库时间较长,并发性不好,尤其是比较长的事务处理;而乐观锁在现实中使用得较多,大多数厂商较多采用乐观锁。

-----------------------------------------------------------------------------

6.Java里面一个字符占几个字节?

java的字符类型char占用2个,Unicode编码

float 4 字节 32位IEEE 754单精度 

double 8 字节 64位IEEE 754双精度 

byte 1字节 -128到127 

short 2 字节 -32,768到32,767 

int 4 字节 -2,147,483,648到2,147,483,647 

long 8 字节 -9,223,372,036,854,775,808到9,223,372,036, 854,775,807 

char 2 字节 整个Unicode字符集 

boolean 1 位 True或者false

下面列举在GCC编译器下32位机器和64位机器各个类型变量所占字节数:

 C类型            32位               64位

char             1                1

short int       2                2

int             4                4

long int       4                8

long long int         8                8

char*             4                8

float             4                4

double             8                8

需要说明一下的是指针类型存储的是所指向变量的地址,所以32位机器只需要32bit,而64位机器需要 64bit 。

-----------------------------------------------------------------------------

7.Java虚拟机内存的堆区(heap),栈区(stack)和静态区(static/method)

JAVA的JVM的内存可分为3个区:堆(heap)、栈(stack)和方法区(method)

堆区:

1)存储的全部是对象,每个对象都包含一个与之对应的class的信息。(class的目的是得到操作指令)

2)jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身.

3)一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。

栈区:

1)每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中

2)每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。

3)栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。

4)由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.

静态区别名方法区:

1)方法区又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。

2)方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。

3)全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。

-----------------------------------------------------------------------------

8.Java中HashMap和HashTable的区别

HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),由于非线程安全,效率上可能高于Hashtable。ashMap允许将null作为一个entry的key或者value,而Hashtable不允许。

HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。 Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现。

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

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

-----------------------------------------------------------------------------

9.JSP 九大内置对象和作用

request 请求对象 类型 javax.servlet.ServletRequest 作用域 Request

response 响应对象 类型 javax.servlet.SrvletResponse 作用域 Page

pageContext 页面上下文对象 类型 javax.servlet.jsp.PageContext 作用域 Page

session 会话对象 类型 javax.servlet.http.HttpSession 作用域 Session

application 应用程序对象 类型 javax.servlet.ServletContext 作用域 Application

out 输出对象 类型 javax.servlet.jsp.JspWriter 作用域 Page

config 配置对象 类型 javax.servlet.ServletConfig 作用域 Page

page 页面对象 类型 javax.lang.Object 作用域 Page

exception 例外对象 类型 javax.lang.Throwable 作用域 page

1)request 对象代表的是来自客户端的请求,例如我们在FORM表单中填写的信息等,是最常用的对象

常用的方法有:getParameter、getParameterNames 和getParameterValues 通过调用这几个方法来获取请求对象中所包含的参数的值。

2)response 对象代表的是对客户端的响应,也就是说可以通过response 对象来组织发送到客户端的数据。但是由于组织方式比较底层,所以不建议普通读者使用,需要向客户端发送文字时直接使用

3)pageContext 对象直译时可以称作“页面上下文”对象,代表的是当前页面运行的一些属性

常用的方法有 :findAttribute、getAttribute、getAttributesScope 和getAttributeNamesInScope

一般情况下pageContext对象用到得也不是很多,只有在项目所面临的情况比较复杂的情况下,才会利用到页面属性来辅助处理。

4)session    对象代表服务器与客户端所建立的会话,当需要在不同的JSP页面中保留客户信息的情况下使用,比如在线购物、客户轨迹跟踪等。“session” 对象建立在cookie的基础上,所以使用时应注意判断一下客户端是否打开了cookie。常用的方法包括getId、 getValue、 getValueNames和putValue等。

HTTP是无状态(stateless)协议;

Web Server 对每一个客户端请求都没有历史记忆;Session用来保存客户端状态信息;由Web Server 写入;存于客户端;客户端的每次访问都把上次的session记录传递给Web Server;Web Server读取客户端提交的session来获取客户端的状态信息

5)application 对象负责提供应用程序在服务器中运行时的一些全局信息,常用的方法有getMimeType和getRealPath等。

6)out 对象代表了向客户端发送数据的对象,与“response” 对象不同,通过“out” 对象发送的内容将是浏览器需要显示的内容,是文本一级的,可以通过“out” 对象直接向客户端写一个由程序动态生成HTML文件。常用的方法除了pirnt和println之外,还包括clear、clearBuffer、flush、getBufferSize和getRemaining,这是因为“out” 对象内部包含了一个缓冲区,所以需要一些对缓冲区进行操作的方法

7)config 对象提供一些配置信息,常用的方法有getInitParameter和getInitParameterNames,以获得Servlet初始化时的参数。

8)page 对象代表了正在运行的由JSP文件产生的类对象,不建议一般读者使用。

9)exception 对象则代表了JSP文件运行时所产生的例外对象,此对象不能在一般JSP文件中直接使用,而只能在使用了“<%@ page isErrorPage="true "%>”的JSP文件中使用

-----------------------------------------------------------------------------

10.Java中java.util.Comparator接口简单描述一下?

java.util.Comparator是比较器接口,如果我们需要控制某个类的次序并且该类本身不支持排序,那么就可以建立一个类比较器来进行排序,实现方式很简单只需要实现java.util.Comparator接口。

java.util.Comparator接口只包括两个函数,它的源码如下:

package java.util;

public interface Comparator<T> {

    int compare(T o1, T o2);

    boolean equals(Object obj);

}

1) 若一个类要实现java.util.Comparator接口:它一定要实现int compare(T o1, T o2) 函数,而另一个可以不实现boolean equals(Object obj) 函数

2)int compare(T o1, T o2) 是比较o1和o2的大小

如果返回值为负数意味着o1比o2小,否则返回为零意味着o1等于o2,返回为正数意味着o1大于o2

-----------------------------------------------------------------------------

11.Java面向对象的特征有哪些方面 

(1)抽象:

抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。抽象包括两个方面,一是过程抽象,二是数据抽象。

(2)继承:

继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。其优点是实现代码的复用。其优点是实现代码划分,隐藏信息以及实现细节。

(3)封装:

封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一 系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。

(4) 多态性:

多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。

-----------------------------------------------------------------------------

12.String是最基本的数据类型吗?

基本数据类型包括byte、int、char、long、float、double、boolean和short。

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

-----------------------------------------------------------------------------

13.Java中String、StringBuffer和StringBuilder的区别

java.lang.String是不可变的对象, 因此在每次对String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象,对于一些经常改变的字符串不要使用String类型,因为每次生成新的对象都会对系统性能产生影响,特别当内存中无引用对象多了以后,JVM虚拟机的GC就会开始工作,性能就会降低。

Java.lang.StringBuffer是线程安全的可变字符序列,在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。可将字符串缓冲区安全地用于多个线程。

java.lang.StringBuilder是一个可变的字符序列,是JDK5.0新增的。此类提供一个与 StringBuffer 兼容的 API,但不保证同步,是非线程安全的。该类被设计用作StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用的时候。

-----------------------------------------------------------------------------

14.说出ArrayList,Vector, LinkedList的存储性能和特性

ArrayList 和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索 

引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程 

安全),通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数 

据时只需要记录本项的前后项即可,所以插入速度较快。

-----------------------------------------------------------------------------

15.Java中&和&&的区别

&是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and)

&和&&都可以作为逻辑运算符的,其逻辑运算规则是相同的,如:

-----------------------------------------------------------------------------

&&具有短路功能,第一个操作符为false就不会再去计算第二个操作符;&作为逻辑运算符时,即使第一个操作符是false,那么它仍然会计算第二个操作符。

-----------------------------------------------------------------------------

16.Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?

方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载 

Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写  

(Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被"屏蔽"了。如果在一个类中定义 

了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。Overloaded的方法是可以改 

变返回值的类型。

-----------------------------------------------------------------------------

17.JVM虚拟机优化

内存泄漏

内存泄漏是比较常见的问题,而且解决方法也比较通用,这里可以重点说一下,而线程、热点方面的问题则是具体问题具体分析了。

内存泄漏一般可以理解为系统资源(各方面的资源,堆、栈、线程等)在错误使用的情况下,导致使用完毕的资源无法回收(或没有回收),从而导致新的资源分配请求无法完成,引起系统错误。

内存泄漏对系统危害比较大,因为他可以直接导致系统的崩溃。

需要区别一下,内存泄漏和系统超负荷两者是有区别的,虽然可能导致的最终结果是一样的。内存泄漏是用完的资源没有回收引起错误,而系统超负荷则是系统确实没有那么多资源可以分配了(其他的资源都在使用)。

 

热点分析

CPU热点:检查系统哪些方法占用的大量CPU时间

内存热点:检查哪些对象在系统中数量最大(一定时间内存活对象和销毁对象一起统计)

这两个东西对于系统优化很有帮助。我们可以根据找到的热点,有针对性的进行系统的瓶颈查找和进行系统优化,而不是漫无目的的进行所有代码的优化。

 

年老代堆空间被占满

异常: java.lang.OutOfMemoryError: Java heap space

说明:

这是最典型的内存泄漏方式,简单说就是所有堆空间都被无法回收的垃圾对象占满,虚拟机无法再在分配新空间。这是非常典型的内存泄漏的垃圾回收情况图。所有峰值部分都是一次垃圾回收点,所有谷底部分表示是一次垃圾回收后剩余的内存。连接所有谷底的点,可以发现一条由底到高的线,这说明,随时间的推移,系统的堆空间被不断占满,最终会占满整个堆空间。因此可以初步认为系统内部可能有内存泄漏。

解决:

这种方式解决起来也比较容易,一般就是根据垃圾回收前后情况对比,同时根据对象引用情况(常见的集合对象引用)分析,基本都可以找到泄漏点。

 

持久代被占满

异常:java.lang.OutOfMemoryError: PermGen space

说明:

Perm空间被占满。无法为新的class分配存储空间而引发的异常。这个异常以前是没有的,但是在Java反射大量使用的今天这个异常比较常见了。主要原因就是大量动态反射生成的类不断被加载,最终导致Perm区被占满。更可怕的是,不同的classLoader即便使用了相同的类,但是都会对其进行加载,相当于同一个东西,如果有N个classLoader那么他将会被加载N次。因此,某些情况下,这个问题基本视为无解。当然,存在大量classLoader和大量反射类的情况其实也不多。

解决:1) -XX:MaxPermSize=16m     2) 换用JDK。比如JRocket。

 

堆栈溢出

异常:java.lang.StackOverflowError

说明:这个就不多说了,一般就是递归没返回,或者循环调用造成

 

线程堆栈满

异常:Fatal: Stack size too small

说明:java中一个线程的空间大小是有限制的。JDK5.0以后这个值是1M。与这个线程相关的数据将会保存在其中。但是当线程空间满了以后,将会出现上面异常。

解决:增加线程栈大小。-Xss2m。但这个配置无法解决根本问题,还要看代码部分是否有造成泄漏的部分。

 

系统内存被占满

异常:java.lang.OutOfMemoryError: unable to create new native thread

说明:这个异常是由于操作系统没有足够的资源来产生这个线程造成的。系统创建线程时,除了要在Java堆中分配内存外,操作系统本身也需要分配资源来创建线程。因此,当线程数量大到一定程度以后,堆中或许还有空间,但是操作系统分配不出资源来了,就出现这个异常了。

分配给Java虚拟机的内存愈多,系统剩余的资源就越少,因此,当系统内存固定时,分配给Java虚拟机的内存越多,那么,系统总共能够产生的线程也就越少,两者成反比的关系。同时,可以通过修改-Xss来减少分配给单个线程的空间,也可以增加系统总共内生产的线程数。

解决:

1) 重新设计系统减少线程数量。

2) 线程数量不能减少的情况下,通过-Xss减小单个线程大小。以便能生产更多的线程。

-----------------------------------------------------------------------------

18.Tomcat优化

Tomcat内存优化,服务器参数配置

Tomcat内存优化主要是对 tomcat 启动参数优化,我们可以在 tomcat 的启动脚本 catalina.sh 中设置 java_OPTS 参数。 

JAVA_OPTS参数说明 

-server 启用jdk 的 server 版; 

-Xms java虚拟机初始化时的最小内存; 

-Xmx java虚拟机可使用的最大内存; 

-XX: PermSize 内存永久保留区域 

-XX:MaxPermSize 内存最大永久保留区域 

服务器内存为2G 可采取以下配置:

JAVA_OPTS=-Xms1024m -Xmx2048m -XX: PermSize=256M -XX:MaxNewSize=256m -XX:MaxPermSize=256m

 

Tomcat并发优化

1) Tomcat连接相关参数

在Tomcat 配置文件 server.xml 中的

 

2) 调整连接器connector的并发处理能力

1>参数说明

maxThreads 客户请求最大线程数 

minSpareThreads Tomcat初始化时创建的 socket 线程数 

maxSpareThreads Tomcat连接器的最大空闲 socket 线程数 

enableLookups 若设为true, 则支持域名解析,可把 ip 地址解析为主机名 

redirectPort 在需要基于安全通道的场合,把客户请求转发到基于SSL 的 redirectPort 端口 

acceptAccount 监听端口队列最大数,满了之后客户请求会被拒绝(不能小于maxSpareThreads ) 

connectionTimeout 连接超时 

minProcessors 服务器创建时的最小处理线程数 

maxProcessors 服务器同时最大处理线程数 

URIEncoding URL统一编码

 

2>Tomcat中的配置示例

3) Tomcat缓存优化

1>参数说明

c ompression 打开压缩功能 

compressionMinSize 启用压缩的输出内容大小,这里面默认为2KB 

compressableMimeType 压缩类型 

connectionTimeout 定义建立客户连接超时的时间. 如果为 -1, 表示不限制建立客户连接的时间

2>Tomcat中的配置示例

4) 参考配置

1>旧有的配置

参考网络对服务器做过如下配置:

2>访问量达到3 百万多的时,更改后的配置

猜你喜欢

转载自blog.csdn.net/MengDiL_yl/article/details/85231664
今日推荐