2021年最新Java面试题及答案整理 --- 基础篇(二)

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

咱们知道finally{}中的语句是必定会执行的,那么这个可能正常脱口而出就是return以前,return以后可能就出了这个方法了,鬼知道跑哪里去了,但更准确的应该是在return中间执行,请看下面程序代码的运行结果:java

public classTest {
    public static void main(String[]args) {
       System.out.println(newTest().test());;
    }
    static int test()
    {
       intx = 1;
       try
       {
          return x;
       }
       finally
       {
          ++x;
       }
    }
}

执行结果以下:mysql

1

运行结果是1,为何呢?主函数调用子函数并获得结果的过程,比如主函数准备一个空罐子,当子函数要返回结果时,先把结果放在罐子里,而后再将程序逻辑返回到主函数。所谓返回,就是子函数说,我不运行了,你主函数继续运行吧,这没什么结果可言,结果是在说这话以前放进罐子里的。面试

22. 运行时异常与通常异常有何异同?

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

24W字Java面试手册下载地址: https://shimo.im/docs/Wyj8QRp...
24W字Java面试手册下载地址: https://shimo.im/docs/Wyj8QRp...
24W字Java面试手册下载地址: https://shimo.im/docs/Wyj8QRp...

23. error和exception有什么区别?

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

24. 简单说说Java中的异常处理机制的简单原理和应用。

异常是指java程序运行时(非编译)所发生的非正常状况或错误,与现实生活中的事件很类似,现实生活中的事件能够包含事件发生的时间、地点、人物、情节等信息,能够用一个对象来表示,Java使用面向对象的方式来处理异常,它把程序中发生的每一个异常也都分别封装到一个对象来表示的,该对象中包含有异常的信息。编程

Java对异常进行了分类,不一样类型的异常分别用不一样的Java类表示,全部异常的根类为java.lang.Throwable。数组

Throwable下面又派生了两个子类:缓存

  • Error和Exception,Error表示应用程序自己没法克服和恢复的一种严重问题,程序只有奔溃了,例如,说内存溢出和线程死锁等系统问题。
  • Exception表示程序还可以克服和恢复的问题,其中又分为系统异常和普通异常:

系统异常是软件自己缺陷所致使的问题,也就是软件开发人员考虑不周所致使的问题,软件使用者没法克服和恢复这种问题,但在这种问题下还可让软件系统继续运行或者让软件挂掉,例如,数组脚本越界(ArrayIndexOutOfBoundsException),空指针异常(NullPointerException)、类转换异常(ClassCastException);安全

普通异常是运行环境的变化或异常所致使的问题,是用户可以克服的问题,例如,网络断线,硬盘空间不够,发生这样的异常后,程序不该该死掉。服务器

java为系统异常和普通异常提供了不一样的解决方案,编译器强制普通异常必须try..catch处理或用throws声明继续抛给上层调用方法处理,因此普通异常也称为checked异常,而系统异常能够处理也能够不处理,因此,编译器不强制用try..catch处理或用throws声明,因此系统异常也称为unchecked异常。

25. == 和 equals 的区别是什么?

"=="

对于基本类型和引用类型 == 的做用效果是不一样的,以下所示:

  • 基本类型:比较的是值是否相同;
  • 引用类型:比较的是引用是否相同;
String x = "string";
String y = "string";
String z = new String("string");
System.out.println(x==y); // true
System.out.println(x==z); // false
System.out.println(x.equals(y)); // true
System.out.println(x.equals(z)); // true
由于 x 和 y 指向的是同一个引用,因此 == 也是 true,而 new String()方法则重写开辟了内存空间,因此 == 结果为 false,而 equals 比较的一直是值,因此结果都为 true。

equals

equals 本质上就是 ==,只不过 String 和 Integer 等重写了 equals 方法,把它变成了值比较。看下面的代码就明白了。

首先来看默认状况下 equals 比较一个有相同值的对象,代码以下:

