大厂春招面试题(一)java

         最近一直在忙春招,很久没有更新博客了,好在结果还算圆满,现在把2017年BAT包括网易面试题整理成一个系列供大家分享!当然面试内容很大一部分取决于不同的面试官以及应聘职位,但对于本科大学生来说,总有一些硬菜是需要掌握的。除了具备良好的基础知识,包括编程语言,数据结构和算法,数据库,操作系统,计算机网络以及计算机组成原理,最好还是应该有个人专研的技术方向,技术方向没有高低贵贱之分,但是能够日积月累,专注热爱才最有助于提高自己的专业能力。面试很大一方面也取决于个人的心态,大厂很重视技术的深度和广度,四面中前三面都是技术面,而且个人感觉面试官也在一步一步升级,到第三面的时候博主已经紧张到好多问题答不出来,好在面试官真的耐心而且说话也好听可怜,在自己卡壳的时候都能循循善诱,帮你理清思路。而且百度面试官技术面真的广,项目涉及的技术都能聊得很愉快,就面试来说都能学到不少东西。对于相关解答有不同意见的欢迎留言反馈,对于博主尚未熟练掌握的内容没有写明答案以免误导大家,下面是关于Java的一些问题:

    

1. Collection类,Collection包结构,与Collections的区别 

         Collection是集合类的上级接口,子接口主要有Set 和List、Map。   Collections是针对集合类的一个帮助类,提供了操作集合的工具方法:一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。 对于java集合的介绍博主前面的博客有详细介绍,自行查阅:http://blog.csdn.net/laona_sdu/article/details/62050753


 2.  java哪些集合类是线程安全的 

vector:比arraylist多了个同步化机制(线程安全),因为效率较低,现在已经不太建议使用。在web应用中,特别是前台页面,往往效率(页面响应速度)是优先考虑的。 

statck:堆栈类,先进后出 

enumeration:枚举,相当于迭代器 

hashtable:比hashmap多了个线程安全  


3.  线程安全是什么意思

       就是线程同步的意思,就是当一个程序对一个线程安全的方法或者语句进行访问的时候,其他的不能再对他进行操作了,必须等到这次访问结束以后才能对这个线程安全的方法进行访问。


 4.Java九种基本数据类型,他们的大小以及封装类

基本类型

大小(字节)

默认值

封装类            

byte

1

(byte)0

Byte

short

2

(short)0

Short

int

4

0

Integer           

long

8

0L

Long

float

4

0.0f

Float

double

8

0.0d

Double

boolean

-

false

Boolean

char

2

\u0000(null)

Character

void

-

-

 

 

 

 

 

 

 

 

 

 

 

 

 

基本数据类型与其对应的封装类由于本质的不同,基本数据类型只能按值传递,而封装类按引用传递。

按值传递重要特点:传递的是值的拷贝,也就是说传递后就互不相关了。

按引用传递重要特点:传递的引用的地址,也就是变量所对应的内存空间的地址

(1):“在Java里面参数传递都是按值传递”这句话的意思是:按值传递是传递的值的拷贝,按引用传递其实传递的是引用的地址值,所以统称按值传递。

(2):在Java里面只有基本类型和按照String str =“Java”这种方式定义的String是按值传递,其它的都是按引用传递。

Integer默认值是null,所以Integer能区分出0和null的情况。一旦java看到null,就知道这个引用还没有指向某个对象,再任何引用使用前,必须为其指定一个对象,否则会报错。基本数据类型在声明时系统会自动给它分配空间,而引用类型声明时只是分配了引用空间,必须通过实例化开辟数据空间之后才可以赋值

String不属于基本数据类型。


5. Switch能否用string做参数

   在 Java 7之前,switch 只能支持 byte、short、char、int或者其对应的封装类以及 Enum 类型。在 Java 7中,String支持被加上了。但不支持浮点数。


6.equals与==的区别

对复合数据类型用==进行比较的时候,比较的是他们在内存中的存放地址,

所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。对java基本数据类型而言,==比较的是对象的值,如果值相等返回true。

equals是一个方法,在object类中方法体为return(this==obj)。但在一些类库当中这个方法被覆盖掉了,

String,Integer,Date在这些类当中equals有其自身的实现,而不再是比较对象在内存中的存放地址了。

