深度分析:那些Java中你必定遇到过的问题,一次性帮你搞定!

一、java中==和equals和hashCode的区别

基本数据类型的比较的值相等.类的比较的内存的地址,便是否是同一个对象,在不覆盖equals的状况下,同比较内存地址,原实现也为 == ,如String等重写了equals方法.hashCode也是Object类的一个方法。返回一个离散的int型整数。在集合类操做中使用,为了提升查询速度。(HashMap,HashSet等比较是否为同一个)若是两个对象equals,Java运行时环境会认为他们的hashcode必定相等。若是两个对象不equals,他们的hashcode有可能相等。若是两个对象hashcode相等,他们不必定equals。若是两个对象hashcode不相等,他们必定不equals。java

二、int与integer的区别

int 基本类型integer 对象 int的封装类程序员

三、String、StringBuffer、StringBuilder区别

String:字符串常量 不适用于常常要改变值得状况,每次改变至关于生成一个新的对象StringBuffer:字符串变量 (线程安全)StringBuilder:字符串变量(线程不安全) 确保单线程下可用,效率略高于StringBuffer面试

四、什么是内部类?

内部类的做用内部类可直接访问外部类的属性Java中内部类主要分为成员内部类、局部内部类(嵌套在方法和做用域内)、匿名内部类(没构造方法)、静态内部类(static修饰的类,不能使用任何外围类的非static成员变量和方法, 不依赖外围类)算法

五、进程和线程的区别

进程是cpu资源分配的最小单位,线程是cpu调度的最小单位。进程之间不能共享资源,而线程共享所在进程的地址空间和其它资源。一个进程内可拥有多个线程,进程可开启进程,也可开启线程。一个线程只能属于一个进程,线程可直接使用同进程的资源,线程依赖于进程而存在。数组

六、final,finally,finalize的区别

final:修饰类、成员变量和成员方法,类不可被继承,成员变量不可变,成员方法不可重写finally:与try…catch…共同使用,确保不管是否出现异常都能被调用到finalize:类的方法,垃圾回收以前会调用此方法,子类能够重写finalize()方法实现对资源的回收缓存

七、Serializable 和Parcelable 的区别

Serializable Java 序列化接口 在硬盘上读写 读写过程当中有大量临时变量的生成,内部执行大量的i/o操做,效率很低。Parcelable Android 序列化接口 效率高 使用麻烦 在内存中读写(AS有相关插件 一键生成所需方法) ,对象不能保存到磁盘中安全

八、静态属性和静态方法是否能够被继承?是否能够被重写?以及缘由?

可继承 不可重写 而是被隐藏若是子类里面定义了静态方法和属性,那么这时候父类的静态方法或属性称之为"隐藏"。若是你想要调用父类的静态方法和属性,直接经过父类名.方法或变量名完成。网络

九、成员内部类、静态内部类、局部内部类和匿名内部类的理解,以及项目中的应用

java中内部类主要分为成员内部类、局部内部类(嵌套在方法和做用域内)、匿名内部类(没构造方法)、静态内部类(static修饰的类,不能使用任何外围类的非static成员变量和方法, 不依赖外围类)使用内部类最吸引人的缘由是:每一个内部类都能独立地继承一个(接口的)实现,因此不管外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。由于Java不支持多继承,支持实现多个接口。但有时候会存在一些使用接口很难解决的问题,这个时候咱们能够利用内部类提供的、能够继承多个具体的或者抽象的类的能力来解决这些程序设计问题。能够这样说,接口只是解决了部分问题,而内部类使得多重继承的解决方案变得更加完整。数据结构

十、string 转换成 integer的方式及原理String 

integer Intrger.parseInt(string);
Integerstring Integer.toString();多线程

十一、哪些状况下的对象会被垃圾回收机制处理掉?

1.全部实例都没有活动线程访问。
2.没有被其余任何实例访问的循环引用实例。
3.Java 中有不一样的引用类型。判断实例是否符合垃圾收集的条件都依赖于它的引用类型。要判断怎样的对象是没用的对象。这里有2种方法:1.采用标记计数的方法:给内存中的对象给打上标记,对象被引用一次,计数就加1,引用被释放了,计数就减一,当这个计数为0的时候,这个对象就能够被回收了。固然,这也就引起了一个问题:循环引用的对象是没法被识别出来而且被回收的。因此就有了第二种方法:2.采用根搜索算法:从一个根出发,搜索全部的可达对象,这样剩下的那些对象就是须要被回收的

