面试常见考题_java基础(全).docx_第1页
面试常见考题_java基础(全).docx_第2页
面试常见考题_java基础(全).docx_第3页
面试常见考题_java基础(全).docx_第4页
面试常见考题_java基础(全).docx_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

J2SE基础 九种基本数据类型的大小,以及他们的封装类。基本类型:boolean byte char short int long float double void 封装类型:Boolean Byte 基本类型大小范围默认值包装类型boolean1True、falseFalseBooleanbyte8-128 +1270Byte char16Unicode0 unicode216 -1u0000Charactershort16-215 215-1Shortint32-231 231-1Integerlong64-263 263-1Longfloat32Floatdouble64DoublevoidVoidl 基本数据类型与其对应的封装类由于本质的不同,具有一些区别:基本数据类型只能按值传递,而封装类按引用传递。基本类型在堆栈中创建;而对于对象类型,对象在堆中创建,对象的引用在堆栈中创建。基本类型由于在堆栈中,效率会比较高,但是可能会存在内存泄漏的问题。 2. Switch能否用string做参数?在java7之前,switch只支持byte、short、char、int 或者其对应的封装类以及Eumn类型,在java7中,String支持被加上了。如在jdk 7 之前的版本使用, 会提示如下错误:Cannot switch on a value of type String for source level below 1.7.Only convertible int values or enum variables are permitted 3. equals与=的区别。值类型是存储在内存的栈中,引用类型的变量在栈中存放其引用类型变量的地址,其值存储在堆中。= 比较的是两个变量的值是否相等,对于引用变量表示的是两个变量在堆中存储的地址是否相同,即栈中的内容是否相同。Equals 比较的是两个变量是否是对同一个对象的引用,即堆中的内容是否相同。public class TestString public static void main(String args) String s1 = Monday; String s2 = Monday; if (s1 = s2) System.out.println(s1 = s2); else System.out.println(s1 != s2); 创建对象之前会在字符串缓冲池中查找是否有此字符串常量,如果存在直接返回其引用,s1、s2两者的引用都是相同的。public class TestString public static void main(String args) String s1 = Monday; String s2 = new String(Monday); s2 = ern(); if (s1 = s2) System.out.println(s1 = s2); else System.out.println(s1 != s2); if (s1.equals(s2) System.out.println(s1 equals s2); else System.out.println(s1 not equals s2); 本程序中的s1指向字符串缓冲区中的常量的引用,s2根据字符串缓冲区中的常量作为构造函数的参数,新建了一个对象并存储在内存中的另一个位置。(如果常量不存在与字符串缓冲区,则先在字符串缓冲区中建立常量,然后newString,这样就创建了两个对象!)附:构造方法 original即为字符串缓冲池中得到的public String(String original) this.value = original.value; this.hash = original.hash; l java字符串缓冲池分析java字符串缓冲池分析:java的虚拟机在内存中开辟出一块单独的区域,用来存储字符串对象,这块内存区域被称为字符串缓冲池。到底创建了几个对象?1,0,2,1,1 String a = abc; String b = abc; String c = new String(xyz); String d = new String(xyz); String e=ab+cd;为什么相等?public static void main(String args) String s1 = Monday; String s2 = new String(Monday); s2 = ern(); if (s1 = s2) System.out.println(s1 = s2); else System.out.println(s1 != s2); if (s1.equals(s2) System.out.println(s1 equals s2); else System.out.println(s1 not equals s2); Intern()方法返回的是在字符串缓冲池中的对象引用!对比: public static void main(String args) String Monday = Monday; String Mon = Mon; String day = day; System.out.println(Monday = Mon + day); System.out.println(Monday = Mon + day); 只有加号左右两边的都是字符串常量时,才能在编译阶段指向缓冲池的常量,day是一个变量,在运行时指向内存中某个地址public static void main(String args) String Monday = Monday; String Mon = Mon; final String day = day; System.out.println(Monday = Mon + day); System.out.println(Monday = Mon + day); Final修饰的day变成一个常量,在编译阶段指向缓冲池。 4. Object有哪些公用方法? clone保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常 equals在Object中与=是一样的,子类一般需要重写该方法 hashCode该方法用于哈希查找,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到 getClassfinal方法,获得运行时类型 wait使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。wait()方法一直等待,直到获得锁或者被中断。wait(long timeout)设定一个超时间隔,如果在规定时间内没有获得锁就返回。调用该方法后当前线程进入睡眠状态,直到以下事件发生:1. 其他线程调用了该对象的notify方法2. 其他线程调用了该对象的notifyAll方法3. 其他线程调用了interrupt中断该线程4. 时间间隔到了此时该线程就可以被调度了,如果是被中断的话就抛出一个InterruptedException异常 notify唤醒在该对象上等待的某个线程 notifyAll唤醒在该对象上等待的所有线程 toString转换成字符串,一般子类都有重写,否则打印句柄l Java中的深复制和浅复制?什么是影子clone?classUnCloneAprivateinti;publicUnCloneA(intii)i=ii;publicvoiddoublevalue()i*=2;publicStringtoString()returnInteger.toString(i);classCloneBimplementsCloneablepublicintaInt;publicUnCloneAunCA=newUnCloneA(111);publicObjectclone()CloneBo=null;tryo=(CloneB)super.clone();catch(CloneNotSupportedExceptione)e.printStackTrace();returno;publicclassObjRefpublicstaticvoidmain(Stringa)CloneBb1=newCloneB();b1.aInt=11;System.out.println(beforeclone,b1.aInt=+b1.aInt);System.out.println(beforeclone,b1.unCA=+b1.unCA);CloneBb2=(CloneB)b1.clone();b2.aInt=22;b2.unCA.doublevalue();System.out.println(=);System.out.println(afterclone,b1.aInt=+b1.aInt);System.out.println(afterclone,b1.unCA=+b1.unCA);System.out.println(=);System.out.println(afterclone,b2.aInt=+b2.aInt);System.out.println(afterclone,b2.unCA=+b2.unCA);原样拷贝原始对象中的内容。对基本数据类型,这样的操作是没有问题的,但对非基本类型变量,我们知道它们保存的仅仅是对象的引用,这也导致clone后的非基本类型变量和原始对象中相应的变量指向的是同一个对象。 输出结果:before clone,b1.aInt = 11before clone,b1.unCA = 111=after clone,b1.aInt = 11after clone,b1.unCA = 222=after clone,b2.aInt = 22after clone,b2.unCA = 222深拷贝的改进方法:改成深度clone很简单,需要两个改变:一是让UnCloneA类也实现和CloneB类一样的clone功能(实现Cloneable接口,重载clone()方法)。二是在CloneB的clone()方法中加入一句o.unCA=(UnCloneA)unCA.clone();深拷贝:class UnCloneA implements Cloneable private int i; public UnCloneA(int ii) i = ii; public void doublevalue() i *= 2; public String toString() return Integer.toString(i); public Object clone() UnCloneA o = null; try o = (UnCloneA) super.clone(); catch (CloneNotSupportedException e) e.printStackTrace(); return o; class CloneB implements Cloneable public int aInt; public UnCloneA unCA = new UnCloneA(111); public Object clone() CloneB o = null; try o = (CloneB) super.clone(); catch (CloneNotSupportedException e) e.printStackTrace(); o.unCA = (UnCloneA) unCA.clone(); return o; l 注意:要知道不是所有的类都能实现深度clone的,StringBuffer没有重载clone()方法,更为严重的是StringBuffer还是一个final类,这也是说我们也不能用继承的办法间接实现StringBuffer的clone。l 我们有两种选择:要么只能实现影子clone,要么就在类的clone()方法中加一句(假设是SringBuffer对象,而且变量名仍为unCA):o.unCA=newStringBuffer(unCA.toString();l String对象是一个例外,它clone后的表现好象也实现了深度clone,虽然这只是一个假象,但却大大方便了我们的编程。class CloneC implements Cloneable public String str; public StringBuffer strBuff; public Object clone() CloneC o = null; try o = (CloneC) super.clone(); catch (CloneNotSupportedException e) e.printStackTrace(); return o; public class StrClone public static void main(String a) CloneC c1 = new CloneC(); c1.str = new String(initializeStr); c1.strBuff = new StringBuffer(initializeStrBuff); System.out.println(before clone,c1.str = + c1.str); System.out.println(before clone,c1.strBuff = + c1.strBuff); CloneC c2 = (CloneC) c1.clone(); c2.str = c2.str.substring(0, 5); c2.strBuff = c2.strBuff.append( change strBuff clone); System.out.println(=); System.out.println(after clone,c1.str = + c1.str); System.out.println(after clone,c1.strBuff = + c1.strBuff); System.out.println(=); System.out.println(after clone,c2.str = + c2.str); System.out.println(after clone,c2.strBuff = + c2.strBuff); 秘密就在于c2.str = c2.str.substring(0,5)这一语句!实质上,在clone的时候c1.str与c2.str仍然是引用,而且都指向了同一个String对象。但在执行c2.str = c2.str.substring(0,5)的时候,它作用相当于生成了一个新的String类型,然后又赋回给c2.str。这是因为String被Sun公司的工程师写成了一个不可更改的类(immutable class),在所有String类中的函数都不能更改自身的值。 5. Java的四种引用,强弱软虚,用到的场景。 四种引用类型包括:强引用、弱引用、软引用、虚引用(幽灵引用),使程序能够更灵活的控制对象的生命周期。1. 强引用(StrongReference):强引用不会被垃圾回收器回收,并且也没有实际的对应类型,平时接触最多的就是强引用。例如Object obj = new Object();这里obj即为强引用。如果一个对象具有强引用,垃圾回收器绝不会回收它。当内存空间不足,java虚拟机宁愿抛出out of MemoryError错误,是程序异常终止,也不会靠回收具有强引用的对象来解决内存不足问题。2. 软引用(SoftReference)如果一个对象只具有软引用,如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可以用来实现内存敏感的高速缓存。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,java虚拟机就会把这个软引用加入到与之关联的引用队列。/* * 只有当内存不够的时候,才回收这类内存,因此在内存足够的时候,它们通常不被回收 * * 无论是否发送GC,执行结果都是: * java.lang.Objectf9f9d8 * null * java.lang.Objectf9f9d8 * null * * 可以看到:只有发送了GC,将对于从内存中释放的时候,JVM才会将reference假如引用队列 */public static void soft() throws Exception Object obj = new Object(); ReferenceQueue refQueue = new ReferenceQueue(); SoftReference softRef = new SoftReference(obj, refQueue);System.out.println(softRef.get(); / java.lang.Objectf9f9d8 System.out.println(refQueue.poll();/ null / 清除强引用,触发GC obj = null; System.gc(); System.out.println(softRef.get(); Thread.sleep(200); System.out.println(refQueue.poll(); 1 为什么需要使用软引用 首先,我们看一个雇员信息查询系统的实例。我们将使用一个Java语言实现的雇员信息查询系统查询存储在磁盘文件或者数据库中的雇员人事档案信息。我们完全有可能需要回头去查看几分钟甚至几秒钟前查看过的雇员档案信息(同样,我们在浏览WEB页面的时候也经常会使用“后退”按钮)。这时我们通常会有两种程序实现方式:一种是把过去查看过的雇员信息保存在内存中,每一个存储了雇员档案信息的Java对象的生命周期贯穿整个应用程序始终;另一种是当用户开始查看其他雇员的档案信息的时候,把存储了当前所查看的雇员档案信息的Java对象结束引用,使得垃圾收集线程可以回收其所占用的内存空间,当用户再次需要浏览该雇员的档案信息的时候,重新构建该雇员的信息。很显然,第一种实现方法将造成大量的内存浪费,而第二种实现的缺陷在于即使垃圾收集线程还没有进行垃圾收集,包含雇员档案信息的对象仍然完好地保存在内存中,应用程序也要重新构建一个对象。我们知道,访问磁盘文件、访问网络资源、查询数据库等操作都是影响应用程序执行性能的重要因素,如果能重新获取那些尚未被回收的Java对象的引用,必将减少不必要的访问,大大提高程序的运行速度。2 如果使用软引用 SoftReference的特点是它的一个实例保存对一个Java对象的软引用,该软引用的存在不妨碍垃圾收集线程对该Java对象的回收。也就是说,一旦SoftReference保存了对一个Java对象的软引用后,在垃圾线程对这个Java对象回收前,SoftReference类所提供的get()方法返回Java对象的强引用。另外,一旦垃圾线程回收该Java对象之后,get()方法将返回null。看下面代码:MyObject aRef = new MyObject();SoftReference aSoftRef = new SoftReference(aRef); 此时,对于这个MyObject对象,有两个引用路径,一个是来自SoftReference对象的软引用,一个来自变量aReference的强引用,所以这个MyObject对象是强可及对象。随即,我们可以结束aReference对这个MyObject实例的强引用:aRef = null;此后,这个MyObject对象成为了软可及对象。如果垃圾收集线程进行内存垃圾收集,并不会因为有一个SoftReference对该对象的引用而始终保留该对象。Java虚拟机的垃圾收集线程对软可及对象和其他一般Java对象进行了区别对待:软可及对象的清理是由垃圾收集线程根据其特定算法按照内存需求决定的。也就是说,垃圾收集线程会在虚拟机抛出OutOfMemoryError之前回收软可及对象,而且虚拟机会尽可能优先回收长时间闲置不用的软可及对象,对那些刚刚构建的或刚刚使用过的“新”软可反对象会被虚拟机尽可能保留。在回收这些对象之前,我们可以通过:MyObject anotherRef=(MyObject)aSoftRef.get(); 重新获得对该实例的强引用。而回收之后,调用get()方法就只能得到null了。3 使用ReferenceQueue清除失去了软引用对象的SoftReference 作为一个Java对象,SoftReference对象除了具有保存软引用的特殊性之外,也具有Java对象的一般性。所以,当软可及对象被回收之后,虽然这个SoftReference对象的get()方法返回null,但这个SoftReference对象已经不再具有存在的价值,需要一个适当的清除机制,避免大量SoftReference对象带来的内存泄漏。在java.lang.ref包里还提供了ReferenceQueue。如果在创建SoftReference对象的时候,使用了一个ReferenceQueue对象作为参数提供给SoftReference的构造方法,如:ReferenceQueuequeue=newReferenceQueue();SoftReferenceref=newSoftReference(aMyObject,queue);那么当这个SoftReference所软引用的aMyOhject被垃圾收集器回收的同时,ref所强引用的SoftReference对象被列入ReferenceQueue。也就是说,ReferenceQueue中保存的对象是Reference对象,而且是已经失去了它所软引用的对象的Reference对象。另外从ReferenceQueue这个名字也可以看出,它是一个队列,当我们调用它的poll()方法的时候,如果这个队列中不是空队列,那么将返回队列前面的那个Reference对象。在任何时候,我们都可以调用ReferenceQueue的poll()方法来检查是否有它所关心的非强可及对象被回收。如果队列为空,将返回一个null,否则该方法返回队列中前面的一个Reference对象。利用这个方法,我们可以检查哪个SoftReference所软引用的对象已经被回收。于是我们可以把这些失去所软引用的对象的SoftReference对象清除掉。常用的方式为:SoftReference ref =null;while(ref = (EmployeeRef)q.poll() !=null) /清除refReferenceQueue清除无用的引用ReferenceQueue q = new ReferenceQueue();/ 获取数据并缓存Object obj = new Object();SoftReference sr = new SoftReference(obj, q);/ 下次使用时Object obj = (Object)sr.get();if (obj = null) / 当软引用被回收后才重新获取 obj = new Object();/ 清理被收回后剩下来的软引用对象SoftReference ref = null;while(ref = q.poll() != null) / 清理工作3. 弱引用:如果一个对象只具有弱引用,类似于可有可无的生活用品。弱引用和软引用的区别:只具有弱引用的对象拥有更短的生命周期。在垃圾回收器线程扫描他所管辖的内存区域过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,java虚拟机就会把这个弱引用加入到与之关联的引用队列中。/* * 弱引用: 当发生GC的时候,Weak引用对象总是会内回收回收。因此Weak引用对象会更容易、更快被GC回收。 * Weak引用对象常常用于Map数据结构中,引用占用内存空间较大的对象 * * 如果不发生垃圾回收: * java.lang.Objectf9f9d8 * null * java.lang.Objectf9f9d8 * null * * 如果发生垃圾回收: * java.lang.Objectf9f9d8 * null * null * java.lang.ref.WeakReference422ede * */public static void weak() throws Exception Object obj = new Object(); ReferenceQueue refQueue = new ReferenceQueue(); WeakReference weakRef = new WeakReference(obj, refQueue); System.out.println(weakRef.get(); /java.lang.Objectf9f9d8 System.out.println(refQueue.poll(); / null / 清除强引用,触发GC obj = null;System.gc(); System.out.println(weakRef.get(); / 这里特别注意:poll是非阻塞的,remove是阻塞的. / JVM将弱引用放入引用队列需要一定的时间,所以这里先睡眠一会儿 / System.out.println(refQueue.poll(); / 这里有可能是null Thread.sleep(200); System.out.println(refQueue.poll(); / System.out.println(refQueue.poll();/这里一定是null,因为已经从队列中移除 / System.out.println(refQueue.remove(); 什么是socket?用于在两个的应用程序之间相互通信,scoket是属于TCPIP的上一层。最早出现在UNIX系统中,是UNIX系统主要的信息传递方式。在WINDOWS系统中,SOCKET称为WINSOCK。两个基本概念:客户方和服务方。当两个应用之间需要采用SOCKET通信时,首先需要在两个应用之间(可能位于同一台机器,也可能位于不同的机器)建立SOCKET连接,发起呼叫连接请求的一方为客户方,接受呼叫连接请求的一方成为服务方。客户方和服务方是相对的,同一个应用可以是客户方,也可以是服务方。在客户方呼叫连接请求之前,它必须知道服务方在哪里。所以需要知道服务方所在机器的IP地址或机器名称,如果客户方和服务方事前有一个约定就好了,这个约定就是PORT(端口号)。也就是说,客户方可以通过服务方所在机器的IP地址或机器名称和端口号唯一的确定方式来呼叫服务方。在客户方呼叫之前,服务方必须处于侦听状态,侦听是否有客户要求建立连接。一旦接到连接请求,服务方可以根据情况建立或拒绝连接。连接方式有两种,同步方式(Blocking)和(noBlocking).客户方发送的消息可以是文本,也可以是二进制信息流。当客户方的消息到达服务方端口时,会自动触发一个事件(event),服务方只要接管该事件,就可以接受来自客户方的消息了。l 使用弱引用构建非敏感数据的缓存a) 全局Map造成的内存泄漏public class SocketManager private Map m = new HashMap(); public void setUser(Socket s, User u) m.put(s, u); public User getUser(Socket s) return m.get(s); public void removeUser(Socket s) m.remove(s); b) 用WeakHashMap堵住泄漏public class SocketManager private Map m = new WeakHashMap(); public void setUser(Socket s, User u) m.put(s, u); public User getUser(Socket s) return m.get(s); 4. 虚引用(PhantomReference):“虚引用”顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。GC一但发现了虚引用对象,将会将PhantomReference对象插入ReferenceQueue队列. * 而此时PhantomReference所指向的对象并没有被GC回收,而是要等到ReferenceQueue被你真正的处理后才会被回收l 对象可及性的判断 在很多时候,一个对象并不是从根集直接引用的,而是一个对象被其他对象引用,甚至同时被几个对象所引用,从而构成一个以根集为顶的树形结构。如图2所示 在这个树形的引用链中,箭头的方向代表了引用的方向,所指向的对象是被引用对象。由图可以看出,从根集到一个对象可以由很多条路径。比如到达对象5的路径就有-,-两条路径。由此带来了一个问题,那就是某个对象的可及性如何判断:单条引用路径可及性判断:在这条路径中,最弱的一个引用决定对象的可及性。多条引用路径可及性判断:几条路径中,最强的一条的引用决定对象的可及性。 比如,我们假设图2中引用和为强引用,为软引用,为弱引用,对于对象5按照这两个判断原则,路径-取最弱的引用,因此该路径对对象5的引用为软引用。同样,-为弱引用。在这两条路径之间取最强的引用,于是对象5是一个软可及对象。四种引用的应用场景: 6. Hashcode的作用。Java中的集合(Collection)有两类,一类是List,再有一类是Set。前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。那么这里就有一个比较严重的问题了:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢?这就是Object.equals方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大降低效率。 于是,Java采用了哈希表的原理。哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上。初学者可以这样理解,hashCode方法实际上返回的就是对象存储的物理地址(实际可能并不是)。 这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。所以这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。a) hashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,hashCode是用来在散列存储结构中确定对象的存储地址的;b) 如果两个对象相同,就是适用于equals(java.lang.Object) 方法,那么这两个对象的hashCode一定要相同;c) 如果对象的equals方法被重写,那么对象的hashCode也尽量重写,并且产生hashCode使用的对象,一定要和equals方法中使用的一致,否则就会违反上面提到的第2点;d) 两个对象的hashCode相同,并不一定表示两个对象就相同,也就是不一定适用于equals(java.lang.Object) 方法,只能够说明这两个对象在散列存储结构中,如Hashtable,他们“存放在同一个篮子里”。 7. ArrayList、LinkedList、Vector的区别。l List接口下的实现类:l ArrayList:List 接口的大小可变数组的实现,实现了所有可选列表操作,并允许包括 null 在内的所有元素。除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。(此类大致上等同于 Vector 类,除了此类是不同步的。)size、isEmpty、get、set、iterator 和 listIterator 操作都以固定时间运行。add 操作以分摊的固定时间 运行,也就是说,添加 n 个元素需要 O(n) 时间。其他所有操作都以线性时间运行(大体上讲)。与用于 LinkedList 实现的常数因子相比,此实现的常数因子较低。每个 ArrayList 实例都有一个容量。该容量是指用来存储列表元素的数组的大小。它总是至少等于列表的大小。在添加大量元素前,应用程序可以使用 ensureCapacity 操作来增加 ArrayList 实例的容量。这可以减少递增式再分配的数量。此实现不是同步的。如果多个线程同时访问一个 ArrayList 实例,而其中至少一个线程从结构上修改了列表,那么它必须 保持外部同步。(这一般通过对自然封装该列表的对象进行同步操作来完成。如果不存在这样的对象,则应该使用 Collections.synchronizedList 方法将该列表“包装”起来。这最好在创建时完成,以防止意外对列表进行不同步的访问: List list = Collections.synchronizedList(new ArrayList(.);此类的 iterator 和 listIterator 方法返回的迭代器是快速失败的:在创建迭代器之后,除非通过迭代器自身的 remove 或 add 方法从结构上对列表进行修改,否则在任何时间以任何方式对列表进行修改,迭代器都会抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就会完全失败,而不是冒着在将来某个不确定时间发生任意不确定行为的风险。l LinkedList:List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾 get、remove 和 insert 元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。此类实现 Deque 接口,为 add、poll 提供先进先出队列操作,以及其他堆栈和双端队列操作。所有操作都是按照双重链接列表的需要执行的。在列表中编索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。使用 Collections.synchronizedList 方法将该列表“包装”起来。这最好在创建时完成,以防止意外对列表进行不同步的访问: Lis

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论