对于复合数据类型之间进行equals比较,在没有覆写equals方法的情况下,他们之间的比较还是基于他们在内存中的存放地址的。

 “equal”不能用于基本数据类型。只能用于类变量。对于基本数据类型要用其包装类。


7. Object有哪些公用方法?

·clone方法:创建并返回此对象的一个副本

保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常。

PS:浅复制是指当对象的字段值被复制时,字段引用的对象不会被复制。

例如,如果一个对象有一个指向字符串的字段,并且我们对该对象做了一个浅复制,那么两个对象将引用同一个字符串

·toString方法:该方法用得比较多,一般子类都有覆盖。返回一个该对象的String类型引用。

·getClass方法:final方法,获得运行时类型。返回值是class。

·finalize方法:该方法用于释放资源(由垃圾回收器调用)。因为无法确定该方法什么时候被调用,很少使用。设计的初衷是在一个对象被真正回收之前,可以用来执行一些清理的工作。因为Java并没有提供类似C++的析构函数一样的机制,就通过 finalize方法来实现。

·equals方法:在Object中和“==”是一样的。子类一般都要重写这个方法。

·hashCode方法:返回一个对象的hashcode。该方法用于哈希查找,可以减少在查找中使用equals的次数,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。一般必须满足obj1.equals(obj2)==true。可以推出obj1.hash-Code()==obj2.hashCode(),但是hashCode相等不一定就满足equals。不过为了提高效率,应该尽量使上面两个条件接近等价。如果不重写hashcode(),在HashSet中添加两个equals的对象,会将两个对象都加入进去。

·wait()

有三种重载方法。使当前线程等待该对象拥有的锁,当前线程必须是该对象的拥有者。

wait()方法一直等待,直到线程获得锁或者被中断。

wait(long timeout)设定一个超时间隔,如果在规定时间内没有获得锁线程就返回。

wait(long timeout, int nanos):对两个参数做了下简单校验,然后调用wait(long timeout)。

调用该方法后当前线程进入睡眠状态,直到以下事件发生。

(1)其他线程调用了该对象的notify方法。

(2)其他线程调用了该对象的notifyAll方法。

(3)其他线程调用了interrupt中断该线程。

(4)时间间隔到了。

此时该线程就可以被调度了,如果是被中断的话就抛出一个InterruptedException异常。

·notify方法:该方法唤醒在该对象上等待的某个线程。

·notifyAll方法:该方法唤醒在该对象上等待的所有线程。


8. Java的四种引用,强弱软虚,用到的场景。

          在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象。也就是说,只有对象处于可触及(reachable)状态,程序才能使用它。从JDK 1.2版本开始,把对象的引用分为4种级别,从而使程序能更加灵活地控制对象的生命周期。这4种级别由高到低依次为:强引用、软引用、弱引用和虚引用。

⑴ 强引用(StrongReference)

强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。

 ps:强引用其实也就是我们平时Aa = new A()这个意思。

显式地设置anull,或超出对象的生命周期范围(方法内的局部变量),则gc认为该对象不存在引用,这时就可以回收这个对象。具体什么时候收集这要取决于gc的算法。

⑵ 软引用(SoftReference)

如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它(回收的是被引用的对象而不是该软引用),该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存(下文给出示例)。

可以通过以下代码实现
Object obj = new Object();
SoftReference<Object> sf = newSoftReference<Object>(obj);

软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。

⑶ 弱引用(WeakReference)

只具有弱引用的对象比只具有软引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。

弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

如果这个对象是偶尔的使用,并且希望在使用时随时就能获取到,但又不想影响此对象的垃圾收集,那么你应该用 Weak Reference 来记住此对象。   也可以使用弱引用构建非敏感数据的缓存,在Java集合中有一种特殊的Map类型—WeakHashMap,在这种Map中存放了键对象的弱引用,当一个键对象被垃圾回收器回收时,那么相应的值对象的引用会从Map中删除。WeakHashMap能够节约存储空间,可用来缓存那些非必须存在的数据。

   下面的代码会让str再次变为一个强引用:

String  abc = abcWeakRef.get();

弱引用不会介入对象的生命周期,主要用于监控对象是否已经被垃圾回收器标记为即将回收的垃圾,可以通过弱引用的isEnQueued方法返回对象是否被垃圾回收器标记。

