java面试题

未完待续…..

1.算法

1>排序

1.Comparable和Comparator接口有什么区别?

Comparable接口用于自然排序,Comparator接口用于需要对排列的顺序进行精准控制的情形。

2.如何实现冒泡算法?
3.如何实现插入排序算法?
4.如何实现快速排序算法?
5.如何实现归并排序算法?
6.如何实现二分搜索?

2>数据结构

1.LinkedList和ArrayList的区别?

LinkedList底层是链表,在插入和移除的时候有优势;ArrayList底层是数组,再随机访问列表中的元素时有优势。

2.Queue和Deque是什么?

Queue是先入先出的数据结构接口,add表示添加,remove表示移除,peek用于返回最老的元素;Deque是对Queue的扩展,它的两端都允许添加和删除元素。

3.实现一个二叉树?
4.TreeMap和HashMap的区别?
5.HashMap和HashTable的区别?
6.LinkedHashMap、ConcurrentHashMap和HashMap的区别?
7.List、Map、Set的区别?
8.所有的集合API类都是从那些类继承来的?

List和Set继承自Collection接口,Map。

9.HashSet和LinkedHashSet的区别?

HashSet是无序的,在插入和删除方面有优势,LinkedHashSet是有序的,在遍历时有优势。

3>设计模式

1.谈谈单例模式?

单例模式指的是只允许创建一个实例的类。单例模式通常用于需要向第三方提供单一入口点的场合,例如数据库和WEB服务,通过这种方式可以方便地在同一个地方管理和配置多个连接。

2.手写单例模式(饿汉,懒汉,双重加锁,枚举)
3.谈谈工厂模式?
4.生成器模式有什么用?

4>算法

1.编写一个算法,打印输出1到n之间的所有数字,将3的倍数替换为StringFizz,将5的倍数替换为Buzz,将15的倍数替换为FizzBuzz?
2.编写一个返回裴波那契数列从第1到第n个数的方法?
3.编写一个方法,返回裴波那契数列中第n个数?
4.编写一个不使用递归的阶乘实现?
5.给定一个单词,编写一个算法找出这一组单词中属于某个给定单词的变为词?
6.编写一个翻转String的方法?
7.如何原地翻转一个链表?
8.如何测试一个单词是否是回文?
9.编写一个算法,将一个列表的Iterator折叠为一个单独的Iterator?
10.编写一个算法,这个方法复制一个Integer的列表,并且对每一个元素都加1?

5>java基础

1.列出java的一些原始类型,阐述JVM是如何处理这些类型的?

java的原始类型有byte、short、int、long、float、double、boolean。如果原始类型在定义时没有设置值,那么会使用一个默认值。必要时,编译器可以将值向上转换至恰当的类型。

2.为什么Integer.MIN_VALUE没有对应的正数?

short、int、long在内存中存储时使用了一种成为二进制补码的形式。得到一个正数值对应的负数值的方法是执行二进制NOT操作然后加1。

3.Java对象是什么?

对象是对状态和行为的封装。对象可以定义为一组变量的集合和一组方法的集合,这组变量可以看成是整合在一起表示一个复杂的实体,而这组方法提供了和这个实体相关的操作。

4.final关键字对对象引用有什么作用?

变量定义时设置变量的值,然后变量表示的内存位置存储的值不能变化。即对象引用不能变化,但是对象内容是可变的。

5.对象中的可见修饰符有什么作用?

可见修饰符控制的是对类中封装的状态以及控制实例行为的方法的访问权。

修饰符范围
private仅类中可见
同一个包中可见
protected同一个包中和类的子类可见
public任意位置可见
6.对于方法和变量来说,static修饰符表示什么意思?

类中定义的静态方法和变量属于类,不属于某个实例,通过类名类访问。

7.多态和继承是什么?

通过多态,可以为某一个特定类型的行为进行定义,并且可以针对这种行为提供多种不同的实现类。
通过继承,可以在定义一个类时从父类继承行为和状态,然后在自己类中添加新的行为,或者覆盖父类中原有的行为。

