2021-03-02-Java面试题

前言

最新更新日期:2021-02-26
从2021-02-18日开始,收集面试题,坚持每日更新5条,加油!!!

面试题

  • JDK 和 JRE 有什么区别?

    JDK:Java Development Kit 的简称,Java 开发工具包,提供了 Java 的开发环境和运行环境。
    JRE:Java Runtime Environment 的简称,Java 运行环境,为 Java 的运行提供了所需环境。

    具体来说 JDK 其实包含了 JRE,同时还包含了编译 Java 源码的编译器 Javac,还包含了很多 Java 程序调试和分析的工具。简单来说:如果你需要运行 Java 程序,只需安装 JRE 就可以了,如果你需要编写 Java 程序,需要安装 JDK。

  • ==和equals的区别

    ==解读
    对于基本类型和引用类型 == 的作用效果是不同的,如下所示:
    基本类型:比较的是值是否相同;
    引用类型:比较的是引用是否相同;
    equals 解读
    equals :比较的是值是否相同;

  • final 在 Java 中有什么作用?

    final 修饰的类叫最终类,该类不能被继承。
    final 修饰的方法不能被重写。
    final 修饰的变量叫常量,常量必须初始化,初始化之后值就不能被修改。

  • Java 中的 Math. round(-1. 5) 等于多少?

    等于 -1,因为在数轴上取值时,中间值(0.5)向右取整,所以正 0.5 是往上取整,负 0.5 是直接舍弃。

  • Java 中操作字符串都有哪些类?它们之间有什么区别?

    操作字符串的类有:String、StringBuffer、StringBuilder。

    String 和 StringBuffer、StringBuilder 的区别在于 String 声明的是不可变的对象,每次操作都会生成新的 String 对象,然后将指针指向新的 String 对象,而 StringBuffer、StringBuilder 可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用 String。

    StringBuffer 和 StringBuilder 最大的区别在于,StringBuffer 是线程安全的,而 StringBuilder 是非线程安全的,但 StringBuilder 的性能却高于 StringBuffer,所以在单线程环境下推荐使用 StringBuilder,多线程环境下推荐使用 StringBuffer。

  • 重载和重写的区别

    重载:发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同,发生在编译时。

    重写:发生在父子类中,方法名、参数列表必须相同,返回值小于等于父类,抛出的异常小于等于父类,访问修饰符大于等于父类;如果父类方法访问修饰符为private则子类中就不是重写。

  • 自动装箱与拆箱

    装箱:将基本类型用它们对应的引用类型包装起来;
    拆箱:将包装类型转换为基本数据类型;
    Java使用自动装箱和拆箱机制,节省了常用数值的内存开销和创建对象的开销,提高了效率,由编译器来完成,编译器会在编译期根据语法决定是否进行装箱和拆箱动作。

  • 构造方法有哪些特性?

    1,名字与类名相同;2,没有返回值,但不能用void声明构造函数;3,生成类的对象时自动执行,无需调用。

  • 静态方法和实例方法有何不同?

    静态方法和实例方法的区别主要体现在两个方面:

    在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。

    静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制

  • 创建线程有几种不同的方式?你喜欢哪一种?为什么?

     1.继承Thread类
     2.实现Runnable接口
     3.应用程序可以使用Executor框架来创建线程池
     4.实现Callable接口
     我更喜欢实现Runnable接口这种方法,当然这也是现在大多程序员会选用的方法。因为一个类只能继承一个父类而可以实现多个接口。同时,线程池也是非常高效的,很容易实现和使用。
    
  • switch 是否能作用在byte 上,是否能作用在long 上,是否能作用在String上?

    在Java 5以前,switch(expr)中,expr只能是byte、short、char、int。从Java 5开始,Java中引入了枚举类型,expr也可以是enum类型,从Java 7开始,expr还可以是字符串(String),但是长整型(long)在目前所有的版本中都是不可以的。

  • 构造器(constructor)是否可被重写(override)?

    构造器不能被继承,因此不能被重写,但可以被重载。

  • 是否可以继承String类?

    String 类是final类,不可以被继承。

  • char 型变量中能不能存贮一个中文汉字,为什么?

    char类型可以存储一个中文汉字,因为Java中使用的编码是Unicode(不选择任何特定的编码,直接使用字符在字符集中的编号,这是统一的唯一方法),一个char类型占2个字节(16比特),所以放一个中文是没问题的。

  • 阐述静态变量和实例变量的区别。

    静态变量是被static修饰符修饰的变量,也称为类变量,它属于类,不属于类的任何一个对象,一个类不管创建多少个对象,静态变量在内存中有且仅有一个拷贝;实例变量必须依存于某一实例,需要先创建对象然后通过对象才能访问到它。静态变量可以实现让多个对象共享内存。

  • 抽象类必须要有抽象方法吗?
    不需要,抽象类不一定非要有抽象方法。
    下面代码,抽象类并没有抽象方法但完全可以正常运行。
    示例代码:

