注:网页版右上方的悬浮框有目录索引
一、Java基础
1】简述 JVM 的运行原理
-
Java平台
- 由 Java 虚拟机和 Java 应用程序接口搭建,Java 语言是进入这个平台的通道,使用 Java 编写并编译的程序可以运行在这个平台上 运行期
- 运行期环境代表着 Java 平台,开发人员编写 .java 文件,然后编译成字节码(.class 文件),再装入内存。一但字节进入虚拟机,就会被解释器执行或补即时代码发生器有选择的转换成机器转换成机器码执行
2】JVM 内存组成结构
- JVM 栈由、堆、栈、本地方法栈、方法区等部分组成
-
堆
-
- 通过 new 创建的对象的内存都在堆中分配,堆的大小可以通过 -Xmx 和 -Xms 来控制
-
- 堆被划分为新生代和旧生代,新生代又被进一步划分为 Eden 和 Survivor 区,最后 Survivor 由 From Space 和 To Space 组成
栈
-
- 每个线程执行每个方法的时候都会在栈中申请一个栈帧,每个栈帧包括局部变量和操作数栈,用于存放此次方法调用过程中的临时变、参数和中间结果。
本地方法栈
-
- 用于支持 native 方法的执行,存储了每个 native 方法调用的状态
方法区
-
- 存放了要加载的类信息、静态变量、final 类型变量、属性和方法信息。用 JVM 持久代(Permanet Generation)来存放方法区,可通过 -Xx:permSize 和 -XX:MaxPermSize 来指定最小值和最大值
注:软件配置文件(.ini)可设置部分属性大小
注:native 关键字:Java 调用非 Java 代码的接口
3】GC 是什么?为什么要有 GC?
- GC 是垃圾收集的意思(Gabage Collection)
- Java 提供的 GC 功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java 语言没有提供释放已分配内存的显示操作方法。
4】简单阐述垃圾回收机制
- 回收的内容是 new 出来的对象所占内存
- 垃圾回收只与内存有关,清理内存外的资源依靠 finalize() 方法。垃圾回收机制在回收某个对象的内存前会调用该对象的 finalize() 方法
- 垃圾回收以单独的线程在后台运行,为减少虚拟机额外消耗,一般在内存不足时会进行垃圾回收。所以就算强制系统垃圾回收,垃圾回收也不一定发生
- 对象在内存中的状态有:可达状态、可恢复状态、不可达状态,当处于“可恢复状态”是可能会进行垃圾回收
5】解释内存中的栈(stack)、堆(heap)和静态区(static area)的用法
-
栈
-
- 基本数据类型的变量、一个对象的引用、函数调用的现场保护:使用内存中的栈空间
-
- 栈空间操作起来最快,但栈很小
堆
-
- 通过 new 关键字和构造器创建的对象放在堆空间
-
- 通常存放大量的对象
-
- 理论上:整个内存没有被使用的空间、硬盘上的虚拟内存都可以被当成堆空间来使用
静态区
-
- 程序中字面量(literal:字面意义的)如:直接书写的 100、“HelloWorld!” 和常量都是放在静态区中。
二、变量和数据类型
1】char 型变量中能不能存储一个中文汉字?为什么?
- 可以
- 一个 char 占16 个字节(2 位),以 unicode 编码。
注:unicode 编码中存有汉字编码
2】有不同的方法交换两个数的位置?
- 建立一个新的临时变量
- 指针方法:取两个数的地址,进入交换
- 加减交换
- 异或方法交换
public class Test {
int a = 1;
int b = 2;
/*
* 异或交换
*/
public void exchange_1(Test t){
System.out.println("\t 异或交换"); // 异或交换
System.out.println("交换前:a="+t.a+",b="+t.b); // 交换前:a=1,b=2
t.a = t.a^t.b;
t.b = t.a^t.b;
t.a = t.a^t.b;
System.out.println("交换后:a="+t.a+",b="+t.b); // 交换后:a=2,b=1
}
public static void main(String[] args) {
Test t = new Test();
t.exchange_1(t);
}
}
3】数据类型有哪些
- 整数:byte、short、int、long
- 浮点数:float、double
- 布尔:boolean
- 字符:char
4】说出一些常用的类、包、接接口、异常,各举例五个
-
类
-
- BufferedReader、BufferedWriter、FileReader、FileWirter、String、Integer
包
-
- java.lang、java.awt、java.io、java.util、java.sql
接口
-
- Remote、List、Map、Document、NodeList
异常
-
- ArithmeticException:算术错误异常
-
- ArrayIndexOutOfBoundsException:数组下标越界
-
- NullPointerException:空指针异常
-
- ClassNotFoundException:不能加载所需的类
-
- InputMismatchException:输入类型不匹配
-
- ClassCastException:强制转换异常
-
- NumberFormatException:数字格式转换异常
4】最有效的方法算出 2 乘以 8 等于几
2 << 2
三、选择结构
1】switch 是否能作用在 byte 上,是否能作用在 long 上,是否能作用在 String 上
- switch(expr1):expr1 是一个整数表达式
- 因此传递给 switch 和 case 语句的参数应该是 int、short、char 或者 byte
- long、String 都不能作用于 switch
2】& 和 && 的区别
- & 和 && 都是逻辑运算符号,&& 又叫短路运算符
-
&
-
- 两边判断表达式都将执行
-
- 两边为非判断表达式时,将以 运算与 身份运行
System.out.println("***与操作***");
System.out.println("1 0 1 1:11");
System.out.println("1 1 0 1:13");
System.out.println("1 0 0 1:09");
System.out.println("\n11&13:"+(11&13)); // 11&13:9
-
&&
-
- 若前面条件不正确,则后面条件不会执行
3】short s1=1;s1=s1+1;
有什么错?short s1=1;s1+=1;
有什么错
-
- 1 默认为 int 型,int(4字节)、shout(2字节);大转小需要强制转换
-
- 可以正确编译,复合赋值【E1 op=E2】可以理解为【E1=(T)((E1) op (E2))】
short s1=1; s1=s1+1;
short s1=1;s1+=1;
4】在一个问题中如果能同时使用多个 if 和 if-else 完成操作,你会选择什么?为什么
- 选择 if-else :执行效率高
- 如果有相似的判断方式,我会考虑 switch
5】== 和 equals() 都可以返回一个 true 或者 false 的结果,请问二者有什么区别?
-
==
-
- ==可以比较基本数据类型的值,也可以比较引用数据类型的值。可以理解为比较内存中的地址
equals
-
- 如果 equals 没有被重写,效果等同于“==”,例:String 类重写了 equals,它的作用是比较内容是否相同
四、循环结构
1】for 循环的语法和执行顺序
2】while do-while for 有一种循环的语法和适用场景是什么?
-
while
-
- 语法:
while(){}
- 语法:
-
- 使用场景:循环次数不固定的时候
-
- 先判断后执行
do-while
-
- 语法:
do{}while(条件){}
- 语法:
-
- 使用场景:循环次数不固定的时候
-
- 先执行后判断
for
-
- 语法:
for( ; ; ){}
- 语法:
-
- 使用场景:循环次数固定的时候使用
-
- 先判断后执行
3】break 和 continue 的区别是什么?
-
break
-
- 跳出循环体
continue
-
- 结束本次循环,进入下一次循环
4】最简单的方式打印死循环?
for(;;){}
5】String s = new String("xyz")
创建了几个 String Object?
- 两个或一个
- “xyz”:对应一个对象,这个对象放在字符串常量缓冲区
- 缓冲区对应的“xyz”,仅且只有一个。若在此句代码之间已有“xyz”,则此句代码不会创建新的字符串“xyz,而是从缓冲区中取
五、多重循环及调试
1】说出算术运算符、关系运算符、逻辑运算符、赋值运算符、位运算符的优先级
- 算术>关系>位运算符>逻辑>赋值
2】double 和 long 谁的范围大?
- double
System.out.println("double 最大值:"+Double.MAX_VALUE); // double 最大值:1.7976931348623157E308
System.out.println("long 最大值:"+Long.MAX_VALUE); // long 最大值:9223372036854775807
3】请用一行代码写出闰年的计算方式
year % 4 == 0 && year % 100 != 0 || year % 400 == 0
4】阐述基本数据类型的包装类是哪些
基本数据类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
double | Double |
float | Float |
char | Character |
boolean | Boolean |
5】描述断点调试的步骤
- 分析错误,设置断点
- 启动调试
- 单步运行
- 观察变量
- 发现问题
- 修正代码,重新运行
- 解决问题
六、一维数组及经典应用
1】数组的概念
- 相同数据类型的数据集合
- 指针从 0 开始
// 一维数据的定义
int[] arr1 = new int[3];
int[] arr2 = new int[]{1,2,3,4};
int[] arr3 = {1,2,3,4,5};
// 输出数组长度
System.out.println(arr1.length+" "+arr2.length+" "+arr3.length);
2】数组在平时的程序代码中使用是否频繁?
- 数组有一缺点:一时声明,便不可改变容量,且内容类型固定
- 因此不频繁
3】实现数组排序和查询相应元素的索引方法是什么?
- Arrays 类的 sort() 方法实现排序功能;
- binarySearch() 方法实现查找元素索引功能;(使用此方法前,数组必须为有序数组)
4】数组有没有 length() 方法? String 有没有 length() 方法?
- 数组没有 length() 方法,有 length 属性。
- String 有 length() 方法。
5】手写冒泡排序
public void show() {
int[] numbers = new int[] { 9, 7, 5, 4, 2, 1, 0, 11, 44214, 123, 124 };
int i, j;
for (i = 0; i < numbers.length - 1; i++) {
for (j = 0; j < numbers.length - 1 - i; j++) {
if (numbers[j] > numbers[j + 1]) {
int temp = numbers[j];
numbers[j] = numbers[j + 1];
numbers[j + 1] = temp;
}
}
}
System.out.println("从小到大排序后的结果是:");
for (i = 0; i < numbers.length; i++)
System.out.print(numbers[i] + " ");
}
七、二维数组及经典应用
1】使用双重循环编程
/*
* 输出杨辉三角形
*/
public static void main(String[] args) {
int[][] arr=new int[10][];
// 给数组 arr[]][] 每一行定义,与行号相等的长度
for(int i=0;i<arr.length;i++) {
arr[i]=new int[i+1];
}
// 赋值
for(int i=0;i<arr.length;i++) {
for(int j=0;j<arr[i].length;j++) {
if(j==0 || i==j) {
arr[i][j]=1;
}else {
arr[i][j]=arr[i-1][j]+arr[i-1][j-1];
}
}
}
// 输出
for(int i=0;i<arr.length;i++) {
for(int j=0;j<arr[i].length;j++) {
System.out.print(arr[i][j]+"\t");
}
System.out.println();
}
}
2】遍历二维数组
/*
* 遍历二维数组
*/
public static void main(String[] args) {
/*
* 二维数组初始化
* 三种方式
*/
// 方式一
int[][] arr1 ={{1},{1,2},{1,2,3}};
// 方式二
int[][] arr2 = new int[][]{{4},{4,6},{4,5,6}};
// 方式三:第行长度随机 [0,9)
int[][] arr3 = new int[10][];
for(int i=0;i<arr3.length;i++){
arr3[i] = new int[(int) (Math.random()*10)];
}
// 将数组(arr1/arr2/arr3)对象赋值给 arr 数组
int[][] arr = arr3;
for(int i=0;i<arr.length;i++){
for(int j=0;j<arr[i].length;j++){
// %-5d:左对齐,占五个位置
// %5d:右对齐,占五个位置
System.out.format("%-5d", arr[i][j]);
}
System.out.println();
}
}
3】判断某个数是否存在于数组中
public static void main(String[] args) {
// 初始化数组
int[][] arr = new int[10][];
// 每行随机设置长度
for(int i=0;i<arr.length;i++){
arr[i] = new int[(int) (Math.random()*10)];
}
// 随机赋值
for(int i=0;i<arr.length;i++){
for(int j=0;j<arr[i].length;j++){
arr[i][j] = (int)(Math.random()*10);
}
}
// 获取从键盘键入的数值
int taget = new Scanner(System.in).nextInt();
ok:
for(int i=0;i<arr.length;i++){
for(int j=0;j<arr[i].length;j++){
if(arr[i][j] == taget){
System.out.println("键入的值:"+taget+",存在于数组中。" +
"位于:i="+i+"、j="+j);
break ok;
}
}
}
}
4】java 中是否有 goto?
- java 中的保留字,现在没有在 java 中使用
八、实例
1】jdk 和 jre 的区别是什么?
-
JRE
-
- Java 运行环境(JRE)是将要执行 Java 程序的 Java 虚拟机
-
- 同时包含了执行 applet 需要的浏览器插件
JDK
-
- Java 开发工具包(JDK)是完整的 Java 软件开发包
-
- 包含了 JRE,编译器和其他的工具(比如:JavaDoc、Java 调试器)
-
- 可以让开发者开发、编译、执行 Java 应用程序
2】如果对象的引用被置为 null,垃圾收集器是否会立即释放对象占用的内存?
- 不会,在下一个垃圾回收周期中,这个对象将是可被回收的
3】串行(serial)收集器和吞吐量(throughput)收集器的区别是什么?
-
串行收集器
-
- 对大多数的小应用(需要大概 100M 左右的内存)就足够了
吞吐量收集器
-
- 使用并行版本的新生代垃圾收集器,它用于中等规模和大规模数据的应用程序
4】String 是基本的数据类型吗?如果不是那么和 String 同种类型的数据类型还有哪些?
- 不是,String 是引用数据类型
- 引用数据类型还有类,接口和数组
5】在 Java 中,对象什么时候可以被垃圾回收?
- 对象 对 当前使用这个对象的应用程序 变得不可触及的时候,这个对象就可以被回收了