重载和重写有什么区别?

重载:允许多个同名但是形式参数个数或参数类型不同的方法存在同一个类中,在调用时根据形式参数列表来调用对应的方法。
重写:对父类的函数进行重新定义,在子类中定义的某方法与其父类有相同的名称和参数,就可以称为该方法被重写或者覆盖了。

8.解释Object类被继承时一些会被重写的方法?

Object是所有类的父类,因此这个类中所有的非final的public和protected方法都可以被重写。
equals:测试两个引用表示的对象是否逻辑上相等。
hashCode:对于两个相等的对象,必须返回一个值,反之不成立。
如果要重写hashCode或equals方法,那么这两个方法都必须重写。
数组在java中是怎样表示的?
数组也是对象,可以像对象一样的操作。

类加载器有哪几种?有什么区别?

启动类加载器(bootstrap):将lib和jre/classes下的类库加载到内存中,该加载器不能直接调用。
标准扩展类加载器(Extension):将jre/lib/ext下和系统变量位置的类库加载到内存中,该加载器可以被调用;
应用程序类加载器(Application):将classpath下的类库加载到内存中。

什么是双亲委派模式?优势是什么?

双亲委派模式的原理:类加载器收到类加载请求,它不会自己先去加载,而是把这个请求委派给父类的加载器去执行,如果父类加载器有父类加载器,则进一步向上委托,直到最顶层的类加载器,若父类加载器可以完成类加载任务,则成功返回,否则就让子类加载器去加载。
这种模式的好处是java类随着它的类加载器一起具备了一种带有优先级的层次关系,通过这种层级关系可以避免类的重复加载,其次是安全考虑,防止核心API库被随意篡改。

怎么实现一个自定义的类加载器?

继承ClassLoader,重写其中的findClass方法。
使用Class.forName可以调用自定义的类加载器加载类。

9.String在内存中是怎样保存的?

String表示的值使用char数组来保存。

10.可不可以修改一个String的值?

String是不可变的,任何修改都会返回一个新的String实例。
不可变对象都是线程安全的,除了String,所有的树脂类,例如Integer、Double、Character都是不可变的。

为什么String不可变?

只有当字符串不可变时,字符串池才可能实现,这样可以在运行时节省很多堆内存
安全性:字符串在很多类中被用作参数,可变的字符串会因被篡改从而导致出现错误;
字符串不可变是线程安全的,多线程调用时可以不用增加同步操作,可以提升性能;
类加载器要用到字符串,不可变提供了安全性,以便正确的类被加载;
支持hash映射和缓存,因字符串不可变,其对应的hashcode不需要重新计算,很适合座位Map中的键。

什么是不可变对象?有什么优点?

不可变对象是指类创建之后,它的状态就不可以被改变。
1.类添加final修饰符,保证类不能被继承;
2.成员变量保证私有,并添加final修饰符;
3.不提供改变成员变量的方法,如setter;
4.通过构造器初始化所有成员,实现深拷贝;
5.在getter方法中,返回对象的拷贝。
不可变对象是线程安全的,在多线程中不需要进行同步节省了同步开销,提升了性能,以及保证了安全性。

11.什么是驻留?

JVM会将所有的字面量保存在一个常量池中。如果出现了重复的String字面量,那么通过池中已经存在的相同常量来引用,这既是String驻留。任何String实例都可以通过Intern()方法添加到这个池中。
String str = “hello”;即为字符串字面量,类加载时创建,String str = new String(“hello”);运行时创建一个新对象,不会引用常量池中的字符串字面量。可以通过Intern()方法来重用字符串字面量。
字符串字面量不会被垃圾回收。

12.解释如何结合泛型使用Collections API?

泛型也称为模板化类型,结合泛型使用Collections类时,编译器就知道约束集合时只允许包含特定类型的对象。

13.类型变体对泛型有什么影响?

B是A的一个子类,但是List不是List的一个子类,这种成为类型变体。
在使用泛型时,使用List

