一、JAVA基本数据类型
类型 | boolean | byte | char | short | int | long | float | double |
---|---|---|---|---|---|---|---|---|
位数 | 1 | 8 | 16 | 16 | 32 | 64 | 32 | 64 |
强制类型转化: |
1. 高位转低位需要强制转换。
2. 低位转高位自动转。
3. 不带后缀标识的浮点数默认为 double 类型(float后缀为F long后缀为L),将一个int类型赋值给float、long、double时,如果该值超出了int类型的范围,则必须添加后缀
4. byte、short、char类型的运算操作首先会把这些值转化为int类型,然后进行计算,要想获得相应类型的值必须强制类型转化
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200811220652712.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMxODA2MTU1,size_16,color_FFFFFF,t_70)
二、<<符号与>>符号
- 符号<<:相当于前面的数乘以2的n次方,比如3<<3 = 3 * 2^3 = 24
- 符号>>:相当于前面的数除以2的n次方,比如27>>3 得27/2^3 =27/8 = 3
- 无符号右移>>>:例如 a >>> b 指的是将 a 向右移动 b 指定的位数,右移后左边空出的位用零来填充,移出右边的位被丢弃。如果数是正数的话等同于>>。
三、线程的几种状态
- 新建(NEW):新创建了一个线程对象,但还没有调用start()方法。
- 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。
线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。 - 阻塞(BLOCKED):表示线程阻塞于锁。
- 等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
- 定时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回,如wait(long timeout)。
- 终止(TERMINATED):表示该线程已经执行完毕。
四、类初始化顺序
- (静态变量、静态初始化块)>(变量、初始化块)>构造器
- 父类(静态变量、静态初始化块)>子类(静态变量、静态初始化块)>父类(变量,初始化块)>父类(构造器)>子类(变量,初始化块)>子类(构造器)。
五、类继承覆盖测试
六、运算符
-
++i: 先加 1再使用。
-
i++:先使用再加 1。
-
按位与运算(&):二元运算符。当被运算的两个值都为 1 时,运算结果为 1;否则为 0。
-
按位或运算(|):二元运算符。当被运算的两个值都为 0 时,运算结果为 0;否则为 1。
-
按位异或运算(^):二元运算符。当被运算的两个值(二进制)中任意一个为 1,另一个为 0 时,运算结果为 1;否则为 0。
如:4 ^ 3 = 7
-
按位非运算(~):一元运算符。当被运算的值为 1 时,运算结果为 0;当被运算的值为 0 时,运算结果为 1。
简单说就是加1取反:如 7 就是 -(7+1) = -8
七、 volatile、transient 关键字
- 使用了volatile关键字修饰的成员变量具备了如下特性
a. 禁止指令重排序优化。
b. 保证该变量对所有线程具备可见性(当线程A修改了volateile修饰的变量的值时,修改后的值对于其他线程来说是可以立即得知的。) - transient:使用了该关键字修饰后的成员变量不会被序列化。
volatile 通过 happens-before(先行发生原则)来保证可见性
八、 JAVA乐观锁、悲观锁
- 悲观锁:加了synchronized关键字之后,一旦线程获得到了锁,其他线程就会被阻塞。
- 乐观锁:CAS操作,是一种轻量级锁,当线程读取数据时不加锁,在准备会写数据时,比较原值是否被修改,如果值未被其他线程修改,则继续执行,如果值被修改,则重新执行读取操作。
注:CAS操作会 有ABA问题,也就是说一个线程把值改成了B,但是另一个线程把值又改成了A,导致最终判断的线程比较值还是A。
九、类加载的过程
-
加载
1)通过一个类的全限定名来获取定义此类的二进制字节流。
2) 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
3) 在内存中生成一个代表这个类的java.lang.Class对象, 作为方法区这个类的各种数据的访问入口。 -
验证:这一阶段用于确保Class文件的字节流中包含的信息符合《Java虚拟机规范》的全部约束要求,保证这些信息被当作代码运行后不会危害虚拟机自身的安全。验证阶段大致分为:文件格式验证、元数据验证、字节码验证、符号引用验证。
-
准备:为类中定义的变量(静态变量、static修饰的变量)分配内存并设置类变量初始值阶段。
-
解析: 解析阶段是Java虚拟机将常量池内的符号引用替换为直接引用的过程。
-
初始化: 执行类构造器方法的过程。
十、类的生命周期
十一、wait和sleep的区别
在等待时wait 会释放锁,sleep会一直持有锁。 wait通常用于线程间的交互,sleep通常被用于暂停执行。
wait 必须持有对象锁,在while循环里使用wait,因为当线程被唤醒的时候可能业务逻辑还不满足条件,还需要在进行循环进行判断,不满足条件继续wait,这也是不使用if的原因
十二、什么是线程安全
在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行.
十三、interrupt、interrupted、isInterrupted
- interrupt :改变线程的状态,不会中断一个正在运行的线程,需要用户自己去监视线程的状态为并做处理
- interrupted:测试当前线程是否已经中断。如果连续调用该方法,则第二次调用将返回false。在api文档中说明interrupted()方法具有清除状态的功能。执行后具有将状态标识清除为false的功能
注:如果线程状态处于阻塞状态被中断,则会抛 InterruptedException中断异常(该线程必须事先预备好处理此异常),从而提早地终结被阻塞状态 - isInterrupted:测试线程是否已经中断,但是不能清除状态标识。