十二、静态代理和动态代理的区别,什么场景使用?

静态代理类:由程序员建立或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。动态代理类:在程序运行时,运用反射机制动态建立而成。

1三、Java中实现多态的机制是什么?

答:方法的重写Overriding和重载Overloading是Java多态性的不一样表现重写Overriding是父类与子类之间多态性的一种表现重载Overloading是一个类中多态性的一种表现.

1四、说说你对Java反射的理解

JAVA反射机制是在运行状态中, 对于任意一个类, 都可以知道这个类的全部属性和方法; 对于任意一个对象, 都可以调用它的任意一个方法和属性。 从对象出发,经过反射(Class类)能够取得取得类的完整信息(类名 Class类型,所在包、具备的全部方法 Method[]类型、某个方法的完整信息(包括修饰符、返回值类型、异常、参数类型)、全部属性 Field[]、某个属性的完整信息、构造器 Constructors),调用类的属性或方法本身的总结: 在运行过程当中得到类、对象、方法的全部信息。

1五、说说你对Java注解的理解

元注解元注解的做用就是负责注解其余注解。java5.0的时候,定义了4个标准的meta-annotation类型,它们用来提供对其余注解的类型做说明。
1.@Target
2.@Retention
3.@Documented
4.@Inherited

1六、Java中String的了解

在源码中string是用final 进行修饰,它是不可更改,不可继承的常量。

1七、String为何要设计成不可变的?

一、字符串池的需求字符串池是方法区(Method Area)中的一块特殊的存储区域。当一个字符串已经被建立而且该字符串在 池 中,该字符串的引用会当即返回给变量,而不是从新建立一个字符串再将引用返回给变量。若是字符串不是不可变的,那么改变一个引用(如: string2)的字符串将会致使另外一个引用(如: string1)出现脏数据。
二、容许字符串缓存哈希码在java中经常会用到字符串的哈希码,例如: HashMap 。String的不变性保证哈希码始终一,所以,他能够不用担忧变化的出现。 这种方法意味着没必要每次使用时都从新计算一次哈希码——这样,效率会高不少。
三、安全String普遍的用于java 类中的参数,如:网络链接(Network connetion),打开文件(opening files )等等。若是String不是不可变的,网络链接、文件将会被改变——这将会致使一系列的安全威胁。操做的方法本觉得链接上了一台机器,但实际上却不是。因为反射中的参数都是字符串,一样,也会引发一系列的安全问题。

1八、Object类的equal和hashCode方法重写,为何?

首先equals与hashcode间的关系是这样的:
一、若是两个对象相同(即用equals比较返回true),那么它们的hashCode值必定要相同;
二、若是两个对象的hashCode相同,它们并不必定相同(即用equals比较返回false)因为为了提升程序的效率才实现了hashcode方法,先进行hashcode的比较,若是不一样,那没就没必要在进行equals的比较了,这样就大大减小了equals比较的次数,这对比须要比较的数量很大的效率提升是很明显的

1九、List,Set,Map的区别

1)Set是最简单的一种集合。集合中的对象不按特定的方式排序,而且没有重复对象。 Set接口主要实现了两个实现类:
HashSet: HashSet类按照哈希算法来存取集合中的对象,存取速度比较快TreeSet :TreeSet类实现了SortedSet接口,可以对集合中的对象进行排序。

2)List的特征是其元素以线性方式存储,集合中能够存放重复对象。
ArrayList() : 表明长度能够改变得数组。能够对元素进行随机的访问,向ArrayList()中插入与删除元素的速度慢。
LinkedList(): 在实现中采用链表数据结构。插入和删除速度快,访问速度慢。