14.具体化是什么意思?

具体化的意思是运行时生效,java的泛型类型是没有具体化的。生成的class文件会抹除掉所有的泛型信息。

15.原始类型的访问可能抛出NullPointerException异常吗?

不可能。

16.@Override注解有什么用?

有一个父类的方法要被重写。

17.描述异常层次结构中的核心类?

Throwable:异常的顶级类。
Error:无法修复的错误,通常是环境或者编译器出错。
Exception:可以修复的异常。
RuntimException:运行时异常。
剩余的为检查时异常。

18.什么是异常链?

抛出一个之前已经捕获的异常时,在这个新的异常中添加引用,这种成为异常链。

19.try-with-resources语句是什么?
20.为什么私有字段还需要通过标记final设置为不可变?

反射机制有能力访问并修改所有字段,因此将私有字段设置为final是很有必要的。

21.java8有什么值得期待的新特性?

接口的默认实现和lambda表达式。

6>单元测试

1.JUnit测试是怎样运行的?

Maven项目中运行mvn test即可。

2.如何验证测试成功?

assertEquals 判断两个对象是否相等。
assertTrue和assertFalse 判断表达式是否符合预期的布尔值。
assertNotNUll 判断一个对象非空。
assertArrayEquals 判断两个数组是否包含同样的值。

7>JVM

1.内存如何分配?

java内存分配主要包括以下几个区域:
寄存器
栈:存放基本类型的数据和对象的引用。
堆:存放new产生的数据。在堆中分配的内存,由垃圾回收来管理。
静态域:存放在类中用static定义的静态成员。
常量池:存放常量,在方法域中,不在堆中。
字符串,其对象的引用存储在栈中,如果是编译器已经创建好的存储在常量池中,如果是运行期创建的放在堆中。因此,字符串在常量池中只有一份,在堆中可能有多份。
基础类型:变量和引用放在栈中,常量存储在常量池中。
局部变量:存于栈内存中。
方法变量:存于堆中的对象里面。

2.什么是垃圾回收?
3.堆和栈有什么区别?
4.怎样定义JVM堆的大小?
5.在java中可能发生内存泄漏吗?
6.从开始编写java到运行的声明周期是什么样的?
7.能不能显示地要求JVM执行垃圾回收?

调用System.gc()告诉JVM进行一次垃圾回收,但是不能保证一定会进行一次垃圾回收。

8.finalize方法作用是什么?
9.什么是原生方法?

8>多线程

什么是线程?

线程是操作系统能用运算调度的最小单位,它包含在进程之中,是进程中的实际运作单位。

进程和线程有什么区别?

线程是进程的子集,一个进程可以有多个线程,每条线程并行执行不同的任务。不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。

如何实现线程?

集成Thread类或者调用Runnable接口来重写run方法实现线程。由于java不支持多继承,但是运行调用多个接口,所以如果需要继承其他类,调用Runnable接口。

Runnable和Callable有什么不同?

Callable的call方法可以返回值和抛出异常,Runnable的run方法没有这些功能。

什么是线程安全?

多线程下运行代码,如果每次运行结果和单线程运行的结果是一样的,而且其他变量的值也和预期的一样,就是线程安全的。

如何停止一个线程?

由于原来的stop、suspend、resume会导致死锁而被废弃了,之后的API没有提供新的停止的方法,要停止一个线程,可以在run方法中使用volatile布尔变量来退出。

一个线程运行时发生异常会怎么样?

如果异常没有被捕获该线程会停止执行。

如何在两个线程间共享数据?

使用共享对象或者像阻塞队列这样并发的数据结构。

notify和notifyAll有什么区别?

notify方法随机唤醒一个线程,所以只有一个线程等待时才有用武之地;notufyAll唤醒所有线程。

为什么wait、notify和notifyAll这些方法不在Thread类里面?

java提供的锁是对象级的而不是线程级的,每个对象都有锁,通过线程获得。如果线程需要等待某些锁那么调用对象中的wait方法就有意义了。如果wait方法定义在Thread类中,线程正在等待的那个锁就不明显了。

