java和javaee面试常用大全

时间:2022-11-06 19:04:12

需要面试资料可加群:451834594,互相交流学习。

1、什么时候用静态变量 静态方法?为什么要使用静态变量、静态方法?

      他们是全局的,那么走到哪里都可以使用。而是使用很方便。static全局变量只在声明此static全局变量的文件中有效;普通全局变量对整个源程序都有效,当此源程序包含多于一个文件的程序时,对其他文件依然有效。

static局部变量的存储区为静态存储区,普通局部变量的存储区为栈;

static局部变量生存周期为整个源程序,但是只能在声明其的函数中调用

static全局变量只在声明此static全局变量的文件中有效;

普通全局变量对整个源程序都有效,当此源程序包含多于一个文件的程序时,对其他文件依然有效。

 

 

 

2、变量,常量,静态变量存储的位置

常见的存储区域1、栈2、堆4、全局/静态存储区5、常量存储区

由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区。里面的变量通常是局部变量、函数参数等。

由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,程序会一直占用内存,导致内存泄漏,在程序结束后,操作系统会自动回收。

全局/静态存储区

全局变量和静态变量被分配到同一块内存中全局变量又分为初始化的和未初始化的

常量存储区

这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改

 

3、子类中如何调用父类中被重写的方法

通过反射进行。可以在运行时调用任意一个对象的方法 

Class cls = Class.forName("com.jdk"); 
Methods methods[]= cls.getDecliedMethod();
jdk jdkobj = new jdk();
String returnvalue = methods.invoke(jdkobj,null)



4、java反射机制应用场景

在运行时判断任意一个对象所属的类。 
Class cls = Class.forName("com.jdk"); 
返回true 
System.out.print(cls.isInstance(new jdk())); 

在运行时构造任意一个类的对象。 
Class cls = Class.forName("com.jdk"); 
jdk jdkobj = cls.newInstance(); 

在运行时判断任意一个类所具有的成员变量和方法。

Class cls = Class.forName("com.jdk"); 
Methods methods[]= cls.getDecliedMethod(); 
Fields  fields[] = cls.getDeclieredFields(); 



5、各种编码方式及区别?

ISO 就直接规定必须用两个字节,也就是16位来统一表示所有的字符。

即读取文件时,
若为unicode(iso)时,前两个字节可以不用读取。注:固定是两个字节一个字。
Javaunicode编码,也就是用16位来编写一个字符。
utf8:用三个字节来编码一个中文字符。
.Java
源文件(含有中文的话)是用:GBK编码。

ASSCII:每个字符存储是需占用1字节

 

6、什么是tcp/ip协议,什么是三次握手?

 TCP为传输控制协议,IP为网际协议,是网络层最重要的协议。采用TCP/IP协议通过互联网传送信息可减少网络中的传输阻塞,方便大批量的数据在网上传输,从而提高网络的传输效率。 

 

第一次握手:建立连接时,客户端发送syn包(syn=jTCP/IP建立连接时使用的握手信号)到服务器,并进入SYN_SENT状态,等待服务器确认;第二次握手服务器收到syn包,必须确认客户的SYNack=j+1),同时自己也发送一个SYN包。第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHEDTCP连接成功)状态,完成三次握手。

 

7、请求方法有哪些种呢?

GET: 完整请求一个资源 (常用)
HEAD: 仅请求响应首部(向服务器索要与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息)
POST:提交表单(常用)
PUT: 上传(向指定资源位置上传其最新内容)
DELETE:删除(请求服务器删除Request-URI所标识的资源)

TRACE 回显服务器收到的请求,主要用于测试或诊断

 

8、如何实现跨域访问?

后台代理方式 :也就是将后台作为代理,每次对其它域的请求转交给本域的后台,本域的后台通过模拟http请求去访问其它域,再将返回的结果返回给前台,这样做的好处是,无论访问的是文档,还是js文件都可以实现跨域。

基于iframe实现跨域 :两个页面必须属于一个基础域(例如都是xxx.com,或是xxx.com.cn),使用同一协议(例如都是 http)和同一端口(例如都是80),这样在两个页面中同时添加document.domain = "xx.com";  

