1. 什么是 Java
Java 是一门面向对象的高级编程语言,不仅排汇了 C ++ 语言的各种长处,比方继承了 C ++ 语言面向对象的技术外围。还摒弃了 C ++ 里难以了解的多继承、指针等概念,,同时也减少了垃圾回收机制,开释掉不被应用的内存空间,解决了治理内存空间的懊恼。
因而 Java 语言具备功能强大和简略易用两个特色。Java 语言作为动态面向对象编程语言的代表,极好地实现了面向对象实践,容许程序员以优雅的思维形式进行简单的编程。
2. Java 的特点有哪些
Java 语言是一种分布式的面向对象语言,具备面向对象、平台无关性、简略性、解释执行、多线程、安全性等很多特点,上面针对这些特点进行逐个介绍。
1. 面向对象
Java 是一种面向对象的语言,它对对象中的类、对象、继承、封装、多态、接口、包等均有很好的反对。为了简略起见,Java 只反对类之间的单继承,然而能够应用接口来实现多继承。应用 Java 语言开发程序,须要采纳面向对象的思维设计程序和编写代码。
2. 平台无关性
平台无关性的具体表现在于,Java 是“一次编写,到处运行(Write Once,Run any Where)”的语言,因而采纳 Java 语言编写的程序具备很好的可移植性,而保障这一点的正是 Java 的虚拟机机制。在引入虚拟机之后,Java 语言在不同的平台上运行不须要从新编译。
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. 总结
- JDK 用于开发,JRE 用于运行 java 程序;如果只是运行 Java 程序,能够只装置 JRE,无序装置 JDK。
- JDk 蕴含 JRE,JDK 和 JRE 中都蕴含 JVM。
- 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、从概念方面来说
1, 根本数据类型: 变量名指向具体的数值
2, 援用数据类型: 变量名不是指向具体的数值, 而是指向存数据的内存地址,. 也及时 hash 值
2、从内存的构建方面来说(内存中, 有堆内存和栈内存两者)
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);
}
二者的区别:
- 申明形式不同:根本类型不应用 new 关键字,而包装类型须要应用 new 关键字来在 堆中调配存储空间;
- 存储形式及地位不同:根本类型是间接将变量值存储在栈中,而包装类型是将对象放在堆中,而后通过援用来应用;
- 初始值不同:根本类型的初始值如 int 为 0,boolean 为 false,而包装类型的初始值为 null;
- 应用形式不同:根本类型间接赋值间接应用就好,而包装类型在汇合如 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 自身就提供了这种反对,咱们能够调用 OutputStream
的writeObject
办法来做,如果要让 java 帮咱们做,要被传输的对象必须实现 serializable
接口,这样,javac 编译时就会进行非凡解决,编译的类才能够被 writeObject
办法操作,这就是所谓的序列化。须要被序列化的类必须实现 Serializable
接口,该接口是一个 mini 接口,其中没有须要实现办法,implements Serializable 只是为了标注该对象是可被序列化的。
例如,在 web 开发中,如果对象被保留在了 Session 中,tomcat 在重启时要把 Session 对象序列化到硬盘,这个对象就必须实现 Serializable 接口。如果对象要通过分布式系统进行网络传输,被传输的对象就必须实现 Serializable 接口。
19. 什么是外部类?外部类的作用
外部类的定义
将一个类定义在另一个类外面或者一个办法外面,这样的类称为外部类。
外部类的作用:
1、成员外部类 成员外部类能够无条件拜访外部类的所有成员属性和成员办法(包含 private 成员和动态成员)。当成员外部类领有和外部类同名的成员变量或者办法时,会产生暗藏景象,即默认状况下拜访的是成员外部类的成员。
2、部分外部类 部分外部类是定义在一个办法或者一个作用域外面的类,它和成员外部类的区别在于部分外部类的拜访仅限于办法内或者该作用域内。
3、匿名外部类 匿名外部类就是没有名字的外部类
4、动态外部类 指被申明为 static 的外部类,他能够不依赖外部类而实例,而通常的外部类须要实例化外部类,从而实例化。动态外部类不能够有与外部类有雷同的类名。不能拜访外部类的一般成员变量,然而能够拜访动态成员变量和静态方法(包含公有类型)一个 动态外部类去掉 static 就是成员外部类,他能够自在的援用外部类的属性和办法,无论是动态还是非动态。然而不能够有动态属性和办法
24W 字 Java 面试手册下载地址:https://shimo.im/docs/Wyj8QRp…
20. Excption 与 Error 包构造
Java 可抛出 (Throwable) 的构造分为三种类型:被查看的异样 (CheckedException), 运行时异样 (RuntimeException), 谬误(Error)。
1、运行时异样
定义:RuntimeException 及其子类都被称为运行时异样。
特点:Java 编译器不会查看它。也就是说,当程序中可能呈现这类异样时,假使既 ” 没有通过 throws 申明抛出它 ”,也 ” 没有用 try-catch 语句捕捉它 ”,还是会编译通过。例如,除数为零时产生的 ArithmeticException 异样,数组越界时产生的 IndexOutOfBoundsException 异样,fail-fast 机制产生的 ConcurrentModificationException 异样(java.util 包上面的所有的汇合类都是疾速失败的,“疾速失败”也就是 fail-fast,它是 Java 汇合的一种谬误检测机制。当多个线程对汇合进行构造上的扭转的操作时,有可能会产生 fail-fast 机制。记住是有可能,而不是肯定。例如:假如存在两个线程(线程 1、线程 2),线程 1 通过 Iterator 在遍历汇合 A 中的元素,在某个时候线程 2 批改了汇合 A 的构造(是构造下面的批改,而不是简略的批改汇合元素的内容),那么这个时候程序就会抛出 ConcurrentModificationException 异样,从而产生 fail-fast 机制,这个错叫并发批改异样。Fail-safe,java.util.concurrent 包上面的所有的类都是平安失败的,在遍历过程中,如果曾经遍历的数组上的内容变动了,迭代器不会抛出 ConcurrentModificationException 异样。如果未遍历的数组上的内容产生了变动,则有可能反映到迭代过程中。这就是 ConcurrentHashMap 迭代器弱统一的体现。ConcurrentHashMap 的弱一致性次要是为了晋升效率,是一致性与效率之间的一种衡量。要成为强一致性,就失去处应用锁,甚至是全局锁,这就与 Hashtable 和同步的 HashMap 一样了。)等,都属于运行时异样。
常见的五种运行时异样:
ClassCastException
(类转换异样)IndexOutOfBoundsException
(数组越界)NullPointerException
(空指针异样)ArrayStoreException
(数据存储异样,操作数组是类型不统一)BufferOverflowException
2、被查看异样
定义:Exception 类自身,以及 Exception 的子类中除了 ” 运行时异样 ” 之外的其它子类都属于被查看异样。
特点: Java 编译器会查看它。此类异样,要么通过 throws 进行申明抛出,要么通过 try-catch 进行捕捉解决,否则不能通过编译。例如,CloneNotSupportedException 就属于被查看异样。
当通过 clone()接口去克隆一个对象,而该对象对应的类没有实现 Cloneable 接口,就会抛出 CloneNotSupportedException 异样。被查看异样通常都是能够复原的。如:
IOException
FileNotFoundException
SQLException
被查看的异样实用于那些不是因程序引起的谬误状况,比方:读取文件时文件不存在引发的FileNotFoundException
。然而,不被查看的异样通常都是因为蹩脚的编程引起的,比方:在对象援用时没有确保对象非空而引起的NullPointerException
。
3、谬误
定义 : Error 类及其子类。
特点 : 和运行时异样一样,编译器也不会对谬误进行查看。
当资源有余、束缚失败、或是其它程序无奈持续运行的条件产生时,就产生谬误。程序自身无奈修复这些谬误的。例如,VirtualMachineError 就属于谬误。呈现这种谬误会导致程序终止运行。OutOfMemoryError、ThreadDeath。
Java 虚拟机标准规定 JVM 的内存分为了好几块,比方堆,栈,程序计数器,办法区等
24W 字 Java 面试手册下载地址:https://shimo.im/docs/Wyj8QRp…