【面试题】JavaSE基础常见面试题

基础部分

1.Java语言的特性?

跨平台性、面向对象、安全性、多线程、简单易用。

2.& 和 && 的区别?

&运算符表示按位与、逻辑与,而&&运算符是短路与运算。

3.String是最基本的数据类型吗?

基本数据类型包括byte、int、char、long、float、double、boolean和short。 取值范围是 -2^(字节数8-1) ~ -2^(字节数8-1) - 1,但Boolean是4个字节,而boolean数组1个字节,这是因为虚拟机用int来代替boolean,保证高效存取。而java.lang.String类是final类型的,因此不能继承也不能修改String类。String还重写了hashCode和equals方法,

4.new一个字符串“xyz”创建了几个对象?

两个或一个,new一个字符串会产生两个对象,一个在堆上,一个在常量池中,堆上的数据每new一次产生一个新的对象,如果常量池中有需要的对象,就不会创建新的对象,直接拿来用,所以一共创建了一个对象,若常量池中没有要用的对象,则会创建一个,所以一共创建了两个对象。

5.数组和String有length()方法吗?

数组没有length()这个方法,有getLength()方法,但有length的属性。String有length()方法

6.int 和 Integer 有什么区别?

int是java的原始数据类型,Integer是java为int提供的封装类。Integer实例变量的缺省值为 null,而int实例变量的缺省值与它们的类型有关。int与Integer之间可以进行自动拆装箱的转换,但Integer的取值范围是-128-127,若超过这个范围,就new一个新的对象返回(Valueof方法)

7.String 、StringBuffer和StringBuilder的区别?

  • String提供了数值不可改变的字符串。而StringBuffer和StringBuilder可以对字符串进行修改。但StringBuffer是线程安全的,而StringBuilder是非线程安全的,相比StringBuffer来说,StringBuilder的效率要高,

  • StringBuilder内部维护了一个char[]类型的value(默认长度是16),不断的append()就是不断的往char[]里填东西的过程,用System.arraycopy成倍复制扩容!

  • 可以重用StringBuilder:通过 sb.setLength(0) 方法可以把char数组的内存区域设置为0,为了避免并发访问,可以在ThreadLocal中使用StringBuilderHolder,该StringBuilder实例的内存空间一直不会被GC回收造成内存浪费。

注:SimpleDateFormat日期类是非线程安全的

8.对于short s1 = 1; s1 = s1 + 1与 s1 += 1各有什么错?

  • 对于short s1 = 1; s1 = s1 + 1;由于s1+1运算时会自动提升表达式的类型,所以结果是int型,再赋值给short类型s1时,编译器将报告需要强制转换类型的错误。

  • 对于short s1 = 1; s1 += 1;由于 +=是java语言规定的运算符,java编译器会对它进行特殊处理,因此可以正确编译。

9.==和equals方法的区别?

  • ==用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,即比较两个基本类型的数据或两个引用变量是否相等

  • equals方法是用于比较两个独立对象的内容是否相同,字符串的比较常用equals方法。

  • 如果一个类没有自己定义equals方法,那么它将继承Object类的equals方法(使用==操作符)

10.public,private,protected及default的区别?

修饰符 同类 同包 子类 其它
public
protected ×
default × ×
private × × ×

封装、继承与多态

1.重写和重载的区别

  • 方法重写
    相同方法名,相同返回值,相同参数列表,子类写了一个和父类一模一样的方法。重写方法的修饰符不能比父类方法严格,也不能是private。重写是运行时活动

  • 方法重载(overlading)
    方法名相同、参数不同(类型不同或者顺序不同)、与返回值无关。 重载是编译时活动