基于script标签实现跨域 :动态创建script标签就可以加载其它域的js文件,然后通过本页面就可以调用加载后js文件的函数,这样做的缺陷就是不能加载其它域的文档,只能是js文件

使用window.name来进行跨域数据共享。window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限。

 

9、主键和索引的区别?

主键是表中的一个或多个字段,它的值用于惟一地标识表中的某一条记录.;使用索引可快速访问数据库表中的特定信息。索引是对数据库表中一列或多列的值进行排序的一种结构,只有当经常查询索引列中的数据时,才需要在表上创建索引。索引占用磁盘空间,并且降低添加、删除和更新行的速度。

添加索引:ALTER TABLE `table_name` ADD INDEX index_name ( `column` ) 

 

10、存储过程使用?

sql存储过程及应用:存储过程(StoredProcedure),是一组为了完成特定功能的SQL 语句。存储过程在被创建以后,可以在程序中被多次调用,而不必重新编写该存储过程的SQL语句,而且数据库专业人员可随时对存储过程进行修改,但对应用程序源代码毫无影响。因为应用程序源代码只包含存储过程的调用语句,从而极大地提高了程序的可移植性。因为存储过程是预编译的,在首次运行一个存储过程时,查询优化器对其进行分析优化,并给出最终被存在系统表中的执行计划,而批处理的Transaction-SQL 语句在每次运行时都要进行编译和优化,因此速度相对要慢一些。

 

11、Web 服务器性能与站点访问性能优化思路

增加带宽,尽可能多地使用静态内容(静态网页是相对于动态网页而言,是指没有后台数据库、不含程序和不可交互的网页),多台服务器负载均衡同时处理大量的并发访问,减少网页中的 HTTP 请求数。

 

12、负载均衡及算法

负载均衡,其意思就是分摊到多个操作单元上进行执行,例如Web服务器FTP服务器企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。

算法:

随机:负载均衡方法随机的把负载分配到各个可用的服务器上

轮询:轮询算法按顺序把每个新的连接请求分配给下一个服务器,最终把所有请求平分给所有的服务器。

加权轮询:该算法中,每个机器接受的连接数量是按权重比例分配的。

最快算法:最快算法基于所有服务器中的最快响应时间分配连接。

最少连接:系统把新连接分配给当前连接数目最少的服务器

多个服务器间数据共享:session复制。tomcat的session复制使所有节点tomcat的会话相同,tomcat使用组播技术,只要集群中一个tomcat节点的session发生改变,会广播通知所有tomcat节点发生改变。

13、高并发量网站解决方案

HTML静态化、图片服务器分离、数据库集群、库表散列(在应用程序中安装业务和应用或者功能模块将数据库进行分离,不同的模块对应不同的数据库或者表,再按照一定的策略对某个页面或者功能进行更小的数据库散列,比如用户表,按照用户ID进行表散列,这样就能够低成本的提升系统的性能并且有很好的扩展性。),缓存(),负载均衡,CDN(分发网络。其目的是通过在现有的Internet中增加一层新的网络架构,将网站的内容发布到最接近用户的网络“边缘”,使用户可以就近取得所需的内容,提高用户访问网站的响应速度)。


 

14、java的垃圾回收机制(如何确定某个对象是“垃圾”?)。

Java的垃圾回收机制是Java虚拟机提供的能力,用于在空闲时间以不定时的方式动态回收无任何引用的对象占据的内存空间。
需要注意的是:垃圾回收回收的是无任何引用的对象占据的内存空间而不是对象本身。

在java中是通过引用来和对象进行关联的,也就是说如果要操作对象,必须通过引用来进行。那么很显然一个简单的办法就是通过引用计数来判断一个对象是否可以被回收。不失一般性,如果一个对象没有任何引用与之关联,则说明该对象基本不太可能在其他地方被使用到,那么这个对象就成为可被回收的对象了。这种方式成为引用计数法。

 

