经常会被问⾯试官到的java⾯试题整理(⾼频)
Java⾯试题
1、java中==和equals和hashCode的区别
基本数据类型的==⽐较的值相等.
类的==⽐较的内存的地址,即是否是同⼀个对象,在不覆盖equals的情况下,同⽐较内存地址,原实现也为 == ,如String等重写了equals⽅法.
hashCode也是Object类的⼀个⽅法。返回⼀个离散的int型整数。在集合类操作中使⽤,为了提⾼查询速度。(HashMap,HashSet等⽐较是否为同⼀个)
如果两个对象equals,Java运⾏时环境会认为他们的hashcode⼀定相等。
如果两个对象不equals,他们的hashcode有可能相等。
如果两个对象hashcode相等,他们不⼀定equals。
如果两个对象hashcode不相等,他们⼀定不equals。
2、int与integer的区别
int 基本类型
integer 对象 int的包装类
3、String、StringBuffer、StringBuilder区别
String:字符串常量 不适⽤于经常要改变值得情况,每次改变相当于⽣成⼀个新的对象
StringBuffer:字符串变量 (线程安全)
StringBuilder:字符串变量(线程不安全) 确保单线程下可⽤,效率略⾼于StringBuffer
4、什么是内部类?内部类的作⽤
内部类可直接访问外部类的属性
Java中内部类主要分为成员内部类、局部内部类(嵌套在⽅法和作⽤域内)、匿名内部类(没构造⽅法)、静态内部类(static修饰的类,不能使⽤任何外围类的⾮static成员变量和⽅法, 不依赖外围类)
5、进程和线程的区别
进程是cpu资源分配的最⼩单位,线程是cpu调度的最⼩单位。
进程之间不能共享资源,⽽线程共享所在进程的地址空间和其它资源。
⼀个进程内可拥有多个线程,进程可开启进程,也可开启线程。
⼀个线程只能属于⼀个进程,线程可直接使⽤同进程的资源,线程依赖于进程⽽存在。
6、final,finally,finalize的区别
final:修饰类、成员变量和成员⽅法,类不可被继承,成员变量不可变,成员⽅法不可重写
finally:与共同使⽤,确保⽆论是否出现异常都能被调⽤到
finalize:类的⽅法,垃圾回收之前会调⽤此⽅法,⼦类可以重写finalize()⽅法实现对资源的回收
7、Serializable 和Parcelable 的区别
Serializable Java 序列化接⼝ 在硬盘上读写 读写过程中有⼤量临时变量的⽣成,内部执⾏⼤量的i/o操作,效率很低。
Parcelable Android 序列化接⼝ 效率⾼ 使⽤⿇烦 在内存中读写(AS有相关插件 ⼀键⽣成所需⽅法) ,对象不能保存到磁盘中
8、静态属性和静态⽅法是否可以被继承?是否可以被重写?以及原因?
可继承 不可重写 ⽽是被隐藏
如果⼦类⾥⾯定义了静态⽅法和属性,那么这时候⽗类的静态⽅法或属性称之为"隐藏"。如果你想要调⽤⽗类的静态⽅法和属性,直接通过⽗类名.⽅法或变量名完成。
9、成员内部类、静态内部类、局部内部类和匿名内部类的理解,以及项⽬中的应⽤
Java中内部类主要分为成员内部类、局部内部类(嵌套在⽅法和作⽤域内)、匿名内部类(没构造⽅法)、静态内部类(static修饰的类,不能使⽤任何外围类的⾮static成员变量和⽅法, 不依赖外围类)
使⽤内部类最吸引⼈的原因是:每个内部类都能独⽴地继承⼀个(接⼝的)实现,所以⽆论外围类是否已经继承了某个(接⼝的)实现,对于内部类都没有影响。
因为Java不⽀持多继承,⽀持实现多个接⼝。但有时候会存在⼀些使⽤接⼝很难解决的问题,这个时
候我们可以利⽤内部类提供的、可以继承多个具体的或者抽象的类的能⼒来解决这些程序设计问题。可以这样说,接⼝只是解决了部分问题,⽽内部类使得多重继承的解决⽅案变得更加完整。
10、string 转换成 integer的⽅式及原理
String àinteger Intrger.parseInt(string);
IntegeràString();
11、哪些情况下的对象会被垃圾回收机制处理掉?
1.所有实例都没有活动线程访问。
2.没有被其他任何实例访问的循环引⽤实例。
3.Java 中有不同的引⽤类型。判断实例是否符合垃圾收集的条件都依赖于它的引⽤类型。
要判断怎样的对象是没⽤的对象。这⾥有2种⽅法:
1.采⽤标记计数的⽅法:
给内存中的对象给打上标记,对象被引⽤⼀次,计数就加1,引⽤被释放了,计数就减⼀,当这个计数为0的时候,这个对象就可以被回收了。当然,这也就引发了⼀个问题:循环引⽤的对象是⽆法被识别出来并且被回收的。所以就有了第⼆种⽅法:
2.采⽤根搜索算法:
从⼀个根出发,搜索所有的可达对象,这样剩下的那些对象就是需要被回收的
12、静态代理和动态代理的区别,什么场景使⽤?
静态代理类:
由程序员创建或由特定⼯具⾃动⽣成源代码,再对其编译。在程序运⾏前,代理类的.class⽂件就已经存在了。
动态代理类:
在程序运⾏时,运⽤反射机制动态创建⽽成。
13、Java中实现多态的机制是什么?
答:⽅法的重写Overriding和重载Overloading是Java多态性的不同表现
重写Overriding是⽗类与⼦类之间多态性的⼀种表现
重载Overloading是⼀个类中多态性的⼀种表现.
14、说说你对Java反射的理解
JAVA反射机制是在运⾏状态中, 对于任意⼀个类, 都能够知道这个类的所有属性和⽅法; 对于任意⼀个对象, 都能够调⽤它的任意⼀个⽅法和属性。 从对象出发,通过反射(Class类)可以取得取得类的完整信息(类名 Class类型,所在包、具有的所有⽅法 Method[]类型、某个⽅法的完整信息(包括修饰符、返回值类型、异常、参数类型)、所有属性 Field[]、某个属性的完整信息、构造器 Constructors),调⽤类的属性或⽅法⾃⼰的总结: 在运⾏过程中获得类、对象、⽅法的所有信息。
15、说说你对Java注解的理解
元注解
元注解的作⽤就是负责注解其他注解。java5.0的时候,定义了4个标准的meta-annotation类型,它们⽤来提供对其他注解的类型作说明。
1.@Target
2.@Retention
3.@Documented
4.@Inherited
16、Java中String的了解
在源码中string是⽤final 进⾏修饰,它是不可更改,不可继承的常量。
17、String为什么要设计成不可变的?
1、字符串池的需求
字符串池是⽅法区(Method Area)中的⼀块特殊的存储区域。当⼀个字符串已经被创建并且该字符串在 池 中,该字符串的引⽤会⽴即返回给变量,⽽不是重新创建⼀个字符串再将引⽤返回给变量。如果字符串不是不可变的,那么改变⼀个引⽤(如: string2)的字符串将会导致另⼀个引⽤(如: string1)出现脏数据。
2、允许字符串缓存哈希码
在java中常常会⽤到字符串的哈希码,例如: HashMap 。String的不变性保证哈希码始终⼀,因此,他可以不⽤担⼼变化的出现。 这种⽅法意味着不必每次使⽤时都重新计算⼀次哈希码——这样,效率会⾼很多。
3、安全
String⼴泛的⽤于java 类中的参数,如:⽹络连接(Network connetion),打开⽂件(opening files )等等。如果String不是不可变的,⽹络连接、⽂件将会被改变——这将会导致⼀系列的安全威胁。操作的⽅法本以为连接上了⼀台机器,但实际上却不是。由于反射中的参数都是字符串,同样,也会引起⼀系列的安全问题。
18、Object类的equal和hashCode⽅法重写,为什么?
⾸先equals与hashcode间的关系是这样的:
1、如果两个对象相同(即⽤equals⽐较返回true),那么它们的hashCode值⼀定要相同;
2、如果两个对象的hashCode相同,它们并不⼀定相同(即⽤equals⽐较返回false)
由于为了提⾼程序的效率才实现了hashcode⽅法,先进⾏hashcode的⽐较,如果不同,那没就不必在进⾏equals的⽐较了,这样就⼤⼤减少了equals⽐较的次数,这对⽐需要⽐较的数量很⼤的效率提⾼是很明显的
19、List,Set,Map的区别
Set是最简单的⼀种集合。集合中的对象不按特定的⽅式排序,并且没有重复对象。 Set接⼝主要实现了两个实现类:HashSet: HashSet 类按照哈希算法来存取集合中的对象,存取速度⽐较快
TreeSet :TreeSet类实现了SortedSet接⼝,能够对集合中的对象进⾏排序。
List的特征是其元素以线性⽅式存储,集合中可以存放重复对象。
ArrayList() : 代表长度可以改变得数组。可以对元素进⾏随机的访问,向ArrayList()中插⼊与删除元素的速度慢。
LinkedList(): 在实现中采⽤链表数据结构。插⼊和删除速度快,访问速度慢。
Map 是⼀种把键对象和值对象映射的集合,它的每⼀个元素都包含⼀对键对象和值对象。 Map没有继承于Collection接⼝ 从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。
HashMap:Map基于散列表的实现。插⼊和查询“键值对”的开销是固定的。可以通过构造器设置容量capacity和负载因⼦load factor,以调整容器的性能。
LinkedHashMap: 类似于HashMap,但是迭代遍历它时,取得“键值对”的顺序是其插⼊次序,或者是最近最少使⽤(LRU)的次序。只⽐HashMap慢⼀点。⽽在迭代访问时发⽽更快,因为它使⽤链表维护内部次序。
TreeMap : 基于红⿊树数据结构的实现。查看“键”或“键值对”时,它们会被排序(次序由Comparabel或Comparator决定)。TreeMap的特点在 于,你得到的结果是经过排序的。TreeMap是唯⼀的带有subMap()⽅法的Map,它可以返回⼀个⼦树。
WeakHashMao :弱键(weak key)Map,Map中使⽤的对象也被允许释放: 这是为解决特殊问题设计的。如果没有map之外的引⽤指向某个“键”,则此“键”可以被垃圾收集器回收。
20、ArrayMap和HashMap的对⽐
1、存储⽅式不同
HashMap内部有⼀个HashMapEntry<K, V>[]对象,每⼀个键值对都存储在这个对象⾥,当使⽤put⽅法添加键值对时,就会new⼀个HashMapEntry对象,
2、添加数据时扩容时的处理不⼀样,进⾏了new操作,重新创建对象,开销很⼤。ArrayMap⽤的是copy数据,所以效率相对要⾼。
3、ArrayMap提供了数组收缩的功能,在clear或remove后,会重新收缩数组,是否空间
4、ArrayMap采⽤⼆分法查;
21、HashMap和HashTable的区别
1 HashMap不是线程安全的,效率⾼⼀点、⽅法不是Synchronize的要提供外同步,有containsvalue和containsKey⽅法。
hashtable是,线程安全,不允许有null的键和值,效率稍低,⽅法是是Synchronize的。有contains⽅法⽅法。Hashtable 继承于Dictionary 类
22、HashMap与HashSet的区别
hashMap:HashMap实现了Map接⼝,HashMap储存键值对,使⽤put()⽅法将元素放⼊map中,HashMap中使⽤键对象来计算hashcode 值,HashMap⽐较快,因为是使⽤唯⼀的键来获取对象。
HashSet实现了Set接⼝,HashSet仅仅存储对象,使⽤add()⽅法将元素放⼊set中,HashSet使⽤成员对象来计算hashcode值,对于两个对象来说hashcode可能相同,所以equals()⽅法⽤来判断对象的相等性,如果两个对象不同的话,那么返回false。HashSet较HashMap来说⽐较慢。
23、HashSet与HashMap怎么判断集合元素重复?
HashSet不能添加重复的元素,当调⽤add(Object)⽅法时候,
⾸先会调⽤Object的hashCode⽅法判hashCode是否已经存在,如不存在则直接插⼊元素;如果已存在则调⽤Object对象的equals⽅法判断是否返回true,如果为true则说明元素已经存在,如为false则插⼊元素。
23、ArrayList和LinkedList的区别,以及应⽤场景
ArrayList是基于数组实现的,ArrayList线程不安全。
LinkedList是基于双链表实现的:
使⽤场景:
(1)如果应⽤程序对各个索引位置的元素进⾏⼤量的存取或删除操作,ArrayList对象要远优于LinkedList对象;
(2) 如果应⽤程序主要是对列表进⾏循环,并且循环时候进⾏插⼊或者删除操作,LinkedList对象要远优于ArrayList对象;
24、数组和链表的区别
数组:是将元素在内存中连续存储的;它的优点:因为数据是连续存储的,内存地址连续,所以在查数据的时候效率⽐较⾼;它的缺点:在存储之前,我们需要申请⼀块连续的内存空间,并且在编译的时候就必须确定好它的空间的⼤⼩。在运⾏的时候空间的⼤⼩是⽆法随着你的需要进⾏增加和减少⽽改变的,当数据两⽐较⼤的时候,有可能会出现越界的情况,数据⽐较⼩的时候,⼜有可能会浪费掉内存空间。在改变数据个数时,增加、插⼊、删除数据效率⽐较低。
链表:是动态申请内存空间,不需要像数组需要提前申请好内存的⼤⼩,链表只需在⽤的时候申请就可以,根据需要来动态申请或者删除内存空间,对于数据增加和删除以及插⼊⽐数组灵活。还有就是链表中数据在内存中可以在任意的位置,通过应⽤来关联数据(就是通过存在元素的指针来联系)
25、开启线程的四种⽅式?
ava有四种创建线程的⽅式,分别是继承Thread类、实现Runable接⼝和使⽤线程池、Callable
四种⽅式的区别:
1. 相⽐于继承Thread类,实现Runnable接⼝,Callable可以避免Java单继承带来的局限性;Runnable,Callable接⼝的实现类可以被
多个线程共享,实现了代码的复⽤。
2. 继承Thread类和实现Runnable⽅法都是实现run⽅法,没有返回值,⽽另外两种都要实现Callable接⼝的call⽅法,有返回值。
26、线程和进程的区别?
线程是进程的⼦集,⼀个进程可以有很多线程,每条线程并⾏执⾏不同的任务。不同的进程使⽤不同的内存空间,⽽所有的线程共享⼀⽚相同的内存空间。别把它和栈内存搞混,每个线程都拥有单独的栈内存⽤来存储本地数据。
27、run()和start()⽅法区别
这个问题经常被问到,但还是能从此区分出⾯试者对Java线程模型的理解程度。start()⽅法被⽤来启动新创建的线程,⽽且start()内部调⽤了run()⽅法,这和直接调⽤run()⽅法的效果不⼀样。当你调⽤run()⽅法的时候,只会是在原来的线程中调⽤,没有新的线程启
动,start()⽅法才会启动新线程。
28、如何控制某个⽅法允许并发访问线程的个数?
semaphore.acquire() 请求⼀个信号量,这时候的信号量个数-1(⼀旦没有可使⽤的信号量,也即信号量个数变为负数时,再次请求的时候就会阻塞,直到其他线程释放了信号量)
29、在Java中wait和seelp⽅法的不同;
Java程序中wait 和 sleep都会造成某种形式的暂停,它们可以满⾜不同的需要。wait()⽅法⽤于线程间通信,如果等待条件为真且其它线程被唤醒时它会释放锁,⽽sleep()⽅法仅仅释放CPU资源或者让当前线程停⽌执⾏⼀段时间,但不会释放锁。
30、谈谈wait/notify关键字的理解
等待对象的同步锁,需要获得该对象的同步锁才可以调⽤这个⽅法,否则编译可以通过,但运⾏时会收到⼀个异常:IllegalMonitorStateException。
调⽤任意对象的 wait() ⽅法导致该线程阻塞,该线程不可继续执⾏,并且该对象上的锁被释放。
唤醒在等待该对象同步锁的线程(只唤醒⼀个,如果有多个在等待),注意的是在调⽤此⽅法的时候,并不能确切的唤醒某⼀个等待状态的线程,⽽是由JVM确定唤醒哪个线程,⽽且不是按优先级。
java线程池创建的四种调⽤任意对象的notify()⽅法则导致因调⽤该对象的 wait()⽅法⽽阻塞的线程中随机选择的⼀个解除阻塞(但要等到获得锁后才真正可执⾏)。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论