2.抽象类与接口的区别?

  • 抽象类表示的是一种继承关系,类是单继承。但可以实现多个接口。

  • 抽象类中可以有自己的数据成员,也可以有非抽象的成员方法,而在接口中,属性只能是public static final的,而方法只能是public abstract的。

  • 抽象类表示的是"is-a"关系,接口表示的是"like-a"关系。

  • 继承抽象类就必须实现该类的所有抽象方法,抽象类中可以有非抽象方法。而实现接口的类必须实现其中的所有方法。

  • 抽象类可以有构造方法、普通成员变量、静态方法,但接口中不能有构造方法、没有普通成员变量、不能包含静态方法

  • 抽象的方法不能同时是静态的,因为抽象方法需要重写,而静态方法不能被重写,不能实现抽象方法的同步锁,而静态方法可以。

  • 抽象类适合使用模板设计模式,如造汽车类,实现抽象方法glass,egineer,frame,非抽象方法make,在make中一次调用抽象方法,再利用多态,就实现了造多种车的场景。

  • 而接口适合使用简单工厂设计模式,如动物接口,定义吃、叫,速度方法,猫来了就实现动物接口中的方法,而不用自己写了。狗来了也是一样。

3.多态的理解

  • 多态性是指允许不同类的对象对同一消息作出响应,

  • 实现多态

  • 前期绑定:在程序执行前进行绑定。 例如: static方法 、final方法

  • 动态绑定,即在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法

  • 多态存在的三个必要条件继承、重写、父类引用指向子类对象

  • 多态的优点:可替换性、可扩充性、接口性、灵活性、简化性、消除类型之间的耦合关系

4.static关键字

  • static关键字可以修饰属性、方法、代码块,可以静态导包。也可以实现静态内部类

  • 内部类又分为普通、匿名、方法、静态内部类,而静态内部类不需要依赖外部类。

  • 匿名内部类不能定义构造函数,也不能存在任何的静态成员变量和静态方法。

  • static方法中不能调用非static的方法和属性,在静态方法中不能使用this和super关键字

  • 当先new子类,后new父类时,初始化时的顺序为:

父类的静态代码块–>子类的静态代码块–>父类的构造代码块–>父类的构造方法–>子类的构造代码块–>子类的构造方法
、、、
父类的构造代码块–>父类的构造方法

  • 静态代码块只能被实例化一次。

  • 执行顺序问题

  • 静态/非静态属性值+静态/匿名代码块:哪个在最后,哪个就是最终值

  • 静态属性值+静态代码块+匿名代码块:无论顺序如何,最终值都是匿名代码块中的值

5.值传递与引用传递

  • 值传递:
    在方法调用的时候,实参将自己的一份拷贝赋给形参,在方法内,对该参数值的修改不影响原来实参。

  • 引用传递
    在方法调用的时候,实参将自己的地址传递的形参,此时方法内对该参数值的改变,就是对该实参的实际操作。(基本类型的数组是引用传递)

  • java中都是值传递

6.hashCode()和equals方法的联系?

  • equals方法的特性:自反性、一致性、传递性、对称性、非空性。

  • 只要重写equals,就必须重写hashCode。

  • 因为Set存储的是不重复的对象,依据hashCode和equals进行判断,所以Set存储的对象必须重写这两个方法。

  • 如果自定义对象做为Map的键,那么必须重写hashCode和equals。 说明:String重写了hashCode和equals方法,所以我们可以非常愉快地使用String对象作为key来使用。

其它

1.常见的异常

  • java中的异常是Throwable,而它又派生了两个子类:Error和Exception,

  • Error表示应用程序本身无法克服和恢复的一种严重问题,例如,说内存溢出和线程死锁等系统问题。

  • Exception表示程序还能够克服和恢复的问题,其中又分为IOException和RuntimeException

  • IOException表示已受检异常,需要使用try/catch块捕获

  • RuntimeException表示运行时异常,指程序存在bug

  • 常见的运行时异常分为

  • NullPointerException

  • IllegalStateException

  • ArrayIndexOutOfBoundsException

  • ClassCastException

  • ClassNotFoundException

2.try/catch/finally语句块

若try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会被执行,因为return语句执行后,将把返回结果放置进函数栈中,此时函数并不是马上返回,它要执行finally语句后才真正开始返回。

3.泛型的理解

  • 泛型是java1.5的新特性,泛型的擦除:编译器在编译阶段去掉泛型信息,在运行的时候加上类型信息,如重载中的擦除。可使用限定类型解决,

  • PECS泛型的通配符:上界extends适用于get,频繁读取数据,而下界super适用于add,经常插入

