常见面试题-1
Contents
Java SE 与 Java EE
- Java SE是Java的基础版本,适合开发桌面引用程序和简单的服务的程序,Java EE是Java的高级版本,适合开发复杂的服务的程序和Web程序
JVM VS JDK VS JRE
- JDK包含JRE,JRE包含JVM
- JVM是Java虚拟机,用来执行Java字节码。虚拟机不是固定的,而是一个规范,只要符合要求,不同的公司具有不同的虚拟机。不同的代码文件都需要通过对应的编译器编译成.class的字节码文件再交给虚拟机运行,例如Java的编译器就是javac
- JDK是Java开发软件包,用于创建和编辑Java程序。
- JRE用来运行已经编译好的Java程序,主要包含JVM和基础类库,基础类提供常用的操作,包含I/O,网络通信等。
- 简单的说就是JRE只包含运行Java程序的环境和类库,而JDK不仅仅包含JRE还包含编译调试Java程序的工具。
什么是字节码
- 字节码就是虚拟机可以理解的代码
- 在Java中代码需要经过编译器编译成 .class 字节码文件,再交给JVM虚拟机,经过解释器一行一行的解释成机器可以理解的代码
- 由于一行一行解释效率很慢,就引入了JIT编译器,JIT是运行时编译,并且编译一次后就将对应字节码的机器码存下来下次直接使用,一般热点代码会使用JIT编译。
- Java语言是解释和编译并存的语言就是因为Java代码需要先由javac编译成.class字节码文件再通过解释器或则JIT编译器转化为机器可以理解的代码执行。
Java和C++的区别
- Java不提供指针访问内存
- Java不允许多继承,但是接口可以多实现。C++可以多继承
- Java由有垃圾回收机制,无需手动释放不需要的内存
- C++同时支持方法和操作符重载,Java只支持方法重载
标识符和关键之
- 标识符是用户定义的一组符号,例如变量名、方法名,关键字是Java中定义好的有特殊含义的标识符。
移位运算符
- 将二进制表示的数左移或则右移n位。
- 左移高位丢弃,低位补零。
- 无符号右移高位补零, 低位丢弃。
- 带符号右移高位补符号位置,低位丢弃。
- float和double不支持移位运算,并且实际上只有int和long支持移位运算,因为其他类型的例如short、byte最终都会提升为int和long进行运算
- 移位运算超出上限会先将要移动的位置mod上上限再进行运算,例如int类型移动42位就是移动42mod32,移动10位。long类型的mod数就是64。
基本类型和包装类型的区别
- 基本类型占用内存比包装类型小
- 基本类型不同类型有各自的默认值,包装类型的默认值都是null
- 基本类型的局部变量存在栈中的局部变量表,成员变量存储在堆中。而包装类型都是对象,全部存储在堆中。
- 基本类型 == 比较的是值,包装类型 == 比较的是对象的地址,因此包装类型值的比较用equals
包装类型的缓存机制
- 包装类型Integer、Long、Shart都初缓存了[-128,127]的范围,创建包装类型时在这个范围内则直接使用。因此创建两个包装类型值都为10,== 实际是相同的。
- Float和Double无缓存,因此创建两个相同值的对象==比较是flase
- 直接创建一个Integer a1 = 11和Integer a2 = new Ingeter(11),实际上是两个不同的对象,因为第一个自动装箱使用的是缓存的对象,第二个实际上创建了一个新的对象
自动装箱与自动拆箱
- 自动装箱就是创建基本类型时调用对应包装类的valueOf()方法
- 自动拆箱就是创建包装类型时自动调用对应的xxxValue()方法
- 当返回值的类型是包装类(基本类型)时,创建了一个基本类型(包装类型)的局部变量进行返回时,就会触发自动装箱(拆箱),由于频繁的自动装箱和拆箱也会影响性能,所以要避免。
成员变量和局部变量的区别
- 成员变量属于类的,可以被private、public、static修饰,局部变量是属于方法的,不可以被上述的修饰符进行修饰,但是二者都可以被final进行修饰。
- 成员变量存储在堆中,局部变量存储在栈帧中
- 成员变量的存活时间长,随着对象的创建而创建,随着垃圾回收而销毁。局部变量的存活时间短,随着方法的创建而创建,随着方法的结束而销毁。
- 成员变量有默认值,因为,成员变量随着对象创建,而他的值可能在后续的setter方法中进行赋值,也可能不赋值,是不可预测的,为了出现未初始化而被使用的错误情况,所有的成员变量都有一个默认值。局部变量是没有默认值的,因为他一定要赋值才能使用。
方法的返回值和类型
- 简单来说,无参无返回值、有参无返回值、有参有返回值、无参有返回值
静态方法为什么不能调用非静态成员
- 静态方法是是static修饰的方法,在类加载时就创建了,而非静态成员是只有实例被创建时才会创建,因此如果允许静态方法可以调用非静态成员就会出现非法操作。
静态方法和成员法的区别
- 静态方法可以通过类名.方法名或则对象名.方法名的方式使用,而成员方法只能通过对象名.方法名的方式使用
重写与重载
- 重载是发生在一个类中的,指一个方法只需要方法名相同即可,参数名、参数数量、返回值、修饰符都可以不相同
- 重写是指子类对父类允许的重写的方法进行逻辑的重写。方法的重写需要遵循两同两小一大,即方法名和参数需要相同;返回类型必须小于或等于父类,抛出的异常必须小于或等于父类;修饰符需要大于等于父类
什么是可变参数
- 用修饰符 …变量名的方式定义,允许调用时传入多个参数
- 可变参数只能作为最后一个参数,前面可以有其他的参数
