摘要:Java基础面试题以及个人总结
基本数据类型和其对应的包装类型
- 基本数据类型根据所在 的作用域存放的位置是不一样的;当基本数据类型是局部变量时,存放的位置是栈;当基本数据类型是成员变量时,存放的位置是堆;当基本数据类型作为成员变量存在时,并且被static修饰时,存放的位置仍然是堆,但是类型就不属于是对象了,而是类。
- 为什么几乎所有的对象实例都是存放在堆中?
答:因为当HotSpot虚拟机引入JIT后,就开始对对象进行逃逸分析,如果发现某一对象没有逃逸到方法外,则通过标量替换来实现栈上分配,而避免堆上分配内存
- 包装类型的缓存机制?
Byte Short Integer Long:当对应的一个基本数据类型的值在-128到127范围内的时候,经过包装类的方法valueOf, 返回一个包装类缓存机制中对于这个数值在缓存中存在的数值的对应的地址IntegerCache.cache[i+(-IntegerCache.low)] (i+ (–128)) i+128;如果不存在,则会创建一个新的对象。
对于两个相同的整数,都是在-128-127的范围的时候,相互比较可以使用== 进行比较,由于他们的都是来自同一个缓存数组,元素下标相同,他们的地址是一致的,所以使用==比较时地址相同,则转而比较数值
但是如果是两个不相同的数,并且不再缓存机制范围内的时候,如果想要比较数值,就必须使用equals方法进行比较,使用==比较的是地址
Character包装类的缓存机制范围:0~127
Boolean包装类直接返回TRUE 或者 FALSE
Float和Double包装类没有缓存机制
- 装箱: 调用对应包装类的valueOf方法;拆箱:调用对应包装类的xxxValue方法;
- 浮点数运算导致精度丢失的原因:计算机存储一个数字的宽度是有限的,无限循环的小数就会被截断,也就是浮点数不能使用二进制精确的表示;
使用BigDecimal类可以进行浮点数的运算,不会出现精度丢失的情况,但是进行加减乘除取模需要使用对应的方法
变量
- 成员变量和局部变量的区别?
成员变量定义在方法外,局部变量定义在方法内;
被static修饰的成员变量属于类,没有被static修饰的成员变量属于对象实例;
没有被static修饰的成员变量存储在堆内存中,局部变量存储在栈内存中;
成员变量在没有赋值的情况下,是自带默认值的,局部变量必须要赋值;
局部变量不能被static修饰,成员变量可以被static修饰,成为静态变量;
成员变量和局部变量都可以被final修饰;
- 静态变量有什么作用?
被static修饰变量成为静态变量,通过类名.变量名访问
静态变量一般会与final一起使用,修饰成静态常量,常量可以避免被继承修改
- 字符型常量和字符串常量的区别
字符型常量由单引号来表示一个字符,字符串常量由双引号来表示一个字符串;
字符型常量只有两个字节,字符串常量有若干个字节;
字符型常量可以表示一个ASCII值;字符串常量则表示一个地址,给字符串值分配的内存地址;
方法
- 静态方法为什么不能调用非静态成员?
静态方法是属于类的,在类加载的时候,就被分配内存;非静态的成员是属于对象实例的,只有在创建实例之后,非静态成员才存在,所以当我们在没有创建对象的时候去访问非静态册成员就会报错。
- 静态方法和实例方法有什么区别?
静态方法的调用方式是 类名.静态方法名,也可以是对象.静态方法名;实例方法只能通过第二种方式访问。
静态方法中只能去访问静态成员,不能访问实例成员;实例方法没有限制。
- 重载和重写的区别?
重载是在同一个类中,有若干个方法名相同,参数不相同的方法;
重写是在子类中,子类继承来自父类的方法,如果对父类的方法进行逻辑的修改,就要使用注解@Override表示进行了重写,覆盖原来的父类的方法。
重载的发生的阶段处于编译期,重写的发生阶段处于运行期。
对于重写,重写必须遵从两同两小一大
两同:方法名,参数必须相同
两小:子类的返回值类型应该比父类的小或者相等;子类定义抛出的异常必须比父类的小或者相等、
一大:子类的修饰符范围必须比父类的修饰符范围大
- 什么是可变长参数
允许调用方法时传入不定长度的参数
public static void method(String… arg){
}
当发生重载的时候,会优先匹配固定长度的方法。