4.常见的IO流

  • 字节流继承于InputStream 和 OutputStream,字符流继承于InputStreamReader 和 OutputStreamWriter。

  • 字节流与字符流的区别
    要把一片二进制数据数据逐一输出到某个设备中,或者从某个设备中逐一读取一片二进制数据,不管输入输出设备是什么,我们要用统一的方式来完成这些操作,用一种抽象的方式进行描述,这个抽象描述方式起名为IO流,对应的抽象类为OutputStream和InputStream,不同的实现类就代表不同的输入和输出设备,它们都是针对字节进行操作的。

  • 字符流是字节流的包装,字符流则是直接接受字符串,

5.final, finally, finalize的区别?

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

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

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

6.如何实现java序列化?

  • 需要实现序列化的几种情况

  • 把内存中的对象保存到一个文件中或者数据库中时候;

  • 用套接字在网络上传送对象的时候;

  • 通过RMI传输对象的时候;

  • 实现Serializable接口,
    该接口是一个标识性接口,标注该类对象是可被序列化的,然后使用一个输出流来构造一个对象输出流并通过writeObject(Object)方法就可以将实现对象写出(即保存其状态);如果需要反序列化则可以用一个输入流建立对象输入流,然后通过readObject方法从流中读取对象。

  • 实现接口Externalizable
    Externalizable接口继承自Serializable接口,但他们的序列化机制是完全不同的,使用Serializable的所有方式,在反序列化是不会调用任何的序列化对象构造器,而使用Externalizable是会调用一个无参构造方法的,

  • 最好指定一个序列化ID,当某个字段被声明为transient后,默认序列化机制就会忽略该字段

  • 当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化

7.反射的常用方法?

  • 使用Class.forName(“类名”)方法获取类

  • 方法

  • getDeclaredConstructors(),获取类声明的所有构造方法,

  • getFields():获得类的所有公共字段

  • getDeclaredMethods():获得类声明的所有方法

  • 直接对 private 的属性赋值:field.setAccessible(true),然后调用set方法设置值。

  • 动态代理类:为其他对象提供一种代理以控制对这个对象的访问,它不会替你作实质性的工作,在生成它的实例时你必须继承InvocationHandler类并重写invoke方法,由它来完成代理的具体操作

8.深拷贝与浅拷贝

  • 深拷贝和浅拷贝都是对象拷贝

  • 浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象。浅拷贝在重写的clone()中,只是拷贝了主对象。

  • 深拷贝把要复制的对象所引用的对象都复制了一遍。
    而深拷贝在重写的clone()中,不仅拷贝了主对象,还拷贝了主对象引用的所有对象。

9.创建对象有几种方式?

创建对象的5种方式

  • 用new语句创建对象,这是最常见的创建对象的方法。
  • 调用java.lang.Class类的newInstance()实例方法。
  • 调用java.lang.reflect.Constructor类的newInstance()实例方法。
  • 调用对象的clone()方法。
  • 通过I/O流(包括反序列化)

注:前三种会调用构造函数,而后两种不会调用构造函数

10.Java中final类有哪些?

  • String
  • Math(long包)
  • Scanner(util包)
  • URL(net包)
  • Parameter(reflect包)
  • Year(time包)

11.JDK7、JDK8、JDK9的新特性

  • JDK7的Switch语句支持string类型 ,在一个语句块中捕获多种异常;支持动态语言;
    支持try-with-resources;引入Java NIO.2开发包;null值的自动处理。
  • JDK8支持lambda表达式,常用来替代匿名内部类,用Metaspace代替PermGen,函数式接口。
  • JDK9提供了JShell工具、模块化、多版本兼容、钻石操作符的升级{}、支持HTTP2.0和websocket协议、String底层存储结构char[]更换为byte[]。

本人才疏学浅,若有错,请指出,谢谢!
如果你有更好的建议,可以留言我们一起讨论,共同进步!
衷心的感谢您能耐心的读完本篇博文!

你可能感兴趣的:(面试)