3)Map 是一种把键对象和值对象映射的集合,它的每个元素都包含一对键对象和值对象。 Map没有继承于Collection接口 从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。
HashMap:Map基于散列表的实现。插入和查询“键值对”的开销是固定的。能够经过构造器设置容量capacity和负载因子load factor,以调整容器的性能。LinkedHashMap: 相似于HashMap,可是迭代遍历它时,取得“键值对”的顺序是其插入次序,或者是最近最少使用(LRU)的次序。只比HashMap慢一点。而在迭代访问时发而更快,由于它使用链表维护内部次序。
TreeMap : 基于红黑树数据结构的实现。查看“键”或“键值对”时,它们会被排序(次序由Comparabel或Comparator决定)。TreeMap的特色在 于,你获得的结果是通过排序的。TreeMap是惟一的带有subMap()方法的Map,它能够返回一个子树。
WeakHashMap :弱键(weak key)Map,Map中使用的对象也被容许释放: 这是为解决特殊问题设计的。若是没有map以外的引用指向某个“键”,则此“键”能够被垃圾收集器回收。

20、ArrayMap和HashMap的对比

一、存储方式不一样HashMap内部有一个HashMapEntry<K, V>[]对象,每个键值对都存储在这个对象里,当使用put方法添加键值对时,就会new一个HashMapEntry对象,二、添加数据时扩容时的处理不同,进行了new操做,从新建立对象,开销很大。ArrayMap用的是copy数据,因此效率相对要高。三、ArrayMap提供了数组收缩的功能,在clear或remove后,会从新收缩数组,收缩空间四、ArrayMap采用二分法查找;

2一、HashMap和HashTable的区别

1 HashMap不是线程安全的,效率高一点、方法不是Synchronize的要提供外同步,有containsvalue和containsKey方法。hashtable是,线程安全,不容许有null的键和值,效率稍低,方法是是Synchronize的。有contains方法方法。Hashtable 继承于Dictionary 类

2二、HashMap与HashSet的区别

hashMap:HashMap实现了Map接口,HashMap储存键值对,使用put()方法将元素放入map中,HashMap中使用键对象来计算hashcode值,HashMap比较快,由于是使用惟一的键来获取对象。HashSet实现了Set接口,HashSet仅仅存储对象,使用add()方法将元素放入set中,HashSet使用成员对象来计算hashcode值,对于两个对象来讲hashcode可能相同,因此equals()方法用来判断对象的相等性,若是两个对象不一样的话,那么返回false。HashSet较HashMap来讲比较慢。

2三、HashSet与HashMap怎么判断集合元素重复?

HashSet不能添加剧复的元素,当调用add(Object)方法时候,首先会调用Object的hashCode方法判hashCode是否已经存在,如不存在则直接插入元素;若是已存在则调用Object对象的equals方法判断是否返回true,若是为true则说明元素已经存在,如为false则插入元素。

2四、ArrayList和LinkedList的区别,以及应用场景

ArrayList是基于数组实现的,ArrayList线程不安全。LinkedList是基于双链表实现的:使用场景:(1)若是应用程序对各个索引位置的元素进行大量的存取或删除操做,ArrayList对象要远优于LinkedList对象;( 2 ) 若是应用程序主要是对列表进行循环,而且循环时候进行插入或者删除操做,LinkedList对象要远优于ArrayList对象;

2五、数组和链表的区别:

数组是将元素在内存中连续存储的;它的优势:由于数据是连续存储的,内存地址连续,因此在查找数据的时候效率比较高;它的缺点:在存储以前,咱们须要申请一块连续的内存空间,而且在编译的时候就必须肯定好它的空间的大小。在运行的时候空间的大小是没法随着你的须要进行增长和减小而改变的,当数据两比较大的时候,有可能会出现越界的状况,数据比较小的时候,又有可能会浪费掉内存空间。在改变数据个数时,增长、插入、删除数据效率比较低。
链表:是动态申请内存空间,不须要像数组须要提早申请好内存的大小,链表只需在用的时候申请就能够,根据须要来动态申请或者删除内存空间,对于数据增长和删除以及插入比数组灵活。还有就是链表中数据在内存中能够在任意的位置,经过应用来关联数据(就是经过存在元素的指针来联系)

2六、开启线程的三种方式?

java有三种建立线程的方式,分别是继承Thread类、实现Runable接口和使用线程池

2七、线程和进程的区别?