什么是ThreadLocal变量?

每个线程都有一个ThreadLocal就是每个线程都拥有了自己独立的一个变量,竞态条件被消除了。它是为创建代价高昂的对象获取线程安全的好办法。

什么是FutureTask?

在并发程序中FutureTask表示一个可以取消的异步运算。它有启动和取消运算、查询运算是否完成和取回运算结果等方法。只有当运算完成的时候结果才能取回。一个FutureTask对象可以调用Callable和Runnable的对象进行包装,并且Future可以提交给Executor来执行。

interrupted和isinterrupted方法的区别?

interrupted会将中断状态清楚而isinterrupted方法不会改变中断状态标识。

什么是线程池?怎么合理使用规划线程池?

创建线程需要花费昂贵的资源和时间,任务来了才创建线程,那么响应时间会变长,而且一个进程能够创建的线程数有限,为了避免这些问题,在程序启动的时候就创建若干线程来响应处理,它们称为线程池。
最佳线程数目 = (线程等待时间 / 线程CPU时间 + 1) * CPU数目,
线程等待时间所占比例越高,需要越多线程。线程CPU时间所占比例越高,需要越少线程。

高并发、任务执行时间短的业务怎么使用线程池?并发不高、任务执行时间长的业务怎么使用线程池?并发高、业务执行时间长的业务怎么使用线程池?

1.高并发、任务执行时间短的业务,线程池线程数可以设置为CPU核数+1,减少线程上下文的切换。
2.并发不高、任务执行时间长的业务,若是IO密集型的任务,可以适当加大线程池中的线程数目,若是计算密集型的任务,线程池的线程数设置得少一些。
3.并发高、业务执行时间长的业务,需要从整体架构进行考虑,比如缓存、增加服务器和中间件等。

现在有T1、T2、T3三个线程,你怎样保证T2在T1执行后执行,T3在T2执行后执行?

使用thread.join方法,可以在T2线程里面调用T1线程的join方法,或者在调用线程的start方法后调用。

Lock接口比synchronized块优势是什么?

synchronized不能扩展锁之外的方法或者块边界,尝试获取锁时不能中途取消等。Lock解决了这些问题。

wait和sleep方法的不同?

两者都会导致当前线程等待,但是wait会释放锁,sleep一直持有锁。wait通常用于线程间交互,sleep通常勇于暂停执行。

什么是原子操作?

原子操作是不可分割的操作,一个原子操作是不会被其他线程打断的。
多个原子操作合并起来后就不是一个原子操作了,就需要同步了。

java中volatile关键字有什么用?

volatile:保证变量的可见性。被volatile修饰的变量,能保证该变量的下一次读或写操作是在上一个写或者读操作之后发生。
线程安全需要原子性和可见性,volatile只保证可见性,synchronized两个都保证。volatile只能修饰变量,synchronized还可修饰方法;volatile不会造成线程的阻塞,synchronized可能会造成线程的阻塞。

什么是竞态条件?如何处理?

竞态条件:设备或者系统出现不恰当的执行顺序,从而得不到正确的结果。例如读取-修改-写入三步,在多线程条件下,三个小操作并不一定会放在一起执行。
解决办法:将必要复合操作使用同步的手段保证原子性或者使用线程安全的类。

为什么要调用start方法而不是直接执行run方法?

当你调用start方法时,会创建一个新的线程并执行run方法里的代码;但是直接调用run方法,不会创建新的线程而是直接执行代码。

怎样唤醒一个阻塞的线程?

如果是调用wait、sleep或者join导致的阻塞,可以中断线程,并通过抛出中断异常来唤醒它。如果是同步I/O,关掉底层Channel然后处理异常。

CycliBarriar和CountdownLatch有什么区别?

两者可以用来让一组线程等待其他线程,CycliBarriar可以重复使用,CountdownLatch只能使用一次。

java内存模型是什么?