class Cat {
    public Cat(String name) {
        this.name = name;
    }

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Cat c1 = new Cat("叶痕秋");
Cat c2 = new Cat("叶痕秋");
System.out.println(c1.equals(c2)); // false

输出结果出乎咱们的意料,居然是 false?这是怎么回事,看了 equals 源码就知道了,源码以下:

public boolean equals(Object obj) {
        return (this == obj);
}

原来 equals 本质上就是 ==。

那问题来了,两个相同值的 String 对象,为何返回的是 true?代码以下:

String s1 = new String("叶子");
String s2 = new String("叶子");
System.out.println(s1.equals(s2)); // true

一样的,当咱们进入 String 的 equals 方法,找到了答案,代码以下:

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

原来是 String 重写了 Object 的 equals 方法,把引用比较改为了值比较。

总结

== 对于基本类型来讲是值比较,对于引用类型来讲是比较的是引用;而 equals 默认状况下是引用比较,只是不少类从新了 equals 方法,好比 String、Integer 等把它变成了值比较,因此通常状况下 equals 比较的是值是否相等。

26. Hashcode的做用

java的集合有两类,一类是List,还有一类是Set。前者有序可重复,后者无序不重复。当咱们在set中插入的时候怎么判断是否已经存在该元素呢,能够经过equals方法。可是若是元素太多,用这样的方法就会比较满。

因而有人发明了哈希算法来提升集合中查找元素的效率。 这种方式将集合分红若干个存储区域,每一个对象能够计算出一个哈希码,能够将哈希码分组,每组分别对应某个存储区域,根据一个对象的哈希码就能够肯定该对象应该存储的那个区域。

hashCode方法能够这样理解:它返回的就是根据对象的内存地址换算出的一个值。这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一会儿能定位到它应该放置的物理位置上。若是这个位置上没有元素,它就能够直接存储在这个位置上,不用再进行任何比较了;若是这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。这样一来实际调用equals方法的次数就大大下降了,几乎只须要一两次。

24W字Java面试手册下载地址: https://shimo.im/docs/Wyj8QRp...
24W字Java面试手册下载地址: https://shimo.im/docs/Wyj8QRp...
24W字Java面试手册下载地址: https://shimo.im/docs/Wyj8QRp...

27. 两个对象的 hashCode() 相同, 那么 equals() 也必定为 true吗?

不对,两个对象的 hashCode() 相同,equals() 不必定 true。

代码示例:

String str1 = "keep";
String str2 = "brother";
System. out. println(String. format("str1:%d | str2:%d",  str1. hashCode(),str2. hashCode()));
System. out. println(str1. equals(str2));

执行结果:

str1:1179395 | str2:1179395

false

代码解读:很显然“keep”和“brother”的 hashCode() 相同,然而 equals() 则为 false,由于在散列表中,hashCode() 相等即两个键值对的哈希值相等,然而哈希值相等,并不必定能得出键值对相等。

28. 泛型经常使用特色

泛型是Java SE 1.5以后的特性, 《Java 核心技术》中对泛型的定义是:

“泛型” 意味着编写的代码能够被不一样类型的对象所重用。

“泛型”,顾名思义,“泛指的类型”。咱们提供了泛指的概念,但具体执行的时候却能够有具体的规则来约束,好比咱们用的很是多的ArrayList就是个泛型类,ArrayList做为集合能够存放各类元素,如Integer, String,自定义的各类类型等,但在咱们使用的时候经过具体的规则来约束,如咱们能够约束集合中只存放Integer类型的元素,如

List<Integer> iniData = new ArrayList<>()

使用泛型的好处?

以集合来举例,使用泛型的好处是咱们没必要由于添加元素类型的不一样而定义不一样类型的集合,如整型集合类,浮点型集合类,字符串集合类,咱们能够定义一个集合来存放整型、浮点型,字符串型数据,而这并非最重要的,由于咱们只要把底层存储设置了Object便可,添加的数据所有均可向上转型为Object。 更重要的是咱们能够经过规则按照本身的想法控制存储的数据类型。

29. 面向对象的特征

面向对象的编程语言有封装、继承 、抽象、多态等4个主要的特征。

  1. 封装: 把描述一个对象的属性和行为的代码封装在一个模块中,也就是一个类中,属性用变量定义,行为用方法进行定义,方法能够直接访问同一个对象中的属性。
  2. 抽象: 把现实生活中的对象抽象为类。分为过程抽象和数据抽象
  • 数据抽象 -->鸟有翅膀,羽毛等(类的属性)
  • 过程抽象 -->鸟会飞,会叫(类的方法)
  1. 继承:子类继承父类的特征和行为。子类能够有父类的方法,属性(非private)。子类也能够对父类进行扩展,也能够重写父类的方法。缺点就是提升代码之间的耦合性。
  2. 多态: 多态是指程序中定义的引用变量所指向的具体类型和经过该引用变量发出的方法调用在编程时并不肯定,而是在程序运行期间才肯定(好比:向上转型,只有运行才能肯定其对象属性)。方法覆盖和重载体现了多态性。

30. Java多态的理解