⑷虚引用(PhantomReference)

“虚引用”顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何垃圾回收器回收时候都可能被回收。

虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。

ReferenceQueue queue = new ReferenceQueue();

PhantomReference pr = new PhantomReference(object, queue);

程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

使用软引用构建敏感数据的缓存:

例如浏览器的后退按钮。按后退时,这个后退时显示的网页内容是重新进行请求还是从缓存中取出呢?这就要看具体的实现策略了。

(1)如果一个网页在浏览结束时就进行内容的回收,则按后退查看前面浏览过的页面时,需要重新构建

(2)如果将浏览过的网页存储到内存中会造成内存的大量浪费,甚至会造成内存溢出

这时候就可以使用软引用

 

1 为什么需要使用软引用

我们知道,访问磁盘文件、访问网络资源、查询数据库等操作都是影响应用程序执行性能的重要因素,如果能重新获取那些尚未被回收的Java对象的引用,必将减少不必要的访问,大大提高程序的运行速度。

2 如何使用软引用

SoftReference的特点是它的一个实例保存对一个Java对象的软引用,该软引用的存在不妨碍垃圾收集线程对该Java对象的回收。也就是说,一旦SoftReference保存了对一个Java对象的软引用后,在垃圾线程对这个Java对象回收前,SoftReference类所提供的get()方法返回Java对象的强引用。另外,一旦垃圾线程回收该Java对象之后,get()方法将返回null

看下面代码:

MyObject aRef = new MyObject();

SoftReference aSoftRef=newSoftReference(aRef);

此时,对于这个MyObject对象,有两个引用路径,一个是来自SoftReference对象的软引用,一个来自变量aReference的强引用,所以这个MyObject对象是强可及对象。

随即,我们可以结束aReference对这个MyObject实例的强引用:

aRef = null;

此后,这个MyObject对象成为了软可及对象。如果垃圾收集线程进行内存垃圾收集,并不会因为有一个SoftReference对该对象的引用而始终保留该对象。Java虚拟机的垃圾收集线程对软可及对象和其他一般Java对象进行了区别对待:软可及对象的清理是由垃圾收集线程根据其特定算法按照内存需求决定的。也就是说,垃圾收集线程会在虚拟机抛出OutOfMemoryError之前回收软可及对象,而且虚拟机会尽可能优先回收长时间闲置不用的软可及对象,对那些刚刚构建的或刚刚使用过的“新”软可反对象会被虚拟机尽可能保留。在回收这些对象之前,我们可以通过:

MyObjectanotherRef=(MyObject)aSoftRef.get();

重新获得对该实例的强引用。而回收之后,调用get()方法就只能得到null了。

 

3 使用ReferenceQueue清除失去了软引用对象的SoftReference

作为一个Java对象,SoftReference对象除了具有保存软引用的特殊性之外,也具有Java对象的一般性。所以,当软可及对象被回收之后,虽然这个SoftReference对象的get()方法返回null,但这个SoftReference对象已经不再具有存在的价值,需要一个适当的清除机制,避免大量SoftReference对象带来的内存泄漏。在java.lang.ref包里还提供了ReferenceQueue。如果在创建SoftReference对象的时候,使用了一个ReferenceQueue对象作为参数提供给SoftReference的构造方法,如:

ReferenceQueue queue = new ReferenceQueue();

SoftReference ref=new SoftReference(aMyObject,queue);

那么当这个SoftReference所软引用的aMyOhject被垃圾收集器回收的同时,ref所强引用的SoftReference对象被列入ReferenceQueue。也就是说,ReferenceQueue中保存的对象是已经失去了它所软引用的对象的Reference对象。另外从ReferenceQueue这个名字也可以看出,它是一个队列,当我们调用它的poll()方法的时候,如果这个队列中不是空队列,那么将返回队列前面的那个Reference对象。

在任何时候,我们都可以调用ReferenceQueue的poll()方法来检查是否有它所关心的非强可及对象被回收。如果队列为空,将返回一个null,否则该方法返回队列中前面的一个Reference对象。利用这个方法,我们可以检查哪个SoftReference所软引用的对象已经被回收。于是我们可以把这些失去所软引用的对象的SoftReference对象清除掉。常用的方式为:

SoftReference ref = null;

while ((ref = (EmployeeRef) q.poll()) !=null) {

// 清除ref

}


9. Hashcode的作用。 

          要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢? 这就是Object.equals方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。 也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000equals方法。这显然会大大降低效率。于是,Java采用了哈希表的原理。 哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上。

          put方法是用来向HashMap中添加新的元素,从put方法的具体实现可知,会先调用hashCode方法得到该元素的hashCode值,然后查看table中是否存在该hashCode值,如果存在则调用equals方法重新确定是否存在该元素,如果存在,则更新value值,否则将新的元素添加到HashMap中。从这里可以看出,hashCode方法的存在是为了减少equals方法的调用次数,从而提高程序效率。

          因此有人会说,可以直接根据hashcode值判断两个对象是否相等吗?肯定是不可以的,因为不同的对象可能会生成相同的hashcode值。虽然不能根据hashcode值判断两个对象是否相等,但是可以直接根据hashcode值判断两个对象不等,如果两个对象的hashcode值不等,则必定是两个不同的对象。如果要判断两个对象是否真正相等,必须通过equals方法。

  也就是说对于两个对象,如果调用equals方法得到的结果为true,则两个对象的hashcode值必定相等;

  如果equals方法得到的结果为false,则两个对象的hashcode值不一定不同;

  如果两个对象的hashcode值不等,则equals方法得到的结果必定为false;

  如果两个对象的hashcode值相等,则equals方法得到的结果未知。

 

10. ArrayList、LinkedList、Vector的区别。 

LinkedList类:快速插入和删除元素

LinkedList是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。

LinkedList 实现 List 接口,能对它进行队列操作。

LinkedList 实现 Deque 接口,即能将LinkedList当作双端队列使用。

LinkedList 实现了Cloneable接口,即覆盖了函数clone(),能克隆。

LinkedList 实现java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。,允许null元素。

此外LinkedList提供额外的get,remove,insert方法在LinkedList的首部或尾部执行操作。

这些操作使LinkedList可用来实现堆栈(stack),队列(queue)或双向队列(deque)。

注意LinkedList没有同步方法。如果多个线程同时访问一个List,则必须自己实现访问同步。

一种解决方法是在创建List时构造一个同步的List:

List list = Collections.synchronizedList(newLinkedList(...));

ArrayList类:快速随机访问元素

ArrayList实现了可变大小的数组。它允许所有元素,包括null。ArrayList没有同步。

size,isEmpty,get,set方法运行时间为常数。但是add方法开销为分摊的常数,添加n个元素需要O(n)的时间。其他的方法运行时间为线性。

每个ArrayList实例都有一个容量(Capacity),即用于存储数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法并没有定义。当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。

和LinkedList一样,ArrayList也是非同步的(unsynchronized)。

Vector

Vector非常类似ArrayList,但是Vector是同步的。

由Vector创建的Iterator,虽然和ArrayList创建的Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的方法时将抛出ConcurrentModificationException,因此必须捕获该异常。


11. String、StringBuffer与StringBuilder的区别。 

(1)三者在执行速度方面的比较:StringBuilder > StringBuffer  >  String

(2)String <(StringBuffer,StringBuilder)的原因

String:字符串常量;StringBuffer:字符串变量;StringBuilder:字符串变量

  从上面的名字可以看到,String是“字符串常量”,也就是不可改变的对象。对照这段代码理解这句话:

String s = "abcd";

s = s+1;

System.out.print(s);// result : abcd1

   JVM是这样解析这段代码的:首先创建对象s,赋予一个abcd,然后再创建一个新的对象s用来执行第二行代码,所以我们说String类型是不可改变的对象了,由于这种机制,每当用String操作字符串时,实际上是在不断的创建新的对象,而原来的对象就会变为垃圾被GC回收掉,可想而知这样执行效率会有多底。

  而StringBuffer与StringBuilder就不一样了,他们是字符串变量,是可改变的对象,每当我们用它们对字符串做操作时,实际上是在一个对象上操作的,这样就不会像String一样创建一些而外的对象进行操作了,当然速度就快了。

一个特殊的例子:String str = “This is only a” + “ simple” + “test”;这时没有String对象的拼接所以没有创建新对象,速度比另外两个都快。