线程是进程的子集,一个进程能够有不少线程,每条线程并行执行不一样的任务。不一样的进程使用不一样的内存空间,而全部的线程共享一片相同的内存空间。别把它和栈内存搞混,每一个线程都拥有单独的栈内存用来存储本地数据。

2八、run()和start()方法区别这个问题常常被问到,

但仍是能今后区分出面试者对Java线程模型的理解程度。start()方法被用来启动新建立的线程,并且start()内部调用了run()方法,这和直接调用run()方法的效果不同。当你调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动,start()方法才会启动新线程。

2九、如何控制某个方法容许并发访问线程的个数?

static Semaphore sSemaphore = new Semaphore(6) 表示该方法最多容许几个线程访问
semaphore.availablePermits():能够获取当前容许进入方法的线程数量
semaphore.acquire() 请求一个信号量,这时候的信号量个数-1(一旦没有可以使用的信号量,也即信号量个数变为负数时,再次请求的时候就会阻塞,直到其余线程释放了信号量)
semaphore.release() 释放一个信号量,此时信号量个数+1

30、在Java中wait和seelp方法的不一样

;Java程序中wait 和 sleep都会形成某种形式的暂停,它们能够知足不一样的须要。wait()方法用于线程间通讯,若是等待条件为真且其它线程被唤醒时它会释放锁,而sleep()方法仅仅释放CPU资源或者让当前线程中止执行一段时间,但不会释放锁。

3一、谈谈wait/notify关键字的理解

等待对象的同步锁,须要得到该对象的同步锁才能够调用这个方法,不然编译能够经过,但运行时会收到一个异常:IllegalMonitorStateException。调用任意对象的 wait() 方法致使该线程阻塞,该线程不可继续执行,而且该对象上的锁被释放。唤醒在等待该对象同步锁的线程(只唤醒一个,若是有多个在等待),注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM肯定唤醒哪一个线程,并且不是按优先级。调用任意对象的notify()方法则致使因调用该对象的 wait()方法而阻塞的线程中随机选择的一个解除阻塞(但要等到得到锁后才真正可执行)。

3二、什么致使线程阻塞?线程如何关闭?

阻塞式方法是指程序会一直等待该方法完成期间不作其余事情,ServerSocket的accept()方法就是一直等待客户端链接。这里的阻塞是指调用结果返回以前,当前线程会被挂起,直到获得结果以后才会返回。此外,还有异步和非阻塞式方法在任务完成前就返回。一种是调用它里面的stop()方法另外一种就是你本身设置一个中止线程的标记 (推荐这种)

3三、如何保证线程安全?

1.synchronized;2.Object方法中的wait,notify;3.ThreadLocal机制 来实现的。

3四、如何实现线程同步?

一、synchronized关键字修改的方法。二、synchronized关键字修饰的语句块三、使用特殊域变量(volatile)实现线程同步

3五、线程间操做

ListList list = Collections.synchronizedList(new ArrayList());

3六、谈谈对Synchronized关键字,类锁,方法锁,重入锁的理解

java的对象锁和类锁:java的对象锁和类锁在锁的概念上基本上和内置锁是一致的,可是,两个锁实际是有很大的区别的,对象锁是用于对象实例方法,或者一个对象实例上的,类锁是用于类的静态方法或者一个类的class对象上的。咱们知道,类的对象实例能够有不少个,可是每一个类只有一个class对象,因此不一样对象实例的对象锁是互不干扰的,可是每一个类只有一个类锁。可是有一点必须注意的是,其实类锁只是一个概念上的东西,并非真实存在的,它只是用来帮助咱们理解锁定实例方法和静态方法的区别的

3七、synchronized 和volatile 关键字的区别

1.volatile本质是在告诉jvm当前变量在寄存器(工做内存)中的值是不肯定的,须要从主存中读取;synchronized则是锁定当前变量,只有当前线程能够访问该变量,其余线程被阻塞住。
2.volatile仅能使用在变量级别;synchronized则可使用在变量、方法、和类级别的
3.volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则能够保证变量的修改可见性和原子性
4.volatile不会形成线程的阻塞;synchronized可能会形成线程的阻塞。
5.volatile标记的变量不会被编译器优化;synchronized标记的变量能够被编译器优化

