1. 一个.java源文件是否可以包含多个类?有什么限制?
可以有多个类,但只能有一个public类,并且该类名与源文件名一致。
2. Java有没有goto?
是保留字,但并没有用。
3. & 和 &&的区别
&和&&都可以作逻辑运算符,例如 if (a==2 & b==3), if (a==2 && b==3).
区别是&&有短路功能,但是&没有。
当&两边的表达式不是布尔值时,还可以作位运算符,例如0x31&0x0f,结果是0x01。
4. 在Java中如何跳出当前的多重嵌套循环?
a. 给外层循环一个标记out,然后在里层循环体重使用 break out的方法。
out: for(int i=0; i<5; i++) { for (int j=0; j<5; j++) { if (j==3) { System.out.println(i); break out; } } }
b. 使用一个在内层循环中可以控制的变量,用这个变量作为外层循环的条件之一。
boolean flag = false; for(int i=0; i<5&&!flag; i++) { for (int j=0; j<5; j++) { if (j==3) { System.out.println(i); flag = true; } } }
5. switch语句能否用在byte上,能否用在long和string上?
switch只能用在int或Integer包装类型和枚举类性上。byte可以转化为整型,所以可以用switch。但是long和String不能转化为整型,所以不可以。
6. short s1=1;s1 = s1 + 1; 有什么错? short s1=1; s1 += 1; 有什么错?
对于s1 = s1 + 1 来说,1是int类型,所以在执行+时,会将结果的类型自动提升为int,所以要么强制类型转换为short,要么把s1的类型变成int。
但是对于+=运算,Java规定 e1 += e2,相当于 e1 = (T1)(e1 + e2), T1 是e1的类型。也就是说+=直接将运算后的结果进行了强制类型转换,所以编译不会报错。但如果T1是byte, short或char类型,而e2的类型是int类型,即便编译不报错,结果也有可能错。因为有可能会发生溢出。
7. char型变量能不能存储一个中文汉字?为什么?
char用来存储unicode,unicode编码的字符集包含了汉字,所以,char型变量中可以存储汉字。但是,如果某个汉字不在unicode中,那就不能存储。
8. 用最有效率的方法算出2乘以8等于几
2 << 3. 将一个数左移n位,就表示乘以2的n次访。
9. 使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?
引用不能变。
10. ==和equals的区别
==比较的是变量的值,如果被比较对象是引用,则比较的是引用地址是否一致
equals比较两个独立对象的内容,如果被比较对象是引用,则比较的是引用的内容是否一致
11. 静态变量和实例变量的区别
静态变量属于类,在类加载完初始化。
实例变量属于对象,在构造对象的时候初始化。
12. 是否可以从一个static方法内部发出对非static方法的调用?
不可以,因为非static方法属于一个对象,在static方法被调用时,有可能没有构造出一个对象。
13. Integer和int的区别
int是基本类型,它的默认值是0
Integer是int的包装类型,默认值是null,而且定义了很多与整数相关的操作方法。
14. Math.round(11.5) 等于多少? Math.round(-11.5)等于多少?
Math.ceil 向上取整,Math.ceil(11.3)=12, Math.ceil(-11.3)=11
Math.floor 向下取整,Math.floor(11.6)=11, Math.floor(-11.6)=12
Math.round 四舍五入,向等于Math.floor(x+0.5), Math.round(11.5) = Math.floor(11.5+0.5)=12, Math.round(-11.5) = Math.floor(-11.5+0.5) = -11.
15. public, private, protected, 默认
16. Override的特点:
方法的重写要遵循“两同两小一大”规则,“两同”即方法名相同,形参列表相同。“两小”指的是子类方法返回值类型应比父类返回值类型更小或相等,子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或相等;“一大”指的是子类方法的访问权限应比父类方法的访问权限更大或相等。尤其需要指出的是,覆盖方法和被覆盖方法要么都是类方法,要么都是实例方法,不能一个是类方法,一个是实例方法。
17. clone() 深拷贝和浅拷贝
clone()的时候要先调用super.clone().
浅拷贝:值拷贝,如果有引用,拷贝的只是引用地址,所以拷贝前和拷贝后对象拥有的引用指向的是同一个对象。
深拷贝:不仅拷贝值,也拷贝引用的对象。
18. 面向对象特征
抽象,封装,继承,多态
19. java中实现多态的机制是什么?
在编译期,父类或接口定义的引用变量可以指向子类或具体实现类的实例对象,而程序调用的方法在运行期才动态绑定。
20. abstract class 和 interface 的区别?
- 抽象类中可以有构造函数,但接口中不能有构造函数
- 抽象类中可以有普通成员变量,但接口中不能有普通成员变量
- 抽象类中可以包含非抽象的普通方法,但接口中的方法必须都是抽象的
- 抽象类中的抽象方法可以使用public和protected,但interface中的抽象方法只能是public
- 抽象类中可以包含静态方法,接口中不能包含静态方法。
- 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以是任意,但接口中定义的变量只能是public static final
- 一个类可以实现多个接口,但只能继承一个抽象类。
21. 内部类的特点
a. 什么是内部类
将一个类定义在另一个类的内部,这个类就叫内部类
b. 为什么会用内部类
每个内部类都能独立地继承一个类,所以无论外部类是否继承了某个类,对于内部类都没有影响。所以内部类是为了解决多继承的问题。
c. 怎么使用内部类
1. 内部类如何使用外部类的属性和方法
class Out { private int age = 12; class In { public void print() { System.out.println(age); } } }
内部类可以对外部类的属性直接进行访问,即使这个属性是private的。这是因为当创建某个外部类的内部对象时,内部对象必定会捕获一个指向外部类对象的引用,只要在内部类访问外部类成员时,就会用这个引用来访问。
2. 外部类如何引用内部类
引用内部类需要指明对象的类型:OuterClassName.InnerClassName
创建内部类对象的方法有两种,如果只需要使用内部类,用第一种,如果既需要外部类对象,也需要内部类对象用第二种:
public class OuterClass { public static void main(String[] args) { // Way 1 Out.In in = new Out().new In(); in.print(); // Way 2 Out out = new Out(); Out.In in2 = out.new In(); in2.print(); } }
3. 成员内部类
就像是外部类的一个普通成员一样,属于对象,不属于类。
package com.ivy.innerClass; public class OuterClass { private String str; public void display() { System.out.println("OuterClass : " + str); } public class InnerClass{ public void display() { System.out.println("InnerClass : " + str); str = "changed str"; OuterClass.this.display(); } } //推荐使用getter方法来获取成员内部类,尤其是该内部类有无参过造函数时。 public InnerClass getInnerClass() { return new InnerClass(); } public static void main(String[] args) { OuterClass outer = new OuterClass(); OuterClass.InnerClass inner = outer.getInnerClass(); inner.display(); } }
成员内部类要注意两点,第一:成员内部类不能存在任何static变量和方法;第二:成员内部类是依附于外部类的,所以只有先创建了外部类才能创建内部类。
解释为什么成员内部类不能存在任何static变量和方法:
成员内部类的第一次加载是在外部类实例化时,而根据static的语义,就是主类能直接通过内部类名来访问内部类中的static方法。如果成员内部类中有static变量或方法,就表示这些变量和方法可以在外部类加载完之后在外部类对象实例化之前的时候就初始化或被调用,但是这个时候内部类并没有加载,就会造成矛盾。
4. 局部内部类
class Out { private int age = 12; public void Print(final int x) { class In { public void inPrint() { System.out.println(x); System.out.println(age); } } new In().inPrint(); } } public class Demo { public static void main(String[] args) { Out out = new Out(); out.Print(3); } }
如果要往局部内部类的方法中传参数,那么形参必须使用final修饰。
5. 匿名内部类
class Out5 { private int age = 12; public void print(int x) { new Inner(){ public void print() { System.out.println(x); System.out.println(age); } }.print(); } abstract class Inner { public abstract void print(); } }
匿名内部类注意点:
a. 使用匿名内部类时,必须使其继承一个类或实现一个接口,但是两者不可兼得,只能继承一个类或实现一个接口。
b. 匿名内部类不能是抽象的,它必须实现继承的类或接口的所有抽象方法。
c. 匿名内部类没有访问修饰符。
d. 匿名内部类是没有构造函数的,因为它连名字都没有。
e. 当所在方法的兴灿需要被匿名内部类使用,那么这个形参必须被final修饰。
解释为什么形参必须用final修饰?
6. 静态内部类
使用static修饰的内部类我们称之为静态内部类,静态内部类与非静态内部类之间存在一个最大的区别,非静态内部类在编译完成之后会隐含地保存着一个引用,该引用指向外部类。但是静态内部类没有这个引用。所以:
静态内部类的创建不需要依赖于外部类
静态内部类不能使用任何外部类的非static成员变量和方法
public class OuterClass { public static void main(String[] args) { Out3.In3 in3 = new Out3.In3(); in3.print(); } } class Out3 { private static int age = 12; private String name = "ax60248"; static class In3 { public void print() { Out3 out = new Out3(); System.out.println(out.name + ":" + age); } } }
in3的实例化有些变化,因为In3是静态的,所以和外部类对象没有关系,可以将Out3.In3 看作一个整体,直接new一个对象出来。
22. super.getClass().getName()返回什么?
getClass() 是final修饰的,所以不能被子类覆盖,所以即使是super.getClass()调用的也是当前类从Object继承来的getClass(). 所以返回当前类的名字,而不是父类的名字。
23. try{} 里有一个return,那么try后的finally的code会被执行吗?什么时候执行,在return前还是后?
会被执行,但并不是在return之前,是中间。
package com.ivy.basic; public class ReturnFinallyDemo { public static void main(String[] args) { // TODO Auto-generated method stub int result = test(); System.out.println(result); } public static int test() { int i=0; try { i = 1; return i; } finally { i = 2; } } }
结果输出1
package com.ivy.basic; public class ReturnFinallyDemo { public static void main(String[] args) { // TODO Auto-generated method stub int result = test2(); System.out.println(result); } public static int test2() { try { return 1; } finally { return 2; } } }
结果输出2.
return并不是让函数马上返回,而是return语句执行后,将把返回结果放置进函数栈中,此时函数并不是马上返回,它要执行finally语句后才真正开始返回。所以finally中的代码在return和break后执行。
24. 异常相关问题
(转载一张别人总结的图片,http://www.cnblogs.com/chenssy/p/3438130.html)
从上面这幅图可以看出,Throwable是java语言中所有错误和异常的超类(万物即可抛)。它有两个子类:Error、Exception。
其中Error为错误,是程序无法处理的,如OutOfMemoryError、ThreadDeath等。
而Exception是程序可以处理的异常。它又分为两种CheckedException(受捡异常),一种是UncheckedException(不受检异常)。其中CheckException发生在编译阶段,必须要使用try…catch(或者throws)否则编译不通过。而UncheckedException发生在运行期,具有不确定性,主要是由于程序的逻辑问题所引起的,难以排查,我们一般都需要纵观全局才能够发现这类的异常错误。
所以:对于可恢复的条件使用被检查的异常(CheckedException),对于程序错误(言外之意不可恢复,大错已经酿成)使用运行时异常(RuntimeException)。
(编译期异常使用checkedException, 运行期使用RuntimeException)
25, Java实现线程的方式
extends Thread
implements Runnable