考试分数占比
卷A
- 单选题:30道,每题1分
- 判断题:10道,每题1分
- 程序阅读题:5道,每题6分
- 编程题:2道,每题15分
卷B
- 单选题:20道
- 判断题:10道
- 填空题:10道
成绩占比:
- 平时成绩:30%
- 前七章占比:85%
考试重点归纳总结
第一章:JAVA语言基础背景知识(单选题,判断题,大题不难)
- Java的发展历史: Java是由Sun Microsystems的工程师James Gosling于20世纪90年代初开发的。起初是为嵌入式系统设计,后来成为一种面向对象的编程语言,以跨平台特性和安全性而著称。
- Java的平台:
- Java SE(Standard Edition): 用于桌面应用程序和通用开发。
- Java EE(Enterprise Edition): 专注于企业级应用程序开发。
- Java ME(Micro Edition): 用于嵌入式系统和移动设备。
- 平台的作用和特点:
- Java SE: 用于通用开发,有丰富的库和API支持,可构建桌面应用。
- Java EE: 针对企业级应用程序开发,包括Web应用和企业系统。
- Java ME: 针对嵌入式系统和移动设备,用于开发针对这些设备的应用程序。
- Java的特点:
- 跨平台性: Java的“编写一次,到处运行”特性,可在不同平台上运行。
- 面向对象: 支持封装、继承和多态。
- 自动内存管理: 具有垃圾回收机制,无需手动管理内存。
- 安全性: 提供字节码验证和安全沙箱等安全特性,有助于防止恶意代码执行。
- 与C、C 的异同比较:
- 相同点: C、C 和Java都是编程语言,具有通用的编程能力。
- 不同点:
- 内存管理: C、C 需要手动管理内存,而Java有垃圾回收机制。
- 平台依赖性: C、C 代码是平台相关的,而Java具有跨平台能力。
- 语言特性: C、C 更接近底层,而Java更注重安全性和易用性。
- 什么是面向对象:
- 面向对象(Object-Oriented)是一种编程范式,它以对象作为程序设计的基本单元,将数据和操作数据的方法封装在一起。面向对象编程思想使得程序更易于理解、维护和扩展。
- 面型对象的特征:
- 封装(Encapsulation): 将数据和操作数据的方法封装在对象内部,只暴露必要的接口给外部使用。这样可以控制数据的访问权限,提高了安全性和灵活性。
- 继承(Inheritance): 允许一个类(子类/派生类)继承另一个类(父类/基类)的属性和方法。子类可以复用父类的特性,减少重复代码,提高了代码的可重用性和扩展性。
- 多态(Polymorphism): 允许不同类的对象对同一消息做出响应,即允许同样的方法调用在不同对象上有不同的行为。多态提高了代码的灵活性和可维护性。
- 实现对象和类的关系:
- 类: 类是对象的模板,定义了对象的属性和行为。
- 对象: 对象是类的实例,包含了类定义的属性和方法。
- 关系: 类定义了对象的结构,对象是类的具体实例。在Java中,通过定义类来创建对象,类描述了对象的结构和行为,实例化类可以创建对象,然后使用这些对象调用方法或访问属性。
第二章:hello world,第一个Java程序
- 一个完整的Java应用程序的组成部分:
- 源代码文件(.java文件): 包含程序员编写的Java代码。
- 类和对象: Java是面向对象的语言,程序由一个或多个类组成,类描述了对象的属性和行为,对象是类的实例。
- 主类(Main Class): 包含
public static void main(String[] args)
方法的类,作为程序的入口点。
- public class 和普通类的区别:
public class
是指公共可访问的类,其类名必须与文件名完全相同。- 普通类是包级私有的,只能在同一个包内被访问。
- 文件中有public class时的文件命名:
- 文件名必须与
public class
的类名完全一致,包括大小写。
- 文件名必须与
- 文件中是否可以有多个类或多个public class:
- 一个文件中只能有一个
public class
,但可以包含多个普通类。
- 一个文件中只能有一个
- 写主函数(psvm):
- 主函数(
main
方法)必须包含在类中,作为程序的入口点。 - 主函数的声明:
public static void main(String[] args)
。
- 主函数(
- Java程序的编译和运行:
- 使用
javac
命令编译Java源文件(.java文件),例如:javac YourFileName.java
。 - 使用
java
命令运行编译后的字节码文件(.class文件),例如:java YourCompiledFileName
(无后缀)。在运行Java程序时如果需要输入参数,可以在命令行中通过 java 命令后面跟随程序的名称和参数来执行。假设有一个名为 MyProgram 的Java类,它包含了一个 main 方法,可以通过以下方式运行并传递参数: - 这里的
arg1
,arg2
,arg3
是要传递给程序的参数,你可以根据实际需求传入任意数量的参数。在程序中,可以通过String[]
形参接收传入的参数: - 可以通过命令行向主函数传递参数,在程序中通过
args
数组获取。 .class
文件中包含了字节码(Bytecode)
。这些 .class 文件包含了Java源代码编译后的二进制指令,这些指令并不是直接在硬件上执行的机器码,而是Java虚拟机(JVM)可以识别和执行的中间代码。
- 使用
java MyProgram arg1 arg2 arg3 ...
代码语言:javascript复制public class MyProgram {
public static void main(String[] args) {
// args 数组包含了传入的参数
for (String arg : args) {
System.out.println(arg);
}
}
}
- 多个class或接口对应的文件数量:
- 每个
public class
或普通类会编译成一个对应的 .class 文件。 - 如果有多个class,编译后会有多个对应的 .class 文件。
- 如果加了接口,编译后也会有一个对应的 .class 文件。
- 每个
第三章:Java基础概览:数据类型、运算符、程序结构与数组(重点内容)
数据类型
- 基本数据类型有哪些?它们的长度是否会根据不同类型而变化?
- Java的基本数据类型包括:
byte
、short
、int
、long
、float
、double
、char
、boolean
。 - 这些基本数据类型在Java中各自占用的字节数是固定的,不会根据不同数据而变化。比如,
int
类型一般占用4个字节(32位),double
类型一般占用8个字节(64位)。
- Java的基本数据类型包括:
- 基本数据类型的位数大致是多少?比如整型的取值范围是多大?
byte
(8位)、short
(16位)、int
(32位)、long
(64位)、float
(32位)、double
(64位)、char
(16位,Unicode字符)、boolean
(未定义)。- 整型的取值范围:
byte
:8位,范围为 -128 到 127short
:16位,范围为 -32768 到 32767int
:32位,范围为 -2147483648 到 2147483647long
:64位,范围为 -9223372036854775808 到 9223372036854775807
引用类型和类型转换
- 除了基本数据类型外,Java中还有哪些引用类型?
- 类(Class):是面向对象编程的基础,用于描述对象的属性和行为。
- 接口(Interface):定义了一组方法的集合,但没有具体的实现,通过实现接口的类来提供方法的具体实现。
- 数组(Array):可以存储多个相同类型的元素的数据结构。
- 枚举(Enum):表示一组固定的常量,限定了变量的取值范围。
- String:用于表示文本字符串的引用类型。
- 集合框架(Collection Framework):包括List、Set、Queue和Map等各种数据结构,用于存储和操作对象的集合。
- 自定义引用类型:通过类或接口定义的自定义数据类型。
- 在Java中,除了基本数据类型(如int、double等),大部分类型都属于引用类型。这些引用类型允许开发者更灵活地处理数据和对象,并且它们在内存中存储的是对象的引用或地址,而不是实际的数据值。
- 基本数据类型之间可以进行哪些类型转换?自动转换、隐式转换、强制转换的区别是什么?
- 基本数据类型之间可以进行自动转换(从小范围类型到大范围类型),例如
int
转换为long
。 - 隐式转换是指在程序编译期间由编译器自动完成的类型转换,确保转换不会造成数据丢失或错误。
- 强制转换是指开发者手动进行的类型转换,需要注意可能会发生数据丢失或溢出的情况。
- 基本数据类型之间可以进行自动转换(从小范围类型到大范围类型),例如
- 在Java中,默认的整型和浮点型的字面量分别是什么?
- 整型的默认字面量是
int
类型,浮点型的默认字面量是double
类型。
- 整型的默认字面量是
定义变量和常量,注释
变量的标识符由什么组成?合法和非法的标识符有哪些?
- 变量的标识符由字母、数字、下划线和美元符号组成,但不能以数字开头,还有关键词也不行。
- 合法的标识符示例:
myVar
、_value
、age123
。 - 非法的标识符示例:
123var
、my-Var
、$money#
。
在Java中,如何定义变量和常量?
定义变量: 使用关键字和标识符,例如 int myVar;
或 String name = "John";
。
定义常量: 使用 final
关键字,例如 final double PI = 3.14;
。
静态成员: 使用 static
关键字创建类级别的变量、方法或静态块。静态变量属于类,与对象实例无关,而静态方法可通过类名直接调用。静态块是在类加载时执行的代码块,用于执行静态变量的初始化或其他类加载时需要执行的逻辑。
public class Example {
public static int count = 0; // 静态变量
public static void printMessage() { // 静态方法
System.out.println("Hello, World!");
}
static {
// 静态块
System.out.println("This is a static block.");
}
}
Java中的注释有哪些类型?如何书写这些注释?
单行注释:使用 //
,例如 // 这是单行注释
。
多行注释:使用 /* */
,例如 /* 这是多行注释 */
。
文档注释:以 /** */
开始,通常用于生成API文档,例如:
/**
* 这是文档注释,描述方法或类的作用
*/
运算符
- Java中的运算符分为哪几种类型?一元运算符和二元运算符的例子有哪些?
- Java中的运算符分为算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符等。
- 一元运算符示例:负号
-
,递增--
。 - 二元运算符示例:加法
-
,乘法*
,除法/
,取模%
。 - 三元运算符示例:只有一个:
? :
- 算术运算符的特点是什么?在整数相除时会发生什么?
- 算术运算符包括加法
-
、乘法*
、除法/
、取模%
。 - 在整数相除时,如果两个整数相除,结果也是整数,小数部分会被舍弃,需要重点注意一下。
- 关系运算符的种类有哪些?Java中的等于运算符存在什么问题?
关系运算符包括大于 >
、小于 <
、大于等于 >=
、小于等于 <=
、等于 ==
、不等于 !=
。
在Java中,==
运算符用于比较两个对象引用(即内存中对象的地址)是否相同,而不是比较对象的内容是否相同。当使用 ==
比较两个对象引用时:
如果比较的是基本数据类型(如 int
, char
, double
等),则比较的是它们的值。
如果比较的是引用类型(如对象),则比较的是对象的引用,即对象在内存中的地址。
==
比较的是对象的引用地址,而 .equals()
方法则是根据对象的内容来进行比较。
如果想要比较两个对象的内容是否相同,应该使用 .equals()
方法(对于自定义类需要覆盖 equals()
方法以适应对象内容的比较),示例:
String str1 = "Hello";
String str2 = new String("Hello");
System.out.println(str1 == str2); // 这里将输出 false,因为str1和str2引用不同的对象
System.out.println(str1.equals(str2)); // 这里将输出 true,因为使用了equals()方法比较的是内容是否相同
自增自减运算符放在前面和后面的区别是什么?
i
(前置自增)会先进行自增操作,然后再使用变量。i
(后置自增)会先使用变量,然后再进行自增操作。- 下面是一些例题:
- 在Java中,
--
运算符的行为取决于它们的位置,前置和后置的区别。
int i = 5000;
int result = (i ) (i ) (i ); // 此行代码的结果是多少?
System.out.println(result); // 结果为 15003
解释:
i
是后置自增运算符,它先返回i
的当前值(5000),然后将i
的值加一。- 在
result
的计算中,第一个(i )
返回的是i
的当前值5000,此时i
变为5001。 - 第二个
(i )
返回的是i
的当前值5001,此时i
变为5002。 - 第三个
(i )
返回的是i
的当前值5002,此时i
变为5003。 - 最后将这三个返回值相加,即
5000 5001 5002 = 15003
。
类似的例子:
代码语言:javascript复制int a = 10;
int b = a a a ; // 结果是多少?
System.out.println(b); // 结果是 34
解释:
a
返回值为10
,此时a
变成11
。a
返回值为12
,此时a
变成12
。a
返回值为12
,此时a
变成13
。- 然后将
10 12 12 = 34
。
逻辑、位运算和优先级
逻辑运算符和位运算符有什么作用?
- 逻辑运算符用于逻辑表达式,包括逻辑与
&&
、逻辑或||
、逻辑非!
等,用于布尔值的操作。 - 位运算符用于对整数的二进制位进行操作,包括按位与
&
、按位或|
、按位异或^
等,用于位级操作。 - 在Java中,
&
和|
是按位与和按位或运算符,而&&
和||
是逻辑与和逻辑或运算符。 - **按位与
&
和逻辑与&&
**:&
执行按位与操作,对两个操作数的每一位执行与操作。&&
执行逻辑与操作,对两个布尔表达式进行短路求值,即如果第一个表达式为false
,则不再计算第二个表达式。
int a = 5; // 二进制:0101
int b = 3; // 二进制:0011
int c = a & b; // 按位与操作:0001 (结果为1)
boolean d = (a < b) && (a != 0); // 逻辑与操作:false (因为a < b为false)
- **按位或
|
和逻辑或||
**:|
执行按位或操作,对两个操作数的每一位执行或操作。||
执行逻辑或操作,对两个布尔表达式进行短路求值,即如果第一个表达式为true
,则不再计算第二个表达式。
int a = 5; // 二进制:0101
int b = 3; // 二进制:0011
int c = a | b; // 按位或操作:0111 (结果为7)
boolean d = (a > b) || (b != 0); // 逻辑或操作:true (因为a > b为true)
- 区别:
- 按位与和按位或是对两个操作数的每一位执行位操作,无论操作数的类型是整数还是布尔值都会执行位运算。
- 逻辑与和逻辑或是对两个布尔表达式进行逻辑运算,并且具有短路求值的特性,根据第一个表达式的结果来决定是否计算第二个表达式。
Java中各个运算符的优先级大致是怎样的?
- 运算符有不同的优先级,例如算术运算符优先级高于关系运算符,逻辑运算符等。
- 优先级高的运算符会先于优先级低的运算符进行计算。
- 下面是运算符优先级表,从上往下从高到低,在表格中越靠上的运算符优先级越高,在表达式中会优先执行:
运算符 | 描述 |
---|---|
() | 圆括号 |
, -- | 后缀递增/递减 |
, - | 正号、负号 |
!, ~ | 逻辑非、按位取反 |
*, /, % | 乘法、除法、取模 |
, - | 加法、减法 |
<<, >>, >>> | 左移、右移、无符号右移 |
<, <=, >, >=, instanceof | 小于、小于等于、大于、大于等于、instanceof |
==, != | 等于、不等于 |
& | 按位与 |
^ | 按位异或 |
| | 按位或 |
&& | 逻辑与 |
|| | 逻辑或 |
? : | 条件运算符 |
=, =, -=,*=, /=, %= | 赋值运算符及组合赋值运算符 |
赋值运算符和程序结构
赋值运算符的作用是什么?Java中可以进行连续赋值吗?
- 赋值运算符用于将右侧的值赋给左侧的变量,例如
int x = 10;
。 - Java中可以进行连续赋值,例如
int a = b = c = 10;
,这里的值会从右向左依次赋给变量。
程序运行的结构是怎样的?在Java中,循环和判断结构是如何使用的?
- 程序运行是从上到下依次执行的,遇到循环、判断等控制结构会按照条件进行分支执行。
- 顺序结构(Sequence Structure):按照代码的书写顺序一行一行地执行,从上到下顺序执行代码。这是最基本的程序执行方式,代码按照写入的顺序依次执行。
- 选择结构(Selection Structure):根据条件选择性地执行代码块。主要有 if-else 语句、switch 语句等。根据条件的真假执行不同的代码分支。
- 当使用
switch
语句时,有一些注意事项:- 括号中变量的要求:
switch
后面的括号中必须是一个可以转换为整数的表达式或者变量,比如整数、字符、枚举或者可以自动转换为整数的表达式。 - case:
case
是用于匹配值的标签。当switch
中的变量与case
后的值匹配时,程序会从匹配的case
开始执行。注意,case
中的值必须是常量表达式,不允许使用变量。 - break:
break
语句用于跳出switch
语句。如果不在case
后使用break
,程序将继续执行下一个case
直到遇到break
或switch
结束。 - default:
default
是可选的,用于处理switch
中没有匹配到任何case
值的情况。它类似于if-else
结构中的else
,处理除了case
中列出的值之外的情况。
- 括号中变量的要求:
- 总的来说,
switch
语句中的每个case
应该以break
结束,以避免执行后续的case
。而default
是可选的,用于处理未匹配到case
值的情况。
- 当使用
- 循环结构(Loop Structure):重复执行一段代码,直到满足退出条件为止。主要有 for 循环、while 循环、do-while 循环等。根据条件重复执行代码块,直到条件不再满足。
int num = 2;
switch (num) {
case 1:
// 执行语句
break;
case 2:
// 执行语句
// 注意:如果没有 break,程序会继续执行下面的 case,直到遇到 break 或 switch 结束
break;
default:
// 默认情况,如果上面的 case 都不匹配,则执行 default 中的语句
break;
}
在switch语句中,变量的要求是什么?break和default的作用分别是什么?
switch
语句中的变量可以是整数类型(int
、byte
、short
、char
)或枚举类型。break
用于退出switch
语句,防止继续执行其他case
或default
分支。default
是switch
语句中的默认分支,用于当没有匹配的case
时执行。
循环和控制语句
- for循环的三段分号的作用是什么?while和do-while循环的逻辑区别是什么?
for
循环的三段分号分别是初始化语句、循环条件、循环后操作,它们分别在进入循环前、每次循环前和每次循环后执行。while
循环在循环开始前先判断条件是否成立,如果不成立,则一次都不执行。do-while
循环则是先执行一次循环体,再判断条件是否成立。
- continue和break在循环中的作用是什么?带标签的break有什么用途?
continue
用于跳过循环体内剩余的代码,直接进入下一次循环。break
用于完全退出当前循环结构,不再执行循环体内的代码。- 带标签的
break
可以用于退出嵌套循环,可以指定要退出的是哪一个循环。
// 使用 continue 跳过偶数并打印奇数
for (int i = 1; i <= 10; i ) {
if (i % 2 == 0) {
continue; // 跳过偶数
}
System.out.print(i " "); // 打印奇数
}
// 输出结果:1 3 5 7 9
System.out.println(); // 换行
// 使用 break 完全退出循环
for (int i = 1; i <= 10; i ) {
if (i == 5) {
break; // 当 i 等于 5 时退出循环
}
System.out.print(i " ");
}
// 输出结果:1 2 3 4
System.out.println(); // 换行
// 带标签的 break 用于退出嵌套循环
outerLoop: // 外部循环标签
for (int i = 1; i <= 3; i ) {
for (int j = 1; j <= 3; j ) {
if (i == 2 && j == 2) {
break outerLoop; // 当 i 和 j 均为 2 时退出外部循环
}
System.out.println("i = " i ", j = " j);
}
}
数组
- 数组的定义和元素组成是怎样的?在Java中,数组长度是否可以变化?
- 数组是具有相同数据类型的元素的集合,在Java中用方括号
[]
定义,例如int[] numbers = new int[5];
。 - 数组的元素可以是基本数据类型或对象类型。
- 在Java中,一旦数组被创建,其长度就是固定的,无法直接改变。
- 数组是具有相同数据类型的元素的集合,在Java中用方括号
- 如何访问数组中的元素?数组的初始化方式有哪些?
- 可以通过索引(下标)访问数组中的元素,索引从0开始计数。
- 数组可以使用大括号
{}
进行初始化,例如int[] numbers = {1, 2, 3, 4, 5};
。
- 一维数组和多维数组有什么区别?数组元素的赋值方式是怎样的?
- 一维数组是一个线性的数据结构,而多维数组是数组的数组,例如二维数组
int[][] matrix = new int[3][3];
。 - 数组元素的赋值可以通过索引直接赋值,例如
numbers[0] = 10;
。
- 一维数组是一个线性的数据结构,而多维数组是数组的数组,例如二维数组
- 数组的展示:
numbers
是一个包含5个整数的一维数组,names
是一个包含3个字符串的一维数组。- 通过
numbers[0]
和numbers[1]
可以访问并设置数组的第一个和第二个元素。 initializedArray
是使用大括号初始化的一维数组。matrix
是一个3x3的二维数组,通过[i][j]
访问不同行和列的元素,并对其进行赋值。
// 数组的定义和元素组成
int[] numbers = new int[5]; // 定义一个包含5个整数的数组
String[] names = new String[3]; // 定义一个包含3个字符串的数组
// 访问数组中的元素
numbers[0] = 10; // 设置数组第一个元素为10
numbers[1] = 20; // 设置数组第二个元素为20
// 数组的初始化方式
int[] initializedArray = {1, 2, 3, 4, 5}; // 使用大括号初始化数组
// 多维数组
int[][] matrix = new int[3][3]; // 定义一个3x3的二维数组
// 数组元素的赋值方式
matrix[0][0] = 1; // 第一行第一列的元素赋值为1
matrix[1][1] = 2; // 第二行第二列的元素赋值为2
第四章:Java面向对象编程基础探索
类中的成员变量和方法定义
- 类怎么定义,成员变量或字段或属性的定义,赋初值,如果没有赋值初始值,能否直接使用?
- 在Java中,定义一个类包括以下几个部分:
- 类的定义
- 在类中定义的变量被称为成员变量、字段或属性。示例中的
myField
就是一个私有的整型成员变量。这些变量可以使用不同的访问修饰符来控制其可见性和访问权限,比如private
、public
、protected
等。 - 如果没有显式赋值初始值,Java会为基本数据类型的成员变量赋予默认值,而不是null。如下:
int
类型的默认值为0
boolean
类型的默认值为false
double
类型的默认值为0.0
- 对象类型的默认值为
null
- 在Java中,如果没有给成员变量赋值初始值,它们仍然会被分配默认值,因此可以直接使用。但是,这可能会导致意想不到的结果,因此最好在使用前为其赋予合适的初值,以避免不确定的情况发生。
public class MyClass {
// 成员变量/字段/属性的定义
private int myField; // 声明一个私有的整型成员变量
// 构造方法
public MyClass() {
// 构造方法
}
// 方法
public void myMethod() {
// 方法体
}
}
- 方法的定义和方法头是什么?方法的签名和参数声明方式是怎样的?方法可以重名吗?
- 方法是类中的函数,由返回类型、方法名、参数列表和方法体组成。方法的签名由方法名和参数列表组成,用于唯一标识一个方法。参数声明指定了方法接受的参数类型和参数名。
- 在Java中,方法可以拥有相同的名称但具有不同的参数列表,这就是方法的重载(Overloading)。方法重载允许在同一个类中定义多个具有相同名称但参数列表不同的方法。参数列表不同可以通过以下方式之一进行区分:
- 参数个数不同
- 参数类型不同
- 参数顺序不同
- 举例来说,下面这两个方法就构成了重载:
public class Example {
public void doSomething(int num) {
// 执行一些操作
}
public void doSomething(double num) {
// 执行一些不同的操作,参数类型不同
}
}
- 方法的调用以及对基本类型和引用类型的参数传递方式?
- 方法的调用使用方法名和参数列表,传递参数可以是基本类型或引用类型。基本类型参数是按值传递,传递的是值的拷贝,而引用类型参数传递的是引用的地址。
- 方法的返回值,void和有返回值的情况下如何使用return?
- 方法可以有返回值,也可以没有(使用
void
)。有返回值的方法使用return
关键字返回结果,void
方法不返回任何值。
- 方法可以有返回值,也可以没有(使用
- 一个函数能否有多个return语句?参数表的不同情况会怎样影响方法的识别?
- 一个函数可以有多个
return
语句,但只有一个会被执行。方法的识别取决于方法名和参数列表的唯一性。
- 一个函数可以有多个
- 函数重载和传入不同类型参数对方法的影响?
- 函数重载是指在同一个类中,方法名相同但参数列表不同的多个方法。传入不同类型参数会根据参数的数量、顺序、类型来调用相应的方法。
- 函数在使用时,对于基本类型参数和引用类型参数的调用和实际使用赋值是怎么样的?
- 函数在使用时对于基本类型参数和引用类型参数的处理方式有所不同:
- 1、基本类型参数(如 int、double 等)
- 调用方式: 传递的是参数的值。
- 实际使用: 在函数中对参数的任何修改不会影响到原始值。因为基本类型参数传递的是值的拷贝,函数中对参数的操作只影响到了拷贝的值。
- 2、引用类型参数(如对象)
- 调用方式: - 传递的是对象的引用(地址)。
- 实际使用: - 在函数中对对象的内容的修改会影响到原始对象,因为传递的是引用,指向同一个对象。修改引用指向的内容会反映在原始对象上。
- 基本类型参数传递的是值的拷贝,函数内部对参数的修改不影响原始值;而引用类型参数传递的是引用(地址),对参数所指向对象的修改会影响到原始对象。
public void manipulatePrimitive(int num) {
num = num * 2; // 对参数进行修改,但不影响原始值
}
public static void main(String[] args) {
int value = 10;
manipulatePrimitive(value);
System.out.println(value); // 输出仍然是 10,原始值未改变
}
代码语言:javascript复制class MyClass {
int number;
MyClass(int number) {
this.number = number;
}
}
public void manipulateReference(MyClass obj) {
obj.number = obj.number * 2; // 修改对象内容,会影响原始对象
}
public static void main(String[] args) {
MyClass obj = new MyClass(5);
manipulateReference(obj);
System.out.println(obj.number); // 输出是 10,原始对象被修改
}
构造方法和类的继承
- 构造方法与类同名,无返回值。构造方法可以重载吗?一个类可以有多个构造方法吗?
- 构造方法与类同名,没有返回值。构造方法可以重载,即在同一个类中可以有多个构造方法,它们具有不同的参数列表,参数表为空的,叫缺省构造方法。
- 没有提供构造方法时编译器会自动添加构造方法,构造方法之间的相互调用需要使用关键字吗?
- 当类中没有显式提供构造方法时,编译器会自动生成默认的无参构造方法。构造方法之间的相互调用可以使用
this
关键字,用于调用同一个类中的其他构造方法。this
关键字在Java中扮演着多重角色。它代表当前对象的引用,允许在类的方法中访问成员变量和方法。这种引用的灵活性让代码更清晰易读。此外,this
还能够在构造方法中调用其他构造方法,减少代码冗余,并作为方法返回值返回当前对象。
- 当类中没有显式提供构造方法时,编译器会自动生成默认的无参构造方法。构造方法之间的相互调用可以使用
public class MyClass {
private int number;
public MyClass(int number) {
this.number = number; // 使用 this 引用成员变量
}
public void printNumber() {
System.out.println(this.number); // 在方法中使用 this 引用成员变量
}
public MyClass increment() {
this.number ; // 使用 this 在方法中操作成员变量
return this; // 返回当前对象
}
public void anotherMethod() {
this.increment(); // 在方法中调用其他方法
}
}
- 关于继承,子类如何表达对父类的继承?继承关系中子类继承了什么?
- 子类通过
extends
关键字表达对父类的继承。继承关系中,子类继承了父类的非私有成员变量和方法。 - 在Java中,子类和父类之间是一种继承关系。这种关系是单一继承的,意味着一个类只能直接继承自一个父类。
- 继承关系有如下特点:
- 继承性:子类继承了父类的特性,可以访问父类的非私有成员变量和方法。
- 派生性:子类可以在继承的基础上拓展,增加新的成员变量和方法。
- 多态性:子类对象可以被当做父类对象使用,这是多态性的一种表现。
- 父子关系:子类是父类的扩展,拥有父类的属性和行为。
- 子类通过
// 父类
class Animal {
void eat() {
System.out.println("Animal is eating.");
}
}
// 子类
class Dog extends Animal {
void bark() {
System.out.println("Dog is barking.");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat(); // 子类对象能够调用父类的方法
dog.bark(); // 子类对象可以调用自己独有的方法
}
}
- 多层继承结构中创建子类对象是否需要调用父类对象?super关键字的作用?
- 在多层继承中,创建子类对象不需要直接调用父类对象。
super
关键字用于在子类中访问父类的成员变量或调用父类的构造方法。 在Java中,显示调用和隐式调用通常指的是在继承关系中,子类对父类方法的调用方式。 - 显示调用(Explicit Invocation): 子类调用父类的方法时,使用
super
关键字显式指明调用的是父类的方法。这种调用方式明确指示了调用的是父类的特定方法。 - 隐式调用(Implicit Invocation): 子类调用父类的方法时,如果没有使用
super
关键字,系统会默认调用父类的对应方法(如果子类没有重写该方法)。这种调用方式不明确指示调用的是父类的方法,而是隐含地依赖于继承关系。 - 在这个例子中,
makeSound()
方法在Dog
类中被重写了。performSound()
方法内部调用makeSound()
方法时,没有显式使用super
关键字,因此隐式调用的是子类Dog
的makeSound()
方法。
- 在多层继承中,创建子类对象不需要直接调用父类对象。
class Animal {
void makeSound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
void makeSound() {
super.makeSound(); // 显式调用父类方法
System.out.println("Dog barks");
}
}
代码语言:javascript复制class Animal {
void makeSound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
void performSound() {
makeSound(); // 隐式调用父类方法
}
}
- 方法的覆盖和重载,以及子类和父类之间相互转换?
- 覆盖(Override)和重载(Overload)是Java中两个不同的概念,用于描述方法的行为。
- 1、覆盖(Override):
- 定义: 在继承关系中,子类可以对父类的方法进行覆盖,也就是在子类中重新实现(重写)父类的方法。子类中的方法签名必须与父类中被覆盖的方法相同(方法名、参数列表和返回类型完全一致)。
- 目的: 允许子类提供自己的实现,替换父类的方法实现。这使得在运行时,调用子类对象的该方法时会执行子类的实现,而不是父类的实现。
- 发生条件: 子类覆盖父类方法必须保持方法签名一致,否则编译器将不会识别为覆盖。
- 2、重载(Overload):
- 定义: 在同一个类中,可以定义多个方法,这些方法具有相同的名称但是参数列表不同(参数类型、参数个数或者参数顺序不同)。
- 目的: 允许使用相同的方法名来提供不同的行为。Java编译器根据不同的方法签名来区分并调用适当的方法。
- 发生条件: 方法名称相同,但参数列表必须不同。
- 3、异同点:
- 相同点:
- 都涉及方法的名称和参数列表。
- 都可以让程序员提供不同的实现方式。
- 不同点:
- 覆盖是子类重写父类中的方法,方法签名必须一致;重载是在同一个类中,方法名相同但方法签名不同。
- 覆盖发生在继承关系中,重载发生在同一个类中。
- 覆盖只能通过子类覆盖父类的方法;重载可以在同一个类中定义多个具有相同名称但不同参数列表的方法。
- 相同点:
- 总体来说,覆盖是方法的多态性表现,重载是方法的多样性表现。覆盖允许子类提供自己的实现以替代父类方法,而重载允许在同一个类中提供多个同名但不同参数列表的方法。
包、访问控制符、static
- 包的引入方式和package、import的使用顺序?Java的访问控制符有哪些?
- 包的引入使用
package
关键字声明在Java文件的开头。import
关键字用于引入其他包中的类。package
声明应该在import
之前。 - Java中有四种访问控制符,它们用于限制类、变量、方法和构造方法的访问范围:
- public: 公共访问级别,对所有类可见。被声明为 public 的类、变量、方法和构造方法可以被任何其他类访问。
- protected: 受保护访问级别,在同一包内的类和所有子类可见。被声明为 protected 的成员可以在同一包内的其他类中访问,并且也可以被子类访问。
- default(不写访问控制符): 默认访问级别,仅在同一包内可见。如果不使用任何访问控制符,则默认为包级私有,只能在同一包内的其他类中访问。
- private: 私有访问级别,只有本类内部可见。被声明为 private 的成员只能在定义它们的类内部访问,其他任何类都无法访问。这就是封装,一般我们会设置seter和geter来读取值。
- 在Java中,类可以被声明为私有的,但是有些限制:
- 私有内部类(Private Inner Class): 类可以嵌套在另一个类中,并且被声明为私有。这样的类称为私有内部类,只能在包含它的外部类内部访问。
- 私有顶级类(Private Top-Level Class): 如果将类声明为顶级(非内部)类并且私有,那么只能在同一文件内的其他类中访问。这个类无法被其他文件中的类所访问。
- 私有类可以在某种程度上提供更严格的访问控制,限制了该类的可见性范围。然而,这种做法在实际开发中很少使用,因为通常情况下,Java类的可访问性要么是公共的(
public
)、包级私有的(默认,没有修饰符)、受保护的(protected
),而不是私有的。 这些访问控制符允许开发人员控制类、方法和变量的可访问性,有助于实现封装和安全性。
- 包的引入使用
public class OuterClass {
private class PrivateInnerClass {
// 内部类的内容
}
// 外部类的内容
}
代码语言:javascript复制// PrivateTopLevelClass.java 文件
class PrivateTopLevelClass {
// 类的内容
}
// 其他类
public class AnotherClass {
public void method() {
// 在同一文件内可以访问 PrivateTopLevelClass 类
PrivateTopLevelClass obj = new PrivateTopLevelClass();
}
}
- 对私有属性如何进行读写控制?Seter和Geter方法的作用?
- 私有属性可以通过公有的setter和getter方法进行读写控制,setter方法用于设置私有属性的值,getter方法用于获取私有属性的值。
- 工厂模式的概念和实现方式?静态成员和方法的含义及访问控制?
- 工厂模式是一种创建对象的设计模式,将对象的创建过程封装在工厂方法中,返回所需对象的实例。
- 静态成员和方法属于类而不是对象,可以通过类名直接访问。静态成员和方法在内存中只有一份副本,不需要创建对象即可访问。
- 非访问控制符有哪些?
- static:static 方法和变量属于类而不是特定的实例,可以通过类名直接访问。用于创建类方法和类变量,使得它们可以在不创建类的实例的情况下被访问。
- final:用于修饰类、方法和变量。final 类表示该类不能被继承,final 方法表示该方法不能被覆盖,final 变量表示该变量只能被赋值一次。
- abstract:用于创建抽象类和抽象方法。abstract 类不能被实例化,只能被继承;abstract 方法没有实现,必须在子类中重写。
- synchronized:用于多线程编程,确保在同一时刻只有一个线程可以访问对象的特定部分。synchronized 方法或代码块在被一个线程访问时,其他试图访问它的线程将被阻塞。
- volatile:用于保证变量在多线程环境下的可见性,禁止指令重排。volatile 变量的值会被立即更新到主存,而不是缓存在线程的工作内存中。
- transient:用于修饰变量,表示该变量不会被序列化。transient 变量在序列化过程中会被忽略。
抽象类、接口和枚举
- 抽象类的定义要求和完全抽象类的接口定义方式?一个类只能有一个父类但是可以有多个接口,关键词和成员变量的定义?
- 抽象类使用
abstract
关键字定义,可以包含抽象方法和具体方法。抽象方法没有方法体,只有声明,而完全抽象类是指全部方法都是抽象方法,没有具体实现。 - 一个类可以继承一个父类,但可以实现多个接口。接口使用
interface
关键字定义,包含抽象方法的声明。 - 在接口中,成员变量默认为
public static final
,方法默认为public abstract
。
- 抽象类使用
- 枚举类型的了解程度和相关知识? (没考,了解一下)
- 枚举是一种特殊的类,限制对象的类型在一个有限的范围内。枚举常用于定义常量集合,列出一组可能的值。Java中的枚举使用
enum
关键字定义。
- 枚举是一种特殊的类,限制对象的类型在一个有限的范围内。枚举常用于定义常量集合,列出一组可能的值。Java中的枚举使用
第五章:Java对象、多态与内部类深度解析
变量及其传递
- 基本数据类型和引用类型的区别是什么?它们在传递过程中有何异同点?
- 基本数据类型直接存储数据值,而引用类型存储的是对象的引用(地址)。
- 传递基本数据类型是拷贝实际的值,而传递引用类型是拷贝引用地址。
- Java中基本数据类型在传递过程中是如何进行拷贝的?引用类型传递的是什么?
- 基本数据类型传递时是传递实际的值(直接拷贝),而引用类型传递时是拷贝对象的引用(地址)。
- 在方法中,为什么成员变量可以使用默认值而方法变量(局部变量)不能?
- 成员变量可以使用默认值是因为它们在对象创建时已经分配了内存并赋予了默认值。方法变量(局部变量)是在方法执行时才创建,没有默认值,必须明确赋值后才能使用。
多态
- 多态的前提条件是什么?哪些条件必须满足才能发生多态?
- 多态的前提条件是存在继承关系,子类覆盖了父类的同名方法,我们称之为虚方法,而且我们一定要有一个子类的对象赋值给了父类的变量,这叫做向上赋形,这时,就会根据各种条件判断应该调用哪个对象。这就叫多态。
- 多态的实现原理是什么?子类如何覆盖父类的同名方法?
- 多态通过动态绑定实现,根据实际对象类型确定调用的方法。子类覆盖父类方法要求方法名和参数列表相同,并且使用
@Override
注解。 - 可以在类中间定义一些语句块,语句块前面还可以加static。初始化块(包括静态初始化块和非静态初始化块)的执行顺序优先于构造方法。当创建类的实例时,会先执行初始化块,然后才执行构造方法。静态初始化块在类加载时执行,只会执行一次,并在任何对象创建之前执行。非静态初始化块在每次创建对象时执行,且优先于构造方法执行。
- 多态通过动态绑定实现,根据实际对象类型确定调用的方法。子类覆盖父类方法要求方法名和参数列表相同,并且使用
对象成员变量初始化
- 除了在构造函数中,对象的成员变量还能在哪些地方进行初始化?语句块和构造方法的执行顺序是怎样的?
- 对象的成员变量可以在构造方法中初始化,同时也可以在实例化代码块中进行初始化。语句块在构造方法之前执行。
对象的清除和垃圾回收(没考,了解一下)
- Java中如何进行对象的清除?是否存在类似析构函数的概念?
- Java自动进行垃圾回收。不存在类似于C 中析构函数的概念,Java的垃圾收集器自动管理对象的销毁。
内部类
- 什么是内部类和匿名类?它与外部类的成员的访问有何特点?(可以看一下)
- 内部类是定义在另一个类内部的类。它可以访问外部类的成员,包括私有成员,而外部类则不能直接访问内部类的成员。
- 匿名类(Anonymous Class)是指在声明类的同时直接创建该类的实例的一种特殊方式。它允许你在需要类的地方(通常是作为参数传递给方法或者实例化对象时),定义一个临时的、一次性的类。匿名类没有名字,一定定义在某个类里面。
- 在内部类中使用static关键字的效果是什么?对外部成员的访问方式有何变化?
- 在内部类中使用
static
关键字,使得内部类的成员可以直接通过类名访问,不需要实例化外部类。
- 在内部类中使用
入侵和反制(不涉及,了解一下)
- 入侵和反制相关概念是什么?在Java中如何体现这些概念?
- 入侵是指通过某种方式进入系统,而反制则是对入侵进行防范或应对的措施。在Java中,安全性和权限管理是对抗潜在入侵的一种方式。
第六章:异常处理与控制流程 - Java中的try-catch-finally机制
异常抛出、捕获以及处理机制
- 异常捕获的基本语法和结构是什么?try-catch-finally块如何使用?
- 异常捕获的基本结构是使用
try-catch-finally
块。在try
块中放置可能抛出异常的代码,catch
块用于捕获并处理异常,finally
块用于清理资源,无论是否有异常都会执行。
- 异常捕获的基本结构是使用
- 在try块中抛出异常,catch块如何捕获?如果没有异常会怎样?
- 如果在
try
块中抛出异常,会匹配对应的catch
块。 - 如果
try
块中没有抛出异常,程序会继续执行try
块后面的代码,并跳过catch
块的执行。 - 如果异常抛出了但没有被捕获,即没有对应的
catch
块来处理,异常将沿着调用栈向上抛出,直至被捕获或导致程序终止。可以通过throws
关键字将异常抛出给调用该方法的地方进行处理,或者使用全局的异常处理器(例如 Thread.setDefaultUncaughtExceptionHandler)捕获未处理的异常。
- 如果在
try {
// 可能抛出异常的代码
// 比如:int result = 10 / 0; // 除零异常
} catch (ArithmeticException e) {
// 捕获特定类型的异常并处理
System.out.println("除零异常:" e.getMessage());
} catch (Exception e) {
// 捕获其他类型的异常
System.out.println("其他异常:" e.getMessage());
} finally {
// finally 块中的代码无论是否发生异常都会执行
// 一般用于资源释放或清理操作
}
- finally块的作用是什么?无论是否捕获到异常,finally块中的内容会执行吗?
finally
块用于确保无论是否发生异常,里面的代码都会执行。即使在catch
块中有return
语句,finally
块也会在return
之前执行。
- 没有声明throw,直接try一个空函数会报错吗?空指针异常会导致什么结果?为什么有些异常报错而有些不会?
- 直接在
try
块中尝试调用空函数不会报错。空指针异常可能导致程序中止,但不会导致编译错误。有些异常需要显式地处理(捕获或声明抛出),而有些异常则属于运行时异常,不强制要求处理。
- 直接在
- 异常分为可检测和不可检测异常,它们的区别是什么?什么是不可检测异常的例子?
- 可检测异常是指在编译时强制要求处理的异常,需要进行捕获或声明抛出。不可检测异常是指编译器不强制要求处理的异常,通常是运行时异常。例如,
NullPointerException
是不可检测异常的一种。
- 可检测异常是指在编译时强制要求处理的异常,需要进行捕获或声明抛出。不可检测异常是指编译器不强制要求处理的异常,通常是运行时异常。例如,
第七章:工具类和常用算法
Java中的类和常用方法
- 包的概念和在Java中的作用是什么?碰到了根类意味着什么?
- 包是用于组织和管理Java类的一种机制,可以避免类名冲突,并提供了访问保护机制。根类通常指的是
java.lang.Object
类,它是所有类的根类。
- 包是用于组织和管理Java类的一种机制,可以避免类名冲突,并提供了访问保护机制。根类通常指的是
- 常用方法,如toString方法的作用是什么?
toString
方法用于返回对象的字符串表示。在未重写该方法时,返回的是对象的哈希码。- equals(Object obj): 用于比较两个对象是否相等。
- hashCode(): 返回对象的哈希码值。
- toString(): 返回对象的字符串表示形式。
- getClass(): 返回对象的运行时类。
- clone(): 用于创建并返回此对象的副本。
- finalize(): 在对象被垃圾回收之前调用。
- wait(), notify(), notifyAll(): 用于多线程的同步。
- 八种基本数据类型的包装类有哪些?它们之间是如何进行自动装箱和拆箱的?
- 基本数据类型的包装类包括
Integer
、Long
、Float
、Double
、Byte
、Short
、Character
、Boolean
。自动装箱是将基本数据类型自动转换为包装类对象,拆箱则相反。
- 基本数据类型的包装类包括
Java常用类和相关方法
- Math类有哪些常用方法?
Math
类包含一系列用于执行基本数学运算的静态方法,如sin()
、cos()
、sqrt()
等。
- System类有什么作用?它如何进行数组的复制?
System
类提供了访问系统资源和方法的接口。它通过arraycopy()
方法进行数组的复制,可以实现数组之间的复制。
- String类有哪些常见方法?
String
类包含一系列用于字符串操作的方法,如length()
、charAt()
、substring()
等。
- Date类一般用于哪些操作?
Date
类用于处理日期和时间,包括获取当前日期时间、日期格式化、日期比较等操作。
集合类和数据结构
- 集合类中的Set、List、Map分别代表什么?哪些是键值对结构?
Set
代表一组无序且不包含重复元素的集合;List
代表有序且可以包含重复元素的集合;Map
代表键值对的集合,每个键对应一个值。Map
是键值对结构,它以键-值对的方式存储数据,如HashMap
、TreeMap
等。
(本章节后面没考,感兴趣的话自己了解)
第八章:Java线程的创建和销毁
线程和调度(没有大题)
- 线程的概念是什么?
- 线程是程序执行的单元,是CPU调度的基本单位。它允许程序同时执行多个任务,提高了程序的并发性能。
- 常见的创建线程的方法有哪些?
- 创建线程的方法包括继承
Thread
类、实现Runnable
接口、使用ExecutorService
等。
- 创建线程的方法包括继承
- 线程的状态有哪些?
- 线程的状态包括新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)、等待(Waiting)、计时等待(Timed Waiting)、终止(Terminated)等。
- 线程如何进行调度?调用后会发生什么变化?
- 线程的调度由操作系统的调度器负责,它会根据线程的优先级和状态进行调度。调度后,线程可能从就绪状态转变为运行状态或者被阻塞。
流处理
- 数据输入输出是什么?流处理又是怎么回事?
- 数据输入输出是指将数据从某个地方读取出来或写入到某个地方。流处理是一种通过流(Stream)将数据从一个地方传输到另一个地方的方式,它可以是字节流或字符流。
- 流处理中的输入输出流有何区别?字符流和字节流有何异同?
- 输入输出流分为字节流和字符流,字节流适用于处理二进制数据,而字符流则适用于处理文本数据。字符流比字节流多了字符编码的处理,字符流通常使用Reader和Writer,而字节流使用InputStream和OutputStream。
- 节点流和过滤器流是什么?具体指什么内容?
- 节点流是直接连接到数据源或目的地的流,例如
FileInputStream
和FileOutputStream
。过滤器流是基于节点流构建的,可以对数据进行加工和处理,例如BufferedInputStream
和BufferedOutputStream
。
- 节点流是直接连接到数据源或目的地的流,例如
第九章:Java文件流I/O
当然,请让我逐一回答您提出的问题。
文件和目录处理(对目录的处理及之后不考)
- 在Java中,如何使用File类来处理文件?
- 可以使用
File
类来创建、删除、重命名、获取文件信息等操作。首先需要创建File
对象,然后可以使用其提供的方法来执行相应的操作。
- 可以使用
- File类有哪些常用的方法?
File
类有许多方法用于操作文件,如createNewFile()
创建新文件、delete()
删除文件、renameTo()
重命名文件、exists()
检查文件是否存在等。
- File类能做哪些对文件的操作?
File
类可以进行多种文件操作,包括获取文件名、路径、大小、修改日期等文件信息的获取,以及创建、删除、重命名文件等文件操作。
第十章:Java面向GUI编程
GUI中的组件、容器和监听器
- GUI中常见的组件有哪些?
- 在GUI中,常见的组件包括:文本框(TextField)、标签(Label)、按钮(Button)、复选框(Checkbox)、单选按钮(RadioButton)、下拉列表框(ComboBox)、列表(List)、滑动条(Slider)、菜单(Menu)和菜单项(MenuItem)等。
- 容器是什么?GUI中有哪些常见的容器?
- 容器是一种能够容纳其他组件的组件。在GUI中,常见的容器包括窗口(Window)、面板(Panel)、框架(Frame)等。
- GUI中有哪些常见的监听器?对于常见组件,常见的监听器需要实现什么方法?
- 常见的监听器包括:ActionListener、ItemListener、MouseListener、KeyListener、WindowListener等。对于常见组件,常见的监听器需要实现对应接口中的方法,例如
ActionListener
需要实现actionPerformed
方法。
- 常见的监听器包括:ActionListener、ItemListener、MouseListener、KeyListener、WindowListener等。对于常见组件,常见的监听器需要实现对应接口中的方法,例如
- 布局管理器有哪些?
- 布局管理器是用于在GUI界面中定位和控制组件位置的工具。常见的布局管理器包括:
- BorderLayout:将组件放置在东、西、南、北、中五个区域。
- FlowLayout:从左到右依次排列组件,自动换行。
- GridLayout:将组件放置在网格中,行列固定。
- GridBagLayout:更灵活的网格布局,可定制性高。
- CardLayout:管理多个组件,只显示一个组件。
- 布局管理器是用于在GUI界面中定位和控制组件位置的工具。常见的布局管理器包括:
- 边界、流式和网格布局是什么?
- 边界布局(BorderLayout)将组件放置在东、西、南、北、中五个区域。
- 流式布局(FlowLayout)按照添加顺序从左到右排列组件,自动换行。
- 网格布局(GridLayout)将组件放置在规则的行列网格中。
- Panel(面板)的默认布局是什么?
Panel
的默认布局是FlowLayout
。