  1. 多态是继封装、继承以后,面向对象的第三大特性。
  2. 多态现实意义理解:
  • 现实事物常常会体现出多种形态,如学生,学生是人的一种,则一个具体的同窗张三既是学生也是人,即出现两种形态。
  • Java做为面向对象的语言,一样能够描述一个事物的多种形态。如Student类继承了Person类,一个Student的对象便既是Student,又是Person。
  1. 多态体现为父类引用变量能够指向子类对象。
  2. 前提条件:必须有子父类关系。

注意:在使用多态后的父类引用变量调用方法时,会调用子类重写后的方法。

  1. 多态的定义与使用格式

定义格式:父类类型 变量名=new 子类类型();

31. 重载和重写的区别

重写(Override)

从字面上看,重写就是 从新写一遍的意思。其实就是在子类中把父类自己有的方法从新写一遍。子类继承了父类原有的方法,但有时子类并不想原封不动的继承父类中的某个方法,因此在方法名,参数列表,返回类型(除过子类中方法的返回值是父类中方法返回值的子类时)都相同的状况下, 对方法体进行修改或重写,这就是重写。但要注意子类函数的访问修饰权限不能少于父类的。

public class Father {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Son s = new Son();
        s.sayHello();
    }

    public void sayHello() {
        System.out.println("Hello");
    }
}

class Son extends Father{

    @Override
    public void sayHello() {
        // TODO Auto-generated method stub
        System.out.println("hello by ");
    }
}

重写 总结:

1.发生在父类与子类之间

2.方法名,参数列表,返回类型(除过子类中方法的返回类型是父类中返回类型的子类)必须相同

3.访问修饰符的限制必定要大于被重写方法的访问修饰符(public>protected>default>private)

4.重写方法必定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常

重载(Overload)

在一个类中,同名的方法若是有不一样的参数列表(参数类型不一样、参数个数不一样甚至是参数顺序不一样)则视为重载。同时,重载对返回类型没有要求,能够相同也能够不一样,但不能经过返回类型是否相同来判断重载

public class Father {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Father s = new Father();
        s.sayHello();
        s.sayHello("wintershii");

    }

    public void sayHello() {
        System.out.println("Hello");
    }

    public void sayHello(String name) {
        System.out.println("Hello" + " " + name);
    }
}

重载 总结:

1.重载Overload是一个类中多态性的一种表现

2.重载要求同名方法的参数列表不一样(参数类型,参数个数甚至是参数顺序)

3.重载的时候,返回值类型能够相同也能够不相同。没法以返回型别做为重载函数的区分标准

24W字Java面试手册下载地址: https://shimo.im/docs/Wyj8QRp...
24W字Java面试手册下载地址: https://shimo.im/docs/Wyj8QRp...
24W字Java面试手册下载地址: https://shimo.im/docs/Wyj8QRp...

33. Java建立对象有几种方式?

java中提供了如下四种建立对象的方式:

  • new建立新对象
  • 经过反射机制
  • 采用clone机制
  • 经过序列化机制

34. ConcurrentModificationException异常出现的缘由

public class Test {
    public static void main(String[] args)  {
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(2);
        Iterator<Integer> iterator = list.iterator();
        while(iterator.hasNext()){
            Integer integer = iterator.next();
            if(integer==2)
                list.remove(integer);
        }
    }
}

执行上段代码是有问题的,会抛出ConcurrentModificationException异常。

缘由:调用list.remove()方法致使modCountexpectedModCount的值不一致。

final void checkForComodification() {
    if (modCount != expectedModCount)
    throw new ConcurrentModificationException();
}

解决办法:在迭代器中若是要删除元素的话,须要调用Iterator类的remove方法。

public class Test {
    public static void main(String[] args)  {
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(2);
        Iterator<Integer> iterator = list.iterator();
        while(iterator.hasNext()){
            Integer integer = iterator.next();
            if(integer==2)
                iterator.remove();   //注意这个地方
        }
    }
}

35. HashMap和HashTable、ConcurrentHashMap区别?

