目录
- 1. 什么是java?Java 语言有哪些特点?
- 2. 面向对象与面向过程的区别?
- 3. JDK和JRE和JVM的区别
- 4. 八种基本数据类型的大小,以及他们的默认值和封装类;
- 5. Java中引用数据类型有哪些,它们与基本数据类型有什么区别?
- 6. instanceof 关键字;
- 7. Java自动封箱与拆箱;
- 8. a=a+b与a+=b有什么区别吗
- 9. java修饰符
- 10. java异常
- 11. 说说你平时是怎么处理 Java 异常的
- 12. 什么是java序列化,如何实现java序列化?或者请解释Serializable接口的作用。
- 13. Java 序列化中如果有些字段不想进行序列化,怎么办?
- 14. 什么是内部类?内部类的作用
- 15. java泛型、泛型常用特点
- 16. 重载和重写的区别;(类、名、参、返、异权)
- 17. equals与==的区别、Hashcode的作用
- 18. Java创建对象有几种方式?
- 19. 深拷贝和浅拷贝的区别是什么?
- 20. 获取一个类Class对象的方式有哪些?
- 21. **String、StringBuffer 和 StringBuilder 的区别是什么?(想想字符串相加的问题)**
- 22. ArrayList和linkedList的区别?(java集合)
- 23. 用过 ArrayList 吗?说一下它有什么特点?
- 24. 有数组了为什么还要搞个 ArrayList 呢?
- 25. 说说什么是 fail-fast?
- 26. HashMap和HashTable的区别?(主要为了问HashMap)
- 27. HashMap 中的 key 我们可以使用任何类作为 key 吗?
- 28. HashMap 的长度为什么是 2 的 N 次方呢?
- 29. Collection包结构,与Collections的区别
- 30. Java 中 IO 流分为几种?
- 31. BIO、NIO、AIO 有什么区别?
- 32. Files的常用方法都有哪些?
- 33. Java反射的作用与原理、实现、优缺点
- 34. Java的四种引用,强软弱虚
- 35. 3*0.1 == 0.3返回值是什么?
- 36. 简述线程、程序、进程、协程的基本概念。以及他们之间关系是什么?
- 37. Object 有哪些常用方法?大致说一下每个方法的含义
对之前写的题目做一个解答,包含个人理解,欢迎大家评论
1. 什么是java?Java 语言有哪些特点?
java是面向对象的高级语言!
与c++相比:
- 吸收了c++面向对象的核心技术;
- 摒弃c++难以理解的多继承和指针等概念;
- 增加了垃圾回收机制!解决了管理内存空间的烦恼;
特点:
java具有有面向对象、平台无关性、简单性、解释执行、多线程、安全性等很多特点
面向对象:Java 只支持类之间的单继承,但是可以使用接口来实现多继承。
平台无关性:“一次编写,到处运行”,因此采用 Java 语言编写的程序具有很好的可移植性,而保证这一点的正是 Java 的虚拟机机制。
简单性:Java 语言的语法与 C 语言和 C++ 语言很相近,上手简单!舍弃c++复杂部分!加入垃圾回收!
解释执行:Java 程序在 Java 平台运行时会被编译成字节码文件,然后可以在有 Java 环境的操作系统上运行。
多线程:Java 支持多个线程同时执行,并提供多线程之间的同步机制。
分布式:Java 语言支持 Internet 应用的开发,在 Java 的基本应用编程接口中就有一个网络应用编程接口,它提供了网络应用编程的类库,包括 URL、URLConnection、Socket 等。Java 的 RIM 机制也是开发分布式应用的重要手段。
健壮性:Java 的强类型机制、异常处理、垃圾回收机制等都是 Java 健壮性的重要保证。
高性能:Java 的高性能主要是相对其他高级脚本语言来说的,随着 **JIT(Just in Time)**的发展,Java 的运行速度也越来越高。
安全性:Java 通常被用在网络环境中,为此,Java 提供了一个安全机制以防止恶意代码的攻击。
2. 面向对象与面向过程的区别?
-面向对象(c++、java……):
为了更好的复用、扩展、维护-面向过程(c):
直接!注重步骤顺序!
Java面向对象三大特性:
- 封装
属性私有化!- 继承
对父类的扩展、子类个性化- 多态
前提:继承+重写+父类引用指向子类子类特有的方法是继承而不是多态!
- 面向对象还有第四个特性:抽象
数据抽象为属性、过程抽象为方法!
3. JDK和JRE和JVM的区别
JDK:(JavaSE Development Kit)java标准的开发包,包含Java编译器、Java运行时环境、以及常用的Java类库等!
JRE:(Java Runtime Environment)Java运行时环境,用于解释执行Java的字节码文件!
JVM:(Java Virtual Mechinal)Java虚拟机;是整个Java实现跨平台的核心!JVM是运行Java字节码的虚拟机。是实现跨平台的关键部分!
总结:
JDK用来开发,JRE用来运行程序!
JDK包含JRE,JRE包含JVM!
JVM是 Java 编程语言的核心并且具有平台独立性。
4. 八种基本数据类型的大小,以及他们的默认值和封装类;
- 封装类的默认值为:null
5. Java中引用数据类型有哪些,它们与基本数据类型有什么区别?
种类:类、接口、数组;
只要不是基本数据类型都是引用数据类型!
与基本数据类型的不同:
概念不同:
- 基本数据类型:变量名指向具体的数值;
- 引用数据类型:变量名不是指向具体的数值,而是指向数据的存储地址,也就是hash值
内存的构建不同:
- 基本数据类型:被创建时,在栈内存中会划分出一定的内存,将数值存在该内存中
- 引用数据类型:堆中存放具体的信息,栈中引用指向堆!
使用方面:
- 基本数据类型:用==和!=判断
- 引用数据类型:
判断内存地址:equals();
判断数值:==;
补充:选择类型的原则
- 如果要表示整数就使用int,表示小数就使用double;
- 如果要描述日期时间数字或者表示文件(或内存)大小用long;
- 如果要实现内容传递或者编码转换使用byte;
- 如果要实现逻辑的控制,可以使用boolean;
- 如果要使用中文,使用char避免中文乱码;
- 如果按照保存范围:byte < int < long < double;
6. instanceof 关键字;
obj instanceof T
判断 obj 是否是 T 的实例化对象、子类
- 实现原理
boolean rs;
if (obj == null) {
rs= false;
} else {
try {
T temp = (T) obj;
rs= true;
} catch (ClassCastException e) {
rs = false;
}
}
return rs;
7. Java自动封箱与拆箱;
装箱就是自动将基本数据类型转换为包装器类型;
拆箱就是自动将包装器类型转换为基本数据类型。
- 在Java SE5之前:自动装箱要这样写:Integer i = new Integer( 10);
- 底层:
装箱:调用包装类的valueOf方法
拆箱:调用new Integer(a).intValue(); 方法
- 为什么要有包装类型?
为了让基本类型也有对象的特征!
如:我们在使用集合类型Collection时就一定要使用包装类型而非基本类型,因为容器都是装object的,这是就需要这些基本类型的包装器类了。
8. a=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;
解释:+= 会把右边的结果强制转换为左边的类型!
9. java修饰符
- 作用:修饰变量、方法(构造方法)、类
- 分类:访问控制 和 非访问控制
访问控制
非访问控制符
- 总结
拓展(重点):
- final 在 Java 中有什么作用?
final作为Java中的关键字可以用于三个地方。用于修饰类、类属性和类方法。
特征:凡是引用final关键字的地方皆不可修改!
(1)修饰类:表示该类不能被继承;
(2)修饰方法:表示方法不能被重写;
(3)修饰变量:表示变量只能一次赋值以后值不能被修改(常量)。如果修饰引用,那么表示引用不可变,引用指向的内容可变.
- 特点:
被final修饰的方法,JVM会尝试将其内联,以提高运行效率
被final修饰的常量,在编译阶段会存入常量池中.
- static都有哪些用法?
除了静态变量和静态方法之外,static也用于静态块,多用于初始化操作
此外static也多用于修饰内部类,此时称之为静态内部类.
最后一种用法就是静态导包,即 import static .
- 解释:import static是在JDK 1.5之后引入的新特性,可以用来指定导入某个类中的静态资源,并且不需要使用类名,可以直接使用资源名,
- static和final区别
10. java异常
发生的原因:
- 用户错误引起:
用户输入流非法数据、要打开的文件不存在、网络通信时连接中断、JVM内存溢出等等- 程序错误引起
- 物理错误引起
异常的层次:
Throwable:Error(错误)、Exception(异常)
Error:通常是灾难性的致命错误,不是程序(程序猿)可以控制的;如:内存耗尽(OOM)、JVM系统错误、堆栈溢出等
Exception:运行时异常(RuntimeException)、编译时异常(IOException)
- RuntimeException:为JVM在运行时自动生成的异常;如:被零除和非法索引、操作数超过数组范围、打开文件不存在等;
JVM不会检查,如果没有抛出或者捕获还是会通过!
是代码本身的问题,需要修改代码
常见五种运行时异常:- IOException:必须手动在代码中添加捕获语句
常见异常:
IOException
FileNotFoundException
SQLException
个人理解:error:通常是系统问题,很难靠程序解决! exception:是设计和实现的问题(很常见)!如果程序正常,不会出现!
JVM要求必须声明抛出可能发送的非运行时异常!
11. 说说你平时是怎么处理 Java 异常的
- 先查看是什么异常:如果是编译时异常,例如文件不存在,会保证文件存在;
- 其次会对异常捕获或抛出异常(代码层面)
try、catch、throw(抛出)、throws(声明) 和 finally
JDK7 之后,Java 新增的 try-with-resource 语法糖来打开资源,并且可以在语句执行完毕后确保每个资源都被自动关闭 。
12. 什么是java序列化,如何实现java序列化?或者请解释Serializable接口的作用。
- 目的:为了网络进行传输或者持久化
- 是什么:将对象的状态信息转换为可以存储或传输的形式的过程
- 实现方法:Serializable接口、Json序列化、FastJson序列化、ProtoBuff序列化
- 作用:jre本身就提供了(将一个java对象变成字节流的形式传出去或者从一个字节流中恢复成一个java对象)的支持,可以以调用 OutputStream 的 writeObject 方法来做,前提:要被传输的对象必须实现 serializable 接口;
- 特点:Serializable 接口,该接口是一个mini接口,其中没有需要实现方法,implements Serializable只是为了标注该对象是可被序列化的。
13. Java 序列化中如果有些字段不想进行序列化,怎么办?
对于不想被序列化的变量,用transient关键字修饰。
- transient关键字的作用就是:阻止用这个关键字修饰的不想被序列化的变量序列化;transient只能修饰变量,不能修饰类和方法。(让JVM跳过该变量)
14. 什么是内部类?内部类的作用
定义:将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。
作用:
成员内部类:
访问行为:成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。
当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。局部内部类:局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。
匿名内部类:匿名内部类就是没有名字的内部类
静态内部类:
实例化情况:指被声明为static的内部类,他可以不依赖内部类而实例,而通常的内部类需要实例化外部类,从而实例化。
类名情况:静态内部类不可以有与外部类有相同的类名。
访问行为:不能访问外部类的普通成员变量,但是可以访问静态成员变量和静态方法(包括私有类型) 一个静态内部类去掉static 就是成员内部类,他可以自由的引用外部类的属性和方法,无论是静态还是非静态。但是不可以有静态属性和方法
15. java泛型、泛型常用特点
泛型是JDK1.5之后的特性:“泛型” 意味着编写的代码可以被不同类型的对象所重用。
- 可以通过规则按照自己的想法控制存储的数据类型。
注意:Java中的泛型是伪泛型;
泛型只在源码中存在,在编译后的字节码文件中,就已经替换为原来的原生类型(Raw Type,也称裸类型)了,并且在相应的地方插入了强制转型代码。因此,在Java程序的运行期中,ArrayList< Integer >和ArrayList< String >就是同一个类。这种泛型实现方法称为类型擦除 ,基于这种方法实现的泛型称为伪泛型。
16. 重载和重写的区别;(类、名、参、返、异权)
重载:在同一个类中、方法名相同、参数列表(类型、个数、顺序)不同、返回值与异常无要求、权限无要求 (发生在编译期)
重写:子类重写父类方法、方法名、参数列表相同、返回值和异常要小于父类、权限要大于父类;(改变的是方法内部逻辑)
17. equals与==的区别、Hashcode的作用
- ==:
基本数据:比较值是否相同
引用数据:比较引用的地址是否相同- equals:本质就是==;
String 和 Integer 等重写了 equals 方法,把它变成了值比较。所以一般情况下equals 比较的是值是否相等。- Hashcode:
用在hash结构中:明确:hash值可能重复,哈希值相同,对象不一定相同;对象相同,hash值一定相同!
hashset如何检查重复:先用hashcode检查是否存在相同hash值,再用equals判断是否为同一个对象!
18. Java创建对象有几种方式?
四种:
- new创建新对象
- 通过反射机制
- 采用clone机制
- 通过序列化机制
19. 深拷贝和浅拷贝的区别是什么?
浅拷贝:
拷贝基本数据类型,对引用数据类型直接使用之前地址,与原来的使用同一个
深拷贝:
拷贝 基本数据类型 和 引用数据类型
20. 获取一个类Class对象的方式有哪些?
搞清楚类对象和实例对象,但都是对象。
第一种:通过类对象的 getClass() 方法获取,细心点的都知道,这个 getClass 是 Object 类里面的
方法。
User user=new User(); //clazz就是一个User的类对象 Class<?> clazz=user.getClass();
第二种:通过类的静态成员表示,每个类都有隐含的静态成员 class。
//clazz就是一个User的类对象 Class<?> clazz=User.class;
第三种:通过 Class 类的静态方法 forName() 方法获取。
Class<?> clazz =Class.forName("com.tian.User");
21. String、StringBuffer 和 StringBuilder 的区别是什么?(想想字符串相加的问题)
String 不可变 : 底层是使用 final 修饰的 char[]、java9后使用byte[] 保存!不可变,线程嘎嘎安全,改变即新建
- StringBuffer 和 StringBuilder
- 共同点:都继承AbstractStringBuilder:
可变的原因:AbstractStringBuilder 使用的char[] 不是final类型,所以两个都可变!- 不同点
线程安全性:
StringBuffer 对方法加了同步锁、或者对调用的方法加了同步锁,所以线程是安全的的! (记忆:buffer:流;通常加锁!)
StringBuilder 未加锁,线程不安全
性能问题:
Strng 生成新对象,重新指向
StringBuffer 自身操作,但是加了锁
StringBuilder 性能最高!但有风险
总结:
操作少量数据:String
单线程大数据:StringBuilder
多线程大数据:StringBuffer
- 常问题目:
String str="i"与 String str=new String(“i”)一样吗?
不一样,因为内存的分配方式不一样。String str="i"的方式,Java 虚拟机会将其分配到常量池中;而
String str=new String(“i”) 则会被分到堆内存中。
String str=new String(“i”) + new String(“j”) 产生多少对象!
- new String(“i”) :一个i在常量池、一个对象在堆中指向i!
‘+’ 的时候:自动生成 StringBuilder 进行 + 操作!
所以一共6个对象!
22. ArrayList和linkedList的区别?(java集合)
从底层数据结构考虑!数组和链表的优缺点!从而考虑到使用场景!
- linkedList 除了继承 List 接口外 还继承了 Deque 接口,可做队列!
23. 用过 ArrayList 吗?说一下它有什么特点?
自动扩容
添加元素:add(o):添加至尾部!add(int,o):插入!
高并发下,线程不安全!
ArrayList 实现了 Cloneable 接口,标识着它可以被复制。注意:ArrayList 里面的 clone() 复制其实是浅复制。
24. 有数组了为什么还要搞个 ArrayList 呢?
定长数组 与 动态数组 的 问题!
25. 说说什么是 fail-fast?
fail-fast 机制是 Java 集合(Collection)中的一种错误机制。当多个线程对同一个集合的内容进行操作(CUD)时,就可能会产生 fail-fast 事件。
解决办法:建议使用“java.util.concurrent 包下的类”去取代“java.util 包下的类”。
26. HashMap和HashTable的区别?(主要为了问HashMap)
- 出生的版本不一样,Hashtable 出生于 Java 发布的第一版本 JDK 1.0,HashMap 出生于JDK 1.2。
- 都实现了 Map、Cloneable、Serializable(当前 JDK 版本 1.8)。
- HashMap 继承的是 AbstractMap,并且 AbstractMap 也实现了 Map 接口。Hashtable 继承Dictionary。
- Hashtable 中大部分 public 修饰普通方法都是 synchronized 字段修饰的,是线程安全的,HashMap 是非线程安全的。
- Hashtable 的 key 不能为 null,value 也不能为 null,这个可以从 Hashtable 源码中的 put 方法看到,判断如果 value 为 null 就直接抛出空指针异常,在 put 方法中计算 key 的 hash 值之前并没有判断 key 为 null 的情况,那说明,这时候如果 key 为空,照样会抛出空指针异常。
- HashMap 的 key 和 value 都可以为 null。在计算 hash 值的时候,有判断,如果
key==null ,则其 hash=0 ;至于 value 是否为 null,根本没有判断过。- Hashtable 直接使用对象的 hash 值。hash 值是 JDK 根据对象的地址或者字符串或者数字算出来的 int 类型的数值。然后再使用除留余数法来获得最终的位置。然而除法运算是非常耗费时
间的,效率很低。**HashMap 为了提高计算效率,将哈希表的大小固定为了 2 的幂,这样在取
模预算时,不需要做除法,只需要做位运算。**位运算比除法的效率要高很多。- Hashtable、HashMap 都使用了 Iterator。而由于历史原因,Hashtable 还使用了
Enumeration 的方式。- 默认情况下,初始容量不同,Hashtable 的初始长度是 11,之后每次扩充容量变为之前的
2n+1(n 为上一次的长度)而 HashMap 的初始长度为 16,之后每次扩充变为原来的两倍。
总结
1、两者父类不同
2、对外提供的接口不同
3、对null的支持不同
4、安全性不同
5、初始容量大小和每次扩充容量大小不同
6、计算hash值的方法不同
7、出现版本不同(此点不答没问题)
通常问完这个就需要往 java 集合来了,什么HashMap 的底层 啊! 线程安全时 使用的 ConcurrentHashMap 的底层啊!(具体的我应该会写个集合的面试题目,敬请期待!!!)
27. HashMap 中的 key 我们可以使用任何类作为 key 吗?
平时可能大家使用的最多的就是使用 String 作为 HashMap 的 key,但是现在我们想使用某个自定义类作为 HashMap 的 key,那就需要注意以下几点:
- 如果类重写了 equals 方法,它也应该重写 hashCode 方法。
- 类的所有实例需要遵循与 equals 和 hashCode 相关的规则。
- 如果一个类没有使用 equals,你不应该在 hashCode 中使用它。
- 咱们自定义 key 类的最佳实践是使之为不可变的,这样,hashCode 值可以被缓存起来,拥有更好的性能。不可变的类也可以确保 hashCode 和 equals 在未来不会改变,这样就会解决与可变相关的问题了。
28. HashMap 的长度为什么是 2 的 N 次方呢?
取余(%)操作中如果除数是 2 的幂次,则等价于与其除数减一的与(&)操作(也就是说
hash % length == hash &(length - 1) 的前提是 length 是 2 的 n 次方)。并且,采用二进
制位操作 & ,相对于 % 能够提高运算效率。
29. Collection包结构,与Collections的区别
Collection是集合类的上级接口,子接口有 Set、List、LinkedList、ArrayList、Vector、Stack、Set;
Collections是集合类的一个帮助(工具)类, 它包含有各种有关集合操作的静态多态方法,用于实现对各种集合的搜索、排序、线程安全化等操作。此类不能实例化,就像一个工具类,服务于Java的Collection框架。
30. Java 中 IO 流分为几种?
分类:
按流的方向(相对于程序):输入流(文件 -> 程序)、输出流(程序 -> 文件)
按操作单元:字节流(8位) 、 字符流(16位)
按角色划分:节点流、处理流
- 为什么有了字节流 还要有 字符流?
- 本质想问:不管是文件读写还是网络发送接收,信息的最小存储单元都是字节,那为什么 I/O 流操作要分为字节流操作和字符流操作呢?”
- 字符流是由Java虚拟机将字节转换得到的,问题就出在这个过程还非常耗时,并且如果不知道编码类型很容易出现乱码问题!
- 所以I/O流就干脆提供一个字节操作字符的接口,便于对字符的操作;如果音频文件、图片就用字节流;而涉及到字符使用字符流比较好!
IO流分类!
以上40多个类从一下4个派生而来:
- InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。
- OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。
31. BIO、NIO、AIO 有什么区别?
BIO:Block IO (同步阻塞IO),传统使用IO,特点是:简单、方便使用;并发处理能力低!
NIO:Non IO(同步非阻塞IO),BIO的升级版本!客户端和服务端通过Channel通讯,实现多路复用!
AIO:Asynchronous IO(异步非阻塞IO),NIO的升级,也叫 NIO2 ,异步操作 基于 事件和回调机制!
总结:
BIO:适合单机
NIO:适合高负载、高并发(JDK1.4引入)
AIO:应用不广 (Java7引入)
32. Files的常用方法都有哪些?
33. Java反射的作用与原理、实现、优缺点
定义:反射机制是在运行时,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意个对象,都能够调用它的任意一个方法。在java中,只要给定类的名字,就可以通过反射机制来获得类的所有信息。
这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。
哪里会用到?
jdbc就是典型的反射
Class.forName('com.mysql.jdbc.Driver.class');//加载MySQL的驱动类
实现方式:
获取Class对象,有4种方法:
1)Class.forName(“类的路径”);
2)类名.class
3)对象名.getClass()
4)基本类型的包装类,可以调用包装类的Type属性来获得该包装类的Class对象
- 优缺点:
优点:
1、能够运行时动态获取类的实例,提高灵活性;
2、与动态编译结合
缺点:
1、使用反射性能较低,需要解析字节码,将内存中的对象进行解析。
- 解决方案:
1、通过setAccessible(true)关闭JDK的安全检查来提升反射速度;
2、多次创建一个类的实例时,有缓存会快很多
3、ReflectASM工具类,通过字节码生成的方式加快反射速度2、相对不安全,破坏了封装性(因为通过反射可以获得私有方法和属性)
34. Java的四种引用,强软弱虚
强引用:强引用是平常中使用最多的引用,强引用在程序内存不足(OOM)的时候也不会被回收,使用方式:
String str = new String("str"); System.out.println(str);
软引用:软引用在程序内存不足时,会被回收,使用方式:
// 注意:wrf这个引用也是强引用,它是指向SoftReference这个对象的,
// 这里的软引用指的是指向new String("str")的引用,也就是SoftReference类中T SoftReference<String> wrf = new SoftReference<String>(new String("str"));
- 可用场景: 创建缓存的时候,创建的对象放进缓存中,当内存不足时,JVM就会回收早先创建的对象。
弱引用:弱引用就是只要JVM垃圾回收器发现了它,就会将之回收,使用方式:
WeakReference<String> wrf = new WeakReference<String>(str);
可用场景: Java源码中的 java.util.WeakHashMap 中的 key 就是使用弱引用,我的理解就是,一旦我不需要某个引用,JVM会自动帮我处理它,这样我就不需要做其它操作。
虚引用:虚引用的回收机制跟弱引用差不多,但是它被回收之前,会被放入 ReferenceQueue 中。注意哦,其它引用是被JVM回收后才被传入 ReferenceQueue 中的。由于这个机制,所以虚引用大多被用于引用销毁前的处理工作。还有就是,虚引用创建的时候,必须带有 ReferenceQueue ,使用例子:
PhantomReference<String> prf = new PhantomReference<String>(new String("str"),new ReferenceQueue<>());
可用场景: 对象销毁前的一些操作,比如说资源释放等。 Object.finalize() 虽然也可以做这类动作,但是这个方式即不安全又低效
35. 3*0.1 == 0.3返回值是什么?
很奇怪的一题!在Java中:30.1=0.30000000000000004,而40.1=0.4!所以此题会返回false!
给个我查看的知乎链接:大家有兴趣自己看看:
https://www.zhihu.com/question/56545018总结一下:既跟浮点数的表示有关,也跟Java的设计机制有关
对于0.1来说,本质是 1 / 10,试着用二进制来算他你就会发现问题!
36. 简述线程、程序、进程、协程的基本概念。以及他们之间关系是什么?
进程:是程序一次执行的过程!是程序执行的基本单位!每个进程有自己独立的空间!通过进程间通信来通信!上下文进程间的切换开销比较大,但相对比较稳定!
程序:是含有指令和数据的文件,被存储在磁盘或其他的数据存储设备中,也就是说程序是静态的代码。
线程:又叫轻量级进程!是CPU调度的最小单位;属于进程,是程序的实际执行者!
- 一个进程有至少一个主线程!和更多子线程!
- 线程也有专属资源,共享进程中的资源;
- 通信:通过共享内存,切换快,资源开销小,比进程不稳定,容易丢失数据!
协程:是一种用户态的轻量级线程!调度由用户控制!
一个线程有多个协程,不由操作系统内核所管理!由程序管理
- 总结
37. Object 有哪些常用方法?大致说一下每个方法的含义
clone 方法
保护方法,实现对象的浅复制,只有实现了 Cloneable 接口才可以调用该方法,否则抛出CloneNotSupportedException 异常,深拷贝也需要实现 Cloneable,同时其成员变量为引用类型的也需要实现 Cloneable,然后重写 clone 方法。
finalize 方法
该方法和垃圾收集器有关系,判断一个对象是否可以被回收(强引用不会回收!)的最后一步就是判断是否重写了此方法。
equals 方法
该方法使用频率非常高。一般 equals 和 == 是不一样的,但是在 Object 中两者是一样的。子类一般都要重写这个方法。
hashCode 方法
该方法用于哈希查找,重写了 equals 方法一般都要重写 hashCode 方法,这个方法在一些具有哈希功能的 Collection 中用到。(HashMap等)
一般必须满足 obj1.equals(obj2)==true 。可以推出 obj1.hashCode()==obj2.hashCode() ,但是hashCode 相等不一定就满足 equals。不过为了提高效率,应该尽量使上面两个条件接近等价。
- JDK 1.6、1.7 默认是返回随机数;
- JDK 1.8 默认是通过和当前线程有关的一个随机数 + 三个确定值,运用 Marsaglia’s xorshiftscheme 随机数算法得到的一个随机数。
wait 方法
配合 synchronized 使用,wait 方法就是使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。wait() 方法一直等待,直到获得锁或者被中断。wait(long timeout)设定一个超时间隔,如果在规定时间内没有获得锁就返回。
调用该方法后当前线程进入睡眠状态,直到以下事件发生。
- 其他线程调用了该对象的 notify 方法;
- 其他线程调用了该对象的 notifyAll 方法;
- 其他线程调用了 interrupt 中断该线程;就抛出一个 InterruptedException 异常
- 时间间隔到了。
notify、notifyAll 方法