StringBuilder:线程非安全的

StringBuffer:线程安全的

当字符串缓冲区被多个线程使用时,JVM不能保证StringBuilder的操作是安全的,虽然他的速度最快,但是可以保证StringBuffer是可以正确操作的。当然大多数情况下就是我们是在单线程下进行的操作,所以大多数情况下是建议用StringBuilder而不用StringBuffer的,就是速度的原因。

对于三者使用的总结:

1.如果要操作少量的数据用String

2.单线程操作字符串缓冲区下操作大量数据StringBuilder

3.多线程操作字符串缓冲区操作大量数据 =StringBuffer


12. Map、Set、List、Queue、Stack的特点与用法。

Set集合里的多个对象之间没有明显的顺序。最多包含一个null元素

只能用Iterator实现单项遍历,Set中没有同步方法。

List集合代表元素有序、可重复的集合,集合中每个元素都有其对应的顺序索引。用Iterator实现单向遍历,也可用ListIterator实现双向遍历

StackVector提供的一个子类,用于模拟"栈"这种数据结构(LIFO后进先出) 。它提供了通常的push和pop操作,以及取堆栈顶点的peek()方法、测试堆栈是否为空的empty方法等

Queue用于模拟"队列"这种数据结构(先进先出 FIFO)。尽量避免add()和remove()方法,而是使用offer()来添加元素,使用poll()来移除元素,它的优点是可以通过返回值来判断是否成功。Queue通常不允许插入null元素。

Map用于保存具有"映射关系"的数据,键Key是唯一不能重复的,一个键对应一个值,值可以重复。其中KeySet()方法可以将所有的keys抽取正一个Set。而Values()方法可以将map中所有的values抽取成一个集合。


13. HashMap和HashTable的区别。 

Hashtable是基于陈旧的Dictionary类的。Hashtable的方法是线程同步的

HashMap是Map接口的一个实现。,而HashMap方法不是线程同步的。 只有HashMap可以让你将空值作为一个表的条目的key或value


14. TreeMap、HashMap、LinkedHashMap的区别。

 Hashmap是一个最常用的Map,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度,遍历时,取得数据的顺序是完全随机的。 

LinkedHashMap保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.也可以在构造时用带参数,按照应用次数排序 

TreeMap取出来的是排序后的键值对。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。


15. try catch finally,try里有return,finally还执行么? 

a.不管有木有出现异常,finally块中代码都会执行

b.trycatch中有return时,finally仍然会执行 

c.finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,管finally中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是在finally执行前确定的 

d.finally中最好不要包含return,否则程序会提前退出,返回值不是trycatch中保存的返回值


16. Excption与Error包结构。OOM你遇到过哪些情况,SOF你遇到过哪些情况。 

http://blog.csdn.net/mccand1234/article/details/51579425

http://www.cnblogs.com/octobershiner/archive/2012/12/20/2827120.html

https://yq.aliyun.com/articles/52841


16. Java面向对象的三个特征与含义。 

封装性:它是将类的一些敏感信息隐藏在类的类部,不让外界直接访问到  

继承性:子类通过继承来接受父类所有的公有的,受保护的成员变量和成员方法 

多态性:程序在运行的过程中,同一种类型在不同的条件下表现不同的结果


17. Override和Overload的含义去区别。 

方法的重写Overriding和重载Overloading是Java多态性的不同表现。

重写 Overriding是父类与子类之间多态性的一种表现。

重载Overloading是一个类中多态性的一种表现。

如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义。

如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。Overloaded的方法可以改变返回值的类型。


18. Interface与abstract类的区别。 

接口可以多重继承,抽象类不可以。

接口定义方法,不给实现;抽象类可以实现部分方法。

接口中基本数据类型的数据成员,都默认为static和final,抽象类则不是。


19. Static class 与non static class的区别。 

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

非静态内部类能够访问外部类的静态和非静态成员。静态内部类只能访问外部类的静态成员。非静态内部类不能脱离外部类实体被创建。


20. java多态的实现原理。 

ⅰ.设计时多态:方法【重载】实现的多态

ⅱ.运行时多态:方法【重写】实现的多态


21. 实现多线程的两种方法:Thread与Runable。 

