java位运算
<<
:左移运算符,向左移若干位,高位丢弃,低位补零。x << 1,相当于 x 乘以 2(不溢出的情况下)。
>>
:带符号右移,向右移若干位,高位补符号位,低位丢弃。正数高位补 0,负数高位补 1。x >> 1
,相当于 x 除以 2。
>>>
:无符号右移,忽略符号位,空位都以 0 补齐。
由于 double
,float
在二进制中的表现比较特殊,因此不能来进行移位操作。
移位操作符实际上支持的类型只有int
和long
,编译器在对short
、byte
、char
类型进行移位前,都会将其转换为int
类型再操作。
基本类型和包装类型的区别
基本数据类型 | 包装类型 | |
---|---|---|
存储方式 | 基本数据类型的局部变量存放在 Java 虚拟机栈中的局部变量表中,基本数据类型的成员变量(未被 static 修饰 )存放在 Java 虚拟机的堆中 | 包装类型属于对象类型,我们知道几乎所有对象实例都存在于堆中 |
占用空间 | 小 | 大 |
默认值 | 有特定的默认值 | null |
比较方式 | == | equals() |
基本数据类型的成员变量如果没有被 static
修饰的话(不建议这么使用,应该要使用基本数据类型对应的包装类型),就存放在堆中。
包装类型的缓存机制了解么?
java 基本数据类型的包装类型的大部分都用到了缓存机制来提升性能。
Byte
,Short
,Integer
,Long
这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character
创建了数值在 [0,127] 范围的缓存数据
两种浮点数类型的包装类 Float
,Double
并没有实现缓存机制。
Boolean
直接返回 True
or False
,没有实现缓存机制。
所有整型包装类对象之间值的比较,全部使用 equals 方法比较。
自动装箱与拆箱了解吗?原理是什么?
- 装箱:将基本类型用它们对应的引用类型包装起来;Integer i = 10;
- 拆箱:将包装类型转换为基本数据类型;int n = i
原理:装箱其实就是调用了 包装类的valueOf()
方法,拆箱其实就是调用了 xxxValue()
方法。
在实际开发中,如果频繁拆装箱的话,也会严重影响系统的性能。我们应该尽量避免不必要的拆装箱操作。
Integer i = 10
等价于Integer i = Integer.valueOf(10)
int n = i
等价于int n = i.intValue()
;
为什么浮点数运算的时候会有精度丢失的风险?怎么解决
因为计算机存储数据是二进制的,在表示一个数字时,其宽度是有限的,无限循环的小数存储在计算机时
会被截断,所以会导致数精度发生损失的情况,导致浮点数没有办法用二进制精确表示。
解决方法:采用BigDecimal对浮点数进行存储和计算,不会造成精度丢失。通常情况下,大部分需要浮点数精确运算结果的业务场景(比如涉及到钱的场景)都是通过 BigDecimal
来做的
超过Long整形的数据如何表示
基本数值类型都有一个表达范围,如果超过这个范围就会有数值溢出的风险。
用BigInteger可以表示超过Long整形的数据,其内部使用int[ ]数组来存储任意大小的整形数据,相对于常规整数类型的运算来说,BigInteger
运算的效率会相对较低。
成员变量和局部变量的区别
成员变量 | 局部变量 | |
---|---|---|
语法形式 | 属于类或对象 可以被 public ,private ,static 等修饰符所修饰 | 属于代码块或方法参数 不可以被 public ,private ,static 等修饰符所修饰 |
存储方式(对象类型都是在内存的,这里讨论的是其句柄) | static修饰->栈内存 无static修饰->堆内存 | 栈内存 |
生存时间 | 随着对象的创建而存在,回收而结束 | 随着方法的调用而自动生成,随着方法的调用结束而消亡 |
默认值 | 如果没有被赋初始值,则会自动以类型的默认值而赋值(一种情况例外:被 final 修饰的成员变量也必须显式地赋值) | 不会自动赋值 |
静态变量的作用
静态变量即被 static
关键字修饰的变量。它可以被类的所有实例对象共享,静态变量只会被分配一次内存,即使创建多个对象,这样可以节省内存。
通常情况下,静态变量会被 final
关键字修饰成为常量。
重载和重写有什么区别?
重载是同一个类中多个同名方法根据不同的传参来执行不同的逻辑处理。
重载发生在编译期
方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同
重写是子类对父类允许访问的方法的实现过程进行重新编写,即覆盖父类方法。
- 重写发生在运行期,方法名、参数列表必须相同,子类方法返回值类型应比父类方法返回值类型更小或相等,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类。
- 如果父类方法访问修饰符为 private/final/static 则子类就不能重写该方法,但是被
static
修饰的方法能够被再次声明。 - 构造方法无法被重写
对“可变长参数”的理解
java从Java5开始支持定义可变长参数。
可变长参数就是允许在调用方法时传入不定长度的参数,即0个或多个参数。用参数类型加…表示
可变参数只能作为函数的最后一个参数,但其前面可以有也可以没有任何其他参数。
当遇到方法重载时,会优先匹配固定参数的方法。