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

1.什么是Java

Java是一门面向对象的高级编程语言,不只吸取了C++语言的各类优势,好比继承了C++语言面向对象的技术核心。还摒弃了C++里难以理解的多继承、指针等概念,,同时也增长了垃圾回收机制,释放掉不被使用的内存空间,解决了管理内存空间的烦恼。java

所以Java语言具备功能强大和简单易用两个特征。Java语言做为静态面向对象编程语言的表明,极好地实现了面向对象理论,容许程序员以优雅的思惟方式进行复杂的编程 。程序员

2. Java的特色有哪些

Java 语言是一种分布式的面向对象语言,具备面向对象、平台无关性、简单性、解释执行、多线程、安全性等不少特色,下面针对这些特色进行逐一介绍。web

1. 面向对象面试

Java 是一种面向对象的语言,它对对象中的类、对象、继承、封装、多态、接口、包等均有很好的支持。为了简单起见,Java 只支持类之间的单继承,可是可使用接口来实现多继承。使用 Java 语言开发程序,须要采用面向对象的思想设计程序和编写代码。编程

2. 平台无关性数组

平台无关性的具体表如今于,Java 是“一次编写,处处运行(Write Once,Run any Where)”的语言,所以采用 Java 语言编写的程序具备很好的可移植性,而保证这一点的正是 Java 的虚拟机机制。在引入虚拟机以后,Java 语言在不一样的平台上运行不须要从新编译。tomcat

Java 语言使用 Java 虚拟机机制屏蔽了具体平台的相关信息,使得 Java 语言编译的程序只需生成虚拟机上的目标代码,就能够在多种平台上不加修改地运行。安全

3. 简单性网络

Java 语言的语法与 C 语言和 C++ 语言很相近,使得不少程序员学起来很容易。对 Java 来讲,它舍弃了不少 C++ 中难以理解的特性,如操做符的重载和多继承等,并且 Java 语言不使用指针,加入了垃圾回收机制,解决了程序员须要管理内存的问题,使编程变得更加简单。多线程

4. 解释执行

Java 程序在 Java 平台运行时会被编译成字节码文件,而后能够在有 Java 环境的操做系统上运行。在运行文件时,Java 的解释器对这些字节码进行解释执行,执行过程当中须要加入的类在链接阶段被载入到运行环境中。

5. 多线程

Java 语言是多线程的,这也是 Java 语言的一大特性,它必须由 Thread 类和它的子类来建立。Java 支持多个线程同时执行,并提供多线程之间的同步机制。任何一个线程都有本身的 run() 方法,要执行的方法就写在 run() 方法体内。

6. 分布式

Java 语言支持 Internet 应用的开发,在 Java 的基本应用编程接口中就有一个网络应用编程接口,它提供了网络应用编程的类库,包括 URL、URLConnection、Socket 等。Java 的 RIM 机制也是开发分布式应用的重要手段。

7. 健壮性

Java 的强类型机制、异常处理、垃圾回收机制等都是 Java 健壮性的重要保证。对指针的丢弃是 Java 的一大进步。另外,Java 的异常机制也是健壮性的一大致现。

8. 高性能

Java 的高性能主要是相对其余高级脚本语言来讲的,随着 JIT(Just in Time)的发展,Java 的运行速度也愈来愈高。

9. 安全性

Java 一般被用在网络环境中,为此,Java 提供了一个安全机制以防止恶意代码的攻击。除了 Java 语言具备许多的安全特性之外,Java 还对经过网络下载的类增长一个安全防范机制,分配不一样的名字空间以防替代本地的同名类,并包含安全管理机制。

Java 语言的众多特性使其在众多的编程语言中占有较大的市场份额,Java 语言对对象的支持和强大的 API 使得编程工做变得更加容易和快捷,大大下降了程序的开发成本。Java 的“一次编写,处处执行”正是它吸引众多商家和编程人员的一大优点。

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

3. JDK和JRE和JVM的区别

1. JDK

JDK(Java SE Development Kit),Java标准的开发包,提供了编译、运行Java程序所须要的各类工具和资源,包括了Java编译器、Java运行时环境、以及经常使用的Java类库等。