abstract class Cat {
    public static void sayHi() {
        System. out. println("hi~");
    }
}
  • 普通类和抽象类有哪些区别?

    普通类不能包含抽象方法,抽象类可以包含抽象方法。
    抽象类不能直接实例化,普通类可以直接实例化。

  • 抽象类能使用 final 修饰吗?
    不能,定义抽象类就是让其他类继承的,如果定义为 final 该类就不能被继承,这样彼此就会产生矛盾,所以 final 不能修饰抽象类,如下图所示,编辑器也会提示错误信息:
    在这里插入图片描述

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

    实现:抽象类的子类使用 extends 来继承;接口必须使用 implements 来实现接口。
    构造函数:抽象类可以有构造函数;接口不能有。
    实现数量:类可以实现很多个接口;但是只能继承一个抽象类。
    访问修饰符:接口中的方法默认使用 public 修饰;抽象类中的方法可以是任意访问修饰符。

  • Java 中 IO 流分为几种?

    按功能来分:输入流(input)、输出流(output)。

    按类型来分:字节流和字符流。

    字节流和字符流的区别是:字节流按 8 位传输以字节为单位输入输出数据,字符流按 16 位传输以字符为单位输入输出数据,1个字符相当于2个字节

  • 访问修饰符public,private,protected,以及不写(默认)时的区别?

    类的成员不写访问修饰时默认为default。默认对于同一个包中的其他类相当于公开(public),对于不是同一个包中的其他类相当于私有(private)。受保护(protected)对子类相当于公开,对不是同一包中的没有父子关系的类相当于私有。Java中,外部类的修饰符只能是public或默认,类的成员(包括内部类)的修饰符可以是以上四种。

修饰符 当前类 同 包 子 类 其他包
public
protected ×
default × ×
private × × ×
  • float f=3.4;是否正确?
    不正确。3.4是双精度数,将双精度型(double)赋值给浮点型(float)属于下转型(down-casting,也称为窄化)会造成精度损失,因此需要强制类型转换float f =(float)3.4; 或者写成float f =3.4F;。

  • short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗?
    对于short s1 = 1; s1 = s1 + 1;由于1是int类型,因此s1+1运算结果也是int 型,需要强制转换类型才能赋值给short型。而short s1 = 1; s1 += 1;可以正确编译,因为s1+= 1;相当于s1 = (short)(s1 + 1);其中有隐含的强制类型转换。

  • &和&&的区别?
    &两边的条件都要判断(不管前面的是ture还是false)。
    &&先判断前面的,若为false,则后面的不再判断,若为true,则继续判断。

  • 接口是否可继承(extends)接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concrete class)?
    接口可以继承接口,而且支持多重继承。抽象类可以实现(implements)接口,抽象类可继承具体类也可以继承抽象类。

  • ArrayList 和 LinkedList 有什么区别
    ArrayList和LinkedList都实现了List接口,有以下的不同点:
    1、ArrayList是基于索引的数据接口,它的底层是数组。它可以以O(1)时间复杂度对元素进行随机访问。与此对应,LinkedList是以元素列表的形式存储它的数据,每一个元素都和它的前一个和后一个元素链接在一起,在这种情况下,查找某个元素的时间复杂度是O(n)。
    2、相对于ArrayList,LinkedList的插入,添加,删除操作速度更快,因为当元素被添加到集合任意位置的时候,不需要像数组那样重新计算大小或者是更新索引。
    3、LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素。

  • 讲讲你理解的 nio和 bio 的区别是啥
    IO(BIO)是面向流的,NIO是面向缓冲区的
    BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。
    NIO:New IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。
    AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。

  • 单例模式实现
    懒汉模式:很懒,用的时候才创建

