Java面试复习
Java面试大纲
立志于找到一份Java开发工作
Java开发环境
1、Java编译过程
- Java语言编译原理
- 编写Java源文件(.Java)首先要经过编译,生成字节码文件(.class);
- Java程序运行需要JVM的支持,JVM是安装在操作系统上的软件,为字节码文件提供运行环境;
Java源文件---------------->字节码文件------------------->JVM(Java虚拟机-----操作系统)
- 一次编程到处使用–跨平台上
- Java官方提供了针对不同平台的JVM软件,遵循着相同的规则,只要是.class文件,就可以在不同的JVM上运行
- Java运行时期
- 编译期:Java源程序------javac编译命令------>.class字节码文件
- 运行期:-----通过Java命令启动jvm---->{jvm:加载.class----->运行.class}
2、JVM,JRE,JDK之间的关系
- JDK:java developmenmt kit (java开发工具包)
- JRE:java runtime environment (Java运行环境)
- JVM: java virtual mechines (Java虚拟机)
- JRE:java runtime environment (Java运行环境)
基本数据类型
1、八种基本类型
-
byte :1字节,存储字节数据
-
short :2字节,兼容性考虑
-
int :4字节,存储普通整数
-
long :8字节,长整数
-
float :4字节,存储浮点数
-
double :8字节,双精度浮点数
-
boolean:1字节,true/false
-
char :2字节,存储一个字符
2、数据类型详解
- 公式:-2^(n-1) ~~~ 2^(n-1) -1
- int的取值范围: -2^31 ~ 2^31-1
- long的取值范围: -263~263-1
- short的取值范围:-215~215-1
- byte的取值范围: -27~27-1 (-128~127)
- 通过时间毫秒数来存储日期和时间
- JDK提供了一个方法,返回1970年1月1日0点0分0秒到此时此刻所经历的毫秒数,其数据类型为 long
long time = System.currentTimeMillis();
System.out.println(time);
- double运算时会出现舍入误差(面试)
2进制中无法精确地表示1/10,就和10进制无法精确表示1/3一样。
- 二进制表示10进制可能会有误差
double money = 3.0;
double price =2.9;
System.out.println(money- price);//输出结果为0.100000000009 舍入误差!
- char
- 本质是一个16位无符号整数,所在编码Unicode编码
- 整数变量:0~65535之间的整数数值
- 字符直接量:用单引号括起来的内容就为字符的实际内容
- Unicode形式:‘\uoo4e’…Unicode的16进制形式
//1.char型变量赋值
char c1 = 65;
char c2 = 'A';
char c3 = '\u0041';
System.out.println(c1);//A
System.out.println(c2);//A
System.out.println(c3);//A
- 转义字符
转义 | 含义 |
---|---|
‘\n’ | 回车符 |
‘\r’ | 换行符 |
‘’’ | 单引号 |
‘"’ | 双引号 |
‘’ | 单斜杠 |
3.基本类型间的转换
-
基本类型转换
基本类型转换(隐式类型转换):小类型–>大类型
byte -->short -->int -->long -->float -->doublechar ---------------^
-
强制类型转换:大类型–>小类型
- 需要转换符
- 造成精度丢失或者数据溢出
5.数据类型之间的转换
(1)、字符串如何转基本数据类型?
调用基本数据类型对应的包装类中的方法 parseXXX(String)或 valueOf(String)即可返回相应基本类型。
(2)、基本数据类型如何转字符串?
一种方法是将基本数据类型与空字符串(“”)连接(+)即可获得其所对应的字符串;另一种方法是调用 String
类中的 valueOf()方法返回相应字符串。
运算符
1.& 和 && 的区别
&运算符有两种用法:(1)按位与;(2)逻辑与。
&&运算符是短路与运算。逻辑与跟短路与的差别是非常巨大的,虽然二者都要求运算符左右两端的布尔值都是
true 整个表达式的值才是 true。
&&之所以称为短路运算是因为,如果&&左边的表达式的值是 false,右边的表达式会被直接短路掉,不会进行
运算。很多时候我们可能都需要用&&而不是&,例如在验证用户登录时判定用户名不是 null 而且不是空字符串,应
当写为 username != null &&!username.equals(“”),二者的顺序不能交换,更不能用&运算符,因为第一个条件如
果不成立,根本不能进行字符串的 equals 比较,否则会产生 NullPointerException 异常。
注意:逻辑或运算符(|)和短路或运算符(||)的差别也是如此。
常考关键字
1.关键字static
- static存在的主要意义
static的主要意义是在于创建独立于具体对象的域变量或者方法。以致于即使没有创建对象,也能使用属性和调用方法!
为什么说static块可以用来优化程序性能,是因为它的特性:只会在类加载的时候执行一次。因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。 - static修饰
- static修饰变量
将修饰的成员变量存储在静态存储区,不在为对象所有,而属于类属性 - static修饰方法
可以使用"类名.方法名"的方式操作方法,避免了先要new出对象的繁琐和资源消耗 - static修饰代码块
只会在类加载的时候执行一次,用来优化程序性能 - static静态导包
将类的方法直接导入到当前类中,从而直接使用“方法名”即可调用类方法,更加方便
- static修饰变量
2.关键字final
- final的几种用法
- 修饰变量
- 用final关键字修饰的变量,只能进行一次赋值操作,并且在生成周期内无法改变它的值。final修饰的变量可以先声明,后赋值。
- final修饰基本数据类型时,起到了常量作用;
- final修饰引用数据类型时,引用的是对象的地址,其值可以被修改;
- final在修饰成员变量时,必须在定义或者构造器中进行初始化赋值,而局部变量只需保证在使用之前被初始化赋值;
- 修饰方法参数
- 编写方法时,可以在参数前面加上final关键字
- 修饰方法
- final关键字修饰方法,表示该方法不能被覆盖(重写);另外,类中所有的private方法都隐式地指定为是final的。
- 修饰类
- 用final修饰的类是无法被继承。且final类中的所有成员方法都是被隐式的指定为final方法
- 修饰变量
- final变量和普通变量的区别
- 当final变量是基本数据类型以及String类型时,如果在编译期间知道它的确切值,则会将其当作编译期常量使用,而普通变量的访问则需要在运行时通过链接来进行;
- final、static、static final修饰的字段赋值的区别
- static关键字:static修饰的字段会在类加载过程中的准备阶段被初始化为0或者null,而后在初始化阶段(触发类构造器)才会被赋值,没有则默认
- final关键字:final修饰的字段在运行时被初始化(可以直接赋值或者在实例构造器中赋值),一旦赋值不可更改
- static final修饰的字段在javac时生成Constant Value属性,在类加载的准备阶段根据该属性的值为该字段赋值,没有默认值,必须显式的赋值。理解:在编译期间就把结果放入了常量池
- final关键字的好处
- final关键字提高了性能,JVM和Java应用都会缓存final变量
- final变量可以安全的在多线程环境下进行共享,而不需要额外的同步开销
- 使用final关键字,JVM会对方法,变量以及类进行优化
- 在匿名类中所有变量都必须时final变量
- final于abstract相反
- 使用final方法的原因
- 锁定方法,防止任何继承类修改它的含义
- 效率方面:已经不需要了
-
final、finally、finalize 有什么区别?
final可以修饰类,变量,方法,修饰的类不能被继承,修饰的变量不能重新赋值,修饰的方法不能被重写finally用于抛异常,finally代码块内语句无论是否发生异常,都会在执行finally,常用于一些流的关闭。
finalize方法用于垃圾回收。
一般情况下不需要我们实现finalize,当对象被回收的时候需要释放一些资源,比如socket链接,在对象初始化时创建,整个生命周期内有效,那么需要实现finalize方法,关闭这个链接。
但是当调用finalize方法后,并不意味着gc会立即回收该对象,所以有可能真正调用的时候,对象又不需要回收了,然后到了真正要回收的时候,因为之前调用过一次,这次又不会调用了,产生问题。所以,不推荐使用finalize方法。
数组
1.数组元素的反转
//方法一:
for(int i = 0;i < arr.length / 2;i++){
String temp = arr[i];
arr[i] = arr[arr.length - i -1];
arr[arr.length - i -1] = temp;
}
//方法二:
for(int i = 0,j = arr.length - 1;i < j;i++,j--){
String temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
2.数组正序和逆序输出
//1.定义数组,长度为10
int[] num = new int[10];
//2.通过元素下标赋值随机数
for (int i = 0; i < num.length; i++) {
Random ran = new Random();
num[i] = ran.nextInt(100);
}
//3.正序遍历
for (int i = 0; i < num.length; i++) {
System.out