java内存模型规定和指引java程序在不同的内存架构、CPU和操作系统之间有确定性的行为。其对一个线程所做的变动能被其他线程可见提供了保证,他们之间是先行发生关系。
1.线程内的代码能够按先后顺序执行;
2.对于同一个锁,一个解锁操作发生在另一个锁定操作之前;
3.前一个对volatile的写操作发生在后一个volatile的读操作之前;
4.一个线程内的任何操作必须在这个线程的start调用之后;
5.一个对象的终结操作必须在这个对象构造完成之后。

什么是死锁,如何避免?

死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象。
死锁的放生必须满足:
- 互斥条件:一个资源每次只能被一个进程使用。
- 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不妨。
- 不剥夺条件:进程已获取的资源,在未使用完之前,不能强行剥夺。
- 循环等待条件:若干线程之间形成一种头尾相接的循环等待资源的关系。
避免死锁的方法就是阻止循环等待条件,规定所有的进程中申请资源必须以一定的顺序做操作。

活锁和死锁有什么区别?

死锁和活锁类似,区别在于活锁的线程或者进程的状态时不断改变的。

怎么检测一个线程是否拥有锁?

Thread提供了holdsLock方法来检测当前线程是否持有锁。

sleep和yield有什么区别?

两者都可以暂缓执行当前线程,且不会释放锁。
sleep可以精确指定休眠时间,yield依赖于CPU的时间片划分。
sleep会抛出中断异常,且可以被中断,yield不可以。

线程池已满,此时提交任务,会发生什么?

此时执行线程池的submit方法会抛出异常。

ReadWriteLock是什么?

读写锁是用来提升并发程序性能的锁分离技术的成果,其维护一对关联的锁,一个用于只读一个用于写。在没有写线程的情况下一个读锁可能同时被多个线程所持有。

多线程最佳实践?

1.给线程取名字;
2.避免锁定和缩小同步的范围;
3.多用同步类;
4.多用并发集合少用同步集合。

9>SQL

什么是内连接?什么是外连接?

内连接:内联接使用比较运算符根据每个表共有的列的值匹配两个表中的行。
SELECT * FROM USER a INNER JOIN user_test b ON a.id=b.id
外连接:外联接可以是左向外联接、右向外联接或全连接。
左外连接:左向外联接的结果集包括 LEFT OUTER子句中指定的左表的所有行,如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值。
SELECT * FROM USER a LEFT JOIN user_test b ON a.id=b.id
右外连接:将返回右表的所有行。如果右表的某行在左表中没有匹配行,则将为左表返回空值。
全连接:完整外部联接返回左表和右表中的所有行。使用FULL JOIN

什么是视图?

将一个常用的查询或者连接设置为一个虚拟表,这个虚拟表被称为视图。

大数据量的表如何快速清空?

方法一:使用truncate。
方法二:使用CREATE TABLE user1 AS SELECT * FROM USER创建一个只有一条数据的相同表,将原表使用drop删除,将新创建表改名即可。

in和exists的区别?

select * from A where id in (select id form B)
in适用于B表比A表数据少的情况(遍历A*B次),exists适用于B表比A表数据多的情况。(执行A次)。

10>WEB

Web应用程序在Servlet API中是如何定义的?

Servlet API通过一个名为web.xml的部署描述文件来定义WEB应用程序,这个文件定义了Servlet以及通过Servlet容器进行配置和服务的方式。

如何安全地管理发向某个具体Servlet的请求?

使用过滤器对请求进行检查,判断是否应该传递给Servlet执行。

如何通过Servlet API处理请求参数?

11>HTTP

什么是http?
什么是http方法?

http方法,是一种指令,告诉web服务器针对请求的资源采取什么操作。常用的有Get、Post、Put、Delete。

什么是Rest?
Rest请求和WebService请求有什么区别?

12>Spring

什么是依赖注入?
什么是IOC?
什么是AOP?
Spring中依赖注入有那些方式?
Spring如何提供Web应用服务?
13>maven
什么是maven?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值