由于它们互相引用对方,导致它们的引用计数都不为0,那么垃圾收集器就永远不会回收它们。解决方案:在Java中采取了可达性分析法(该方法的基本思想是通过一系列的“GC Roots”对象作为起点进行搜索,如果在“GC Roots”和一个对象之间没有可达路径,则称该对象是不可达的,不过要注意的是被判定为不可达的对象不一定就会成为可回收对象。被判定为不可达的对象要成为可回收对象必须至少经历两次标记过程,如果在这两次标记过程中仍然没有逃脱成为可回收对象的可能性,则基本上就真的成为可回收对象了。)如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。

 

15、单例设计模式的实现?

 

饿汉式是(静态初始化对象)线程安全的,因为虚拟机保证只会装载一次,在装载类的时候是不会发生并发的。

懒汉式也是可以实现线程安全的,只要加上synchronized即可,但是这样一来,会降低整个访问的速度,而且每次都要判断。可以使用"双重检查加锁"的方式来实现,就可以既实现线程安全,又能够使性能不受到很大的影响。并不是每次进入getInstance方法都需要同步,而是先不同步,进入方法过后,先检查实例是否存在,如果不存在才进入下面的同步块,这是第一重检查。进入同步块过后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例,这是第二重检查。这样一来,就只需要同步一次了,从而减少了多次在同步情况下进行判断所浪费的时间。