3八、ReentrantLock 、synchronized和volatile比较

java在过去很长一段时间只能经过synchronized关键字来实现互斥,它有一些缺点。好比你不能扩展锁以外的方法或者块边界,尝试获取锁时不能中途取消等。Java 5 经过Lock接口提供了更复杂的控制来解决这些问题。 ReentrantLock 类实现了 Lock,它拥有与 synchronized 相同的并发性和内存语义且它还具备可扩展性。

3九、死锁的四个必要条件?

死锁产生的缘由系统资源的竞争系统资源的竞争致使系统资源不足,以及资源分配不当,致使死锁。进程运行推动顺序不合适互斥条件:一个资源每次只能被一个进程使用,即在一段时间内某 资源仅为一个进程所占有。此时如有其余进程请求该资源,则请求进程只能等待。
请求与保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源 已被其余进程占有,此时请求进程被阻塞,但对本身已得到的资源保持不放。
不可剥夺条件:进程所得到的资源在未使用完毕以前,不能被其余进程强行夺走,即只能 由得到该资源的进程本身来释放(只能是主动释放)。
循环等待条件: 若干进程间造成首尾相接循环等待资源的关系这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不知足,就不会发生死锁。
死锁的避免与预防:死锁避免的基本思想:系统对进程发出每个系统可以知足的资源申请进行动态检查,并根据检查结果决定是否分配资源,若是分配后系统可能发生死锁,则不予分配,不然予以分配。这是一种保证系统不进入死锁状态的动态策略。理解了死锁的缘由,尤为是产生死锁的四个必要条件,就能够最大可能地避免、预防和解除死锁。因此,在系统设计、进程调度等方面注意如何让这四个必要条件不成立,如何肯定资源的合理分配算法,避免进程永久占据系统资源。此外,也要防止进程在处于等待状态的状况下占用资源。所以,对资源的分配要给予合理的规划。
死锁避免和死锁预防的区别:死锁预防是设法至少破坏产生死锁的四个必要条件之一,严格的防止死锁的出现,而死锁避免则不那么严格的限制产生死锁的必要条件的存在,由于即便死锁的必要条件存在,也不必定发生死锁。死锁避免是在系统运行过程当中注意避免死锁的最终发生。

40、什么是线程池,如何使用?

建立线程要花费昂贵的资源和时间,若是任务来了才建立线程那么响应时间会变长,并且一个进程能建立的线程数有限。为了不这些问题,在程序启动的时候就建立若干线程来响应处理,它们被称为线程池,里面的线程叫工做线程。从JDK1.5开始,Java API提供了Executor框架让你能够建立不一样的线程池。好比单线程池,每次处理一个任务;数目固定的线程池或者是缓存线程池(一个适合不少生存期短的任务的程序的可扩展线程池)。

4一、Java中堆和栈有什么不一样?

为何把这个问题归类在多线程和并发面试题里?由于栈是一块和线程紧密相关的内存区域。每一个线程都有本身的栈内存,用于存储本地变量,方法参数和栈调用,一个线程中存储的变量对其它线程是不可见的。而堆是全部线程共享的一片公用内存区域。对象都在堆里建立,为了提高效率线程会从堆中弄一个缓存到本身的栈,若是多个线程使用该变量就可能引起问题,这时volatile 变量就能够发挥做用了,它要求线程从主存中读取变量的值。

4二、有三个线程T1,T2,T3,怎么确保它们按顺序执行?

在多线程中有多种方法让线程按特定顺序执行,你能够用线程类的join()方法在一个线程中启动另外一个线程,另一个线程完成该线程继续执行。为了确保三个线程的顺序你应该先启动最后一个(T3调用T2,T2调用T1),这样T1就会先完成而T3最后完成。线程间通讯咱们知道线程是CPU调度的最小单位。在Android中主线程是不可以作耗时操做的,子线程是不可以更新UI的。而线程间通讯的方式有不少,好比广播,Eventbus,接口回掉,在Android中主要是使用handler。handler经过调用sendmessage方法,将保存消息的Message发送到Messagequeue中,而looper对象不断的调用loop方法,从messageueue中取出message,交给handler处理,从而完成线程间通讯。

看完有什么不懂的欢迎在下方留言评论