2. JRE

JRE(Java Runtime Environment),Java运行时环境,用于解释执行Java的字节码文件。普通用户只须要安装JRE来运行Java程序便可,而做为一名程序员必须安装JDK,来编译、调试程序。

3. JVM

JVM(Java Virtual Mechinal),Java虚拟机,是JRE的一部分。它是整个Java实现跨平台的核心,负责解释执行字节码文件,是可运行Java字节码文件的虚拟计算机。全部平台上的JVM向编译器提供相同的接口,而编译器只须要面向虚拟机,生成虚拟机能识别的代码,而后由虚拟机来解释执行。

当使用Java编译器编译Java程序时,生成的是与平台无关的字节码,这些字节码只面向JVM。也就是说JVM是运行Java字节码的虚拟机。

不一样平台的JVM是不一样的,可是他们都提供了相同的接口。JVM是Java程序跨平台的关键部分,只要为不一样平台实现了相同的虚拟机,编译后的Java字节码就能够在该平台上运行。

为何要采用字节码:

在 Java 中,JVM 能够理解的代码就叫作 字节码(即Java源代码通过虚拟机编译器编译后扩展名为 .class 的文件),它不面向任何特定的处理器,只面向虚拟机。Java 语言经过字节码的方式,在必定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特色。因此 Java 程序运行时比较高效,并且,因为字节码并不针对一种特定的机器,所以,Java 程序无须从新编译即可在多种不一样操做系统的计算机上运行。

什么是跨平台:

所谓跨平台性,是指java语言编写的程序,一次编译后,能够在多个系统平台上运行。

实现原理:Java程序是经过java虚拟机在系统平台上运行的,只要该系统能够安装相应的java虚拟机,该系统就能够运行java程序。

Java 程序从源代码到运行须要三步:

4. 总结

  1. JDK 用于开发,JRE 用于运行java程序 ;若是只是运行Java程序,能够只安装JRE,无序安装JDK。
  2. JDk包含JRE,JDK 和 JRE 中都包含 JVM。
  3. JVM 是 Java 编程语言的核心而且具备平台独立性。

4. Oracle JDK 和 OpenJDK 的对比

  • Oracle JDK版本将每三年发布一次,而OpenJDK版本每三个月发布一次;
  • OpenJDK 是一个参考模型而且是彻底开源的,而Oracle JDK是OpenJDK的一个实现,并非彻底开源的;
  • Oracle JDK 比 OpenJDK 更稳定。OpenJDK和Oracle JDK的代码几乎相同,但Oracle JDK有更多的类和一些错误修复。所以,若是您想开发企业/商业软件,我建议您选择Oracle JDK,由于它通过了完全的测试和稳定。某些状况下,有些人提到在使用OpenJDK 可能会遇到了许多应用程序崩溃的问题,可是,只需切换到Oracle JDK就能够解决问题;
  • 在响应性和JVM性能方面,Oracle JDK与OpenJDK相比提供了更好的性能;
  • Oracle JDK不会为即将发布的版本提供长期支持,用户每次都必须经过更新到最新版本得到支持来获取最新版本;
  • Oracle JDK根据二进制代码许可协议得到许可,而OpenJDK根据GPL v2许可得到许可。

5. Java有哪些数据类型

Java有 8 种基本数据类型,分别为:

  • 6 种数字类型 (四个整数形,两个浮点型):byte、short、int、long、float、double
  • 1 种字符类型:char
  • 1 种布尔型:boolean。

byte:

  • byte 数据类型是8位、有符号的,以二进制补码表示的整数;
  • 最小值是 -128(-2^7)
  • 最大值是 127(2^7-1)
  • 默认值是 0
  • byte 类型用在大型数组中节约空间,主要代替整数,由于 byte 变量占用的空间只有 int 类型的四分之一;
  • 例子:byte a = 100,byte b = -50。