相同点:

  1. HashMap和Hashtable都实现了Map接口
  2. 均可以存储key-value数据

不一样点:

  1. HashMap能够把null做为key或value,HashTable不能够
  2. HashMap线程不安全,效率高。HashTable线程安全,效率低。
  3. HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。
什么是fail-fast?
就是最快的时间能把错误抛出而不是让程序执行。

36. 如何保证线程安全又效率高?

Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。

ConcurrentHashMap将整个Map分为N个segment(相似HashTable),能够提供相同的线程安全,可是效率提高N倍,默认N为16。

37. 咱们可否让HashMap同步?

HashMap能够经过下面的语句进行同步:

Map m = Collections.synchronizeMap(hashMap);

38. Java 中 IO 流分为几种?

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

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

字节流和字符流的区别是:字节流按 8 位传输以字节为单位输入输出数据,字符流按 16 位传输以字符为单位输入输出数据。

39. BIO、NIO、AIO 有什么区别?

  • BIO:Block IO 同步阻塞式 IO,就是咱们日常使用的传统 IO,它的特色是模式简单使用方便,并发处理能力低。
  • NIO:Non IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端经过 Channel(通道)通信,实现了多路复用。
  • AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操做基于事件和回调机制。

40. Files的经常使用方法都有哪些?

  • Files. exists():检测文件路径是否存在。
  • Files. createFile():建立文件。
  • Files. createDirectory():建立文件夹。
  • Files. delete():删除一个文件或目录。
  • Files. copy():复制文件。
  • Files. move():移动文件。
  • Files. size():查看文件个数。
  • Files. read():读取文件。
  • Files. write():写入文件。

41. Java反射的做用于原理

一、定义:

反射机制是在运行时,对于任意一个类,都可以知道这个类的全部属性和方法;对于任意个对象,都可以调用它的任意一个方法。在java中,只要给定类的名字,就能够经过反射机制来得到类的全部信息。

这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。

二、哪里会用到反射机制?

jdbc就是典型的反射

Class.forName('com.mysql.jdbc.Driver.class');//加载MySQL的驱动类

这就是反射。如hibernate,struts等框架使用反射实现的。

24W字Java面试手册下载地址: https://shimo.im/docs/Wyj8QRp...
24W字Java面试手册下载地址: https://shimo.im/docs/Wyj8QRp...
24W字Java面试手册下载地址: https://shimo.im/docs/Wyj8QRp...

42. 反射的实现方式

第一步:获取Class对象,有4种方法: 1)Class.forName(“类的路径”); 2)类名.class 3)对象名.getClass() 4)基本类型的包装类,能够调用包装类的Type属性来得到该包装类的Class对象

43. 实现Java反射的类:

1)Class:表示正在运行的Java应用程序中的类和接口 注意: 全部获取对象的信息都须要Class类来实现。 2)Field:提供有关类和接口的属性信息,以及对它的动态访问权限。 3)Constructor:提供关于类的单个构造方法的信息以及它的访问权限 4)Method:提供类或接口中某个方法的信息

44. 反射机制的优缺点:

优势:

一、可以运行时动态获取类的实例,提升灵活性;

二、与动态编译结合

缺点:

一、使用反射性能较低,须要解析字节码,将内存中的对象进行解析。

解决方案:

​ 一、经过setAccessible(true)关闭JDK的安全检查来提高反射速度;

​ 二、屡次建立一个类的实例时,有缓存会快不少

​ 三、ReflectASM工具类,经过字节码生成的方式加快反射速度

二、相对不安全,破坏了封装性(由于经过反射能够得到私有方法和属性)

45. Java 中 IO 流分为几种?

  • 按照流的流向分,能够分为输入流和输出流;
  • 按照操做单元划分,能够划分为字节流和字符流;
  • 按照流的角色划分为节点流和处理流。

Java Io 流共涉及 40 多个类,这些类看上去很杂乱,但实际上颇有规则,并且彼此之间存在很是紧密的联系, Java I0 流的 40 多个类都是从以下 4 个抽象类基类中派生出来的。

  • InputStream/Reader: 全部的输入流的基类,前者是字节输入流,后者是字符输入流。
  • OutputStream/Writer: 全部输出流的基类,前者是字节输出流,后者是字符输出流。

按操做方式分类结构图:

相关文章
相关标签/搜索