懒汉式:”双重检查加锁”

     public class Singleton { 
/**
* 对保存实例的变量添加volatile的修饰
*/
private volatile static Singleton instance = null;
private Singleton(){
}
public static Singleton getInstance(){
//先检查实例是否存在,如果不存在才进入下面的同步块
if(instance == null){
//同步块,线程安全地创建实例
synchronized(Singleton.class){
//再次检查实例是否存在,如果不存在才真正地创建实例
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}


资源利用率高,不执行getInstance()就不会被实例,可以执行该类的其他静态方法

 

缺点

第一次加载时不够快,多线程使用不必要的同步开销大

22.   

饿汉式:
publicclass Singleton1 {

private Singleton1() {
}

publicstatic Singleton1 instance = new Singleton1();

public Singleton1 getInstance() {
return instance;
}

}


优点:1.线程安全 
2.
在类加载的同时已经创建好一个静态对象,调用时反应速度快
缺点:资源效率不高,可能getInstance()永远不会执行到,但执行该类的其他静态方法或者加载了该类(class.forName),那么这个实例仍然初始化
解决方案:

.静态内部类

class Singleton5 {
private Singleton5() {
}

privatestaticclass SingletonHelp {
static Singleton5 instance = new Singleton5();
}

publicstatic Singleton5 getInstance() {
return SingletonHelp.instance;
}
}


资源利用率高,不执行getInstance()不被实例,可以执行该类其他静态方法

 

缺点

第一次加载时反应不够快

 

 

16、对设计模式的理解以及使用场景?

单例模式:确保一个类只有一个实例,自行提供这个实例并向整个系统提供这个实例,如网站的计数器,数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。多线程的线程池的设计。

 

装饰模式:以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案;
代理模式:给一个对象提供一个代理对象,并有代理对象来控制对原有对象的引用;

装饰模式应该为所装饰的对象增强功能;代理模式对代理的对象施加控制,并不提供对象本身的增强功能,代理对象完成用户请求,屏蔽用户对真实对象的访问。静态代理是在程序运行之前就已经存在了代理类,动态代理是程序运行中在内存中生成代理类。  
装饰器模式来说,装饰者(decorator)和被装饰者(decoratee)都实现同一个接口。 
对代理模式来说,代理类(proxy class)和真实处理的类(real class)都实现同一个接口。

适配器模式是用新接口来调用原接口,原接口对新系统是不可见或者说不可用的。装饰者模式原封不动的使用原接口适配器是知道被适配者的详细情况的(就是那个类或那个接口)。装饰者只知道其接口是什么,至于其具体类型(是基类还是其他派生类)只有在运行期间才知道。

适配器模式主要是为了接口的转换,而装饰者模式关注的是通过组合来动态的为被装饰者注入新的功能或行为(即所谓的责任)。

 

17、设计模式的原则

1、开闭原则,对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码2、里氏代换原则,任何基类可以出现的地方,子类一定可以出现3、依赖倒转原则,真对接口编程,依赖于抽象而不依赖于具体。

18、进程和线程的区别?

进程就是一个应用程序在处理机上的一次执行过程,它是一个动态的概念,而线程是进程中的一部分,进程包含多个线程在运行。

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源。一个程序至少有一个进程,一个进程至少有一个线程.

 

19、在多线程情况下hashmap的线程不安全问题

Hashtable替换HashMap,如果从结构上对Hashtable 进行修改,除非通过 Iterator 自身的移除或添加方法,否则在任何时间以任何方式对其进行修改,Iterator 都将抛出 ConcurrentModificationException,面对并发的修改,Iterator 很快就会完全失败,而不冒在将来某个不确定的时间发生任意不确定行为的风险。   ConcurrentHashMap和Hashtable主要区别就是围绕着锁的粒度以及如何锁,可以简单理解成把一个大的HashTable分解成多个,形成了锁分离

 

20、spring是何时创建对象的?

框架读取配置文件spring.xml后,将配置文件中每个bean元素对应到BeanDefinition. 
根据配置的class元素值首先得到对应的Class对象,然后用Class.newInstance()方法生成对象实例.有了对象实例后根据配置文件的依赖关系进行初始化加工等工作.完了就可以投放使用.

 

21、启动线程的方法?

Thread类的start()方法来启动一个线程,
这时此线程是处于就绪状态,
并没有运行。
然后通过此Thread类调用方法run()来完成其运行操作的,
这里方法run()称为线程体,
它包含了要执行的这个线程的内容,

 

22、线程的优先级?

* 1.Java中线程优先级:1--10

 * 2.默认优先级:5;设置优先级:setPriority(intp)

我们可以设定,但仍然由操作系统来决定;

 

23、线程的常用操作?

休眠线程:Thread.sleep(1000);

加入线程:* 调用join()的对象,会保证先执行完毕,其它线程才会开始执行;

礼让线程:yield()当前执行的线程,会退回到"就绪"状态,等待操作系统再次分配执行时间.

               操作系统很有可能会再次让这个线程执行;

守护线程:守护线程:当主进程结束时,线程也会跟着结束(但不会立即结束,有个小缓冲)

setDaemon(true);

中断线程:Object-->wait()     Thread-->sleep()  Thread-->yield()

       此方式,会在当线程处于上述三种状态之一时,引发一个异常,

                                                       我们可以在异常中,停止掉线程;

停止线程:stop(),但是常用使用退出标志,使线程正常退出

反对使用stop(),是因为它不安全。它会解除由线程获取的所有锁定,而且如果对象处于一种不连贯状态,那么其他线程能在那种状态下检查和修改它们。结果很难检查出真正的问题所在。suspend()方法容易发生死锁。调用suspend()的时候,目标线程会停下来,但却仍然持有在这之前获得的锁定。此时,其他任何线程都不能访问锁定的资源,除非被"挂起"的线程恢复运行。对任何线程来说,如果它们想恢复目标线程,同时又试图使用任何一个锁定的资源,就会造成死锁。所以不应该使用suspend(),而应在自己的Thread类中置入一个标志,指出线程应该活动还是挂起。若标志指出线程应该挂起,便用wait()命其进入等待状态。若标志指出线程应当恢复,则用一个notify()重新启动线程。

 

 * wait():会释放锁;

 *sleep():不释放锁;

 *yield():不释放锁;

sleep100L)意思为:占用CPU,线程休眠100毫秒
wait
100L)意思为:不占用CPU,线程等待100毫秒

24、同步的好处和弊端?

并发访问:* 1.是否是多线程环境

 * 2.是否有共享数据

 * 3.是否有多条语句操作共享数据

同步的好处:

 * 1.它解决了多个线程的并发性访问的问题;

 * 同步的弊端:

 * 1.由于判断锁对象,所以会有额外的执行代码,所以效率会降低;

56、多线程有几种实现方法?同步有几种实现方法?

多线程有两种实现方法,分别是继承Thread类与实现Runnable接口

同步的实现方面有两种,分别是synchronized,waitnotify

wait():使一个线程处于等待状态,并且释放所持有的对象的lock

sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException异常。

notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。

Allnotity():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。

 

 

25、线程的了解?

锁和死锁:两个或者多个线程之间相互等待,导致线程都无法执行。

生产者消费者,当生产者生产产品满足数量时,进行等待,被消费完时,唤醒,继续生产。

为什么wait(),notify(),notifyAll()等方法都定义在Object类中:

                   1).因为每个类都有可能被多线程访问;

                   2).如果被线程访问时,如果资源没准备好,每个类都有权利要求访问的线程等待、及唤醒;