short:

  • short 数据类型是 16 位、有符号的以二进制补码表示的整数
  • 最小值是 -32768(-2^15)
  • 最大值是 32767(2^15 - 1)
  • Short 数据类型也能够像 byte 那样节省空间。一个short变量是int型变量所占空间的二分之一;
  • 默认值是 0
  • 例子:short s = 1000,short r = -20000。

int:

  • int 数据类型是32位、有符号的以二进制补码表示的整数;
  • 最小值是 -2,147,483,648(-2^31)
  • 最大值是 2,147,483,647(2^31 - 1)
  • 通常地整型变量默认为 int 类型;
  • 默认值是 0
  • 例子:int a = 100000, int b = -200000。

long:

  • 注意:Java 里使用 long 类型的数据必定要在数值后面加上 L,不然将做为整型解析
  • long 数据类型是 64 位、有符号的以二进制补码表示的整数;
  • 最小值是 -9,223,372,036,854,775,808(-2^63)
  • 最大值是 9,223,372,036,854,775,807(2^63 -1)
  • 这种类型主要使用在须要比较大整数的系统上;
  • 默认值是 0L
  • 例子: long a = 100000L,Long b = -200000L。
    "L"理论上不分大小写,可是若写成"l"容易与数字"1"混淆,不容易分辩。因此最好大写。

float:

  • float 数据类型是单精度、32位、符合IEEE 754标准的浮点数;
  • float 在储存大型浮点数组的时候可节省内存空间;
  • 默认值是 0.0f
  • 浮点数不能用来表示精确的值,如货币;
  • 例子:float f1 = 234.5f。

double:

  • double 数据类型是双精度、64 位、符合IEEE 754标准的浮点数;
  • 浮点数的默认类型为double类型;
  • double类型一样不能表示精确的值,如货币;
  • 默认值是 0.0d
  • 例子:double d1 = 123.4。

