一、JavaSE之基础篇
1、JavaSE基础之语法
######(1)、简述你对JVM,JRE,JDK的理解?
JVM:java虚拟机。是一个模拟的计算机,相当于真实存在的计算机(软件+硬件)。
JDK:是整个java的核心。程序员的产品。包括了java的运行环境、java的工具、java的基础类库。
JRE:运行环境。
拓展----JVM、JDK和JRE之间的关系:JDK包括JRE,JRE包括JVM
######(2)、一个".java"源文件中是否可以包括多个类(非内部类)?有什么限制?
一个".java"源文件中可以有多个类,但只能有一个public的类,并且public的类名必须与文件名相一致。
一个".java"源文件中可以只有非public类,但是,如果只有一个非public类,此类可以跟文件名不同。
######(3)、Java有没有goto?
goto在java中作为保留字存在,现在在java中没有使用了。
######(4)、说说&和&&的区别 ?
1.&和&&都可以用作逻辑与的运算符,&&为短路与,&不是短路与。另外&可以做为整数的位运算符。
例1:对于if(str != null&& !str.equals(“”))表达式,当str为null时,后面的表达式不会执行,所以不会出现NullPointerException如果将&&改为&,则会抛出NullPointerException异常。
2.&&还具有短路的功能,即如果第一个表达式为false,则不再计算第二个表达式.
例2:If(x==33 & ++y>0) y会增长,if(x==33 && ++y>0)不会增长。
备注:这道题先说两者的共同点,再说出&&和&的特殊之处,并列举一些经典的例子。
######(5)、在JAVA中如何跳出当前的多重嵌套循环?
Break + 标签
直接使用Break
使用方法的return
例如下面代码片段:
Break + 标签
ok: for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
System.out.println("i=" + i + ",j=" + j);
if (j == 5)
break ok;
}
}直接使用Break
int arr[][] ={{1,2,3},{4,5,6,7},{9}};
boolean found = false;
for(int i=0;i<arr.length&& !found;i++) {
for(int j=0;j<arr[i].length;j++){
System.out.println("i=" + i + ",j=" + j);
if(arr[i][j] ==5) {
found = true;
break;
}
}
}使用方法的return
private static int test() {
int count = 0;
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
count++;
System.out.println("i=" + i + ",j=" + j);
if (j == 5) {
return count;
}
}
}
return 0;
}
######(6)、switch语句能否作用在byte上,能否作用在long上,能否作用在String上?
switch语句可以作用在byte, short, char, int, String, enum, 封装类对象。
其它基本数据类型及引用数据类型都不能做为case的条件。
######(7)、short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?
对于short s1 = 1; s1 = s1 + 1;由于s1+1运算时会自动提升表达式的类型,所以结果是int型,再赋值给short类型s1时,编译器将报告需要强制转换类型的错误。
对于short s1 = 1; s1 += 1;由于 +=是java语言规定的运算符,java编译器会对它进行特殊处理,因此可以正确编译。
######(8)、char型变量中能不能存贮一个中文汉字?为什么?
char型变量中能存贮一个中文汉字,因为char型变量是用来存储Unicode编码的字符的,unicode编码字符集中包含了汉字。
补充说明:unicode编码占用两个字节,所以,char类型的变量也是占用两个字节。
######(9)、用最有效率的方法算出2乘以8等於几?
2 << 3 因为将一个数左移n位,就相当于乘以了2的n次方,那么,一个数乘以8只要将其左移3位即可,而位运算cpu直接支持的,效率最高,所以,2乘以8等於几的最效率的方法是2 << 3。
######(10)、使用final关键字修饰一个变量时,是引用变量不能变,还是引用的对象不能变?
是引用变量不能变,引用变量所指向的对象中的内容是可以改变的,但是不能再去new新的对象。例1:如下面代码,编译就会出错 final StringBuffer a=new StringBuffer("immutable"); a=new StringBuffer("");例2:如下面代码,编译正确 final StringBuffer a=new StringBuffer("immutable"); a.append(“123”);
######(11)、"=="和equals方法有什么区别?
他们的区别主要是在引用数据类型上面:
1.==为比较两侧的对象是否同一对象,是用内存地址来比较的;
2.equals是方法,默认是用内存地址比较,重写后,主要是用来比较两侧的对象的值是否相同,和equals方法中的实现有关;
注意:==可以两侧都为null,但equals左侧的引用指向的对象不能空,否则会出现NullPointerException异常。
######(12)、静态变量和实例变量的区别?
1.在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加。
2.在程序运行时的区别:
实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。
静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。
总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。
######(13)、是否可以从一个static方法内部发出对非static方法的调用?
不可以。
因为非static方法(实例方法)是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调用,而static方法调用时不需要创建对象,可以直接调用。
也就是说,当一个static方法被调用时,可能还没有创建任何实例对象,如果从一个static方法中发出对非static方法的调用,那个非static方法是关联到哪个对象上的呢?这个逻辑无法成立,所以,一个static方法内部发出对非static方法的调用。
######(14)、Integer与int的区别?
1.int是java提供的8种原始数据类型之一,意思整型,占用4字节。
2.Integer是java为int提供的封装类,是引用数据类型。
3.int的默认值为0,而Integer的默认值为null,即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况。例如,要想表达出没有参加考试和考试成绩为0的区别,则只能使用Integer。
4.在JSP开发中,Integer的默认为null,所以用el表达式在文本框中显示时,值为空白字符串,而int默认的默认值为0,所以用el表达式在文本框中显示时,结果为0,所以,int不适合作为web层的表单数据的类型。
5.在Hibernate中,如果将OID定义为Integer类型,那么Hibernate就可以根据其值是否为null而判断一个对象是否是临时的,如果将OID定义为了int类型,还需要在hbm映射文件中设置其unsaved-value属性为0。
6.另外,Integer提供了多个与整数相关的操作方法,例如,将一个字符串转换成整数,Integer中还定义了表示整数的最大值和最小值的常量。
######(15)、Math.round(11.5)等于多少? Math.round(-11.5)等于多少?
Math.round(11.5)的结果为12,Math.round(-11.5)的结果为-11。
解析:Math类中提供了三个与取整有关的方法:ceil、floor、round,这些方法的作用与它们的英文名称的含义相对应。
例如:ceil的英文意义是天花板,该方法就表示向上取整,Math.ceil(11.3)的结果为12,Math.ceil(-11.3)的结果是-11;floor的英文意义是地板,该方法就表示向下取整,Math.ceil(11.6)的结果11,Math.ceil(-11.6)的结果是-12。
######(16)、下面的代码有什么不妥之处?if(username.equals(“zxx”){......}
username可能为null,会报空指针错误;改为"zxx".equals(username)int x = 1;
return x==1?true:false; 这个改成return x==1;就可以!
######(17)、请说出作用域public,private,protected,以及不写时的区别?
这四个作用域的可见范围如下表所示。(说明:如果在修饰的元素上面没有写任何访问修饰符,则表示friendly/default。)
######(18)、Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?
1.Overload是重载的意思,Override是重写的意思。
2.Overload和Override有共同之处,两个方法的方法名都必须相同,如果不同,既不构成Overload,也不构成Override。
3.Override必须发生在父子类之间,Overload可以不在父子类之间。
4.Override(重写)的特点:
a)参数列表完全相同:个数相同、类型相同、顺序相同;
b)子类的返回值不能比父类的返回值范围大;
c)子类方法抛出的异常不能比父类方法抛出的异常范围大;
d)修饰符只能为public、protected、friendly,不能为private;
e)父子类方法不能使用static修饰。
4.重载发生在同一个类或父子类之间,重载中参数列表至少满足个数不同、类型不同、顺序不同中的一个条件,不包含父子类之间的static方法。
######(19)、构造器Constructor是否可被override(即构造函数是否可被重写)?
不能。
因为构造器Constructor不能被继承,因此不能Override(重写)。但构造器Constructor可以被Overload(重载)。
######(20)、接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承具体类(concrete class)? 抽象类中是否可以有静态的main方法? 抽象类是否可有以内部类? 接口是否可以有内部类?
接口可以继承接口;
抽象类可以实现(implements)接口;
抽象类可以继承具体类;
抽象类中可以有静态的main方法;
抽象类可有以内部类;
接口可以有内部类,但必须是static内部类,但不一定是final的。
(注意:抽象类与普通类的唯一区别就是不能创建实例对象和允许有abstract方法。)
######(21)、写clone()方法时,通常都有一行代码(不是必须有),是什么?
super.clone();
因为clone有缺省行为,首先要把类中的成员复制到位,然后才是复制自己的成员。
######(22)、面向对象的特征有哪些方面?封装,隐藏内部实现,只暴露公共行为;
继承,提高代码的重用性;
多态,体现现实生活中相似对象的差异性;
抽象,抽取现实世界中相似对象的共同点。
######(23)、满足多态的必要条件有哪些?要有继承;
要有重写;
父类引用指向子类对象;
######(24)、java中实现多态的机制是什么?
通过继承父类或实现接口。
1.继承指子类继承父类的所有属性、方法、内部类。对于属性而言,如果子类的属性名和父类的属性名相同,则子类会把父类的属性隐藏。属性根据引用来调用,方法根据对象来调用;Java中只有单继承,一个子类只能直接继承一个父类。
2.实现接口指某类可以实现接口中的部分或所有方法,并能继承接口中的所有的属性和内部类。接口中的属性都为public static final类型,方法都为public类型,内部类都为public static类型。接口可以继承多个接口,实现类可以实现多个接口。
######(25)、abstract class和interface有什么区别?
含有abstract修饰符的class即为抽象类,abstract类不能创建的实例对象。含有abstract方法的类必须定义为abstract class,abstract class类中的方法不必是抽象的。abstract class类中定义抽象方法必须在具体(Concrete)子类中实现,所以,不能有抽象构造方法或抽象静态方法。如果的子类没有实现抽象父类中的所有抽象方法,那么子类也必须定义为abstract类型。
接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。接口中的方法定义默认为public abstract类型,接口中的成员变量类型默认为public static final。
下面比较一下两者的语法区别:抽象类可以有构造方法,接口中不能有构造方法。
抽象类中可以有普通成员变量,接口中没有普通成员变量
抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
抽象类中的抽象方法的访问类型可以是public,protected和默认类型,但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。
抽象类中可以包含静态方法,接口中不能包含静态方法
抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。
一个类可以实现多个接口,但只能继承一个抽象类。
下面接着再说说两者在应用上的区别:
1.接口更多的是在系统架构设计方法发挥作用,主要用于定义模块之间的通信契约;
2.而抽象类在代码实现方面发挥作用,可以实现代码的重用。
######(26)、25、抽象(abstract)的方法(method)是否可以同时是静态(static)的? 是否可以同时是本地化(native)的? 是否可以同时是同步(synchronized)的? 是否可以同时是最终(final)的?
1.抽象(abstract)的方法(method)不可以是静态(static)的,因为抽象的方法是要被子类实现的,而static与子类扯不上关系!
2.本地化(native)方法表示该方法要用另外一种依赖平台的编程语言实现的,不存在着被子类实现的问题,所以,它也不能是抽象的,不能与abstract混用。
3.同步(synchronized)和抽象(abstract)合用的问题不能共用,抽象(abstract)方法只能存在于抽象类或接口中,它不能直接产生对象,而默认同步(synchronized)方法对当前对象加锁,没有对象是不能加锁。另外synchronized不能被继承,子类继承时,需要另加修改符。
4.最终(final)方法和抽象(abstract)不能共用,因为final是不能被子类重写的,而抽象方法必须被某级子类重写。
######(27)、什么是内部类?静态内部类和内部类有什么不同?
内部类就是在一个类的内部定义的类。
静态内部类和内部类的区别:静态内部类需要使用static修饰,而普通内部类不能使用static修饰;
静态内部类只能定义在和属性同级,普通内部类可以定义在除参数位置以外的任意位置;
静态内部类必需有名称,而普通内部类可以是匿名的;
静态内部类没有this引用,只此只能访问外部类的静态成员,而普通内部类可以访问外部类的全部成员;
静态内部类访问外部类的同名函数时,使用“外部类名.方法名”即可,而普通内部类需要使用“外部类名.this.外部方法”;
静态内部类可以定义静态方法,而普通内部类不能定义静态方法,但能定义简单数据类型的静态属性,不能定义引用类型的静态属性。
######(28)、内部类可以引用它的包含类的成员吗?有没有什么限制?
如果内部类为静态内部类,只能调用外部类的静态成员;如果有重名成员,需要用“外部类名.成员名”访问;不能调用外部类的对象成员。
如果内部类为非静态内部类,则可以调用外部类的所有成员;如果有重名成员,需要使用“外部类名.this.成员名”。
######(29)、匿名内部类是否可以继承其它类? 是否可以实现接口?
可以继承其他类或者实现其他接口。不仅是可以,而且是必须的!
######(30)、super.getClass()方法和this.getClass()方法返回对象是否相同?
返回的Class对象是同一对象,都是子类的对象。
######(31)、String是最基本的数据类型吗?
String是引用数据类型。
基本数据类型包括byte、int、char、long、float、double、boolean和short。
######(32)、String s = "Hello";s = s + " world!";这两行代码执行后,原始的String对象中的内容到底变了没有?
没有。
因为String被设计成不可变(immutable)的类,所以它的所有对象都是不可变对象。
######(33)、是否可以继承String类?
String类是final类故不可以继承。
######(34)、String s = new String("xyz");创建了几个String Object?二者之间有什么区别?
两个对象。一个是"xyz",是缓冲区对象。另一个是new出来的String对象。这两个对象的值相同,但不是同一个对象。
######(35)、新建对象有几种方式?使用new关键字
使用反射,调用newInstance方法
使用clone方法
使用序列化与反序列化
动态代理(Proxy类和CGLIB)
######(36)、String和StringBuffer的区别?
相同之处:这两个类都实现了CharSequence接口。
不同之处:类型不同,因为不是一个类,也没有继承关系,做参数时不能共用
String对象是不可变对象,不能修改值。而StringBuffer是可变对象,能修改值。
拼接字符串时,String会产生新对象,而StringBuffer只是增加新字符,不产生新对象,因此效率高。
String覆盖了equals方法和hashCode方法,而StringBuffer没有覆盖equals方法和hashCode方法,所以,将StringBuffer对象存储进Java集合类中时会出现问题。
######(37)、StringBuffer和StringBuilder的区别?
相同之处:这两类都是可变长的字符串存储类,都实现了CharSequence接口。
不同之处:类型不同,因为不是一个类,也没有继承关系,做参数时不能共用。
StringBuffer为线程安全类,StringBuilder为线程非安全类。
StringBuffer性能低,StringBuilder性能高,如果在局部优先使用StringBuilder。
JDK在1.5之前,字符串相加使用StringBuffer对象,在1.5之后使用StringBuilder对象。
######(38)、如何把一段逗号分割的字符串转换成一个数组?
1.用正则表达式,核心代码片段为:String [] result = orgStr.split(“,”, -1);
2.用 StingTokenizer
3.最笨的办法,用String.indexOf();代码片段如下:
2.用 StingTokenizer:
StringTokenizer tokener = new StringTokenizer(s, ",");
String[] result = new String[tokener.countTokens()];
Integer i = 0;
while (tokener.hasMoreTokens()) {
result[i++] = tokener.nextToken();
}
3.最笨的办法,用String.indexOf()
int index = -1;
int oldIndex = 0;
List<String> ss = new ArrayList<String>();
while ((index = s.indexOf(',', index + 1)) != -1) {
ss.add(s.substring(oldIndex, index));
oldIndex = index + 1;
}
if (s.charAt(s.length() - 1) == ',') {
ss.add("");
}
String[] array = ss.toArray(new String[ss.size()]);
System.out.println(Arrays.toString(array));
######(39)、数组有没有length()这个方法? String有没有length()这个方法? JS的数组有没有length()方法? JS的字符串有没有length()方法?
数组没有length()这个方法,有length的属性。String有有length()这个方法。JS中只有length属性,没有length方法。
######(40)、String s="a"+"b"+"c"+"d"这条语句一共创建了多少个对象?
产生了一个对象,即"abcd"。
分析如下:
String s1 = "a";
String s2 = s1 + "b";
String s3 = "a" + "b";
System.out.println(s2 == "ab"); // false
System.out.println(s3 == "ab"); // true
String s = "a" + "b" + "c" + "d";
System.out.println(s == "abcd"); // true s被优化为”abcd”
######(41)、能不能自己写个类,也叫java.lang.String?
可以。
但在应用的时候,需要用自己的类加载器去加载,
否则,系统的类加载器永远只是去加载rt.jar包中的那个java.lang.String。
######(42)、try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行,在return前还是后?
也许你的答案是在return之前,但往更细地说,应该是在return中间执行。
请看下面程序代码的运行结果:
public class Test {
public static void main(String[] args) {
System.out.println(test());
}
static int test() { int x = 1; try { return x; } finally { ++x; } } } ---------执行结果 --------- 1 运行结果是1,为什么呢?主函数调用子函数并得到结果的过程,好比主函数准备一个空罐子,当子函数要返回结果时,先把结果放在罐子里,然后再将程序逻辑返回到主函数。所谓返回,就是子函数说,我不运行了,你主函数继续运行吧,这没什么结果可言,而结果已经被放进罐子里了。
######(43)、final, finally, finalize的区别?
1.final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。
注意:内部类要访问局部变量,局部变量必须定义成final类型。
如下面代码:
final int[] number = { 20 }; new Thread() { @Override public void run() { for (int k = 0; k < 20; k++) { number[0]++; } } }.start(); Thread.sleep(10); System.out.println(number[0]); 2.finally是异常处理语句结构的一部分,表示总是执行,用来释放资源。 3.finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。JVM不保证此方法总被调用。