Java 面试题之基础篇

1. ".java" 源文件中可以包含多少个类?有什么限制?

  • 可以包含多个类,但只能包含一个public类,并且public类名必须与文件名相同。通常一个文件里只包含一个类。

2. switch语句能否作用在byte上,能否作用在long类型上,能否作用域String上?

  • switch(e),其中e必须是int型或 enum型,由于short、char或者byte会自动转为int的,所以,这些类型以及这些类型的包装类型也是可以的。显然,long类型是不可以的,String在jdk1.7之前不支持,在此之后是支持的。

3.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编译器会对它进行特殊处理,因此可以正确编译。

4.char类型变量占几个字节?

  • char型变量是用来存储Unicode编码的字符,占用两个字节。

5.使用final关键字修饰一个变量时,是引用不能变还是引用的对象不能变?

  • 使用final关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的。例如,对于如下语句:final StringBuffer sb = new StringBuffer("test");
    sb = new StringBuffer(""); // 错误
    sb.append("hello "); //正确

6.静态变量和实例变量的区别?

  • 在语言定义上的区别:静态变量前要加static关键字,而实例变量前则不加

  • 在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,实例变量才会被分配空间,才能使用这个实例变量。静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建如何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。

  • 例如,对于下面的程序,无论创建多少个实例对象,永远都只分配一个staticVar变量,并且每创建一个实例对象,这个staticVar就会加1;但是,每创建一个实例对象,就会分配一个instanceVar,即可能分配多个instanceVar,并且每个instanceVar的值都只自加了1次。

public class Test{
 public static int staticVar = 0;
 public int instanceVar = 0;
 public void Add(){
   staticVar++;
   instanceVar++;
   System.out.println("static var=" + staticVar + "instance Var=" + instanceVar);
 }
}

7.是否可以从一个static方法内部发出对非static方法的调用?

  • 不可以。因为非static方法是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调用,而static方法调用时不需要创建对象,可以直接调用。也就是说,当一个static方法被调用时,可能还没有创建任何实例对象,如果从一个static方法中发出对非static方法的调用,那个非static方法是关联到哪个对象上的呢?这个逻辑无法成立,所以,一个static方法内部发出对非static方法的调用。

8.Integer和int的区别?

  • int是java提供的8种原始数据类型之一。Java为每个原始类型提供了封装类,Integer是java为int提供的封装类。int的默认值为0,而Integer的默认值为null,即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况。

9.接口是否可继承接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concreteclass)?抽象类中是否可以有静态的main方法?

  • 接口可以继承接口。抽象类可以实现(implements)接口,抽象类可以继承具体类。抽象类中可以有静态的main方法。

10.Java中实现多态的机制是什么?

  • 靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象,而程序调用的方法在运行期才动态绑定,就是引用变量所指向的具体实例对象的方法,也就是内存里正在运行的那个对象的方法,而不是引用变量的类型中定义的方法。

11.抽象类和接口有什么区别?

  • 抽象类可以有构造方法,接口中不能有构造方法。

  • 抽象类中可以有普通成员变量,接口中没有普通成员变量

  • 抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。

  • 抽象类中的抽象方法的访问类型可以是public,protected和默认类型,但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。

  • 抽象类中可以包含静态方法,接口中不能包含静态方法

  • 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是publicstatic final类型,并且默认即为publicstatic final类型。

  • 一个类可以实现多个接口,但只能继承一个抽象类。

12.内部类可以引用它的包含类的成员吗?有没有什么限制?

  • 完全可以。如果不是静态内部类,则没有什么限制。

  • 如果你把静态嵌套类当作内部类的一种特例,那在这种情况下不可以访问外部类的普通成员变量,而只能访问外部类中的静态成员,例如,下面的代码:

class Outer{
 static int x;
 static class Inner{
   void test()
   {
     System.out.println(x);
   }
 }
} 

13.String s = new String("xyz");创建了几个StringObject?是否可以继承String类?

  • 两个或者一个,”xyz”作为一个常量对象,这个对象会放在字符串常量缓冲区,常量”xyz”不管出现多少遍,在常量缓冲区中的只存在一个。new String("xyz")时,如果常量缓冲区不存在该对象,则需先在常量缓冲区创建一个新的对象,然后在使用该常量缓冲区对象内容来创建一个新String对象,因此会创建两个对象,如果常量缓冲区以存在该对象("xyz"),则只会创建一个对象。

  • String类是不能继承的,因为String默认final修饰,是不可继承的。

14.下面这条语句一共创建了多少个对象:String s="a"+"b"+"c"+"d";

  • 对于下面代码:

String s1 = "a";
String s2 = s1 + "b";
String s3 = "a" + "b";
System.out.println(s2 == "ab");
System.out.println(s3 == "ab");
  • 对于第一条打印结果为false;第二条语句打印结果为true。这说明编译器可以对字符串常量直接相加的表达式进行优化,不必要等到运行期再去进行加法运算处理,而是在编译时去掉其中的加号,直接将其编译成一个这些常量相连的结果。

  • 题目中的第一行代码被编译器在编译时优化后,相当于直接定义了一个"abcd"的字符串,所以,上面的代码应该只创建了一个String对象。看如下代码:

String s = "a" + "b" + "c" + "d"
System.out.println(s == "abcd");  //true

15.try {}里有一个return语句,那么紧跟在这个try后的finally{}里的code会不会被执行,什么时候被执行,在return前还是后?

  • 我们知道finally{}里的语句是一定会执行的,那么这个是return之前还是return之后呢?看下面的代码:

public class Test{
 public static void main(String[] args){
   System.out.println(new Test().test());
 }

 int test(){
   int x = 1;
   try{
     return x;
   }finally{
     ++x;
   }
 }
}
  • 运行的结果是1,说明return语句已经执行了再去执行finally语句,不过并没有直接返回,而是将返回结果保存下来,然后去finally语句里执行。

16.final, finally, finalize的区别?

  • final用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。内部类要访问局部变量,局部变量必须定义成final类型。

  • finally是异常处理语句结构的一部分,表示总是执行。

  • finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。但是JVM不保证此方法总被调用。

17.运行时异常与一般异常有何异同?

  • 异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。

18. error和exception有申请区别?

  • error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。exception表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况。

19. Java 中堆和栈有什么区别?

  • JVM 中堆和栈属于不同的内存区域,使用目的也不同。栈常用于保存方法帧和局部变量,而对象总是在堆上分配。栈通常都比堆小,也不会在多个线程之间共享,而堆被整个 JVM 的所有线程共享。

  • 栈:在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java 会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用。

  • 堆:堆内存用来存放由 new 创建的对象和数组,在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或者对象之后,还可以在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或者对象,引用变量就相当于是为数组或者对象起的一个名称。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿里巴巴P8技术专家

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值