char:

  • char类型是一个单一的 16 位 Unicode 字符;
  • 最小值是 \u0000(即为 0);
  • 最大值是 \uffff(即为 65535);
  • char 数据类型能够储存任何字符;
  • 例子:char letter = 'A';(单引号

boolean:

  • boolean数据类型表示一位的信息;
  • 只有两个取值:true 和 false;
  • 这种类型只做为一种标志来记录 true/false 状况;
  • 默认值是 false
  • 例子:boolean one = true。

这八种基本类型都有对应的包装类分别为:Byte、Short、Integer、Long、Float、Double、Character、Boolean

类型名称 字节、位数 最小值 最大值 默认值 例子
byte字节 1字节,8位 -128(-2^7) 127(2^7-1) 0 byte a = 100,byte b = -50
short短整型 2字节,16位 -32768(-2^15) 32767(2^15 - 1) 0 short s = 1000,short r = -20000
int整形 4字节,32位 -2,147,483,648(-2^31) 2,147,483,647(2^31 - 1) 0 int a = 100000, int b = -200000
lang长整型 8字节,64位 -9,223,372,036,854,775,808(-2^63) 9,223,372,036,854,775,807(2^63 -1) 0L long a = 100000L,Long b = -200000L
double双精度 8字节,64位 double类型一样不能表示精确的值,如货币 0.0d double d1 = 123.4
float单精度 4字节,32位 在储存大型浮点数组的时候可节省内存空间 不一样统计精准的货币值 0.0f float f1 = 234.5f
char字符 2字节,16位 \u0000(即为0) \uffff(即为65,535) 能够储存任何字符 char letter = 'A';
boolean布尔 返回true和false两个值 这种类型只做为一种标志来记录 true/false 状况; 只有两个取值:true 和 false; false boolean one = true

6. Java中引用数据类型有哪些,它们与基本数据类型有什么区别?

引用数据类型分3种:类,接口,数组;

简单来讲,只要不是基本数据类型.都是引用数据类型。 那他们有什么不一样呢?

一、从概念方面来讲

1,基本数据类型:变量名指向具体的数值

2,引用数据类型:变量名不是指向具体的数值,而是指向存数据的内存地址,.也及时hash值

二、从内存的构建方面来讲(内存中,有堆内存和栈内存二者)

1,基本数据类型:被建立时,在栈内存中会被划分出必定的内存,并将数值存储在该内存中.

2,引用数据类型:被建立时,首先会在栈内存中分配一块空间,而后在堆内存中也会分配一块具体的空间用来存储数据的具体信息,即hash值,而后由栈中引用指向堆中的对象地址.

举个例子

//基本数据类型做为方法参数被调用
public class Main{
    public static void main(String[] args){
        //基本数据类型
        int i = 1;
        int j = 1;
        double d = 1.2;
 
        //引用数据类型
        String str = "Hello";
        String str1= "Hello";
    }
}

由上图可知,基本数据类型中会存在两个相同的1,而引用型类型就不会存在相同的数据。
假如"hello"的引用地址是xxxxx1,声明str变量并其赋值"hello"实际上就是让str变量引用了"hello"的内存地址,这个内存地址就存储在堆内存中,是不会改变的,当再次声明变量str1也是赋值为"hello"时,此时就会在堆内存中查询是否有"hello"这个地址,若是堆内存中已经存在这个地址了,就不会再次建立了,而是让str1变量也指向xxxxx1这个地址,若是没有的话,就会从新建立一个地址给str1变量。

7. 从使用方面来讲

1,基本数据类型:判断数据是否相等,用==和!=判断。
2,引用数据类型:判断数据是否相等,用equals()方法,==和!=是比较数值的。而equals()方法是比较内存地址的。

补充:数据类型选择的原则

  • 若是要表示整数就使用int,表示小数就使用double;
  • 若是要描述日期时间数字或者表示文件(或内存)大小用long;
  • 若是要实现内容传递或者编码转换使用byte;
  • 若是要实现逻辑的控制,可使用booleam;
  • 若是要使用中文,使用char避免中文乱码;
  • 若是按照保存范围:byte < int < long < double;
24W字Java面试手册下载地址: https://shimo.im/docs/Wyj8QRp...

8. Java中的自动装箱与拆箱

什么是自动装箱拆箱?

从下面的代码中就能够看到装箱和拆箱的过程

//自动装箱
Integer total = 99;

//自定拆箱
int totalprim = total;

装箱就是自动将基本数据类型转换为包装器类型;拆箱就是自动将包装器类型转换为基本数据类型。

在Java SE5以前,自动装箱要这样写:Integer i = new` `Integer(10``);

对于Java的自动装箱和拆箱,咱们看看源码编译后的class文件,其实装箱调用包装类的valueOf方法,拆箱调用的是Integer.Value方法,下面就是变编译后的代码:

常见面试一:

这段代码输出什么?

public class Main {
    public static void main(String[] args) {
         
        Integer i1 = 100;
        Integer i2 = 100;
        Integer i3 = 200;
        Integer i4 = 200;
         
        System.out.println(i1==i2);
        System.out.println(i3==i4);
    }
}

答案是:

true
false

为何会出现这样的结果?输出结果代表i1和i2指向的是同一个对象,而i3和i4指向的是不一样的对象。此时只需一看源码便知究竟,下面这段代码是Integer的valueOf方法的具体实现:

public static Integer valueOf(int i) {
        if(i >= -128 && i <= IntegerCache.high)
            return IntegerCache.cache[i + 128];
        else
            return new Integer(i);
    }
private static class IntegerCache {
        static final int high;
        static final Integer cache[];

        static {
            final int low = -128;

            // high value may be configured by property
            int h = 127;
            if (integerCacheHighPropValue != null) {
                // Use Long.decode here to avoid invoking methods that
                // require Integer's autoboxing cache to be initialized
                int i = Long.decode(integerCacheHighPropValue).intValue();
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - -low);
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);
        }

        private IntegerCache() {}
    }

从这2段代码能够看出,在经过valueOf方法建立Integer对象的时候,若是数值在[-128,127]之间,便返回指向IntegerCache.cache中已经存在的对象的引用;不然建立一个新的Integer对象。

上面的代码中i1和i2的数值为100,所以会直接从cache中取已经存在的对象,因此i1和i2指向的是同一个对象,而i3和i4则是分别指向不一样的对象。

常见面试二:

public class Main {
    public static void main(String[] args) {
         
        Double i1 = 100.0;
        Double i2 = 100.0;
        Double i3 = 200.0;
        Double i4 = 200.0;
         
        System.out.println(i1==i2);
        System.out.println(i3==i4);
    }
}

输出结果为:

false
false

缘由很简单,在某个范围内的整型数值的个数是有限的,而浮点数却不是。

9. 为何要有包装类型?

让基本数据类型也具备对象的特征

基本类型 包装器类型
boolean Boolean
char Character
int Integer
byte Byte
short Short
long Long
float Float
double Double

为了让基本类型也具备对象的特征,就出现了包装类型(如咱们在使用集合类型Collection时就必定要使用包装类型而非基本类型)由于容器都是装object的,这是就须要这些基本类型的包装器类了。

自动装箱:new Integer(6);,底层调用:Integer.valueOf(6)

自动拆箱: int i = new Integer(6);,底层调用i.intValue();方法实现。

Integer i  = 6;
Integer j = 6;
System.out.println(i==j);

答案在下面这段代码中找:

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

两者的区别:

  1. 声明方式不一样:基本类型不使用new关键字,而包装类型须要使用new关键字来在堆中分配存储空间
  2. 存储方式及位置不一样:基本类型是直接将变量值存储在栈中,而包装类型是将对象放在堆中,而后经过引用来使用;
  3. 初始值不一样:基本类型的初始值如int为0,boolean为false,而包装类型的初始值为null;
  4. 使用方式不一样:基本类型直接赋值直接使用就好,而包装类型在集合如Collection、Map时会使用到。
24W字Java面试手册下载地址: https://shimo.im/docs/Wyj8QRp...

10. a=a+b与a+=b有什么区别吗?

+=操做符会进行隐式自动类型转换,此处a+=b隐式的将加操做的结果类型强制转换为持有结果的类型,而a=a+b则不会自动进行类型转换.如:

byte a = 127;
byte b = 127;
b = a + b; // 报编译错误:cannot convert from int to byte
b += a;

如下代码是否有错,有的话怎么改?

short s1= 1;
s1 = s1 + 1;

有错误.short类型在进行运算时会自动提高为int类型,也就是说s1+1的运算结果是int类型,而s1是short类型,此时编译器会报错.

正确写法:

short s1= 1; 
s1 += 1;

+=操做符会对右边的表达式结果强转匹配左边的数据类型,因此没错.

11. 能将 int 强制转换为 byte 类型的变量吗?若是该值大于 byte 类型的范围,将会出现什么现象?

咱们能够作强制转换,可是 Java 中 int 是 32 位的,而 byte 是 8 位的,因此,若是强制转化,int 类型的高 24 位将会被丢弃,由于byte 类型的范围是从 -128 到 127

12. Java程序是如何执行的

咱们平常的工做中都使用开发工具(IntelliJ IDEA 或 Eclipse 等)能够很方便的调试程序,或者是经过打包工具把项目打包成 jar 包或者 war 包,放入 Tomcat 等 Web 容器中就能够正常运行了,但你有没有想过 Java 程序内部是如何执行的?其实不管是在开发工具中运行仍是在 Tomcat 中运行,Java 程序的执行流程基本都是相同的,它的执行流程以下:

  • 先把 Java 代码编译成字节码,也就是把 .java 类型的文件编译成 .class 类型的文件。这个过程的大体执行流程:Java 源代码 -> 词法分析器 -> 语法分析器 -> 语义分析器 -> 字符码生成器 -> 最终生成字节码,其中任何一个节点执行失败就会形成编译失败;
  • 把 class 文件放置到 Java 虚拟机,这个虚拟机一般指的是 Oracle 官方自带的 Hotspot JVM;
  • Java 虚拟机使用类加载器(Class Loader)装载 class 文件;
  • 类加载完成以后,会进行字节码效验,字节码效验经过以后 JVM 解释器会把字节码翻译成机器码交由操做系统执行。但不是全部代码都是解释执行的,JVM 对此作了优化,好比,以 Hotspot 虚拟机来讲,它自己提供了 JIT(Just In Time)也就是咱们一般所说的动态编译器,它可以在运行时将热点代码编译为机器码,这个时候字节码就变成了编译执行。Java 程序执行流程图以下:

13. final 在 Java 中有什么做用?

final做为Java中的关键字能够用于三个地方。用于修饰类、类属性和类方法。

特征:凡是引用final关键字的地方皆不可修改!

(1)修饰类:表示该类不能被继承;

(2)修饰方法:表示方法不能被重写;

(3)修饰变量:表示变量只能一次赋值之后值不能被修改(常量)。

14. final有哪些用法?

final也是不少面试喜欢问的地方,但我以为这个问题很无聊,一般能回答下如下5点就不错了:

  • 被final修饰的类不能够被继承
  • 被final修饰的方法不能够被重写
  • 被final修饰的变量不能够被改变.若是修饰引用,那么表示引用不可变,引用指向的内容可变.
  • 被final修饰的方法,JVM会尝试将其内联,以提升运行效率
  • 被final修饰的常量,在编译阶段会存入常量池中.

除此以外,编译器对final域要遵照的两个重排序规则更好:

在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操做之间不能重排序 初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操做之间不能重排序.

15. static都有哪些用法?

全部的人都知道static关键字这两个基本的用法:静态变量和静态方法.也就是被static所修饰的变量/方法都属于类的静态资源,类实例所共享.

除了静态变量和静态方法以外,static也用于静态块,多用于初始化操做:

public calss PreCache{
    static{
        //执行相关操做
    }
}

此外static也多用于修饰内部类,此时称之为静态内部类.

最后一种用法就是静态导包,即import static.import static是在JDK 1.5以后引入的新特性,能够用来指定导入某个类中的静态资源,而且不须要使用类名,能够直接使用资源名,好比:

import static java.lang.Math.*;
 
public class Test{
 
    public static void main(String[] args){
        //System.out.println(Math.sin(20));传统作法
        System.out.println(sin(20));
    }
}

16. static和final区别

关键词 修饰物 影响
final 变量 分配到常量池中,程序不可改变其值
final 方法 子类中将不能被重写
final 不能被继承
static 变量 分配在内存堆上,引用都会指向这一个地址而不会从新分配内存
static 方法块 虚拟机优先加载
static 能够直接经过类来调用而不须要new

17. 为何有些java类要实现Serializable接口

为了网络进行传输或者持久化

什么是序列化

将对象的状态信息转换为能够存储或传输的形式的过程

除了实现Serializable接口还有什么序列化方式

  • Json序列化
  • FastJson序列化
  • ProtoBuff序列化

18. 什么是java序列化,如何实现java序列化?或者请解释Serializable接口的做用。

咱们有时候将一个java对象变成字节流的形式传出去或者从一个字节流中恢复成一个java对象,例如,要将java对象存储到硬盘或者传送给网络上的其余计算机,这个过程咱们能够本身写代码去把一个java对象变成某个格式的字节流再传输。

可是,jre自己就提供了这种支持,咱们能够调用OutputStreamwriteObject方法来作,若是要让java帮咱们作,要被传输的对象必须实现serializable接口,这样,javac编译时就会进行特殊处理,编译的类才能够被writeObject方法操做,这就是所谓的序列化。须要被序列化的类必须实现Serializable接口,该接口是一个mini接口,其中没有须要实现方法,implements Serializable只是为了标注该对象是可被序列化的。

例如,在web开发中,若是对象被保存在了Session中,tomcat在重启时要把Session对象序列化到硬盘,这个对象就必须实现Serializable接口。若是对象要通过分布式系统进行网络传输,被传输的对象就必须实现Serializable接口。

19. 什么是内部类?内部类的做用

内部类的定义

将一个类定义在另外一个类里面或者一个方法里面,这样的类称为内部类。

内部类的做用:

一、成员内部类 成员内部类能够无条件访问外部类的全部成员属性和成员方法(包括private成员和静态成员)。 当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认状况下访问的是成员内部类的成员。

二、局部内部类 局部内部类是定义在一个方法或者一个做用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该做用域内。

