Java面试题总结之Java基础(二)
1、写clone()方法时,通常都有一行代码,是什么?
答:super.clone(),他负责产生正确大小的空间,并逐位复制。
2、GC 是什么? 为什么要有GC?
答:GC 是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java 提供的GC 功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java 语言没有提供释放已分配内存的显示操作方法。Java 程序员不用担心内存管理,因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方法之一:System.gc() 或Runtime.getRuntime().gc() 。
3、垃圾回收的优点和原理。并考虑2 种回收机制。
答:1.Java 语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java 程序员在编写程序的时候不再需要考虑内存管理。
2.由于有垃圾回收机制,Java 中的对象不再有“作用域”的概念,只有对象的引用才有“作用域”。
3.垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。
4.垃圾回收器通常是作为一个单独的低级别的线程运行,在不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。
回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收。
4、垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?
答:1.对于GC 来说,当程序员创建对象时,GC 就开始监控这个对象的地址、大小以及使用情况。通常,GC 采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是"可达的",哪些对象是"不可达的"。当GC 确定一些对象为"不可达"时,GC 就有责任回收这些内存空间。
2.可以。
3.程序员可以手动执行System.gc(),通知GC 运行,但是Java 语言规范并不保证GC 一定会执行。
5、String s=new String(“xyz”);创建了几个String Object?
答:两个对象,一个是"xyx",一个是指向"xyx"的引用对象s。
6、接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)?
答:接口可以继承接口。抽象类可以实现(implements)接口,抽象类可继承实体类,但前提是实体类必须有明确的构造函数。
7、Java 的接口和C++的虚类的相同和不同处。
c++虚类相当与java里面的抽象类,与接口的不同之处如下:
1、一个子类只能继承一个抽象类(虚类),但能实现多个接口;
2、一个抽象类可以有构造方法,接口没有构造方法;
3、一个抽象类中的方法不一定是抽象方法,即其中一些方法可以有实现(有方法体),接口中的方法都是抽象方法,不能有方法体,只有声明;
4、一个抽象类可以是public、private、protected、default,
接口只能是public;
5、一个抽象类中的方法可以是public、private、protected、default,
接口中的方法只能是public和default。
相同之处:都不能实例化。
接口是一类特殊的抽象类,是更抽象的抽象类。
8、一个“.java”源文件中是否可以包含多个类(不是内部类)?有什么限制?
答:可以;一个“.java”源文件里面可以包含多个类,但是只允许有一个public类,并且类名必须和文件名一致。
9、说出一些常用的类,包,接口,各举5 个。
答:常用的类:BufferedReader,BufferedWriter ,FileReader ,FileWirter, String ,Integer;
常用的包:java.lang ,java.awt, java.io ,java.util ,java.sql;
常用的接口:Remote ,List ,Map ,Document ,NodeList
10、Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类?是否可以implements(实现)interface(接口)?
答:可以继承其他类或实现其他接口,在swing 编程中常用此方式。
11、内部类可以引用他包含类的成员吗?有没有什么限制?
答:可以,如果不是静态内部类,那没有什么限制! 如果你把静态嵌套类当作内部类的一种特例,那在这种情况下不可以访问外部类的普通 成员变 量,而只能访问外部类中的静态成员
12、java 中实现多态的机制是什么?
答:方法的覆盖Overriding 和重载Overloading 是java 多态性的不同表现;覆盖Overriding 是父类与子类之间多态性的一种表现,重载Overloading 是一个类中多态性的一种表现。
13、在java 中一个类被声明为final 类型,表示了什么意思?
答:表示该类不能被继承,是*类。
14、下面哪些类可以被继承?
1)java.lang.Thread (T)
2)java.lang.Number (T)
3)java.lang.Double (F)
4)java.lang.Math (F)
5)java.lang.Void (F)
6)java.lang.Class (F)
7)java.lang.ClassLoader (T)
答:1、2、7 可以被继承。
15、指出下面程序的运行结果:
class A {
static {
System.out.print("1");
}
public A() {
System.out.print("2");
}
}
class B extends A {
static {
System.out.print("a");
}
public B() {
System.out.print("b");
}
}
public class Hello {
public static void main(String[] ars) {
A ab = new B(); // 执行到此处,结果: 1a2b
ab = new B(); // 执行到此处,结果: 1a2b2b
}
}
答:输出结果为1a2b2b;类的static 代码段,可以看作是类首次加载(虚拟机加载)执行的代码,而对于类加载,首先要执行其基类的构造方法,再执行其本身的构造方法。
16、写出下面程序的打印结果?
父类:
public class FatherClass {
public FatherClass() {
System.out.println("FatherClass Create");
}
}
子类:
public class ChildClass extends FatherClass {
public ChildClass() {
System.out.println("ChildClass Create");
}
public static void main(String[] args) {
FatherClass fc = new FatherClass();
ChildClass cc = new ChildClass();
}
}
答:输出结果为:
FatherClass Create
FatherClass Create
ChildClass Create
17、内部类的实现方式?
答:示例代码如下:
public class OuterClass {
private class InterClass {
public InterClass() {
System.out.println("InterClass Create");
}
}
public OuterClass() {
InterClass ic = new InterClass();
System.out.println("OuterClass Create");
}
public static void main(String[] args) {
OuterClass oc = new OuterClass();
}
}
输出结果为:
InterClass Create
OuterClass Create
18、关于内部类:
public class OuterClass {
private double d1 = 1.0;
//insert code here
}
在第3行插入一个内部类声明,哪两个内部类声明有效?(选择两个。)
A. class InnerOne{
public static double methoda() {return d1;}
}
B. public class InnerOne{
static double methoda() {return d1;}
}
C. private class InnerOne{
double methoda() {return d1;}
}
D. static class InnerOne{
protected double methoda() {return d1;}
}
E. abstract class InnerOne{
public abstract double methoda();
}
答:答案为C、E;说明如下:
1)静态内部类可以有静态成员,而非静态内部类则不能有静态成员;故A、B错;
2)静态内部类的非静态成员可以访问外部类的静态变量,而不可访问外部类的非静态变量;故D 错;
3)非静态内部类的非静态成员可以访问外部类的非静态变量;故C 正确。
19、数据类型之间的转换:
1)如何将数值型字符转换为数字?
2)如何将数字转换为字符?
3)如何取小数点前两位并四舍五入?
答:1)调用数值类型相应包装类中的方法parse***(String)或valueOf(String)即可返回相应基本类型或包装类型数值;
2)将数字与空字符串相加即可获得其所对应的字符串;对于基本类型数字还可调用String 类中的valueOf(…)方法返回相应字符串,而对于包装类型数字则可调用其toString()方法获得相对应字符串;
3) //方法1
public void test1(double c)
{
java.text.DecimalFormat df = new java.text.DecimalFormat("#.##");
System.out.println(df.format(c));
}
//方法2
public void test2(double c)
{
java.math.BigDecimal bd = new java.math.BigDecimal(String.valueOf(c)); bd = bd.setScale(2,java.math.BigDecimal.ROUND_HALF_UP);
System.out.println(bd);
}
//方法3
public void test3(double c)
{
long l1 = Math.round(c*100); //四舍五入
double ret = l1/100.0; //注意:使用 100.0 而不是 100
System.out.println(ret);
}
//方法4
public void test4(double c)
{
c=((int)(c*100))/100.0;
System.out.println(c);
}
20、字符串操作:如何实现字符串的反转及替换?
答:可用字符串构造一StringBuffer 对象,然后调用StringBuffer 中的reverse方法即可实现字符串的反转,调用replace 方法即可实现字符串的替换。
public static String reverse(String s){
String str;
StringBuffer sbBuffer =new StringBuffer(s);
str=sbBuffer.reverse().toString();
return str;
}
21、编码转换:怎样将GB2312 编码的字符串转换为ISO-8859-1 编码的字符串?
答:String s1 = "你好";
String s2 = new String(s1.getBytes("GB2312"), "ISO-8859-1");
22、写一个函数,要求输入一个字符串和一个字符长度,对该字符串进行分隔。
答:代码如下:
public static String[] split(String str, int length) {
int n = (str.length() + length - 1) / length;
String ret[] = new String[n];
for (int i = 0; i < n; i++) {
if (i < n - 1) {
ret[i] = str.substring(i * length, (i + 1) * length);
} else {
ret[i] = str.substring(i * length);
}
}
return ret;
}
23、写一个函数,传入2 个参数,1 个字符串,1 个字节数,返回截取的字符串,要求字符串中的中文不能出现乱码:如(“我ABC”,4)应该截为“我AB”,输入(“我ABC 汉DEF”,6)应该输出为“我ABC”而不是“我ABC+汉的半个”。
答:代码如下:
public String subString(String str, int subBytes) {
int bytes = 0; // 用来存储字符串的总字节数
for (int i = 0; i < str.length(); i++) {
if (bytes == subBytes) {
return str.substring(0, i);
}
char c = str.charAt(i);
if (c < 256) {
bytes += 1; // 英文字符的字节数看作1
} else {
bytes += 2; // 中文字符的字节数看作2
if (bytes - subBytes == 1) {
return str.substring(0, i);
}
}
}
return str;
}
24、日期和时间:
1)如何取得年月日、小时分秒?
2)如何取得从1970 年到现在的毫秒数?
3)如何取得某个日期是当月的最后一天?
4)如何格式化日期?
答:1)创建java.util.Calendar 实例(Calendar.getInstance()),调用其get()方法传入不同的参数即可获得参数所对应的值,如:calendar.get(Calendar.YEAR);//获得年
2)以下方法均可获得该毫秒数:Calendar.getInstance().getTimeInMillis();System.currentTimeMillis();
3)示例代码如下:
Calendar time = Calendar.getInstance();
time.set(Calendar.DAY_OF_MONTH,
time.getActualMaximum(Calendar.DAY_OF_MONTH));
4)利用java.text.DataFormat 类中的format()方法可将日期格式化。
25、Java 编程,打印昨天的当前时刻。
答:public class YesterdayCurrent {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, -1);
System.out.println(cal.getTime());
}
}
26、java 和javasciprt 的区别。
答:JavaScript 与Java 是两个公司开发的两个不同的产品。Java 是SUN 公司推出的新一代面向对象的程序设计语言,特别适合于Internet 应用程序开发;而JavaScript 是Netscape 公司的产品,其目的是为了扩展Netscape Navigator功能,而开发的一种可以嵌入Web 页面中的基于对象和事件驱动的解释性语言,它的前身是Live Script;而Java 的前身是Oak 语言。下面对两种语言间的异同作如下比较:
1)基于对象和面向对象:Java 是一种真正的面向对象的语言,即使是开发简单的程序,必须设计对象;JavaScript 是种脚本语言,它可以用来制作与网络无关的,与用户交互作用的复杂软件。它是一种基于对象(Object Based)和事件驱动(Event Driver)的编程语言。因而它本身提供了非常丰富的内部对象供设计人员使用;
2)解释和编译:Java 的源代码在执行之前,必须经过编译;JavaScript 是一种解释性编程语言,其源代码不需经过编译,由浏览器解释执行;
3)强类型变量和类型弱变量:Java 采用强类型变量检查,即所有变量在编译之前必须作声明;JavaScript 中变量声明,采用其弱类型。即变量在使用前不需作声明,而是解释器在运行时检查其数据类型;
4)代码格式不一样。
27、什么时候用assert?
答:assertion(断言)在软件开发中是一种常用的调试方式,很多开发语言中都支持这种机制。一般来说,assertion 用于保证程序最基本、关键的正确性。assertion 检查通常在开发和测试时开启。为了提高性能,在软件发布后, assertion 检查通常是关闭的。在实现中,断言是一个包含布尔表达式的语句,在执行这个语句时假定该表达式为true;如果表达式计算为false,那么系统会报告一个Assertionerror。
断言用于调试目的:
assert(a > 0); // throws an Assertionerror if a <= 0
断言可以有两种形式:
assert Expression1 ;
assert Expression1 : Expression2 ;
Expression1 应该总是产生一个布尔值。
Expression2 可以是得出一个值的任意表达式;这个值用于生成显示更多调试信息的String 消息。
断言在默认情况下是禁用的,要在编译时启用断言,需使用source 1.4 标记:
javac -source 1.4 Test.java
要在运行时启用断言,可使用-enableassertions 或者-ea 标记。
要在运行时选择禁用断言,可使用-da 或者-disableassertions 标记。
要在系统类中启用断言,可使用-esa 或者-dsa 标记。还可以在包的基础上启用或者禁用断言。可以在预计正常情况下不会到达的任何位置上放置断言。断言可以用于验证传递给私有方法的参数。不过,断言不应该用于验证传递给公有方法的参数,因为不管是否启用了断言,公有方法都必须检查其参数。不过,既可以在公有方法中,也可以在非公有方法中利用断言测试后置条件。另外,断言不应该以任何方式改变程序的状态。
28、Java 中的异常处理机制的简单原理和应用?
答:当JAVA 程序违反了JAVA 的语义规则时,JAVA 虚拟机就会将发生的错误表示为一个异常。违反语义规则包括2 种情况。一种是JAVA 类库内置的语义检查。例如数组下标越界,会引发IndexOutOfBoundsException;访问null 的对象时会引发NullPointerException。另一种情况就是JAVA 允许程序员扩展这种语义检查,程序员可以创建自己的异常,并*选择在何时用throw 关键字引发异常。所有的异常都是java.lang.Thowable 的子类。
29、error 和exception 有什么区别?
答:1.Exception 和 Error 都是继承了 Throwable 类,在 Java 中只有 Throwable 类型的实例才可以被抛出(throw)或者捕获(catch),它是异常处理机制的基本组成类型。
2.Exception 和 Error 体现了 Java 平台设计者对不同异常情况的分类。Exception 是程序正常运行中,可以预料的意外情况,可能并且应该被捕获,进行相应处理。
3.Error 是指在正常情况下,不大可能出现的情况,绝大部分的 Error 都会导致程序(比如 JVM 自身)处于非正常的、不可恢复状态。既然是非正常情况,所以不便于也不需要捕获,常见的比如 OutOfMemoryError 之类,都是 Error 的子类。
4.Exception 又分为可检查(checked)异常和不检查(unchecked)异常,可检查异常在源代码里必须显式地进行捕获处理,这是编译期检查的一部分。前面我介绍的不可查的 Error,是 Throwable 不是 Exception。
5.不检查异常就是所谓的运行时异常,类似 NullPointerException、ArrayIndexOutOfBoundsException 之类,通常是可以编码避免的逻辑错误,具体根据需要来判断是否需要捕获,并不会在编译期强制要求。
30、try {}里有一个return 语句,那么紧跟在这个try 后的finally {}里的code会不会被执行,什么时候被执行,在return 前还是后?
答:会执行,在return 前执行。