26、什么是线程池?

对于一个Thread线程,不能多次的调用start();

 *   如果想再次运行,需要再次实例化此线程对象;

 *   如果这个线程对象实例化时,很耗时,那么我们多次使用,就很不方便;

"线程池",它可以缓存一些"线程对象", 我们可以反复的调用缓冲的线程对象;

 

 一个线程池包括以下四个基本组成部分:
               1、线程池管理器(ThreadPool):用于创建并管理线程池,包括创建线程池,销毁线程池,添加新任务;
               2、工作线程(PoolWorker):线程池中线程,在没有任务时处于等待状态,可以循环的执行任务;
               3、任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;
               4、任务队列(taskQueue):用于存放没有处理的任务。

 

27、网络通信:

TCP(传输层)上传任何东西都是可靠的,只要两台机器上建立起了连接,在本机上发送的数据就一定能传到对方的机器上,UDP就好比发电报,发出去就完事了,对方有没有接收到它都不管,所以UDP是不可靠的。TCP传送数据虽然可靠,但传送得比较慢,UDP传送数据不可靠,但是传送得快。

Ip(网络层):网间数据通信。

 端口号是用来区分一台机器上不同的应用程序的。

客户端通过端口6666向服务器端请求连接,服务器端接受客户端的连接请求以后,就在服务器端上安装一个Socket,然后让这个Socket与客户端的Socket连接,这样服务器端就可以与客户端互相通信了,当有另外一个客户端申请连接时,服务器端接受了以后,又会安装另外一个Socket与这个客户端的Socket进行连接。

 

28、error和exception有什么区别?

error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。 exception 表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况。

 

29、Java中的异常处理机制的简单原理和应用。

异常是指java程序运行时(非编译)所发生的非正常情况或错误,与现实生活中的事件很相似,现实生活中的事件可以包含事件发生的时间、地点、人物、情节等信息,可以用一个对象来表示,Java使用面向对象的方式来处理异常,它把程序中发生的每个异常也都分别封装到一个对象来表示的,该对象中包含有异常的信息。

Java对异常进行了分类,不同类型的异常分别用不同的Java类表示,所有异常的根类为java.lang.Throwable,Throwable下面又派生了两个子类:Error和Exception,Error 表示应用程序本身无法克服和恢复的一种严重问题,程序只有死的份了,例如,说内存溢出和线程死锁等系统问题。Exception表示程序还能够克服和恢复的问题,其中又分为系统异常和普通异常,系统异常是软件本身缺陷所导致的问题,也就是软件开发人员考虑不周所导致的问题,软件使用者无法克服和恢复这种问题,但在这种问题下还可以让软件系统继续运行或者让软件死掉,例如,数组脚本越界(ArrayIndexOutOfBoundsException),空指针异常(NullPointerException)、类转换异常(ClassCastException);普通异常是运行环境的变化或异常所导致的问题,是用户能够克服的问题,例如,网络断线,硬盘空间不够,发生这样的异常后,程序不应该死掉。

java为系统异常和普通异常提供了不同的解决方案,编译器强制普通异常必须try..catch处理或用throws声明继续抛给上层调用方法处理,所以普通异常也称为checked异常,而系统异常可以处理也可以不处理,所以,编译器不强制用try..catch处理或用throws声明,所以系统异常也称为unchecked异常。