三、匿名内部类 匿名内部类就是没有名字的内部类

四、静态内部类 指被声明为static的内部类,他能够不依赖内部类而实例,而一般的内部类须要实例化外部类,从而实例化。静态内部类不能够有与外部类有相同的类名。不能访问外部类的普通成员变量,可是能够访问静态成员变量和静态方法(包括私有类型) 一个 静态内部类去掉static 就是成员内部类,他能够自由的引用外部类的属性和方法,不管是静态仍是非静态。可是不能够有静态属性和方法

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

20. Excption与Error包结构

Java可抛出(Throwable)的结构分为三种类型:被检查的异常(CheckedException)运行时异常(RuntimeException)错误(Error)

一、运行时异常

定义:RuntimeException及其子类都被称为运行时异常。

特色:Java编译器不会检查它。也就是说,当程序中可能出现这类异常时,假若既"没有经过throws声明抛出它",也"没有用try-catch语句捕获它",仍是会编译经过。例如,除数为零时产生的ArithmeticException异常,数组越界时产生的IndexOutOfBoundsException异常,fail-fast机制产生的ConcurrentModificationException异常(java.util包下面的全部的集合类都是快速失败的,“快速失败”也就是fail-fast,它是Java集合的一种错误检测机制。当多个线程对集合进行结构上的改变的操做时,有可能会产生fail-fast机制。记住是有可能,而不是必定。例如:假设存在两个线程(线程一、线程2),线程1经过Iterator在遍历集合A中的元素,在某个时候线程2修改了集合A的结构(是结构上面的修改,而不是简单的修改集合元素的内容),那么这个时候程序就会抛出 ConcurrentModificationException 异常,从而产生fail-fast机制,这个错叫并发修改异常。Fail-safe,java.util.concurrent包下面的全部的类都是安全失败的,在遍历过程当中,若是已经遍历的数组上的内容变化了,迭代器不会抛出ConcurrentModificationException异常。若是未遍历的数组上的内容发生了变化,则有可能反映到迭代过程当中。这就是ConcurrentHashMap迭代器弱一致的表现。ConcurrentHashMap的弱一致性主要是为了提高效率,是一致性与效率之间的一种权衡。要成为强一致性,就获得处使用锁,甚至是全局锁,这就与Hashtable和同步的HashMap同样了。)等,都属于运行时异常。

常见的五种运行时异常:

  • ClassCastException(类转换异常)
  • IndexOutOfBoundsException(数组越界)
  • NullPointerException(空指针异常)
  • ArrayStoreException(数据存储异常,操做数组是类型不一致)
  • BufferOverflowException

二、被检查异常

定义:Exception类自己,以及Exception的子类中除了"运行时异常"以外的其它子类都属于被检查异常。

特色 : Java编译器会检查它。 此类异常,要么经过throws进行声明抛出,要么经过try-catch进行捕获处理,不然不能经过编译。例如,CloneNotSupportedException就属于被检查异常。

当经过clone()接口去克隆一个对象,而该对象对应的类没有实现Cloneable接口,就会抛出CloneNotSupportedException异常。被检查异常一般都是能够恢复的。 如:

IOException

FileNotFoundException

SQLException

被检查的异常适用于那些不是因程序引发的错误状况,好比:读取文件时文件不存在引起的FileNotFoundException。然而,不被检查的异常一般都是因为糟糕的编程引发的,好比:在对象引用时没有确保对象非空而引发的NullPointerException

三、错误

定义 : Error类及其子类。

特色 : 和运行时异常同样,编译器也不会对错误进行检查。

当资源不足、约束失败、或是其它程序没法继续运行的条件发生时,就产生错误。程序自己没法修复这些错误的。例如,VirtualMachineError就属于错误。出现这种错误会致使程序终止运行。OutOfMemoryError、ThreadDeath。

Java虚拟机规范规定JVM的内存分为了好几块,好比堆,栈,程序计数器,方法区等

24W字Java面试手册下载地址: https://shimo.im/docs/Wyj8QRp...
相关文章
相关标签/搜索