资源描述
。你对Java的集合框架了解吗?能否说说常用的类?说说Hashtable与HashMap的区别:源代码级别的区别呢?平时用过的 List 有哪些?(除了 ArrayList 和 LinkedList),ArrayList 和 LinkedList 的区别?ArrayList的特点,内部容器是如何扩充的?Properties类的特点?线程安全?平时使用过的框架有哪些?(我提到了 Struts2)请说一下Struts2的初始化?和类的创建?(从源代码角度出发)据你了解,除了反射还有什么方式可以动态的创建对象?(我提到了 CGLIB 我以为 他会接着问CGLIB,揪心中,结果他没问)请说一下Struts2是如何把Action交给Spring托管的?它是单例的还是多例?你们页面的 表单对象是多例还是单例?请说一下你们业务层对象是单例还是多例的?请说一下Struts2源代码中有哪些设计模式?请说一下,你觉得你最熟悉的技术特点?(我提到了并发编程)请说一下线程安全出现的原因?请说一下线程池的中断策略(4个)?各有什么特点?请说一下Tomcat配置不同应用的不同端口如何配置?如何配置数据源?如何实现动态 部署?请说一下Java常用的优化?你了解最新的Servlet规范吗?简单说一下?(我提到了推)那请你说一下“推”是如何实现的?线程安全下,StringBuffer与StringBuilder的区别?它们是如何扩充内部数组容量的?(源 代码)请说一下Tomcat中的设计模式?(我提到观察者模式)是否可以说说Java反射的相关优化机制?(我说我不太清楚他说没关系-!)请说一些Mysql的常用优化策略?因为我之前有提到过“推”,他可能对我的知识面比较感兴趣,要我说说平时都看些什么书,还了解一些什么其他的技术范畴。(他首先提到SOA,我说有了解,并且是未来的趋势,还有提到云计算,我说有过一定了 解,但是并未深究)之后是几个职业方面的问题?你觉得你的潜力?你在团队中的位置?你觉得跟团队中最好的还有哪些差距?你要花多 少时间赶上他们?你对阿里巴巴还有什么疑问吗?(我很冏的问了,“阿里巴巴的牛人平时都跟你们有互动 吗?-一本意是指培训,但是话没说清楚”,冏了)PS,下面是时候对问题的整理,里面纯粹仅限于个人浅见,如果有错误,还希望各位能指 点一二。?你对Java的集合框架了解吗?能否说说常用的类?Java集合框架类图:我常用的类:HashMap,Hashtable,HashSet,ArrayList,fector,LinkedList,Collections,Arrays;?说说Hashtable与HashMap的区别(源代码级别)1.最明显的区别在于Hashtable是同步的(每个方法都是synchronized),而HashMap 则不是.2.HashMap 继承至 AbstractMap,Hashtable 继承至 Dictionary,前者为 Map 的骨干,其 内部已经实现了 Map所需 要做的大部分工作,它的子类只需要实现它的少量方法即可具有Map的多项特性。而后者内部都为抽象方法,需要 它的实现类一一作自己的实现,且该类已过时3.两者检测是否含有key时,hash算法不一致,HashMap内部需要将key的hash 码重新计算一边再检测,Hashtable则直接利用key本身的hash码来做验证。HashMap:Java代码l.int hash=(key=null)?0:hash(key.hashCode();2.-3.static int hash(int h)4.h 八=(h 20)A(h 12);5.return h A(h 7)A(h 4);6.)int hash=(key=null)?0:hash(key.hashCodeQ);static int hash(int h)h 八二(h 20)A(h 12);return h A(h 7)A(h 4);)Hashtable:Java代码l.int hash=key.hashCode();int hash=key.hashCode();4.两者初始化容量大小不一致,HashMap内部为16*0.75,Hashtable为11*0.75HashMap:Java代码1.s tatic final int DEFAULTJNITIAL_CAPACITY=16;2.s tatic final float DEFAULT_LOAD_FACTOR=0.75f;3.public HashMapQ 4.this.loadFactor=DEFAULT_LOAD_FACTOR;5.threshold=(int)(DEFAULT_INITIAL_CAPACITY*DEFAULT_LOAD_FACTOR);6.table=new Entry DEF AULT_INITIAL_CAPACITY;7.init();8.9 static final int DEFAULT_INITIAL_CAPACITY=16;static final float DEFAULT_LOAD_FACTOR=0.75f;public HashMapO this.loadFactor:DEFAULT_LOAD_FACTOR;threshold=(int)(DEFAULT_INITIAL_CAPACITY*DEFAULT_LOAD_FACTOR);table=new Entry DEFAULT_INITIAL_CAPACITY;init();)Hashtable:Java代码1.public HashtableQ 2.this(ll,O.75f);3.4.-5.public Hashtable(int initialCapacity,float loadFactor)6.7.this.loadFactor=loadFactor;8.table 二 new EntryinitialCapacity;9.threshold 二(int)(initialCapacity*loadFactor);10.public HashtableQ this(ll,0.75f);)public Hashtable(int initialCapacity,float loadFactor)this.loadFactor 二 loadFactor;table=new EntryinitialCapacity;threshold 二(int)(initialCapacity*loadFactor);)其实后续的区别应该还有很多,这里先列出4点。?平时除了 Array List和LinkedList夕卜,还用过的List有哪些?ArrayList 和 LinkedList 的区别?事实上,我用过的List主要就是这2个,另外用过fector.ArrayList 和 LinkedList 的区别:1.毫无疑问,第一点就是两者的内部数据结构不同,ArrayList内部元素容器是一个Object 的数组,而LinkedList内部实际上一个链表的数据结构,其有一个内部类来表示链表.Java代码l.(ArrayList)2.private transient Object elementData;3.4 5.6.(LinkedList)7.private transient Entry header=new Entry(null,null,null);/链表头8.9.内部链表类.lO.private static class Entry 11.E element;数据元素12.Entry next;/前驱13.Entry previous;/后马区14.Entry(E element,Entry next,Entry previous)15.this.element=element;16.this.next=next;17.this.previous 二 previous;18.19.)(ArrayList)private transient Object elementData;(LinkedList)private transient Entry header=new Entry(null,null,null);/链表头内部链表类.private static class Entry E element;数据元素Entry next;/前驱Entry previous;后马区Entry(E element,Entry next,Entry previous)this.element 二 element;this.next=next;this.previous=previous;)2.两者的父类不同,也就决定了两者的存储形式不同。ArrayList继承于AbstractList,而 LinkedList继承于AbstractSequentialList.两者都实现了 List的骨干结构,只是前者的访问形 式趋向于“随机访问”数据存储(如数组),后者趋向于“连续访问”数据存储(如链接 列表)Java代码1.public class ArrayList extends AbstractList2.3.public class LinkedList extends AbstractSequentialList public class ArrayList extends AbstractList public class LinkedList extends AbstractSequentialList3.再有就是两者的效率问题,ArrayList基于数组实现,所以毫无疑问可以直接用下标来索 弓I,其索弓I数据快,插入元素设计到数组元素移动,或者数组扩充,所以插入元素要慢。LinkedList基于链表结构,插入元素只需要改变插入元素的前后项的指向即可,故插入数据 要快,而索引元素需要向前向后遍历,所以索引元素要慢。?ArrayList的特点,内部容器是如何扩充的?上一点谈到了 ArrayList的特点,这里略,重点来看其内部容器的扩充:Java代码1.public void ensureCapacity(int minCapacity)2.modCount+;3.int oldCapacity=elementData.length;4.if(minCapacity oldCapacity)5.Object oldData=elementData;6.这里扩充的大小为原大小的大概60%7.int newCapacity=(oldCapacity*3)/2+1;8.if(newCapacity oldCapacity)Object oldData二 elementData;这里扩充的大小为原大小的大概60%int newCapacity=(oldCapacity*3)/2+1;if(newCapacity minCapacity)newCapacity=minCapacity;创建一个指定大小的新数组来覆盖原数组elementData 二 Arrays.copyOf(elementData,newCapacity);?Properties类的特点?线程安全吗?Properties继承于Hashtable,所以它是线程安全的.其特点是:它表示的是一个持久的属性集,它可以保存在流中或者从流中加载,属性列表的每一个 键和它所对应的值都是一个“字符串”其中,常用的方法是load()方法,从流中加载属性:Java代码1.public synchronized void load(InputStream inStream)throws lOException 2./将输入流转换成LineReader3.Ioad0(new LineReader(inStream);4.)5.6.private void loadO(LineReader Ir)throws lOException 7.char convtBuf=new char1024;8.int limit;9.int keyLen;10.int valueStart;11.char c;12.boolean hasSep;13.boolean precedingBackslash;14./一行一行处理15.while(limit 二 lr.readLine()=0)16.c=0;17.keyLen=0;18.valueStart=limit;19.hasSep=false;20.precedingB ackslash=false;21.下面用2个循环来处理key,value22.while(keyLen limit)23.c=lr.lineBufkeyLen;24./need check if escaped.25.if(c=II c=&!precedingBackslash)26.valueStart 二 keyLen+1;27.hasSep=true;28.break;29.else if(c=II c=t II c=f)30.&JprecedingBackslash)31.valueStart=keyLen+1;32.break;33.34.if(c=N)35.precedingB ackslash=!precedingB ackslash;36.else 37.precedingB ackslash=false;38.39.keyLen+;40.41.42.while(valueStart limit)43.c=lr.lineBufvalueStart;44.if(c!=&c!=t&c!=)45.if(!hasSep&(c=士 II c=:)46.hasSep=true;47.else 48.break;49.50.51.valueStart+;52.53.54.String key=loadConvert(lr.lineBuf,0,keyLen,convtBuf);55.String value=loadConvert(lr.lineBuf,valueStart,limit56.-valueStart,convtBuf);57./存入内部容器中,这里用的是Hashtable内部的方法.58.put(key,value);59.)60.public synchronized void load(InputStream inStream)throws lOException/将输入流转换成LineReaderload0(new LineReader(inStream);private void loadO(LineReader Ir)throws lOException char convtBuf=new char1024;int limit;int keyLen;int valueStart;char c;boolean hasSep;boolean precedingB ackslash;/一行一行处理while(limit=lr.readLine()=0)c=0;keyLen=0;valueStart=limit;hasSep 二 false;precedingB ackslash=false;/下面用2个循环来处理key,valuewhile(keyLen limit)c=Ir.lineBuf keyLen;/need check if escaped.if(c=二七 II c=二&!precedingBackslash)valueStart=keyLen+1;hasSep=true;break;else if(c=II c=H II c=f)&!precedingB ackslash)valueStart=keyLen+1;break;)if(c 二二 N)precedingB ackslash=!precedingB ackslash;else precedingBackslash 二 false;)keyLen+;)while(valueStart limit)c.Ir.lineBufvalueStart;if(c!二&c!=X,&c!=!f)if(!hasSep&(c=士 II c=:)hasSep=true;else break;)valueStart+;)String key 二 loadConvert(lr.lineBuf,0,keyLen,convtBuf);String value=loadConvert(lr.lineBuf,valueStart,limit-valueStart,convtBuf);/存入内部容器中,这里用的是Hashtable内部的方法.put(key,value);)LineReader 类,是 Properties 内部的类:Java代码1.class LineReader 2.public LineReader(InputStream inStream)3.this.inStream=inStream;4.inByteBuf 二 new byte8192;5.)6.7.public LineReader(Reader reader)8.this.reader=reader;9.inCharBuf 二 new char8192;10.11.12.byte inByteBuf;13.char inCharBuf;14.char lineBuf=new char1024;15.int inLimit=0;16.int inOff=0;17.InputStream inStream;18.Reader reader;19.20,/*21.*读取一行22.*23.*return24.*throws lOException25.*/26.int readLineQ throws lOException 27.int len=0;28.char c=0;29.boolean skipWhiteSpace=true;/空白30.boolean isCommentLine=false;/注释31.boolean isNewLine=true;/是否新行.32.boolean appendedLineBegin=false;/力口 至行开始33.boolean precedingBackslash=false;/反斜杠34.boolean skipLF=false;35.while(true)36.if(inOff=inLimit)37./从输入流中读取一定数量的字节并将其存储在缓冲区数组inCharBuf/inByteBuf中,这里区分字节流和字符流38.inLimit=(inStream 二二 null)?reader.read(inCharBuf)39.:inStream.read(inByteBuf);40.inOff=0;41./读取到的为空.42.if(inLimit=0)43.if(len=0 II isCommentLine)44.return-1;45.46.return len;47.)48.49.50.51.52.53.54.55.)if(inStream!=null)/由于是字节流,需要使用ISO8859-1来解码c 二(char)(Oxff&inByteBufinOff+);else c=inCharBuf inOff+;)56.if(skipLF)57.skipLF=false;58.if(c=n)59.continue;60.61.62.if(skipWhiteSpace)63.if(c 二=llc=tllc=F)64.continue;65.66.if(!appendedLineBegin&(c=V II c=二n)67.continue;68.69.skipWhiteSpace=false;70.appendedLineBegin=false;71.)72.if(isNewLine)7 3.isNewLine=false;74.if(c=#|c=T)75./注释行,忽略.76.isCommentLine=true;77.continue;78.79.80./读取真正的属性内容81.if(c!=n&c!=W)82./这里类似于ArrayList内部的容量扩充,使用字符数组来保存读取的内容.83.84.85.86.87.88.89.90.lineBuflen+=c;if(len=lineBuf.length)int newLength=lineBuf.length*2;if(newLength=inLimit)inLimit=(inStream 二二 null)?reader.read(inCharBuf):inStream.read(inByteBuf);inOff=0;if(inLimit=0)return len;)if(precedingB ackslash)len-=1;skipWhiteSpace=true;appendedLineBegin=true;precedingBackslash=false;if(c=T)skipLF=true;else return len;)class LineReader public LineReader(InputStream inStream)this.inStream=inStream;inByteBuf=new byte8192;public LineReader(Reader reader)this.reader=reader;inCharBuf 二 new char8192;)byte inByteBuf;char inCharBuf;char lineBuf=new char1024;int inLimit=0;int inOff=0;InputStream inStream;Reader reader;*读取一行*return*throws lOException*/int readLine()throws lOException int len=0;char c=0;boolean skipWhiteSpace=true;/空白boolean isCommentLine=false;/注释boolean isNewLine=true;/是否新行.boolean appendedLineBegin=false;/力口 至行开始boolean precedingBackslash=false;/反斜杠boolean skipLF=false;while(true)if(inOff=inLimit)/从输入流中读取一定数量的字节并将其存储在缓冲区数组 inCharBuf/inByteBuf中,这里区分字节流和字符流inLimit=(inStream=null)?reader.read(inCharBuf):inStream.read(inByteBuf);inOff=0;/读取到的为空.if(inLimit=0)if(len 二二 0 II isCommentLine)return-1;return len;if(inStream!=null)/由于是字节流,需要使用ISO8859-1来解码c=(char)(Oxff&inByteBufinOff+);else c 二 inCharBufinOff+;if(skipLF)skipLF=false;if(c=n)continue;if(skipWhiteSpace)if(c=L|c=tllc=f)continue;)if(JappendedLineBegin&(c=V II c=XT)continue;)skipWhiteSpace=false;appendedLineBegin=false;)if(isNewLine)isNewLine=false;if(c=#|c=T)/注释行,忽略.isCommentLine=true;continue;/读取真正的属性内容if(c!=n&c!=V)/这里类似于ArrayList内部的容量扩充,使用字符数组来保存读取的内容.lineBuflen+=c;if(len 二二 lineBuf.length)int newLength=lineBuf.length*2;if(newLength=inLimit)inLimit 二(inStream=null)?reader.read(inCharBuf):inStream.read(inByteBuf);inOff=0;if(inLimit=0)return len;)if(precedingB ackslash)len-=1;skipWhiteSpace=true;appendedLineBegin=true;precedingB ackslash=false;if(c=)skipLF 二 true;)else return len;这里特别的是,实际上,Pr叩erties从流中加载属性集合,是通过将流中的字符或者字节分成一行行来处理的。?请说一下Struts!的初始化?和类的创建?(从源代码角度出发)(我当时回答这个问题的思路我想应该对了,我说是通过反射加配置文件来做的)由于这个问题研究起来可以另外写一篇专门的模块,这里只列出相对简单的流程,后续会希 望有时间整理出具体的细节:首先,Struts2是基于Xwork框架的,如果你有仔细看过Xwork的文档,你会发现,它的初 始化过程基于以下几个类:Configuring XWork2 centers around the following classes1.ConfigurationManager2.ConfigurationProvider3.Configuration而在ConfigurationProvider的实现类XmlConfigurationProvider的内部,你可以看到下面的 代码Java代码1.public XmlConfigurationProvider()2.this(xwork.xml,true);3.public XmlConfigurationProvider()this(,xwork.xmr,true);同样的,Struts2的初始化也是这样的一个类,只不过它继承于Xwork原有的类,并针对 Struts2做了一些特别的定制。Java代码1.public class StrutsXmlConfigurationProvider2.extends XmlConfigurationProvider 3.public StrutsXmlConfigurationProvider(boolean errorlfMissing)4.(5.this(nstruts.xmr,errorlfMissing,null);6.)7 public class StrutsXmlConfigurationProviderextends XmlConfigurationProvider public StrutsXmlConfigurationProvider(boolean errorlfMissing)(thisCstruts.xmr1,errorlfMissing,null);)如果你要查看这个类在哪里调用了,你会追踪到Dispatch的类,记得吗?我们使用Struts2,第一步就是在Web.xml中配置一个过滤器FilterDispatcher,没错,在web容器初始化过滤器的时候,同时也会初始化Dispatch.FilterDispatch.initQ:Java代码1.public void init(FilterConfig filterConfig)2.throws ServletException 3.try(4.this.filterConfig=filterConfig;5.initLogging();6.dispatcher=createDispatcher(filterConfig);7.dispatcher.initQ;初始化 Dispatcher.8.dispatcher.getContainer().inj ect(this);9.staticResourceLoader.setHostConfig(new FilterHostConfig(filterConfig);10.finally 11.ActionContext.setContext(null);12.)13.public void init(FilterConfig filterConfig)throws ServletException try(this.filterConfig=filterConfig;initLogging();dispatcher=createDispatcher(filterConfig);dispatcher.initQ;初始化 Dispatcher.dispatcher.getContainer().inject(this);staticResourceLoader.setHostConfig(new FilterHostConfig(filterConfig);finally ActionContext.setContext(null);)Dispatch.init():Java代码1.SPAN style=FONT-WEIGHT:normal,这里是加载配置文件,真正初始化Struts!的Action实例还没开始,2.public void init()3.if(configurationManager=null)4.configurationManager=5.new ConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);6.)7.init_DefaultProperties();/18.init_TraditionalXmlConfigurations();/29.init_LegacyStrutsProperties();/310.init_CustomConfigurationProviders();/511.init_FilterInitParameters();/612.init_AliasStandardObjects();/713.Container container 二 init_PreloadConfiguration();14.container.inj ect(this);15.init_CheckConfigurationReloading(container);16.init_CheckW ebLogicW orkaround(container);17.if(!dispatcherListeners.isEmpty()18.for(DispatcherListener 1:dispatcherListeners)19.l.dispatcherlnitialized(this);20.21.)22.这里是加载配置文件,真正初始化Struts2的Action实例还没开始,public void init()if(configurationManager 二二 null)configurationManager=new ConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);)init_DefaultProperties();/1init_TraditionalXmlConfigurations();/2init_LegacyStrutsProperties();/3init_CustomConfigurationProviders();/5init_FilterInitParameters();/6init_AliasStandardObjects();/7Container container=init_PreloadConfiguration();container.inject(this);init_CheckConfigurationReloading(container);init_CheckW ebLogicW orkaround(container);if(!dispatcherListeners.isEmpty()for(DispatcherListener 1:dispatcherListeners)l.dispatcherlnitialized(this);)到初始化Action类的时候,你需要去FilterDispatcher的doFilter方法去看代码,你会发现:Java代码1.public void doFilter(ServletRequest req,ServletResponse res,2.FilterChain chain)throws lOException,ServletException 3 4.dispatcher.serviceAction(request,response,servletContext,mapping);public void doFilter(ServletRequest req,ServletResponse res,FilterChain chain)throws lOException,ServletException dispatcher.serviceAction(request,response,servletContext,mapping);再追踪至U Dispatcher 类,看到这个方法:Java代码1.SPAN style=FONT-WEIGHT:normalApublic void serviceAction(HttpServletRequest request,2.HttpServletResponse response,ServletContext context,3.ActionMapping mapping)throws ServletException 4.5.ActionProxy proxy=config.getContainer().getInstance(6.ActionProxyFactory.class).7.createActionProxy(namespace,8.name,9.method,10.extraContext,11.true,false);12.13.public void serviceAction(HttpServletRequest request,HttpServletResponse response,ServletContext context,ActionMapping mapping)throws ServletException ActionProxy proxy=config.getContainer().getInstance(ActionProxy F actory class).createActionProxy(namespace,name,method,extraContext,true,false);这行代码已经明确的告诉你了,它的作用就是创建ActionProxy,而我们想要知道 的是,他是如何创建的;而上面代码中的config,实际上是Xwork中的.Configuration,如果你打开Xwork源代码,你会发现,他其实是一个接口,真正做处理的,这里是com.opensymphony.xwork2.config.impl.DefaultConfiguration 类,通过它的 getContainer()方 法,获取到一个Container类型的实例,而Container也是一个接口,其实现类是:com.opensymphony.xwork2.inject.
展开阅读全文