public class Singleton {
    private static Singleton instance;
    private Singleton (){}

    public static synchronized Singleton getInstance() {
	if (instance == null) {
	    instance = new Singleton();
	}
	return instance;
    }
}

饿汉模式:很饿,一开始就迫不及待的创建了

public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){}  
    public static Singleton getInstance() {  
    return instance;  
    }  
}
  • Array 和 ArrayList 有何区别?
    Array可以容纳基本类型和对象,而ArrayList只能容纳对象。
    Array是指定大小的,而ArrayList初始大小是固定的。
    Array没有提供ArrayList那么多功能,比如addAll、removeAll和iterator等。

  • springMVC的执行流程
    springMVC是由dispatchservlet为核心的分层控制框架。首先客户端发出一个请求,web服务器解析请求url并去匹配dispatchservlet的映射url,如果匹配上就将这个请求放入到dispatchservlet,dispatchservlet根据mapping映射配置去寻找相对应的handel,然后把处理权交给找到的handel,handel封装了处理业务逻辑的代码,当handel处理完后会返回一个逻辑视图modelandview给dispatchservlet,此时的modelandview是一个逻辑视图不是一个正式视图,所以dispatchservlet会通过viewresource视图资源去解析modelandview,然后将解析后的参数放到view中返回到客户端并展现。

  • Java 中,Comparator 与Comparable 有什么不同?
    Comparable 接口用于定义对象的自然顺序,是排序接口,而 comparator 通常用于定义用户定制的顺序,是比较接口。我们如果需要控制某个类的次序,而该类本身不支持排序(即没有实现Comparable接口),那么我们就可以建立一个“该类的比较器”来进行排序。Comparable 总是只有一个,但是可以有多个 comparator 来定义对象的顺序。

  • object中定义了哪些方法?

    clone(), equals(), hashCode(), toString(), notify(), notifyAll(),

    wait(), finalize(), getClass()

  • Collection与Collections的区别是什么?

    Collection是Java集合框架中的基本接口;

    Collections是Java集合框架提供的一个工具类,其中包含了大量用于操作或返回集合的静态方法。

  • 常用数据结构:
    集合,线性结构(数组,队列,链表和栈),树形结构,图状结构

  • JVM分为哪些区,每一个区干吗的?
    1)方法区(method):被所有的线程共享。方法区包含所有的类信息和静态变量。

    2)堆(heap):被所有的线程共享,存放对象实例以及数组,Java堆是GC的主要区域。

    3)栈(stack):每个线程包含一个栈区,栈中保存一些局部变量等。

    4)程序计数器:是当前线程执行的字节码的行指示器。

  • 谈谈你对ajax的认识?

    Ajax是一种创建交互式网页应用的的网页开发技术;AsynchronousJavaScriptandXML的缩写。
    Ajax的优势:通过异步模式,提升了用户体验。优化了浏览器和服务器之间的传输,减少不必要的数据往返,减少了带宽占用。Ajax引擎在客户端运行,承担了一部分本来由服务器承担的工作,从而减少了大用户量下的服务器负载。
    Ajax的最大特点:可以实现局部刷新,在不更新整个页面的前提下维护数据,提升用户体验度。

  • 两个对象值相同equals结果为true,但却可有不同的 hashCode,这句话对不对?

    不对,如果两个对象x和y满足x.equals(y) == true,它们的哈希值(hashCode)应当相同。Java 对于equals方法和hashCode方法是这样规定的:

    (1)如果两个对象相同(equals方法返回true),那么它们的hashCode值一定要相同;

    (2)如果两个对象的 hashCode相同,它们并不一定相同。当然,你未必按照要求去做,但是如果你违背了上述原则就会发现在使用集合时,相同的对象可以出现在Set 集合中,同时增加新元素的效率会大大降低(对于使用哈希存储的系统,如果哈希码频繁的冲突将会造成存取性能急剧下降)。

  • 在 Java 中,如何跳出当前的多重嵌套循环?
    在最外层循环前加一个标记如outfor,然后用break outfor;可以跳出多重循环。例如以下代码:
    在这里插入图片描述
    运行结果如下所示:
    j = 0
    j = 1
    j = 2
    j = 3
    j = 4

  • 当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里是值传递还是引用传递?

    是值传递。Java 语言的方法调用只支持参数的值传递。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的内存地址。这个值(内存地址)被传递后,同一个内存地址指向堆内存当中的同一个对象,所以通过哪个引用去操作这个对象,对象的属性都是改变的。

  • 抽象的(abstract)方法是否可同时是静态的(static), 是否可同时是本地方法(native),是否可同时被 synchronized?

    都不能。
    抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。
    本地方法是由本地代码(如 C++ 代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。
    synchronized 和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。

  • Java中为什么要用 clone?

    在实际编程过程中,我们常常要遇到这种情况:有一个对象 A,在某一时刻 A 中已经包含了一些有效值,此时可能会需要一个和 A 完全相同新对象 B,并且此后对 B 任何改动都不会影响到 A 中的值,也就是说,A 与 B 是两个独立的对象,但 B 的初始值是由 A 对象确定的。在 Java 语言中,用简单的赋值语句是不能满足这种需求的。要满足这种需求虽然有很多途径,但clone()方法是其中最简单,也是最高效的手段。

  • 谈谈你对多态的理解?

    多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源代码,就可以让引用变量绑定到各种不同的对象上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。
    通俗版:一个接口会有多个实现类,不同的实现类的内容不一样,这就是多态,相当于一个接口有多种实现状态的意思

  • 面向对象的三大特性:封装、多态和继承:

    (1)封装(对应可扩展性):隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别。封装是通过访问控制符(public protected private)来实现。一个类就可看成一个封装。

    (2)继承(重用性和扩展性):子类继承父类,可以继承父类的方法和属性。可以对父类方向进行覆盖(实现了多态)。但是继承破坏了封装,因为他是对子类开放的,修改父类会导致所有子类的改变,因此继承一定程度上又破坏了系统的可扩展性,只有明确的IS-A关系才能使用。继承要慎用,尽量优先使用组合。

    (3)多态(可维护性和可扩展性):接口的不同实现方式即为多态。接口是对行为的抽象,刚才在封装提到,找到变化部分并封装起来,但是封装起来后,怎么适应接下来的变化?这正是接口的作用,接口的主要目的是为不相关的类提供通用的处理服务,我们可以想象一下。比如鸟会飞,但是超人也会飞,通过飞这个接口,我们可以让鸟和超人,都实现这个接口。

    面向对象编程(OOP)其实就是一种设计思想,在程序设计过程中把每一部分都尽量当成一个对象来考虑,以实现软件系统的可扩展性,可维护性和可重用性。

  • error和exception的区别?
    Error类和Exception类的父类都是Throwable类,他们的区别如下:

    Error类一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢出等。对于这类错误的导致的应用程序中断,仅靠程序本身无法恢复和预防,遇到这样的错误,建议让程序终止。

    Exception类表示程序可以处理的异常,可以捕获且可能恢复。遇到这类异常,应该尽可能处理异常,使程序恢复运行,而不应该随意终止异常。

    Exception类又分为未检查异常(UnCheckedException)和受检查的异常(CheckedException)。运行时异常ArithmeticException,IllegalArgumentException编译能通过,但是一运行就终止了,程序不会处理运行时异常,出现这类异常,程序会终止。而受检查的异常,要么用 try…catch 捕获,要么用throws字句声明抛出,交给它的父类处理,否则编译不会通过。

  • 调用下面的方法,得到的返回值是什么?
    在这里插入图片描述
    代码走到第3行的时候遇到了一个MathException,这时第4行的代码就不会执行了,代码直接跳转到catch语句中,走到第 6 行的时候,异常机制有一个原则:如果在catch中遇到了return或者异常等能使该函数终止的话那么有finally就必须先执行完finally代码块里面的代码然后再返回值。因此代码又跳到第8行,可惜第8行是一个return语句,那么这个时候方法就结束了,因此第6行的返回结果就无法被真正返回。如果finally仅仅是处理了一个释放资源的操作,那么该道题最终返回的结果就是2。因此上面返回值是3。

  • 说出最常见的5个RuntimeException?
    java.lang.NullPointerException 空指针异常;出现原因:调用了未经初始化的对象或者是不存在的对象。

    java.lang.ClassNotFoundException 指定的类找不到;出现原因:类的名称和路径加载错误;通常都是程序试图通过字符串来加载某个类时可能引发异常。

    java.lang.NumberFormatException 字符串转换为数字异常;出现原因:字符型数据中包含非数字型字符。

    java.lang.IndexOutOfBoundsException 数组角标越界异常,常见于操作数组对象时发生。

    java.lang.IllegalArgumentException 方法传递参数错误。

    java.lang.ClassCastException 数据类型转换异常。

    java.lang.NoClassDefFoundException 未找到类定义错误。

    SQLException SQL 异常,常见于操作数据库时的 SQL 语句错误。

    java.lang.InstantiationException 实例化异常。

    java.lang.NoSuchMethodException 方法不存在异常。

  • throw 和 throws 的区别?
    throw:
    throw 语句用在方法体内,表示抛出异常,由方法体内的语句处理。
    throw是具体向外抛出异常的动作,所以它抛出的是一个异常实例,执行throw一定是抛出了某种异常。
    throws:
    throws语句是用在方法声明后面,表示如果抛出异常,由该方法的调用者来进行异常的处理。
    throws主要是声明这个方法会抛出某种类型的异常,让它的使用者要知道需要捕获的异常的类型。
    throws表示出现异常的一种可能性,并不一定会发生这种异常。

  • Java 的基本数据类型都有哪些各占几个字节?
    按照口诀记忆:

    数据类型:byte short int long float double boolean char

    占用字节数:12484812(byte对应1,short对应2,以此类推)

  • 字节流如何转为字符流?
    字节输入流转字符输入流通过 InputStreamReader 实现,该类的构造函数可以传入 InputStream 对象。

    字节输出流转字符输出流通过 OutputStreamWriter 实现,该类的构造函数可以传入 OutputStream 对象。

  • 如何将一个 java 对象序列化到文件里?
    在 java 中能够被序列化的类必须先实现 Serializable 接口,该接口没有任何抽象方法只是起到一个标记作用。

public class Test {
    public static void main(String[] args) throws Exception {
        //对象输出流
        ObjectOutputStream objectOutputStream =
                new ObjectOutputStream(new FileOutputStream(new File("D://obj")));
        objectOutputStream.writeObject(new User("zhangsan", 100));
        objectOutputStream.close();
        //对象输入流
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(new File("D://obj")));
        User user = (User) objectInputStream.readObject();
        System.out.println(user);
        objectInputStream.close();
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41270550/article/details/113842086