配色: 字号:
JavaSE
2018-01-01 | 阅:  转:  |  分享 
  
1.一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制?答:可以有多个类,但只能有一个public的类,并且public
的类名必须与文件名相一致。2.Java有没有goto?答:goto?是Java中的保留字,在目前版本的Java中没有使用。(根据J
amesGosling(Java之父)编写的《TheJavaProgrammingLanguage》一书的附录中给出了一个
Java关键字列表,其中有goto和const,但是这两个是目前无法使用的关键字,因此有些地方将其称之为保留字,其实保留字这个词应
该有更广泛的意义,因为熟悉C语言的程序员都知道,在系统类库中使用过的有特殊意义的单词或单词的组合都被视为保留字)3.说说&和&&的
区别?答:①&和&&都可以用作逻辑与的运算符,表示逻辑与(and),当运算符两边的表达式的结果都为true时,整个运算结果才为tr
ue,否则,只要有一方为false,则结果为false。②&&还具有短路的功能,即如果第一个表达式为false,则不再计算第二个表
达式,例如,对于if(str!=null&&!str.equals(“?”))表达式,当str为null时,后面的表达式不
会执行,所以不会出现NullPointerException如果将&&改为&,则会抛出NullPointerException异常
。If(x==33&++y>0)y会增长,If(x==33&&++y>0)不会增长③&还可以用作位运算符,当&操作符两边
的表达式不是boolean类型时,&表示按位与操作,我们通常使用0x0f来与一个整数进行&运算,来获取该整数的最低4个bit位,例
如,0x31&0x0f的结果为0x01。4.switch语句能否作用在byte上,能否作用在long上,能否作用在String
上?答:在switch(expr1)中,expr1只能是一个整数表达式或者枚举常量(更大字体),整数表达式可以是int基本类型或I
nteger包装类型,由于,byte,short,char都可以隐含转换为int,所以,这些类型以及这些类型的包装类型也是可以的。
显然,long和String类型都不符合switch的语法规定,并且不能被隐式转换成int类型,所以,它们不能作用于swtich语
句中。但是在JDK7的新特性中,switch语句可以用字符串。5.shorts1=1;s1=s1+1;有什么错?s
horts1=1;s1+=1;有什么错?答:①对于shorts1=1;s1=s1+1;由于s1+1运算
时会自动提升表达式的类型,所以结果是int型,再赋值给short类型s1时,编译器将报告需要强制转换类型的错误。②对于short
s1=1;s1+=1;由于+=?是java语言规定的运算符,java编译器会对它进行特殊处理,因此可以正确编译。6.ch
ar型变量中能不能存贮一个中文汉字?为什么?答:char型变量是用来存储Unicode编码的字符的,unicode编码字符集中包含
了汉字,所以,char型变量中当然可以存储汉字啦。不过,如果某个特殊的汉字没有被包含在unicode编码字符集中,那么,这个cha
r型变量中就不能存储这个特殊汉字。补充说明:unicode编码占用两个字节,所以,char类型的变量也是占用两个字节。7.用最有效
率的方法算出2乘以8等於几?答:2<<3,因为将一个数左移n位,就相当于乘以了2的n次方,那么,一个数乘以8只要将其左移3位即
可,而位运算cpu直接支持的,效率最高,所以,2乘以8等於几的最效率的方法是2<<3。8.使用final关键字修饰一个变量时,
是引用不能变,还是引用的对象不能变??答:使用final关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是
可以改变的。9."=="和equals方法究竟有什么区别?答:①==比较的是地址值,equals比较的是值?②一般我们会重写equ
als让它按照我们的意愿去比较相关属性,而不是单纯的比较地址值。10.静态变量和实例变量的区别?答:①在语法定义上的区别:静态变量
前要加static关键字,而实例变量前则不加。②在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量
才会被分配空间,才能使用这个实例变量。静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建
任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以
直接使用类名来引用。③例如,对于下面的程序,无论创建多少个实例对象,永远都只分配了一个staticVar变量,并且每创建一个实例对
象,这个staticVar就会加1;但是,每创建一个实例对象,就会分配一个instanceVar,即可能分配多个instanceV
ar,并且每个instanceVar的值都只自加了1次。?publicclassVariantTest{publicstat
icintstaticVar=0;publicintinstanceVar=0;publicVariantTes
t(){staticVar++;instanceVar++;System.out.println(“staticVar=”+st
aticVar+?”,instanceVar=”+instanceVar);}}11.是否可以从一个static方法内部发出对
非static方法的调用?答:不可以。因为非static方法是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调
用,而static方法调用时不需要创建对象,可以直接调用。也就是说,当一个static方法被调用时,可能还没有创建任何实例对象,如
果从一个static方法中发出对非static方法的调用,那个非static方法是关联到哪个对象上的呢?这个逻辑无法成立,所以,一
个static方法内部发出对非static方法的调用。12.Integer与int的区别答:①int是java提供的8种原始数据类
型之一。Java为每个原始类型提供了封装类,Integer是java为int提供的封装类。int的默认值为0,而Integer的默
认值为null,即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况,例如,要想表达出没有参加考试和考试
成绩为0的区别,则只能使用Integer。在JSP开发中,Integer的默认为null,所以用el表达式在文本框中显示时,值为空
白字符串,而int默认的默认值为0,所以用el表达式在文本框中显示时,结果为0,所以,int不适合作为web层的表单数据的类型。②
在Hibernate中,如果将OID定义为Integer类型,那么Hibernate就可以根据其值是否为null而判断一个对象是否
是临时的,如果将OID定义为了int类型,还需要在hbm映射文件中设置其unsaved-value属性为0。③另外,Integer
提供了多个与整数相关的操作方法,例如,将一个字符串转换成整数,Integer中还定义了表示整数的最大值和最小值的常量。13.Mat
h.round(11.5)等於多少?Math.round(-11.5)等於多少?答:Math类中提供了三个与取整有关的方法:cei
l.floor.round,这些方法的作用与它们的英文名称的含义相对应,例如,ceil的英文意义是天花板,该方法就表示向上取整,所
以,Math.ceil(11.3)的结果为12,Math.ceil(-11.3)的结果是-11;floor的英文意义是地板,该方法
就表示向下取整,所以,Math.floor(11.6)的结果为11,Math.floor(-11.6)的结果是-12;最难掌握的是
round方法,它表示“四舍五入”,算法为Math.floor(x+0.5),即将原来的数字加上0.5后再向下取整,所以,Math
.round(11.5)的结果为12,Math.round(-11.5)的结果为-11。14.请说出作用域public,priva
te,protected,以及不写时的区别?答:?类的成员不写访问修饰时默认为default。默认对于同一个包中的其他类相当于公开
(public),对于不是同一个包中的其他类相当于私有(private)。受保护(protected)对子类相当于公开,对不是同一
包中的没有父子关系的类相当于私有。Java中,外部类的修饰符只能是public或默认,类的成员(包括内部类)的修饰符可以是以上四种
。15.Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?答:①方法重载(Overlo
ad):在本类中出现了方法名相同但参数列表不同的方法,与返回值无关,可以改变返回值类型,只看参数列表;②方法重写(Override
):子类中出现了和父类中方法声明一模一样的方法,与返回值有关,返回值和类型都是一样的。16.面向对象的特征有哪些方面??答:①抽象
:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的
细节是什么。②继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类、基类);得到继承信息的类被称为子类
(派生类)。继承让变化中的软件系统有了一定的延续性,同时继承也是封装程序中可变因素的重要手段(如果不能理解请阅读阎宏博士的《Jav
a与模式》或《设计模式精解》中关于桥梁模式的部分)。③封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定
义的接口。面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象。我们在类中编写的方法就是对实现细节的一种封装;我们编写一个
类就是对数据和数据操作的封装。可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程接口(可以想想普通洗衣机和全自动洗衣机
的差别,明显全自动洗衣机封装更好因此操作起来更简单;我们现在使用的智能手机也是封装得足够好的,因为几个按键就搞定了所有的事情)。④
多态性:多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态
性分为编译时的多态性和运行时的多态性。如果将对象的方法视为对象向外界提供的服务,那么运行时的多态性可以解释为:当A系统访问B系统提
供的服务时,B系统有多种提供服务的方式,但一切对A系统来说都是透明的(就像电动剃须刀是A系统,它的供电系统是B系统,B系统可以使用
电池供电或者用交流电,甚至还有可能是太阳能,A系统只会通过B类对象调用供电的方法,但并不知道供电系统的底层实现是什么,究竟通过何种
方式获得了动力)。方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时
的多态性(也称为后绑定)。运行时的多态是面向对象最精髓的东西,要实现多态需要做两件事:(a)?方法重写(子类继承父类并重写父类中已
有的或抽象的方法);(b)对象造型(用父类型引用引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行
为)。17.String是最基本的数据类型吗??答:不是。Java中的基本数据类型只有8个:byte、short、int、long
、float、double、char、boolean;除了基本类型(primitivetype)和枚举类型(enumeratio
ntype),剩下的都是引用类型(referencetype)。18.floatf=3.4;是否正确??答:不正确。3.4是
双精度数,将双精度型(double)赋值给浮点型(float)属于下转型(down-casting,也称为窄化)会造成精度损失,因
此需要强制类型转换floatf=(float)3.4;?或者写成floatf=3.4F;。19.解释内存中的栈(stack
)、堆(heap)和静态区(staticarea)的用法?答:①通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数
调用的现场保存都使用内存中的栈空间;②而通过new关键字和构造器创建的对象放在堆空间;③程序中的字面量(literal)如直接书写
的100、"hello"和常量都是放在静态区中。④栈空间操作起来最快但是栈很小,通常大量的对象都是放在堆空间,理论上整个内存没有被
其他进程使用的空间甚至硬盘上的虚拟内存都可以被当成堆空间来使用。⑤例如:Stringstr=newString("hell
o");上面的语句中变量str放在栈上,用new创建出来的字符串对象放在堆上,而"hello"这个字面量放在静态区。20.数组有没
有length()方法?String有没有length()方法??答:数组没有length()方法,有length的属性。Stri
ng有length()方法。JavaScript中,获得字符串的长度是通过length属性得到的,这一点容易和Java混淆。21.
在Java中,如何跳出当前的多重嵌套循环??答:在最外层循环前加一个标记如A,然后用breakA;可以跳出多重循环。(Java中
支持带标签的break和continue语句,作用有点类似于C和C++中的goto语句,但是就像要避免使用goto一样,应该避免使
用带标签的break和continue,因为它不会让你的程序变得更优雅,很多时候甚至有相反的作用,所以这种语法其实不知道更好)22
.构造器(constructor)是否可被重写(override)??答:构造器不能被继承,因此不能被重写,但可以被重载。23.两
个对象值相同(x.equals(y)==true),但却可有不同的hashcode,这句话对不对??答:不对,如果两个对象x
和y满足x.equals(y)==true,它们的哈希码(hashcode)应当相同。Java对于eqauls方法和hash
Code方法是这样规定的:(1)如果两个对象相同(equals方法返回true),那么它们的hashCode值一定要相同;(2)如
果两个对象的hashCode相同,它们并不一定相同。当然,你未必要按照要求去做,但是如果你违背了上述原则就会发现在使用容器时,相同
的对象可以出现在Set集合中,同时增加新元素的效率会大大下降(对于使用哈希存储的系统,如果哈希码频繁的冲突将会造成存取性能急剧下降
)。补充:关于equals和hashCode方法,很多Java程序都知道,但很多人也就是仅仅知道而已,在JoshuaBloch的
大作《EffectiveJava》(很多软件公司,《EffectiveJava》、《Java编程思想》以及《重构:改善既有代码
质量》是Java程序员必看书籍,如果你还没看过,那就赶紧去亚马逊买一本吧)中是这样介绍equals方法的:首先equals方法必须
满足自反性(x.equals(x)必须返回true)、对称性(x.equals(y)返回true时,y.equals(x)也必须返
回true)、传递性(x.equals(y)和y.equals(z)都返回true时,x.equals(z)也必须返回true)和
一致性(当x和y引用的对象信息没有被修改时,多次调用x.equals(y)应该得到同样的返回值),而且对于任何非null值的引用x
,x.equals(null)必须返回false。实现高质量的equals方法的诀窍包括:1.使用==操作符检查"参数是否为这个对
象的引用";2.使用instanceof操作符检查"参数是否为正确的类型";3.对于类中的关键属性,检查参数传入对象的属性是否与之
相匹配;4.编写完equals方法后,问自己它是否满足对称性、传递性、一致性;5.重写equals时总是要重写hashCode;6
.不要将equals方法参数中的Object对象替换为其他的类型,在重写时不要忘掉@Override注解。24.是否可以继承Str
ing类??答:String?类是final类,不可以被继承。补充:继承String本身就是一个错误的行为,对String类型最好
的重用方式是关联关系(Has-A)和依赖关系(Use-A)而不是继承关系(Is-A)。25.当一个对象被当作参数传递到一个方法后,
此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递??答:是值传递。Java语言的方法调用只支持参
数的值传递。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的属性可以在被调用过程中被改变,但对对象引
用的改变是不会影响到调用者的。C++和C#中可以通过传引用或传输出参数来改变传入的参数的值。在C#中可以编写如下所示的代码,但是在
Java中却做不到。namespaceCS01{?classProgram{?publicstaticvoidswa
p(refintx,refinty){?inttemp=x;?x=y;?y=temp;?}?public
staticvoidMain(string[]args){?inta=5,b=10;?swap(ref
a,refb);?//a=10,b=5;?Console.WriteLine("a={0},b={1}
",a,b);?}?}}说明:Java中没有传引用实在是非常的不方便,这一点在Java8中仍然没有得到改进,正是如此在Jav
a编写的代码中才会出现大量的Wrapper类(将需要通过方法调用修改的引用置于一个Wrapper类中,再将Wrapper对象传入方
法),这样的做法只会让代码变得臃肿,尤其是让从C和C++转型为Java程序员的开发者无法容忍。26.String和StringBu
ilder、StringBuffer的区别??答:(1)String和StringBuffer、StringBuider:?①St
ring:是不可变字符序列;?②StringBuffer、StringBuider:是可变字符序列;③String覆盖了equal
s方法和hashCode方法,而StringBuffer没有覆盖equals方法和hashCode方法,所以,将StringBuf
fer对象存储进Java集合类中时会出现问题。?(2)StringBuffer和StringBuider:①StringBuff
er:是JDK1.0版本的,线程安全,效率低;?②StringBuilder:是JDK1.5版本的,线程不安全,效率高;③如果一个
字符串变量是在方法里面定义,这种情况只可能有一个线程访问它,不存在不安全的因素了,则用StringBuilder。如果要在类里面定
义成员变量,并且这个类的实例对象会在多线程环境下使用,那么最好用StringBuffer。27.描述一下JVM加载class文件的
原理机制??答:JVM中类的装载是由类加载器(ClassLoader)和它的子类来实现的,Java中的类加载器是一个重要的Java
运行时系统组件,它负责在运行时查找和装入类文件中的类。由于Java的跨平台性,经过编译的Java源程序并不是一个可执行程序,而是一
个或多个类文件。当Java程序需要使用某个类时,JVM会确保这个类已经被加载、连接(验证、准备和解析)和初始化。类的加载是指把类的
.class文件中的数据读入到内存中,通常是创建一个字节数组读入.class文件,然后产生与所加载类对应的Class对象。加载完成
后,Class对象还不完整,所以此时的类还不可用。当类被加载后就进入连接阶段,这一阶段包括验证、准备(为静态变量分配内存并设置默认
的初始值)和解析(将符号引用替换为直接引用)三个步骤。最后JVM对类进行初始化,包括:1)如果类存在直接的父类并且这个类还没有被初
始化,那么就先初始化父类;2)如果类中存在初始化语句,就依次执行这些初始化语句。类的加载是由类加载器完成的,类加载器包括:根加载器
(BootStrap)、扩展加载器(Extension)、系统加载器(System)和用户自定义类加载器(java.lang.Cl
assLoader的子类)。从Java2(JDK1.2)开始,类加载过程采取了父亲委托机制(PDM)。PDM更好的保证了Jav
a平台的安全性,在该机制中,JVM自带的Bootstrap是根加载器,其他的加载器都有且仅有一个父类加载器。类的加载首先请求父类加
载器加载,父类加载器无能为力时才由其子类加载器自行加载。JVM不会向Java程序提供对Bootstrap的引用。下面是关于几个类加
载器的说明:Bootstrap:一般用本地代码实现,负责加载JVM基础核心类库(rt.jar);Extension:从java.e
xt.dirs系统属性所指定的目录中加载类库,它的父加载器是Bootstrap;System:又叫应用类加载器,其父类是Exten
sion。它是应用最广泛的类加载器。它从环境变量classpath或者系统属性java.class.path所指定的目录中记载类,
是用户自定义加载器的默认父加载器。28.抽象类(abstractclass)和接口(interface)有什么异同??答:(1)
成员特点:①构造方法:接口没有;抽象类有;②成员变量:接口中只有常量;抽象类中常量、变量都可;③成员方法:接口只有抽象方法;抽象类
中抽象方法、非抽象方法都可;(2)关系特点:①类与类:只有单继承,但可以多层继承;②类与接口:实现关系,可以单实现,也可以多实现;
③接口与接口:继承关系,可以单继承,也可以多继承;(3)设计理念:①接口是简单工厂设计模式,likea的关系?,接口中定义的是该
继承体系的扩展功能;③抽象类是模板设计模式,isa的关系,抽象类中定义的是继承体系的共性功能;29.Java中会存在内存泄漏吗,
请简单描述??答:理论上Java因为有垃圾回收机制(GC)不会存在内存泄露问题(这也是Java被广泛使用于服务器端编程的一个重要原
因);然而在实际开发中,可能会存在无用但可达的对象,这些对象不能被GC回收,因此也会导致内存泄露的发生。例如Hibernate的S
ession(一级缓存)中的对象属于持久态,垃圾回收器是不会回收这些对象的,然而这些对象中可能存在无用的垃圾对象,如果不及时关闭(
close)或清空(flush)一级缓存就可能导致内存泄露。30.抽象的(abstract)方法是否可同时是静态的(static)
,是否可同时是本地方法(native),是否可同时被synchronized修饰??答:都不能。抽象方法需要子类重写,而静态的方法
是无法被重写的,因此二者是矛盾的。本地方法是由本地代码(如C代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。synchron
ized和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。31.是否可以从一个静态(static)方法内部发出对非
静态(non-static)方法的调用??答:不可以,静态方法只能访问静态成员,因为非静态方法的调用要先创建对象,在调用静态方法时
可能对象并没有被初始化。32.GC是什么?为什么要有GC??答:GC是垃圾收集的意思,Java提供的GC功能可以自动监测对象是否超
过作用域从而达到自动回收内存的目的,从而有效的防止内存泄露。要请求垃圾收集,可以调用下面的方法之一:System.gc()或Run
time.getRuntime().gc(),但JVM可以屏蔽掉显示的垃圾回收调用。33.Stringst=null和?St
ringst=“”的区别?Strings=newString("xyz")创建了几个对象??答:(1)String
st=null表示声明了一个String对象的引用str,但是没有为其分配存内存空间。(2)Stringst=“”表示创
建了一个长度等于0的空字符串,并在内存中分配了内存空间。(3)Stringst=newString(“xyz”);表示创建
了两个对象:?①堆内存中一个newString;?②常量池中一个字符串。34.接口是否可继承(extends)接口?抽象类是否可
实现(implements)接口?抽象类是否可继承具体类(concreteclass)??答:接口可以继承接口,而且支持多重继承
。抽象类可以实现(implements)接口,抽象类可继承具体类也可以继承抽象类。35.AnonymousInnerClass
(匿名内部类)是否可以继承其它类?是否可以实现接口??答:可以继承其他类或实现其他接口,在Swing编程和Android开发中常用
此方式来实现事件监听和回调。36.内部类可以引用它的包含类(外部类)的成员吗?有没有什么限制??答:一个内部类对象可以访问创建它的
外部类对象的成员,包括私有成员。37.final、finally和finalized的区别??答:(1)final:被final修
饰的类,不被能继承;被final修饰的方法,不能被重写;被fianl修饰的量,为常量,只能被赋值一次;?(2)finally:异常
处理,和try、catch结合使用,可加可不加,用于执行一些必须执行的代码,如释放资源等;?(3)finalized:Object
类中的方法,其中定义了对象要被垃圾回收器回收之前,要做的一些清理工作。38.数据类型之间的转换??答:(1)如何将字符串转换为基本
数据类型?调用基本数据类型对应的包装类中的方法parseXXX(String)或valueOf(String)即可返回相应基本类型
;?(2)如何将基本数据类型转换为字符串?一种方法是将基本数据类型与空字符串("")连接(+)即可获得其所对应的字符串;另一种方法
是调用String类中的valueOf()方法返回相应字符串39.如何实现字符串的反转及替换??答:方法很多,可以自己写实现也可以
使用String或StringBuffer/StringBuilder中的方法。有一道很常见的面试题是用递归实现字符串反转,代码如
下所示:?publicstaticStringreverse(StringoriginStr){?if(originSt
r==null||originStr.length()<=1)?returnoriginStr;?returnre
verse(originStr.substring(1))+originStr.charAt(0);?}40.怎样将GB231
2编码的字符串转换为ISO-8859-1编码的字符串??答:代码如下所示:Strings1="你好";Strings2=
newString(s1.getBytes("GB2312"),"ISO-8859-1");41..比较一下Java和Jav
aSciprt?答:其实Java和JavaScript最重要的区别是一个是静态语言,一个是动态语言:(1)基于对象和面向对象:Ja
va是一种真正的面向对象的语言,即使是开发简单的程序,必须设计对象;JavaScript是种脚本语言,它可以用来制作与网络无关的,
与用户交互作用的复杂软件。它是一种基于对象(Object-Based)和事件驱动(Event-Driven)的编程语言,因而它本身
提供了非常丰富的内部对象供设计人员使用。(2)解释和编译:Java的源代码在执行之前,必须经过编译。JavaScript是一种解释
性编程语言,其源代码不需经过编译,由浏览器解释执行。(目前的浏览器几乎都使用了JIT(即时编译)技术来提升JavaScript的运
行效率)(3)强类型变量和类型弱变量:Java采用强类型变量检查,即所有变量在编译之前必须作声明;JavaScript中变量是弱类
型的,甚至在使用变量前可以不作声明,JavaScript的解释器在运行时检查推断其数据类型。(4)代码格式不一样。42.Error
和Exception有什么区别?答:①Error表示系统级的错误和程序不必处理的异常,是恢复不是不可能但很困难的情况下的一种严重问
题;比如内存溢出,不可能指望程序能处理这样的情况;②Exception表示需要捕捉或者需要程序进行处理的异常,是一种设计或实现问题
;也就是说,它表示如果程序运行正常,从不会发生的情况。43.try{}里有一个return语句,那么紧跟在这个try后的final
ly{}里的代码会不会被执行,什么时候被执行,在return前还是后?答:会执行,在方法返回调用者前执行。44.throw和thr
ows的区别、及处理方式?答:(1)throw:用于抛出异常对象,后面跟的是异常对象;throw用在方法体内;?(2)throws
:用于抛出异常类,后面跟的是异常类名,可以跟多个,用逗号隔开。throws用在方法上?(3)异常处理方式:抛出throws、捕捉t
ry-catch-finally。?(4)什么时候定义try,什么时候定义throws??①功能内部如果出现异常,如果可以
处理,就用try;?②如果内部处理不了,就必须声明出来,让调用者处理。45.编译时异常和运行时异常的区别?答:(1)编译时异常在函
数内被抛出,函数必须声明,否则编译失败。?声明的原因:是需要调用者对该异常进行处理。必须进行处理,否则无法编译通过;(throws
)?(2)运行时异常如果在函数内被抛出,在函数上不需要声明。?不声明的原因:不需要调用者处理,运行时异常发生,已经无法再让程序继续
运行,所以,不让调用处理的,直接让程序停止,由调用者对代码进行修正。(throw)46.List、Set、Map是否继承自Coll
ection接口?答:List、Set是,Map不是。Map是键值对映射容器,与List和Set有明显的区别,而Set存储的零散的
元素且不允许有重复元素(数学中的集合也是如此),List是线性结构的容器,适用于按数值索引访问元素的情形。47.阐述ArrayLi
st、Vector、LinkedList的存储性能和特性?答:(1)ArrayList:①ArrayList底层是通过数组实现的,
与LinkedList相比,查询快,增删慢;②ArrayList的起始容量是10.当数组需要增长时,新的容量按如下公式获得:新容量
=(旧容量3)/2+1,也就是说每一次容量大概会增长50%。(2)Vector:①Vector:底层也是通过数组实现的,与Arr
ayList相比,它是同步的,线程安全的;一般情况下:ArrayList适用于单线程,Vector适用于多线程。②Vector的容
量增长与“增长系数有关”,若指定了“增长系数”,且“增长系数有效(即,大于0)”;那么,每次容量不足时,“新的容量”=“原始容量+
增长系数”。若增长系数无效(即,小于/等于0),则“新的容量”=“原始容量x2”。(3)LinkedList:①LinkedLi
st底层是通过链表实现的,与ArrayList相比,查询慢,增删快;②LinkedList在添加新元素时,先是在双向链表中找到要插
入节点的位置index;找到之后,再插入一个新节点。同时,双向链表查找index位置的节点时,有一个加速动作:若index向链表长度的1/2,则从前向后查找;否则,从后向前查找。48.简述集合架构体系??49.Collection和Collection
s的区别??答:Collection是一个接口,它是Set、List等容器的父接口;Collections是个一个工具类,提供了一
系列的静态方法来辅助容器操作,这些方法包括对容器的搜索、排序、线程安全化等等。50.List、Map、Set三个接口存取元素时,各
有什么特点??答:(1)List以特定索引来存取元素,可以有重复元素。Set不能存放重复元素(用对象的equals()方法来区分元
素是否重复)。?(2)Map保存键值对(key-valuepair)映射,映射关系可以是一对一或多对一。?(3)Set和Map容
器都有基于哈希存储和排序树的两种实现版本,基于哈希存储的版本理论存取时间复杂度为O(1),而基于排序树版本的实现在插入或删除元素时
会按照元素或元素的键(key)构成排序树从而达到排序和去重的效果。51.TreeMap和TreeSet在排序时如何比较元素?Col
lections工具类中的sort()方法如何比较元素??答:(1)TreeSet要求存放的对象所属的类必须实现Comparabl
e接口,该接口提供了比较元素的compareTo()方法,当插入元素时会回调该方法比较元素的大小。?(2)TreeMap要求存放的
键值对映射的键必须实现Comparable接口从而根据键对元素进行排序。?(3)Collections工具类的sort方法有两种重
载的形式,第一种要求传入的待排序容器中存放的对象比较实现Comparable接口以实现元素的比较;第二种不强制性的要求容器中的元素
必须可比较,但是要求传入第二个参数,参数是Comparator接口的子类型(需要重写compare方法实现元素的比较),相当于一个
临时定义的排序规则,其实就是通过接口注入比较元素大小的算法,也是对回调模式的应用(Java中对函数式编程的支持)。52、Threa
d类的wait()和sleep()的区别?答:(1)所在类不同:wait()是Object类中的方法;sleep()是Tr
ead类中的方法;?(2)slepp()没有释放同步锁,而wait()释放了同步锁;?(3)slepp()必须制定时间,而w
ait()不用;?(4)slepp()可以在任何地方使用,而wait()、notify()、notifyAll()只能在
同步方法或同步代码块中使用;?(5)slepp()必须捕获异常,而wait()、notify()、notifyAll()不
用;53.线程的sleep()方法和yield()方法有什么区别??答:①?sleep()方法给其他线程运行机会时不考虑线程的优先
级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会;②线程执行sleep(
)方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态;③?sleep()方法声明抛出Int
erruptedException,而yield()方法没有声明任何异常;④?sleep()方法比yield()方法(跟操作系统C
PU调度相关)具有更好的可移植性。54.当一个线程进入一个对象的synchronized方法A之后,其它线程是否可进入此对象的sy
nchronized方法B??答:不能。其它线程只能访问该对象的非同步方法,同步方法则不能进入。因为非静态方法上的synchron
ized修饰符要求执行方法时要获得对象的锁,如果已经进入A方法说明对象锁已经被取走,那么试图进入B方法的线程就只能在等锁池(注意不
是等待池哦)中等待对象的锁。55.简述线程的五种状态?答:(1)新建(new):当一个线程处于新建状态时,它仅仅是一个空的线程对象
,系统不为它分配资源。Treadt=newTread(newRunner());?(2)就绪(Runable):此时线程
处在随时可以运行的状态,在随后的任意时刻,都可能进入运行状态。t.star();?(3)运行(Running):处于这个状态的线
程占用CPU,执行程序代码。?(4)阻塞(Blocked):阻塞状态是指线程因为某些原因放弃CPU,暂时停止运行,直到线程重新进入
就绪状态。wait、sleep、同步锁被占用;?(5)死亡(Dead):当线程退出run()方法时,就进入死亡状态,该线程生命周期
结束。可能正常执行完run()方法退出,也可能是遇到异常。56.创建多线程的两种方式期区别?答:(1)第一种方式:继承Thread
类,由子类重写run方法。步骤如下:?①定义类继承Thread类;?②目的是重写run方法,将要执行的代码都存储到run方法中;?
③通过创建Thread类的子类对象,创建线程对象;?④调用线程的start方法,开启线程,并执行run方法。?(2)第二种方式:实
现Runnable接口。步骤如下:?①定义类实现Runnable接口。?②覆盖接口中的run方法(用于封装线程要运行的代码)。?③
通过Thread类创建线程对象;?④将实现了Runnable接口的子类对象作为实际参数传递给Thread类中的构造函数。?⑤调用T
hread对象的start方法。开启线程,并运行Runnable接口子类中的run方法。(3)区别:?①继承Thread?:?好处
:可以直接使用Tread类中的方法,代码简单;?弊端:如果该类已有父类,就不能用这种方法了;?②实现Runnable接口:?好处:
可以避免单继承的局限性,即使自己的线程类有父类也没关系;?弊端:不能直接使用Tread类中的方法,要先获取线程对象,代码复杂。57
.synchronized关键字的用法?答:synchronized关键字可以将对象或者方法标记为同步,以实现对对象和方法的互斥访
问,可以用synchronized(对象){?…?}定义同步代码块,或者在声明方法时将synchronized作为方法的修饰符。
在第60题的例子中已经展示了synchronized关键字的用法。58.举例说明同步和异步。答:如果系统中存在临界资源(资源数量少
于竞争资源的线程数量的资源),例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就
必须进行同步存取(数据库操作中的排他锁就是最好的例子)。当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序
等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。事实上,所谓的同步就是指阻塞式操作,而异步就是非阻塞式
操作。59.启动一个线程是调用run()还是start()方法?答:启动一个线程是调用start()方法,使线程所代表的虚拟处理机
处于可运行状态,这意味着它可以由JVM调度并执行,这并不意味着线程就会立即运行。run()方法是线程启动后要进行回调(callba
ck)的方法。60.什么是线程池(threadpool)?答:在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获
取内存资源或者其它更多资源。在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收。所以提高服务程序效
率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些很耗资源的对象创建和销毁,这就是”池化资源”技术产生的原因。线程池顾名思
义就是事先创建若干个可执行的线程放入一个池(容器)中,需要的时候从池中获取线程不用自行创建,使用完毕不需要销毁线程而是放回池中,从
而减少创建和销毁线程对象的开销。61.同步代码块与同步函数的区别?答:(1)同步代码块:位置比较灵活,锁对象可以任意对象,但必须是
同一对象。格式:synchronized(对象){//任意对象都可以。这个对象就是锁。?需要被同步的代码;?}?(2)同步函
数:声明方法时加synchronized关键字,同步函数使用的锁是this,静态同步函数的锁是该类的字节码文件对象。?(3)在一个
类中只有一个同步,可以使用同步函数。如果有多同步,必须使用同步代码块,来确定不同的锁。所以同步代码块相对灵活一些。62.Java中
如何实现序列化,有什么意义??答:序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行
读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决对象流读写操作时可能引发的问题(如果不进行序列化可能会存在数据乱序的问
题)。要实现序列化,需要让一个类实现Serializable接口,该接口是一个标识性接口,标注该类对象是可被序列化的,然后使用一个
输出流来构造一个对象输出流并通过writeObject(Object)方法就可以将实现对象写出(即保存其状态);如果需要反序列化则
可以用一个输入流建立对象输入流,然后通过readObject方法从流中读取对象。例如,在web开发中,如果对象被保存在了Sessi
on中,tomcat在重启时要把Session对象序列化到硬盘,这个对象就必须实现Serializable接口。如果对象要经过分布
式系统进行网络传输或通过rmi等远程调用,这就需要在网络上传输对象,被传输的对象就必须实现Serializable接口。63.Ja
va中有几种类型的流??答?(1)字节流?InputStream/OutputStream?①FileInputStream/Fi
leOutputStream:文件字节流,用于文件的读写操作?②BufferedInputStream/BufferedFileO
utputStream:加缓冲区的字节流,用于提高效率?(2)字符流?Reader/Writer?①FileReader/File
Writer:文件字符流,用于文本文件的读写操作?②BufferedReader/BufferedWriter:加缓冲区的字符流,
用于提高效率?(3)转换流?InputStreamReader/OutputStreamWriter64.Statement和Pr
eparedStatement有什么区别?哪个性能更好??答:与Statement相比:①PreparedStatement接口代
表预编译的语句,它主要的优势在于可以减少SQL的编译错误并增加SQL的安全性(减少SQL注射攻击的可能性);②PreparedSt
atement中的SQL语句是可以带参数的,避免了用字符串连接拼接SQL语句的麻烦和不安全;③当批量处理SQL或频繁执行相同的查询
时,PreparedStatement有明显的性能上的优势,由于数据库可以将编译优化后的SQL语句缓存起来,下次执行相同结构的语句
时就会很快(不用再次编译和生成执行计划)。补充:为了提供对存储过程的调用,JDBCAPI中还提供了CallableStateme
nt接口。存储过程(StoredProcedure)是数据库中一组为了完成特定功能的SQL语句的集合,经编译后存储在数据库中,用
户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。虽然调用存储过程会在网络开销、安全性、性能上获得很多好处,但
是存在如果底层数据库发生迁移时就会有很多麻烦,因为每种数据库的存储过程在书写上存在不少的差别。65.使用JDBC操作数据库时,如何
提升读取数据的性能?如何提升更新数据的性能??答:要提升读取数据的性能,可以指定通过结果集(ResultSet)对象的setFet
chSize()方法指定每次抓取的记录数(典型的空间换时间策略);要提升更新数据的性能可以使用PreparedStatement语
句构建批处理,将若干SQL语句置于一个批处理中执行。66.在进行数据库编程时,连接池有什么作用??答:由于创建连接和释放连接都有很
大的开销(尤其是数据库服务器不在本地时,每次建立连接都需要进行TCP的三次握手,释放连接需要进行TCP四次握手,造成的开销是不可忽
视的),为了提升系统访问数据库的性能,可以事先创建若干连接置于连接池中,需要时直接从连接池获取,使用结束时归还连接池而不必关闭连接
,从而避免频繁创建和释放连接所造成的开销,这是典型的用空间换取时间的策略(浪费了空间存储连接,但节省了创建和释放连接的时间)。池化
技术在Java开发中是很常见的,在使用线程时创建线程池的道理与此相同。基于Java的开源数据库连接池主要有:C3P0、Proxoo
l、DBCP、BoneCP、Druid等。补充:在计算机系统中时间和空间是不可调和的矛盾,理解这一点对设计满足性能要求的算法是至关
重要的。大型网站性能优化的一个关键就是使用缓存,而缓存跟上面讲的连接池道理非常类似,也是使用空间换时间的策略。可以将热点数据置于缓
存中,当用户查询这些数据时可以直接从缓存中得到,这无论如何也快过去数据库中查询。当然,缓存的置换策略等也会对系统性能产生重要影响,
对于这个问题的讨论已经超出了这里要阐述的范围。67.什么是DAO模式??答:DAO(DataAccessObject)顾名思义
是一个为数据库或其他持久化机制提供了抽象接口的对象,在不暴露底层持久化方案实现细节的前提下提供了各种数据访问操作。在实际的开发中,
应该将所有对数据源的访问操作进行抽象化后封装在一个公共API中。用程序设计语言来说,就是建立一个接口,接口中定义了此应用程序中将会
用到的所有事务方法。在这个应用程序中,当需要和数据源进行交互的时候则使用这个接口,并且编写一个单独的类来实现这个接口,在逻辑上该类
对应一个特定的数据存储。DAO模式实际上包含了两个模式,一是DataAccessor(数据访问器),二是DataObject(
数据对象),前者要解决如何访问数据的问题,而后者要解决的是如何用对象封装数据。68.JDBC中如何进行事务处理??答:Connec
tion提供了事务处理的方法,通过调用setAutoCommit(false)可以设置手动提交事务;当事务完成后用commit()
显式提交事务;如果在事务处理过程中发生异常则通过rollback()进行事务回滚。除此之外,从JDBC3.0中还引入了Savep
oint(保存点)的概念,允许通过代码设置保存点并让事务回滚到指定的保存点。69.获得一个类的类对象有哪些方式??答:(1)Cla
ss.forName(classname):用于做类加载//根据给定的类名来获得,用于类加载Stringclassname=
"cn.itcast.reflect.Person";?????//来自配置文件Classclazz1=Class.for
Name(classname);????????//此对象代表Person.class?(2)对象.getClass():用于获
得对象的类型//如果拿到了对象,不知道是什么类型,用于获得对象的类型Objectobj=newPerson();Class
clazz2=obj.getClass();????????????????????//获得对象具体的类型?(3)类名.c
lass:用于获得指定的类型,传参用//如果是明确地获得某个类的Class对象,主要用于传参Classclazz3=Pers
on.class;70.如何通过反射创建对象?答:(1)调用空参数的构造函数:使用了Class类中的newInstance()方法
。//第一步:获取字节码文件//①通过?Class.forName(“类名”)来获取字节码文件Classclazz=Clas
s.forName("cn.itcast.bean.Person");//②通过类.class?通过加载器来获取字节码文件cl
azz=Person.class;//③通过对象.getClass()来获取字节码文件Objectobj=newP
erson("zhangsan",19);clazz=obj.getClass();//第二步:通过节码文件,创建对象Obj
ectobj=clazz.newInstance();//该实例化对象的方法调用就是指定类中的空参数构造函数,给创建对象进行
初始化。(2)调用带参数的构造函数:先要获取指定参数列表的构造器,然后通过该构造函数的对象的newInstance(实际参数)进行
对象的初始化。publicstaticvoidmethod_2()throwsException{//既然类中没有空参
数的构造函数,那么只有获取指定参数的构造函数,用该函数来进行实例化。Classclazz=Class.forName("cn
.itcast.bean.Person");//获取一个带参数的构造器。Constructorconstructor=cla
zz.getConstructor(String.class,int.class);//想要对对象进行初始化,使用构造器的方法ne
wInstance();Objectobj=constructor.newInstance("zhagnsan",30);/
/获取所有构造器。Constructor[]constructors=clazz.getConstructors();?
??//只包含公共的//constructors=clazz.getDeclaredConstructors();?????
?//本类公有,包含私有的for(Constructorcon:constructors){System.out.prin
tln(con);}}71.简述一下面向对象的"六原则一法则"??答:?(1)单一职责原则:一个类只做它该做的事情。其核心就是我们
常说的"高内聚",写代码最终极的原则只有六个字"高内聚、低耦合",就像葵花宝典的八字中心思想一样"欲练此功必先自宫"一样重要。我们
都知道一句话叫"因为专注,所以专业",一个对象如果承担太多的职责,那么注定它什么都做不好。这个世界上任何好的东西都有两个特征,一个
是功能单一,好的相机绝对不是电视购物里面卖的那种一个机器有一百多种功能的,它基本上只能照相;另一个是模块化,好的自行车是组装车,从
减震叉、刹车到变速器,所有的部件都是可以拆卸和重新组装的,这从我们的框架演化的过程中也可以开出来:。。。。)(2)开闭原则:软件
实体应当对扩展开放,对修改关闭。(在理想的状态下,当我们需要为一个软件系统增加新功能时,只需要从原来的系统派生出一些新类就可以,不
需要修改原来的任何一行代码。要做到开闭有两个要点:?①抽象是关键,一个系统中如果没有抽象类或接口系统就没有扩展点;?②封装可变性,
将系统中的各种可变因素封装到一个继承结构中,如果多个可变因素混杂在一起,系统将变得复杂而换乱。)(3)依赖倒转原则:面向接口编程
。(该原则说得直白和具体一些就是声明方法的参数类型、方法的返回类型、变量的引用类型时,尽可能使用抽象类型而不用具体类型,因为抽象类
型可以被它的任何一个子类型所替代,请参考下面的里氏替换原则。)?(4)里氏替换原则:任何时候都可以用子类型替换掉父类型。(关于里氏
替换原则的描述,BarbaraLiskov女士的描述比这个要复杂得多,但简单的说就是能用父类型的地方就一定能使用子类型。里氏替换
原则可以检查继承关系是否合理,如果一个继承关系违背了里氏替换原则,那么这个继承关系一定是错误的,需要对代码进行重构。例如让猫继承狗
,或者狗继承猫,又或者让正方形继承长方形都是错误的继承关系,因为你很容易找到违反里氏替换原则的场景。需要注意的是:子类一定是增加父
类的能力而不是减少父类的能力,因为子类比父类的能力更多,把能力多的对象当成能力少的对象来用当然没有任何问题。)?(5)接口隔离原则
:接口要小而专,绝不能大而全。(臃肿的接口是对接口的污染,既然接口表示能力,那么一个接口只应该描述一种能力,接口也应该是高度内聚的
。例如,琴棋书画就应该分别设计为四个接口,而不应设计成一个接口中的四个方法,因为如果设计成一个接口中的四个方法,那么这个接口很难用
,毕竟琴棋书画四样都精通的人还是少数,而如果设计成四个接口,会几项就实现几个接口,这样的话每个接口被复用的可能性是很高的)?(6)
聚合复用原则:优先使用聚合关系复用代码。(通过继承来复用代码是面向对象程序设计中被滥用得最多的东西,因为所有的教科书都无一例外的对
继承进行了鼓吹从而误导了初学者,类与类之间简单的说有三种关系,Is-A关系、Has-A关系、Use-A关系,分别代表继承、关联和依
赖。其中,关联关系根据其关联的强度又可以进一步划分为关联、聚合和合成,但说白了都是Has-A关系,合成聚合复用原则想表达的是优先考
虑Has-A关系而不是Is-A关系复用代码。例如Properties类继承了Hashtable类,API中原话:因为Propert
ies?继承于?Hashtable,所以可对Properties?对象应用put?和putAll?方法。但不建议使用这两个方法,因
为它们允许调用者插入其键或值不是String?的项。相反,应该使用setProperty?方法。这个继承明显就是错误的,更好的做法
是在Properties类中放置一个Hashtable类型的成员并且将其键和值都设置为字符串来存储数据。)?(7)迪米特法则:迪米
特法则又叫最少知识原则,一个对象应当对其他对象有尽可能少的了解。(迪米特法则简单的说就是如何做到"低耦合",门面模式和调停者模式就
是对迪米特法则的践行。对于门面模式可以举一个简单的例子,你去一家公司洽谈业务,你不需要了解这个公司内部是如何运作的,你甚至可以对这
个公司一无所知,去的时候只需要找到公司入口处的前台美女,告诉她们你要做什么,她们会找到合适的人跟你接洽,前台的美女就是公司这个系统
的门面。再复杂的系统都可以为用户提供一个简单的门面,JavaWeb开发中作为前端控制器的Servlet或Filter不就是一个门
面吗。调停者就是中间人,中间件dubbo为例)72.简述一下你了解的设计模式??答:所谓设计模式,就是一套被反复使用的代码设计经验
的总结(情境中一个问题经过证实的一个解决方案)。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。设计模式使人
们可以更加简单方便的复用成功的设计和体系结构。将已证实的技术表述成设计模式也会使新系统开发者更加容易理解其设计思路。在GoF的《D
esignPatterns:ElementsofReusableObject-OrientedSoftware》中给出
了三类(创建型[对类的实例化过程的抽象化]、结构型[描述如何将类或对象结合在一起形成更大的结构]、行为型[对在不同的对象之间划分责
任和算法的抽象化])共23种设计模式,包括:AbstractFactory(抽象工厂模式),Builder(建造者模式),Fac
toryMethod(工厂方法模式),Prototype(原始模型模式),Singleton(单例模式);Facade(门面模式
),Adapter(适配器模式),Bridge(桥梁模式),Composite(合成模式),Decorator(装饰模式),Fly
weight(享元模式),Proxy(代理模式);Command(命令模式),Interpreter(解释器模式),Visitor
(访问者模式),Iterator(迭代子模式),Mediator(调停者模式),Memento(备忘录模式),Observer(观
察者模式),State(状态模式),Strategy(策略模式),TemplateMethod(模板方法模式),?ChainO
fResponsibility(责任链模式)。面试被问到关于设计模式的知识时,可以拣最常用的作答,例如:①工厂模式:工厂类可以根
据条件生成不同的子类实例,这些子类有一个公共的抽象父类并且实现了相同的方法,但是这些方法针对不同的数据进行了不同的操作(多态方法)
。当得到子类的实例后,开发人员可以调用基类中的方法而不必考虑到底返回的是哪一个子类的实例。②代理模式:给一个对象提供一个代理对象,
并由代理对象控制原对象的引用。实际开发中,按照使用目的的不同,代理可以分为:远程代理、虚拟代理、保护代理、Cache代理、防火墙代
理、同步化代理、智能引用代理。③适配器模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起使用的
类能够一起工作。-?模板方法模式:提供一个抽象类,将部分逻辑以具体方法或构造器的形式实现,然后声明一些抽象方法来迫使子类实现剩余的
逻辑。不同的子类可以以不同的方式实现这些抽象方法(多态实现),从而实现不同的业务逻辑。④除此之外,还可以讲讲上面提到的门面模式、桥
梁模式、单例模式、装潢模式(Collections工具类和I/O系统中都使用装潢模式)等,反正基本原则就是拣自己最熟悉的、用得最多
的作答,以免言多必失。73.用Java写一个单例类??答:①饿汉式单例publicclassSingleton{?priva
teSingleton(){}?privatestaticSingletoninstance=newSingleto
n();?publicstaticSingletongetInstance(){?returninstance;?}}②懒
汉式单例publicclassSingleton{?privatestaticSingletoninstance=
null;?privateSingleton(){}?publicstaticsynchronizedSingleton
getInstance(){?if(instance==null)instance?=?newSingleton();
?returninstance;?}}注意:实现一个单例有两点注意事项:①将构造器私有,不允许外界通过构造器创建对象;②通过公开
的静态方法向外界返回类的唯一实例。这里有一个问题可以思考:Spring的IoC容器可以为普通的类创建单例,它是怎么做到的呢?74.
线程如何同步和通讯?答:(1)同步有两种方法实现:一种是利用synchronized标示,另外一种是加锁。生成锁的对象的方法是:p
rivatestaticLocklock=newReentrantLock();Lock是一个接口,而Reentran
tlock是一个实现的类。构造方法有:ReentrantLock()和ReentrantLock(fair:boolean)两种。
其中第二种传递的是一个boolean值的参数,当设置为true时系统会按照等待的先后时间让线程活得锁,但是效率和性能不如默认值的好
,但是同时也可以避免资源匮乏。synchronized可以声明方法,也可以用来标记某段代码。用来标记某段代码时的用法是:synch
ronized(){}。?(2)通讯方面有两种方法,第一种是利用锁生成Condition对象,然后调用await()和signal
()或者signalall(),另外一种是利用继承的object类中的wait()和notify()或者notifyall()唤醒
方法。个人觉得利用锁生成的condition对象的方法会比较灵活。75.hashCode方法的作用?答:hashcode这个方法是
用来鉴定2个对象是否相等的。与equals方法的区别:①一般来讲,equals这个方法是给用户调用的,如果你想判断2个对象是否相等
,你可以重写equals方法,然后在代码中调用,就可以判断他们是否相等了。简单来讲,equals方法主要是用来判断从表面上看或者从
内容上看,2个对象是不是相等。举个例子,有个学生类,属性只有姓名和性别,那么我们可以认为只要姓名和性别相等,那么就说这2个对象是相
等的。②hashcode方法一般用户不会去调用,比如在hashmap中,由于key是不可以重复的,他在判断key是不是重复的时候就
判断了hashcode这个方法,而且也用到了equals方法。这里不可以重复是说equals和hashcode只要有一个不等就可以
了!所以简单来讲,hashcode相当于是一个对象的编码,就好像文件中的md5,他和equals不同就在于他返回的是int型的,比
较起来不直观。我们一般在覆盖equals的同时也要覆盖hashcode,让他们的逻辑一致。举个例子,还是刚刚的例子,如果姓名和性别
相等就算2个对象相等的话,那么hashcode的方法也要返回姓名的hashcode值加上性别的hashcode值,这样从逻辑上,他
们就一致了。③要从物理上判断2个对象是否相等,用==就可以了。76.什么是SOA,谈谈你的SOA的理解?答:(1)SOA的概念SO
A(Service-orientedarchITecture,面向服务架构),而?WebService是实现?SOA?的其中一种
方式,所以两者并不是一个概念。?WebService基于?SOAP?协议的,本质就是基于XML的,正是因为基于?XML,所以SOA
才能整合不同的平台,不同的应用。(2)SOA的作用:①整合异构系统。准确点说,整合企业的遗留系统、正在开发的系统和即将开发的新系统
。不同的系统可能采用不同的平台,如操作系统的选择;不同的开发语言;不同的系统架构。②及时的响应用户的业务变化。大量的SOA组件,通
过整合和拆散,然后打包成一个个的粒度合适的SOA组件,再经过流程管理工具的处理,实现业务的不断变化。就像变形金刚那样,零件还是那些
零件,但是经过一定的变化,也就是对SOA组件的拆和并,就可以玩不同的花样。当然这是理想情况,至于到底实际情况如何,笔者也没有搞过
,所以不清楚。77.java中实现多态的机制是什么?答:靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象,而程序调
用的方法在运行期才动态绑定,就是引用变量所指向的具体实例对象的方法,也就是内存里正在运行的那个对象的方法,而不是引用变量的类型中定
义的方法。78..super.getClass()方法调用?下面程序的输出结果是多少?importjava.util.Date;
publicclassTestextendsDate{publicstaticvoidmain(String[]a
rgs){?newTest().test();?}publicvoidtest(){?System.out.println
(?super.getClass().getName());?}}答:结果是Test。原因:在test方法中,直接调用getCla
ss().getName()方法,返回的是Test类名?由于getClass()在Object类中定义成了final,子类不能覆盖
该方法,所以,在test方法中调用getClass().getName()方法,其实就是在调用从父类继承的getClass()方法
,等效于调用super.getClass().getName()方法,所以,super.getClass().getName()方
法返回的也应该是Test。如果想得到父类的名称,调用:getClass().getSuperClass().getName();7
9.请写出你最常见到的5个runtimeexception?答:(1)Objectx=newInteger(0);?System.out.println((String)x);当试图将对象强制转换为不是实例的子类时,抛出该异常(ClassCastException)(2)inta=5/0;一个整数“除以零”时,抛出ArithmeticException异常。(3)Strings=null;intsize=s.size();当应用程序试图在需要对象的地方使用?null时,抛出NullPointerException异常?(4)"hello".indexOf(-1);指示索引或者为负,或者超出字符串的大小,抛出StringIndexOutOfBoundsException异常(5)String[]ss=newString[-1];如果应用程序试图创建大小为负的数组,则抛出NegativeArraySizeException异常。80.当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?答:分几种情况:?(1)其他方法前是否加了synchronized关键字,如果没加,则能。?(2)如果这个方法内部调用了wait,则可以进入其他synchronized方法。?(3)如果其他个方法都加了synchronized关键字,并且内部没有调用wait,则不能。如果其他方法是static,它用的同步锁是当前类的字节码,与非静态的方法不能同步,因为非静态的方法用的是this。81.简述synchronized和java.util.concurrent.locks.Lock的异同?答:(1)主要相同点:Lock能完成synchronized所实现的所有功能(2)主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放。Lock还有更强大的功能,例如,它的tryLock方法可以非阻塞方式去拿锁。82.HashMap和Hashtable的区别?答:(1)相同点:HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,(2)主要区别在于①HashMap允许将null作为一个entry的key或者value,而Hashtable不允许。②Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,83.两个对象值相同(x.equals(y)==true),但却可有不同的hashcode,这句话对不对?答:对。①如果对象要保存在HashSet或HashMap中,它们的equals相等,那么,它们的hashcode值就必须相等。因为HashSet和HashMap在保证值唯一的时候,会先调用hashcode(),如果相同,再调用equals()方法,如果不同,则“类似于桶结构一样”挂在一个hashcode值上②如果不是要保存在HashSet或HashMap,则与hashcode没有什么关系了,这时候hashcode不等是可以的,例如arrayList存储的对象就不用实现hashcode,当然,我们没有理由不实现,通常都会去实现的。84.描述一下JVM加载class文件的原理机制?答:JVM中类的装载是由ClassLoader和它的子类来实现的,JavaClassLoader是一个重要的Java运行时系统组件。它负责在运行时查找和装入类文件的类。85.heap和stack有什么区别?答:java的内存分为两类,一类是栈内存,一类是堆内存。栈内存是指程序进入一个方法时,会为这个方法单独分配一块私属存储空间,用于存储这个方法内部的局部变量,当这个方法结束时,分配给这个方法的栈会释放,这个栈中的变量也将随之释放。堆是与栈作用不同的内存,一般用于存放不放在当前方法栈中的那些数据,例如,使用new创建的对象都放在堆里,所以,它不会随方法的结束而消失。方法中的局部变量使用final修饰后,放在堆中,而不是栈中。86.传统for循环、增强for循环、及迭代器的区别?答:(1)传统for循环:可以定义角标,通过角标操作元素。(2)增强for循环:对集合进行遍历,集合不能为空。只能获取集合元素,无法获取角标,不能对集合进行操作。增强for循环有一个局限性,必须要有被遍历的目标。(3)迭代器(Iterator):除了遍历,还可以进行remove集合中元素的动作。如果是用ListIterator,还可以在遍历过程中进行增删改的动作。
献花(0)
+1
(本文系金银宝100首藏)