Java面试题归档(一)
参考网站JavaGuide整理
JAVA
java语言的特点
- 简单易学
- 面向对象(封装、继承、多态)
- 平台无关性(虚拟机实现)
- 支持多线程(C语言无内置多线程机制,java提供了)
- 可靠性
- 安全性
- 支持网络编程并且很方便
- 编译与解释并存
JVM vs JDK vs JRE
- JVM: java虚拟机是运行java字节码的java虚拟机。 字节码和不同系统的JVM实现是java语言“一次编译,随处可以运行”的关键所在。
- JDK: 拥有JRE的一切,并且还有编译器(javac)和工具。
- JRE: Java运行时环境,包括JVM
为什么说Java语言“编译与解释并存”
- 因为java程序要经过先编译,后解释两个编译步骤,由Java编写的程序需要先经过编译步骤,生成字节码(.class文件),这种字节码必须由Java解释器来解释执行。
Java和C++的区别
-
Java和C++都是面向对象的语言,都支持封装、继承、多态;
-
Java不提供指针来直接访问内存,因此Java更加安全;
-
Java的类是单继承,C++支持多重继承,但是Java的类接口可以多实现;
-
Java有自动内存管理垃圾回收机制,不需要程序员手动释放无用内存。
-
C++支持方法重载和操作符重载,Java只支持方法重载。
-
支持多线程(C语言无内置多线程机制,java提供了)
成员变量和局部变量的区别
- 语法形式:成员变量是属于类的,而局部变量是在代码块或方法中定义的变量或者方法的参数;成员变量可以被访问控制修饰符所修饰,局部变量不能被访问控制修饰符和static所修饰,但是都可以被final所修饰;
- 存储方式:如果成员变量是使用static修饰的,那么这个成员变量是属于类的,如果没有使用static修饰,这个成员变量是属于实例的。实例对象存放在堆内存,局部变量存放在栈中;
- 生存时间:成员变量属于对象的一部分,他随着对象的创建而存在,而局部变量的随着方法的调用而自动生成,随着方法的调用结束而消亡;
- 默认值:从变量是否具有默认值来看,成员变量如果没有被赋初始值,则会自动以类型的默认值而赋值(final修饰的变量必须显式赋值),而局部变量不会被自动赋值。
静态方法为什么不能调用非静态成员
- 静态方法是属于类的,在类加载的时候就会分配内存,可以通过类名直接访问。而非静态对象属于实例对象,只有在对象实例化之后才存在,需要通过类的实例对象去访问。
- 在类的非静态成员不存在的时候静态成员就已经存在了,此时调用在内存中还不存在的非静态成员,属于非法操作。
静态方法和实例方法的不同
-
调用方式
在外部调用静态方法时,可以使用 类名.方法名 的方式,也可以使用 对象.方法名 的方式,而实例方法只有后面这种方式。调用静态方法无需创建对象。
-
访问类成员是否存在限制
静态方法在访问本类成员的时候,只允许访问静态成员,不允许访问实例成员,而实例方法不存在限制。
重载和重写的区别
- 重载发生在 编译期 同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同、方法返回值类型和访问修饰符可以不同。
- 重写发生在 **运行期 **间,方法名、参数列表必须相同,子类返回值类型应该比父类方法更小或者相等,抛出异常范围小于等于父类,访问修饰符范围大于等父类;如果父类方法访问修饰符为 private/final/static 则子类不能重写该方法,但是被static修饰的方法能够被再次声明;构造方法无法被重写。
基本类型和包装类型的区别
- 成员变量包装类型不赋值就是null,而基本类型有默认值且不是null;
- 包装类型可用于泛型,而基本类型不可以;
- 包装数据类型的局部变量存放在Java虚拟机栈中的局部变量表中,基本数据类型的成员变量(未被static修饰存放在Java虚拟机的堆中)。包装类型属于对象累心给,我们知道几乎所有的对象实例都存放在堆中;
- 相比于对象类型,基本类型占用的空间非常少。
包装类型的缓存机制
-
Java基本数据类型的包装类的大部分都默认使用缓存机制来提升性能。
-
Byte,Short,Integer,Long默认创建数值 [-128,127]的相应类型的缓存数据,Chracter创建了数值在[0,127]范围的缓存数据,Boolean直接返回True或者False。Float, Double并没有实现缓存机制。
-
所有整型包装类对象之间的值比较,全部使用equals方法比较。
自动装箱与拆箱的原理
- 装箱:将基本类型用他们对应的引用类型包装起来;Integer i = Integer.valueOf(10);
- 拆箱:将包装类型转换为基本数据类型。int n = i.intValue();
如果频繁拆箱装箱的话,也会严重影响系统的性能,我们应该避免不必要的拆箱装箱操作。
浮点数在运算时丢失精度和超过Long的数据问题
-
使用BigDecimal可以实现对浮点数的运算,不会造成精度丢失,比如大部分涉及到钱的场景。
-
BigInteger内部使用int[] 数组来存储任意大小的整型数据, 但运算效率会降低。