http://www.oschina.net/question/565065_86563

http://www.cnblogs.com/Li-Cheng/p/4332179.html

实现Runnable接口  实际工作中,几乎所有的多线程应用都用实现Runnable这种方式。Runnable适合多个相同程序代码的线程去处理同一资源的情况。把虚拟CPU(线程)同程序的代码、数据有效的分离,较好的体现了面向对象的设计思想。  避免由于Java的单继承特性带来的局限性。也就是如果新建的类要继承其他类的话,因为JAVA中不支持多继承,就只能实现java.lang.Runnable接口。  有利于程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。我们只需要把实现了Runnable的类的对象实例放入线程池,那么线程池就自动维护线程的启动、运行、销毁。我们不需要自行调用start()方法来开启这个线程。线程放入线程池之后会处于等待状态直到有足够空间时会唤醒这个线程。

继承Thread  不能再继承他类了。编写简单,可以直接操纵线程,无需使用Thread.currentThread()

 在我们刚接触的时候可能会迷糊继承Thread类和实现Runnable接口实现多线程,其实在接触后我们会发现这完全是两个不同的实现多线程,一个是多个线程分别完成自己的任务,一个是多个线程共同完成一个任务


22. 线程同步的方法:sychronized、lock、reentrantLock等。 

Sychronized(同步)是java中最基本同步互斥的手段,可以修饰代码块,方法,类,在修饰代码块的时候需要一个reference对象作为锁的对象,在修饰方法的时候默认是当前对象作为锁的对象,在修饰类时候默认是当前类的Class对象作为锁的对象

. ReentrantLock除了synchronized的功能,多了三个高级功能.  等待可中断,在持有锁的线程长时间不释放锁的时候,等待的线程可以选择放弃等待,

公平锁:按照申请锁的顺序来一次获得锁称为公平锁.synchronized的是非公平锁,ReentrantLock可以通过构造函数实现公平锁  绑定多个Condition.通过多次newCondition可以获得多个Condition对象,可以简单的实现比较复杂的线程同步的功能.通过await(),signal();


23. 锁的等级:方法锁、对象锁、类锁。 

方法锁,synchronized标记的方法 

对象锁,在方法上加了synchronized的锁,或者synchronized(this)的代码段

类锁,在代码中的方法上加了static和synchronized的锁,因为在静态方法中加同步锁会锁住整个类


24. 写出生产者消费者模式。 


25. ThreadLocal的设计理念与作用。 

ThreadLocal并不是一个Thread,而是Thread的局部变量,也许把它命名为ThreadLocalVariable更容易让人理解一些。当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。


26. ThreadPool用法与优势。 

见个人博客:http://blog.csdn.net/laona_sdu/article/details/60468540


27. Concurrent包里的其他东西:ArrayBlockingQueue、CountDownLatch等等。 


28. wait()和sleep()的区别。 

sleep指线程被调用时,占着CPU不工作,形象地说明为“占着CPU睡觉”,此时,系统的CPU部分资源被占用,其他线程无法进入,会增加时间限制。

wait指线程处于进入等待状态,形象地说明为“等待使用CPU”,此时线程不占用任何资源,不增加时间限制


29. foreach与for循环与iterator效率对比。 

针对列表的 foreach的效率最低, 耗时是普通for循环的2倍以上。个人理解它的实现应该和iterator相似


30. Java IO与NIO。 

Java NIO和IO之间第一个最大的区别是,IO是面向流的,NIO是面向缓冲区的。 JavaIO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。此外,它不能前后移动流中的数据。如果需要前后移动从流中读取的数据,需要先将它缓存到一个缓冲区。

Java NIO的缓冲导向方法略有不同。数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。但是,还需要检查是否该缓冲区中包含所有您需要处理的数据。而且,需确保当更多的数据读入缓冲区时,不要覆盖缓冲区里尚未处理的数据。


31. 反射的作用于原理。 Reflection

JAVA反射(放射)机制: Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。 

Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。


32. 泛型常用特点,List<String>能否转为List<Object>。 

         泛型,即“参数化类型”。参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)  在Java的泛型接口中 把List < String> 转换成List < Object > 是可以的。


33. 解析XML的几种方式的原理与特点:DOM、SAX、PULL。 

Dom解析 在内存中创建一个DOM树,该结构通常需要加载整个文档然后才能做工作。由于它是基于信息层次的,因而DOM被认为是基于树或基于对象的,树在内存中是持久的,因此可以修改它以便应用程序能对数据和结构作出更改,能随机访问文件内容,也可以修改原文件内容 

SAX解析 SAX处理的优点非常类似于流媒体的优点。分析能够立即开始,而不是等待所有的数据被处理。SAX解析器采用了基于事件的模型,它在解析XML文档的时候可以触发一系列的事件,当发现给定的tag的时候,它可以激活一个回调方法,告诉该方法制定的标签已经找到。而且,由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中。这对于大型文档来说是个巨大的优点线性解析,不能随机访问,也无法修改原文件

Pull解析器的工作方式为允许你的应用程序代码主动从解析器中获取事件,正因为是主动获取事件,因此可以在满足了需要的条件后不再获取事件,结束解析。如果在一个XML文档中我们只需要前面一部分数据,但是使用SAX方式或DOM方式会对整个文档进行解析,中间不能终止暂停,尽管XML文档中后面的大部分数据我们其实都不需要解析,因此这样实际上就浪费了处理资源。使用PULL方式正合适。


34. Java与C++对比。 

1.java从C++发展过来,两者都是OOP(面向对象)。请大家始终记得 OOP 的三大精神 --------- 封装,继承,多态。Java 是完全封装的,而 C++ 的函数是可以定义在 Class 的外部的。从这里就可以看出 C++的 OOP 思想不够彻底,至少在封装这一点上。

2. java因为是运行在虚拟机上,不需要考虑内存管理和垃圾回收机制。也是就你可以声明一个对象而不用考虑释放他,虚拟机帮你做这事情。而c和c++语言本身没有多少内存管理的概念,写c和c++程序如果用到指针就一定要考虑内存申请和释放。内存泄漏是c和c++最头疼的问题

3. C++ 有个常量修饰符 const, 而 Java 中一个常量一般是用static + final 等价实现。

4. Java 的朋友很不习惯的就是 C++ 的每个类都有个分号结尾

5. C++ 有多重继承,而在 Java 中只是单根继承,但是用Java 的接口可以达到类似的效果。

6. C++当中可以实现多继承,没有接口的概念。这点是java的改进之处,使得java更适合 团队合作开发。

7.Java跨平台。java运行在虚拟机上,号称与平台无关。也就是你开发的java程序无论是unix,linux还是windows都可以正常运行。见博客

8.c语言在一些比较低层,和硬件打交道的地方用得比较多。另外很多开源软件由于unix/linux开发习惯也大多采用c来开发。Java是现在最流行的开发语言,c++比起java稍稍不那么流行一些,但是功能很强大。如能深入掌握,可以写出兼顾效率和美观的优秀代码。


35. Java1.7与1.8新特性。 


36. 设计模式:单例、工厂、适配器、责任链、观察者等等。 

见博主博客http://blog.csdn.net/laona_sdu/article/details/62420760

37. JNI的使用。 

JNI作为java和操作系统间的一个直接接口,可以通过JNI使得java直接调用操作系统的资源。目前JNI只能通过C/C++实现,因为jni只是对操作系统资源调用的一个桥接过程。所以理论上在windows下只要是dll文件均可以被调用

jni一般有以下一些应用场景 

1.高性能 ,在一些情况下因为处理运算量非常大,为了获取高性能,直接使用java是不能胜任的,如:一些图形的处理 

2.调用一些硬件的驱动或者一些软件的驱动,比如调用一些外部系统接口的驱动,如:读卡器的驱动,OCI驱动 

3.需要使用大内存,远远超过jvm所能分配的内存,如:进程内Cache 

4.调用C或者操作系统提供的服务,如:java调用搜索服务,其中搜索是由C/C++实现的,不过这个一般可以设计成更加通用的方式,比如soa的方式  所有这些场景的前提是牺牲了java代码的可移植性,不同的os,甚至版本都需要写不同版本的native实现


        Java里有很多很杂的东西,有时候需要你阅读源码,找到一本适合自己的书也好,如果从网上查建议到官方网站或者权威的网站,有自己的理解和辨别,很多网上的东西不能偏信也不能全信。 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值