文章目录
- Java 跨平台原理
- 高级语言的编译运行方式
- Java JRE和JDK
- Java 注释
- (一)什么是注释?
- (二)注释的分类
- (三)注释的使用细节
- Java 关键字
- (一)什么是关键字?
- (二)关键字的特点
- (三)class关键字的含义
- Java 字面量
- (一)什么是字面量?
- (二)字面量的分类
- (三)特殊类型的字面量
- Java 变量
- (一)什么是变量?
- (二)变量的使用场景
- (三)变量的定义格式
- Java 基础语法
- (一)数据类型
- (二)标识符
- (三)键盘录入
- Java 运算符
- (一)什么是运算符?
- 1. 算术运算符:
- 2. 赋值运算符:
- 3. 比较运算符:
- 4. 逻辑运算符:
- 5. 位运算符:
- 6. 条件运算符(三元运算符):
- 7. 其他运算符:
- 7. 算术运算符的优先级
- (二)什么是表达式?
- (三)练习:数值拆分
- (四)隐式转换和强制转换
- (五)字符串的加操作
- (六)字符的加操作
- (七)原码反码补码
- Java 判断和循环
- (一)流程控制语句
- 1,顺序结构
- 2,分支结构
- 3,循环结构
- (二)两道力扣算法题
- 1,回文数
- 2,求商和余数
- (三)无限循环和跳转控制语句
- 1,无限循环
- 2,跳转控制语句
- (四)循环高级综合练习
- 1,逢七过
- 2,平方根
- 3,判断是否为质数
- 4,猜数字
- Java 数组
- (一)数组概述
- (二)数组的定义与静态初始化
- (三)数组元素访问
- (四)数组变量
- (五)数组动态初始化
- (六)数组内存图
- (七)数组常见问题
- (八)数组常见操作
Java 跨平台原理
- Java语言的跨平台是通过虚拟机实现的。
- Java语言不是直接运行在操作系统里面的。
而是运行在虚拟机中的。 - 针对于不同的操作系统,安装不同的虚拟机就可以了。
高级语言的编译运行方式
编程、编译、运行
编程:Java程序员写的 .java 代码,C程序员写的 .c 代码,Python程序员写的 .py 代码。
编译:机器只认识0011的机器语言,把.java .c .py 的代码做转化让机器认识的过程。
运行:让机器执行编译后的指令。
- 编译型
- 解释型
- 混合型,半编译,半解释
Java JRE和JDK
-
JDK是什么?有哪些内容组成?
Jdk(Java Development kit)是java开发工具包- Jvm虚拟机:java程序运行的地方
- 核心类库:java已经写好的东西,我们可以直接使用
- 开发工具:javac(编译工具)、java(运行工具)、jdb(调试工具)、jhat(内存分析工具)…
-
JRE是什么?有哪些内容组成?
- Jre是java的运行环境
- Jvm、核心类库、运行工具
-
JDK、JER、JVM三者包含关系
- Jdk包含了jre
- Jre包含了jvm
Java 注释
(一)什么是注释?
注释就是对代码进行解释说明的文字,在Java中,注释是用于向代码添加说明、描述和解释的文本。注释在编译过程中会被编译器忽略,不会成为最终的可执行代码的一部分。
(二)注释的分类
Java中有三种类型的注释:
-
单行注释:以双斜线
//
开头。单行注释从//
开始,一直到行末,用于注释单行的代码或提供简短的解释。// 这是一个单行注释 int age = 25; // 定义一个变量并赋值
-
多行注释:以斜线和星号
/*
开头,以星号和斜线*/
结尾。多行注释可以跨越多行,用于注释多行代码块或提供详细的解释。/* 这是一个多行注释, 可以跨越多行, 用于注释多个代码行 */ int age = 25; // 定义一个变量并赋值
-
文档注释(Javadoc注释):以斜线和两个星号
/**
开头,以星号和斜线*/
结尾。文档注释用于生成API文档,用于描述类、方法、字段等的作用、用法和参数说明等。/** * 这是一个文档注释,用于生成API文档 * @param name 姓名 * @return 拼接后的字符串 */ public String getGreeting(String name) { return "Hello, " + name + "!"; }
注释在编写代码时具有重要的作用,它可以提高代码的可读性和可维护性,并且能够为其他开发人员提供足够的说明和指引。良好的注释能够有效地解释代码的逻辑、用途和设计意图。
(三)注释的使用细节
- 注释内容不会参与编译和运行,仅仅对代码的解释说明。
- 不管是单行注释还是多行注释,在书写的时候都不要嵌套。
Java 关键字
(一)什么是关键字?
在Java中,关键字(keyword)是指被编程语言定义并保留下来,具有特殊用途和含义的单词或标识符。这些关键字在Java中具有预定义的语法和语义,不能被用作变量名或其他标识符。
Java的关键字用于表示控制结构、数据类型、修饰符、访问控制等方面。它们被认为是Java语言的一部分,具有特殊的含义,编译器能够根据这些关键字做预定义的处理。
以下是Java的关键字示例:
- 关键字:abstract、assert、boolean、break、byte、case、catch、char、class、const、continue、default、do、double、else、enum、extends、false、final、finally、float、for、goto、if、implements、import、instanceof、int、interface、long、native、new、null、package、private、protected、public、return、short、static、strictfp、super、switch、synchronized、this、throw、throws、transient、true、try、void、volatile、while
这些都是Java编程语言中的关键字。请注意,在编写Java代码时,应避免使用这些关键字作为标识符,以免产生语法错误。
(二)关键字的特点
Java关键字具有以下特点:
-
预定义性:Java关键字是编程语言的一部分,已经被Java语言定义和保留,具有预定的含义和用法。
-
限定标识符:Java关键字不能被用作变量名、方法名或其他标识符。因为它们在语言中具有特殊的含义和功能,编译器会根据关键字进行特定的处理。
-
大小写敏感性:Java关键字对大小写敏感。关键字必须以正确的大小写形式出现,否则会被视为普通的标识符。
-
语法意义:每个Java关键字都具有特定的语法意义。关键字的使用方式和上下文会决定它的具体作用和效果。
-
保留性:Java关键字是被保留的,不能被用作其他用途。Java语言的发展和演变中,新的关键字可能会被引入,但已存在的关键字不会被取消或更改其含义。
-
可扩展性:Java关键字的数量是有限的,但Java的语法并不限制开发者使用这些关键字之外的自定义标识符。
(三)class关键字的含义
在Java中,class
是一个关键字,用于定义类。可以将 class
关键字理解为类的声明标识符,它指示编译器在代码中定义一个新的类。
使用 class
关键字,可以创建包含属性和方法的对象模板。类是面向对象编程的基本单位,用于创建对象的蓝图或模板。
下面是示例代码展示如何使用 class
关键字定义一个类:
public class MyClass {
private int myField;
public MyClass() {
// 构造方法
}
public void myMethod() {
// 方法定义
}
}
在上面的示例中,使用 class
关键字定义了一个名为 MyClass
的类。该类包含一个私有字段 myField
和两个方法:构造方法 MyClass()
和公有方法 myMethod()
。
通过使用 class
关键字,可以定义和创建多个对象,这些对象都是基于同一个类的模型。通过实例化具体的对象,可以使用该对象所表示的类中定义的属性和方法。
总结起来,class
关键字用于在Java中定义类。它是面向对象编程的基本概念之一,用于创建对象的模板和蓝图。通过类的定义,可以定义属性(field)和方法(method),并通过实例化来创建具体的对象。
Java 字面量
(一)什么是字面量?
告诉程序员:数据在程序中的书写格式
在Java中,字面量是表示数据的常量值。字面量可以直接在代码中使用,而不需要进行计算或其他操作。
以下是一些常见的字面量类型及其示例:
-
整数字面量:表示整数值的字面量,可以是十进制、八进制或十六进制形式。
int decimalLiteral = 10; // 十进制字面量 int octalLiteral = 012; // 八进制字面量,以0开头 int hexadecimalLiteral = 0xA; // 十六进制字面量,以0x或0X开头
-
浮点数字面量:表示浮点数值的字面量,可以是普通的浮点数或科学计数法表示。
double floatLiteral = 3.14; // 普通浮点数字面量 double scientificLiteral = 1.23e-4; // 科学计数法表示,1.23乘以10的负4次方
-
字符字面量:表示一个字符的字面量,用单引号括起来。
char characterLiteral = 'A';
-
字符串字面量:表示一个字符串的字面量,用双引号括起来。
String stringLiteral = "Hello World";
-
布尔字面量:表示布尔值的字面量,可以是
true
或false
。boolean booleanLiteral = true;
-
null字面量:表示一个空引用的字面量。
String nullLiteral = null;
除了上述常见的字面量类型,还有其他字面量形式,如布尔型的二进制字面量(例如0b1010
表示十进制的10)、字符型的Unicode字面量(例如'\u0041'
表示字符’A’)等。
在使用字面量时,需要注意数据类型的匹配和溢出问题。例如,超出整数范围的字面量将导致编译错误或运行时异常。
(二)字面量的分类
字面量类型 | 说明 | 举例 |
---|---|---|
整数类型 | 不带小数点的数字 | 666,-88 |
小数类型 | 带小数点的数字 | 13.14,-5.12 |
字符串类型 | 用双引号括起来的内容 | “Hello World”,“你好世界” |
字符类型 | 用单引号括起来的,内容只能有一个 | ‘A’,‘0’,‘love’ |
布尔类型 | 布尔值,表示真假 | 只有两个值:true,false |
空类型 | 一个特殊的值,空值 | 值是:null |
(三)特殊类型的字面量
例如:\t
\r
\n
…
-
\t 制表符
在打印时,把前面的字符串长度补齐到8,或者8的整数倍。最少补1个空格,最多补8个空格。 -
\r 制表符
在打印时,在\r
后有新内容时,会先删除之前以前存在过的文本,即只打印\r
后面的内容。 -
\n 制表符
在打印时,\n
之前的内容打印在前一行,\n
之后的内容会先换行到下一行的行首,然后逐个打印\n后面的内容。
Java 变量
(一)什么是变量?
在Java中,变量是用于存储和操作数据的内存空间的名称。它们用于在程序中存储数据,并且可以在程序的不同部分进行访问和修改。在Java中,每个变量都具有特定的数据类型,这决定了变量可以存储的数据种类和范围。
在Java中,变量必须先声明后使用。声明变量时需要指定变量的名称和类型。例如,以下是声明两个整数类型的变量的示例:
int num1;
int num2;
这样,num1
和num2
就成为可以在程序中使用的变量。
变量还可以在声明时进行初始化,即为变量指定初始值。例如:
int num = 10;
这里,变量num
被初始化为10。
Java中的变量可以被赋予新的值,以改变其存储的数据。例如:
num = 20;
现在,num
的值变为20。
除了基本数据类型(如整数、浮点数、布尔值等),Java还支持引用数据类型。引用数据类型的变量存储的是对实际数据的引用,而不是数据本身。例如,可以声明一个字符串类型的变量,如下所示:
String name = "John";
在这里,name
变量存储了对字符串对象"John"的引用。
(二)变量的使用场景
-
计算:变量可以存储数据,进行各种数学计算,例如加法、减法、乘法和除法。
-
循环:变量在循环过程中起到重要作用。循环通常涉及迭代或遍历数据集,通过变量来跟踪迭代次数或当前的索引。
-
条件语句:变量可以用于存储条件的结果,并且在条件语句中进行判断。根据条件的不同结果,可以执行不同的代码分支。
-
存储用户输入:变量可以用于存储用户在程序中输入的值,这样程序就可以根据用户的输入做出相应的处理。
-
存储中间结果:在复杂的计算过程中,可以使用变量存储中间结果,以便后续使用或进行进一步计算。
-
字符串操作:变量可以用于存储和操作字符串,例如拼接、截取和替换等。
-
数组和列表:变量可以用于存储和操作数组或列表中的元素。通过变量,可以轻松访问数组或列表中的特定元素,进行添加、删除和修改等操作。
-
文件操作:变量可以用于存储文件路径、文件名或其他文件相关的信息,以便进行文件的读取、写入和修改等操作。
(三)变量的定义格式
在Java中,定义变量的格式如下:
<数据类型> <变量名>;
其中,<数据类型>
是指变量的数据类型,例如int
、double
、String
等;<变量名>
是指变量的名称,用于在程序中标识和访问变量。
以下是一些示例:
- 定义一个整数类型的变量
num
:
int num;
- 定义一个字符串类型的变量
name
:
String name;
- 定义一个布尔类型的变量
isTrue
:
boolean isTrue;
变量的定义可以包含初始化,即在定义的同时为变量赋予初始值。
例如,定义一个整数类型的变量age
并初始化为30:
int age = 30;
定义一个字符串类型的变量message
并初始化为"Hello World":
String message = "Hello World";
注意,变量名必须遵循一定的命名规则,如:
- 变量名必须以字母、下划线或美元符号开头,不能以数字开头。
- 变量名可以包含字母、数字、下划线或美元符号。
- 变量名区分大小写。
以下是一些合法的变量名示例:
int num;
String firstName;
double _salary;
boolean isValid;
而以下是一些不合法的变量名示例:
int 1num; // 不能以数字开头
String class; // 使用了Java关键字作为变量名
float my-salary; // 包含了非法字符 "-"
Java 基础语法
(一)数据类型
在Java中,有多种数据类型可用来存储不同种类的数据。以下是Java中常用的数据类型:
-
基本数据类型:
- 整数类型:
byte
、short
、int
、long
- 浮点类型:
float
、double
- 字符类型:
char
- 布尔类型:
boolean
- 整数类型:
-
引用数据类型:
- 字符串类型:
String
- 数组类型:
int[]
、String[]
等 - 类类型:自定义的类和对象
- 字符串类型:
以下是数据类型的详细说明:
-
整数类型:
byte
:8位有符号整数,范围为 -128 到 127。short
:16位有符号整数,范围为 -32,768 到 32,767。int
:32位有符号整数,范围为 -2,147,483,648 到 2,147,483,647。long
:64位有符号整数,范围为 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807。
-
浮点类型:
float
:32位浮点数,范围是 IEEE 754 标准的 1.4e-45 到 3.4028235e+38。double
:64位浮点数,范围是 IEEE 754 标准的 4.9e-324 到 1.7976931348623157e+308。
-
字符类型:
char
:16位 Unicode 字符,范围为 ‘\u0000’ (0) 到 ‘\uffff’ (65,535)。
-
布尔类型:
boolean
:表示逻辑值的布尔类型,只有两个取值:true
或false
。
-
引用数据类型:
String
:表示字符串的引用类型,用于存储一组字符序列。- 数组类型:用于存储相同类型元素的集合,可以是基本类型或引用类型的数组。
除上述基本数据类型外,还可以自定义类类型,用于创建自己的类和对象。
这些数据类型在Java中具有不同的内存占用和操作特性,根据实际需求选择合适的数据类型来存储和处理数据。
(二)标识符
在Java中,标识符是用于给变量、方法、类、接口和其他实体命名的名称。标识符可以由字母、数字、下划线和美元符号组成,必须遵循以下规则:
- 标识符以字母(A-Z 或 a-z)、下划线(_)或美元符号($)开头。
- 标识符后面可以是字母、数字、下划线或美元符号的组合。
- 标识符是区分大小写的,例如
myVariable
和myvariable
是不同的标识符。 - 标识符不能是Java的关键字和保留字,如
int
、class
、public
等。(Java关键字列表可参考官方文档)
以下是一些有效的标识符示例:
age
person_name
MAX_SIZE
_total
$amount
以下是一些无效的标识符示例:
123abc // 以数字开头
my-variable // 包含非法字符 "-"
class // Java关键字
准确选择和命名标识符对于编写可读性高、易于理解和维护的代码非常重要。建议在选择标识符时使用有意义且具有描述性的名称,遵循Java的命名规范和最佳实践。
(三)键盘录入
在Java中,可以使用java.util.Scanner
类来进行键盘录入。Scanner
类提供了一种简便的方式来读取用户从键盘输入的数据。
以下是使用Scanner
类进行键盘录入的步骤:
- 导入
java.util.Scanner
类:
import java.util.Scanner;
- 创建
Scanner
对象,并将其与标准输入流(键盘输入)关联:
Scanner scanner = new Scanner(System.in);
- 使用
Scanner
对象的方法读取输入的数据。常用的方法包括:
next()
: 读取下一个以空格分隔的字符串。nextInt()
: 读取下一个整数。nextLine()
: 读取一行输入(包括空格)。
示例代码如下:
package net.army.java.test;
import java.util.Scanner;
/**
* 功能:键盘录入案例
* 日期:2023年07月26日
* 作者:梁辰兴
*/
public class KeyboardInputExample {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入您的名字:");
String name = scanner.next();
System.out.print("请输入您的年龄:");
int age = scanner.nextInt();
System.out.println("您的名字是:" + name);
System.out.println("您的年龄是:" + age);
scanner.close(); // 关闭Scanner对象
}
}
在上面的示例中,首先创建了一个Scanner
对象,并使用next()
方法读取用户输入的名字,使用nextInt()
方法读取用户输入的年龄。然后输出输入的名字和年龄。最后通过调用close()
方法关闭Scanner
对象。
请注意,当使用Scanner
进行键盘录入时,需要根据具体的数据类型使用相应的读取方法,以确保输入的数据类型匹配。另外,要确保输入与期望的格式相符,否则可能会抛出异常。
以上是使用Scanner
类进行键盘录入的基本步骤。你可以根据具体需求使用不同的Scanner
方法来读取不同类型的数据。
Java 运算符
(一)什么是运算符?
在Java中,运算符(operator)是一种用于执行各种操作的特殊符号或关键字。它们用于对操作数(operands)进行计算、比较和操作。Java中的运算符允许进行数学计算、逻辑操作、关系比较、赋值和其他各种操作。
在Java中,有以下几类常见的运算符:
1. 算术运算符:
- 加法:+
- 减法:-
- 乘法:*
- 除法:/
- 取余:%
- 自增:++
- 自减:–
2. 赋值运算符:
- 简单赋值:=
- 加法赋值:+=
- 减法赋值:-=
- 乘法赋值:*=
- 除法赋值:/=
- 取余赋值:%=
3. 比较运算符:
- 相等:==
- 不等:!=
- 大于:>
- 小于:<
- 大于等于:>=
- 小于等于:<=
4. 逻辑运算符:
- 与:&&
- 或:||
- 非:!
5. 位运算符:
- 按位与:&
- 按位或:|
- 按位异或:^
- 左移:<<
- 右移:>>
- 无符号右移:>>>
6. 条件运算符(三元运算符):
在Java中,三元表达式也被称为条件运算符(Conditional Operator),它是一种简洁的条件判断语法。
三元表达式的语法如下:
条件 ? 表达式1 : 表达式2
其中,条件是一个布尔表达式,如果条件为真,则返回表达式1的结果,否则返回表达式2的结果。
三元表达式的执行过程如下:
- 首先判断条件的值,如果条件为真,则执行表达式1;
- 如果条件为假,则执行表达式2;
- 最终返回执行的表达式的结果。
下面是一个简单的示例:
int a = 10;
int b = 20;
int max = (a > b) ? a : b;
System.out.println(max); // 输出:20
在上述示例中,条件(a > b)
为假,所以返回表达式b
的值,即20。
三元表达式可以简化条件判断的代码,使代码更加简洁和可读。然而,过度使用三元表达式可能会使代码变得难以理解和维护,所以需要谨慎使用。
7. 其他运算符:
- instanceof:判断对象是否是某个类的实例
- 空安全调用运算符:?. (Java 8之后新增)
这些运算符可以用于操作不同类型的数据,实现各种计算、赋值和判断逻辑。
7. 算术运算符的优先级
在Java中,算术运算符的优先级从高到低依次为:
- 后置递增(++)和递减(–)
- 前置递增(++)和递减(–)
- 一元加(+)和一元减(-)
- 乘法(*)、除法(/)和取模(%)
- 加法(+)和减法(-)
(二)什么是表达式?
在Java中,表达式是由操作数、运算符和方法调用组成的代码片段,它们能够产生一个值。表达式能够被用于赋值、条件判断、计算等多种场景中。常见的表达式类型包括算术表达式、关系表达式、逻辑表达式等。例如:
- 算术表达式:x + y、a - b、c * d等
- 关系表达式:a > b、x <= y、c == d等
- 逻辑表达式:(x > 5) && (y < 10)、(a == b) || (c != d)等
除了基本的运算符,Java还提供了丰富的内置函数和方法,可以用于构建更复杂的表达式。
(三)练习:数值拆分
要求:
键盘录入一个三位数,将其拆分为个位,十位,百位后,并打印在控制台
编程思路:
编写这个程序的思路如下:
- 导入
java.util.Scanner
类,以便从键盘读取输入。 - 创建
Scanner
对象来读取用户的输入。 - 使用
System.out.print()
方法提示用户输入一个三位数。 - 使用
scanner.nextInt()
方法获取用户输入的三位数。 - 使用数学运算将该三位数拆分成百位数、十位数和个位数:
- 将三位数除以100,得到百位数。
- 用三位数对100取余再除以10,得到十位数。
- 将三位数对10取余,得到个位数。
- 使用
System.out.println()
方法打印百位数、十位数和个位数的值。 - 使用
scanner.close()
方法关闭Scanner
对象,释放资源。
package net.army.java.test;
import java.util.Scanner;
/**
* 功能:数值拆分
* 日期:2023年08月08日
* 作者:梁辰兴
*/
public class NumberSplitter {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入一个三位数: ");
int number = scanner.nextInt();
int hundreds = number / 100; // 获取百位数
int tens = (number % 100) / 10; // 获取十位数
int ones = number % 10; // 获取个位数
System.out.println("百位数: " + hundreds);
System.out.println("十位数: " + tens);
System.out.println("个位数: " + ones);
scanner.close();
}
}
运行结果
(四)隐式转换和强制转换
在Java中,算术运算符的隐式转换和强制转换可以用来处理不同数据类型之间的运算。
-
隐式转换:当进行算术运算时,如果操作数的数据类型不同,Java会自动进行隐式转换,将较低精度的数据类型转换为较高精度的数据类型。隐式转换是自动进行的,不需要手动干预。
例如,当一个整数与一个浮点数相加时,整数会被隐式转换为浮点数,以便进行运算。示例代码如下:
int num1 = 10; double num2 = 2.5; double result = num1 + num2; // 隐式转换,num1被转换为double类型
总结
取值范围
byte < short < int < long < float < double什么时候转换?
数据类型不一样,不能进行计算,需要转成一样的才可以进行计算。转换规则1
取值范围小的,和取值范围大的进行计算,小的会先提升为大的,再进行计算。转换规则2
byte short char 三种类型的数据在运算的时候,都会直接提升为int,然后在进行运算。 -
强制转换:有时需要手动将一个数据类型转换为另一个数据类型,这就需要使用强制转换。强制转换可以通过将要转换的数据类型放在圆括号中,并放在需要转换的值之前来完成。
强制转换的注意事项:
- 强制转换可能会导致数据丢失或溢出。如果转换后的数据类型无法容纳原始数据类型的值,可能会导致不正确的结果。
- 强制转换只能在具有相关性的数据类型之间进行。例如,可以将一个整数转换为浮点数,但不能将一个整数转换为布尔值。
示例代码如下:
double num1 = 2.5; int num2 = (int) num1; // 强制转换,将num1转换为int类型
需要注意的是,在进行强制转换时,应该谨慎使用,并且在转换之前进行类型检查,以确保数据的完整性和正确性。
(五)字符串的加操作
在Java中,字符串的加法操作是使用"+"符号来连接两个字符串。这个操作称为字符串拼接。
例如:
String str1 = "Hello";
String str2 = "World";
String result = str1 + str2;
System.out.println(result); // 输出:HelloWorld
可以使用"+"符号进行多个字符串的拼接,拼接的顺序按照操作的顺序进行。
例如:
String str1 = "Hello";
String str2 = " ";
String str3 = "World";
String result = str1 + str2 + str3;
System.out.println(result); // 输出:Hello World
此外,Java还提供了StringBuilder
和StringBuffer
类用于高效地拼接字符串。
(六)字符的加操作
在Java中,字符的加法操作会将字符的ASCII码值进行加法运算,然后返回结果。
例如:
char ch1 = 'A';
char ch2 = 'B';
int result = ch1 + ch2;
System.out.println(result); // 输出:131
char ch3 = 'a';
char ch4 = 'b';
int result2 = ch3 + ch4;
System.out.println(result2); // 输出:195
在上述示例中,字符’A’的ASCII码值是65,字符’B’的ASCII码值是66,所以ch1 + ch2
的结果是131。
字符’a’的ASCII码值是97,字符’b’的ASCII码值是98,所以ch3 + ch4
的结果是195。
需要注意的是,字符的加法操作会返回一个整数类型的结果,而不是字符类型。如果需要将结果转换为字符,可以使用强制类型转换。
例如:
char ch1 = 'A';
char ch2 = 'B';
int result = ch1 + ch2;
char charResult = (char) result;
System.out.println(charResult); // 输出:ö
在上述示例中,字符’A’和字符’B’的ASCII码值之和是131,将131强制类型转换为字符,得到的结果是字符’ö’。
(七)原码反码补码
原码、反码和补码都是计算机在表示和处理有符号整数时使用的编码方式。
-
原码(Sign-Magnitude):原码是最基本的表示形式,它将一个数值表示成带有符号位的二进制数,符号位为0表示正数,为1表示负数。其他位表示数值的绝对值。例如,+7的原码是
00000111
,-7的原码是10000111
。 -
反码(One’s Complement):反码是在原码的基础上,对负数的数值位取反。也就是说,负数的反码是正数的符号位不变,其他位取反。例如,-7的反码是
11111000
。 -
补码(Two’s Complement):补码是在反码的基础上,对最低有效位(即数值位)加1。也就是说,负数的补码是反码的最低有效位加1。例如,-7的补码是反码
11111000
的最低有效位加1,得到11111001
。
为什么要使用补码表示负数呢?这是因为在计算机中,使用补码可以简化负数的运算操作,同时可以将加法和减法统一为相同的操作。另外,补码还可以更有效地利用计算机硬件来进行整数运算。
需要注意的是,正数的原码、反码和补码都是相同的。对于负数而言,反码和补码是不同的,但它们在数值上是等价的。
总结:原码是最基本的表示形式,反码是对负数的数值位取反,补码是对反码的最低有效位加1。在计算机中,常用补码来表示和处理有符号整数。
Java 判断和循环
(一)流程控制语句
1,顺序结构
在Java中,流程控制语句的顺序结构是指代码按照自上而下的顺序逐行执行,没有分支或循环的控制流程。
下面是一些常见的流程控制语句的顺序结构:
-
声明变量:在程序中,先声明需要使用的变量。
-
赋值语句:给变量赋予初始值。
-
表达式语句:执行一条表达式,可以是算术运算、方法调用等。
-
方法调用:调用自定义方法或者Java提供的方法。
-
输入输出语句:从标准输入读取数据或者向标准输出打印数据。
-
条件语句:使用if语句判断某个条件是否成立,根据条件的真假执行相应的代码块。
-
循环语句:使用for循环、while循环或do-while循环来重复执行一段代码块,直到满足终止条件。
-
跳转语句:使用break、continue或return语句来跳出当前循环或方法。
以上这些流程控制语句可以按照自上而下的顺序在代码中编写,它们的执行顺序将按照代码的顺序进行。在顺序结构中,每一条语句都只会执行一次,没有分支或循环的控制流程。
2,分支结构
在Java中,流程控制语句的分支结构主要有三种:if语句、switch语句和三元运算符。
- if语句:if语句根据条件的真假执行不同的代码块。基本的if语句结构如下:
if (条件) {
// 如果条件为真,执行这里的代码
} else {
// 如果条件为假,执行这里的代码
}
可以使用多个if语句嵌套,形成更复杂的条件分支。
- switch语句:switch语句根据表达式的值,执行与之对应的代码块。基本的switch语句结构如下:
switch (表达式) {
case 值1:
// 如果表达式的值等于值1,执行这里的代码
break;
case 值2:
// 如果表达式的值等于值2,执行这里的代码
break;
// 可以有多个case
default:
// 如果表达式的值都不匹配上面的值,执行这里的代码
}
注意,每个case后面都要加上break语句,否则会继续执行下一个case的代码块。
- 三元运算符:三元运算符也可以用来进行简单的分支控制。它的基本语法如下:
(条件) ? 表达式1 : 表达式2
如果条件为真,返回表达式1的值;如果条件为假,返回表达式2的值。
这些分支结构可以根据不同的条件执行不同的代码块,灵活控制程序的执行流程。
3,循环结构
在Java中,流程控制语句的循环结构有三种:for循环、while循环和do-while循环。
- for循环:for循环是一种经常用于循环执行已知次数的情况下的循环结构。它的基本语法如下:
for (初始化语句; 条件表达式; 更新语句) {
// 循环体,会重复执行的代码
}
在初始化语句中,我们可以初始化一个计数器变量;在条件表达式中,我们定义循环终止的条件;在更新语句中,我们可以更新计数器变量的值。循环体中的代码会根据条件重复执行,直到条件不满足为止。
- while循环:while循环在循环开始之前先判断条件是否满足,如果满足则执行循环体中的代码。它的基本语法如下:
while (条件) {
// 循环体,会重复执行的代码
}
在循环体中的代码执行完毕后,会再次判断条件是否满足,如果满足则继续执行循环体中的代码,否则跳出循环。
- do-while循环:do-while循环先执行一次循环体中的代码,然后再判断条件是否满足,如果满足则继续执行循环体中的代码。它的基本语法如下:
do {
// 循环体,会重复执行的代码
} while (条件);
在do-while循环中,无论条件是否满足,循环体中的代码至少执行一次。
这些循环结构可以根据条件的满足与否,重复执行一段代码,实现程序的循环逻辑。
(二)两道力扣算法题
1,回文数
- 需求:给你一个整数x。
如果x是一个回文整数,打印true,否则,返回false。 - 解释:回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
例如:121是回文,而123不是。
以下是一个解决力扣算法题「回文数」的示例代码:
public class Solution {
public boolean isPalindrome(int x) {
// 负数肯定不是回文数,直接返回false
if (x < 0) {
return false;
}
// 将整数转为字符串
String str = String.valueOf(x);
// 使用双指针法判断是否是回文数
int left = 0;
int right = str.length() - 1;
while (left < right) {
if (str.charAt(left) != str.charAt(right)) {
return false;
}
left++;
right--;
}
return true;
}
}
这个算法的思路是先将整数转为字符串,然后使用双指针法从字符串两端向中间进行比较。如果遇到不相等的字符,则不是回文数,直接返回false。如果所有字符都相等,则是回文数,返回true。
注意,这个算法的时间复杂度是O(n),其中n是整数x的位数。
2,求商和余数
- 需求:给定两个整数,被除数和除数(都是正数,且不超过int的范围)
将两数相除,要求不使用乘法、除法和%运算符。
得到商和余数。
以下是一个解决力扣算法题「求商和余数」的示例代码:
public class Solution {
public int[] divide(int dividend, int divisor) {
// 判断被除数是否为0
if (dividend == 0) {
return new int[] {0, 0};
}
// 判断除数是否为0
if (divisor == 0) {
throw new ArithmeticException("除数不能为0");
}
// 判断被除数是否为最小值,且除数为-1
if (dividend == Integer.MIN_VALUE && divisor == -1) {
return new int[] {Integer.MAX_VALUE, 0};
}
// 判断结果的符号
int sign = (dividend > 0 ^ divisor > 0) ? -1 : 1;
// 将被除数和除数转为正数
long absDividend = Math.abs((long) dividend);
long absDivisor = Math.abs((long) divisor);
// 计算商和余数
int quotient = 0;
while (absDividend >= absDivisor) {
absDividend -= absDivisor;
quotient++;
}
return new int[] {sign * quotient, (int) absDividend * sign};
}
}
这个算法的思路是首先判断特殊情况,比如被除数为0、除数为0以及被除数为最小值且除数为-1。然后判断结果的符号,根据被除数和除数的正负情况来确定。接着将被除数和除数转为正数,使用循环计算商和余数。最后返回结果数组,第一个元素为商,第二个元素为余数。
需要注意的是,由于题目要求结果为整数,所以在计算过程中需要将被除数和除数转为long类型,以避免溢出。
(三)无限循环和跳转控制语句
1,无限循环
Java中实现无限循环的方式有多种,以下是几种常见的方式:
- 使用while循环:
while(true) {
// 循环体
}
- 使用for循环:
for(;;) {
// 循环体
}
- 使用do-while循环:
do {
// 循环体
} while(true);
- 使用递归调用:
public void infiniteLoop() {
// 循环体
infiniteLoop();
}
需要注意的是,无限循环可能会导致程序无法正常终止,因此在使用无限循环时需要谨慎考虑退出条件,并确保程序能够正常结束。
2,跳转控制语句
在Java中,有三种跳转控制语句可以用于改变程序的执行顺序:
break
语句:用于跳出循环或者switch
语句。当break
语句被执行时,程序会跳出当前循环或者switch
语句,继续执行break
语句后面的代码。
示例:
for (int i = 0; i < 10; i++) {
if (i == 5) {
break; // 当i等于5时跳出循环
}
System.out.println(i);
}
continue
语句:用于结束当前循环的当前迭代,并继续执行下一次迭代。当continue
语句被执行时,程序会跳过当前迭代剩余的代码,开始下一次迭代。
示例:
for (int i = 0; i < 10; i++) {
if (i == 5) {
continue; // 当i等于5时跳过当前迭代
}
System.out.println(i);
}
return
语句:用于结束方法的执行,并返回一个值(如果方法有返回值的话)。当return
语句被执行时,程序会跳出当前方法,并将返回值返回给方法的调用者。
示例:
public int sum(int a, int b) {
int result = a + b;
return result; // 返回结果并结束方法的执行
}
这些跳转控制语句可以帮助我们在特定条件下改变程序的执行流程,从而实现更复杂的逻辑控制。但是需要注意的是,过多使用跳转控制语句可能会导致代码难以理解和维护,因此在使用时需要慎重考虑。
(四)循环高级综合练习
1,逢七过
逢七过是一个小游戏,规则是从1开始数数,当数到7的倍数(如7、14、21等)或者数字中含有7时,要说“过”,否则要说当前数字。
下面是一个Java练习的示例代码,演示了如何实现逢七过游戏:
public class FeiQiGuo {
public static void main(String[] args) {
int count = 100; // 需要数数的次数
for (int i = 1; i <= count; i++) {
if (i % 7 == 0 || String.valueOf(i).contains("7")) {
System.out.println("过");
} else {
System.out.println(i);
}
}
}
}
在上面的代码中,使用for
循环来进行数数,循环变量i
从1开始逐渐增加,直到达到指定的次数count
为止。然后使用if
条件语句判断当前数字是否为7的倍数或者含有7,如果是,则输出"过",否则输出当前数字。最终输出结果为1到100的数列,其中满足逢七过规则的数字会输出"过"。
你可以根据需要修改count
的值来控制数数的次数。
2,平方根
可以使用Scanner类来获取键盘输入的整数,然后使用循环实现求平方根的功能。具体实现如下:
import java.util.Scanner;
public class SquareRoot {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入一个大于等于2的整数:");
int number = scanner.nextInt();
scanner.close();
int squareRoot = calculateSquareRoot(number);
System.out.println("The square root of " + number + " is: " + squareRoot);
}
// 计算整数平方根的方法
public static int calculateSquareRoot(int number) {
int low = 0; // 平方根的下界
int high = number; // 平方根的上界
while (low <= high) {
int mid = (low + high) / 2; // 计算中间值
int square = mid * mid; // 计算中间值的平方
if (square == number) {
return mid; // 如果中间值的平方等于给定的整数,则返回中间值作为平方根
} else if (square < number) {
low = mid + 1; // 如果中间值的平方小于给定的整数,则将下界更新为中间值+1
} else {
high = mid - 1; // 如果中间值的平方大于给定的整数,则将上界更新为中间值-1
}
}
return high; // 若没有找到精确的平方根,则返回上界作为平方根的整数部分
}
}
在上述示例中,首先使用Scanner类获取键盘输入的整数。然后调用calculateSquareRoot方法计算平方根,并将计算结果打印出来。最后,关闭Scanner对象。
3,判断是否为质数
要判断一个整数是否为质数,可以使用以下步骤:
- 导入java.util.Scanner类,用于获取键盘输入。
- 创建Scanner对象,用于获取键盘输入的整数。
- 提示用户输入一个正整数。
- 调用Scanner的nextInt方法获取用户输入的整数,并将其赋值给变量x。
- 关闭Scanner对象。
- 创建一个布尔型变量isPrime,并初始化为true,表示x是质数。
- 使用for循环遍历从2到x-1的所有整数:
- 如果x能够被当前整数整除,说明x不是质数,将isPrime设置为false,并跳出循环。
- 在循环结束后,通过判断isPrime的值来确定x是否为质数:
- 如果isPrime为true,表示x是质数,打印"是质数"的提示;
- 如果isPrime为false,表示x不是质数,打印"不是质数"的提示。
完整代码如下所示:
import java.util.Scanner;
public class PrimeNumberChecker {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个正整数:");
int x = scanner.nextInt();
scanner.close();
boolean isPrime = true;
for (int i = 2; i < x; i++) {
if (x % i == 0) {
isPrime = false;
break;
}
}
if (isPrime) {
System.out.println(x + " 是质数");
} else {
System.out.println(x + " 不是质数");
}
}
}
注意,该代码假设输入的整数x大于1,因为质数定义为大于1的自然数。对于输入小于等于1的情况,可以在代码中进行额外的判断和处理。
4,猜数字
要实现这个功能,可以使用以下步骤:
- 导入java.util.Random类,用于生成随机数。
- 创建Random对象,用于生成随机数。
- 使用Random的nextInt方法,生成一个1到100之间的随机整数,并将其赋值给变量target。
- 创建一个整型变量guess,用于存储用户猜测的数字。
- 使用一个循环,不断提示用户猜测数字,并判断猜测的结果:
- 提示用户输入一个数字。
- 使用Scanner类获取用户输入的数字,并将其赋值给guess变量。
- 使用if语句判断guess与target的关系:
- 如果guess等于target,表示猜测正确,打印"恭喜你,猜对了!"的提示,并跳出循环。
- 如果guess小于target,表示猜测的数字偏小,打印"猜测的数字偏小,请继续猜测!"的提示。
- 如果guess大于target,表示猜测的数字偏大,打印"猜测的数字偏大,请继续猜测!"的提示。
- 循环结束后,打印"游戏结束!"的提示。
完整代码如下所示:
import java.util.Random;
import java.util.Scanner;
public class NumberGuessingGame {
public static void main(String[] args) {
Random random = new Random();
int target = random.nextInt(100) + 1;
Scanner scanner = new Scanner(System.in);
int guess;
while (true) {
System.out.println("请输入一个1-100之间的整数:");
guess = scanner.nextInt();
if (guess == target) {
System.out.println("恭喜你,猜对了!");
break;
} else if (guess < target) {
System.out.println("猜测的数字偏小,请继续猜测!");
} else {
System.out.println("猜测的数字偏大,请继续猜测!");
}
}
System.out.println("游戏结束!");
scanner.close();
}
}
该程序会生成一个1到100之间的随机数字,然后用户可以通过输入数字来猜测该数字的值,程序会根据猜测结果给出相应提示,直到猜对为止。
Java 数组
(一)数组概述
在Java中,数组是一种用于存储多个相同类型数据的数据结构。它是一个固定大小的、连续的内存区域,可以存储多个元素,并通过索引来访问这些元素。
数组的特点包括:
- 数组的长度是固定的,一旦创建就不能改变。在创建数组时需要指定数组的长度。
- 数组中的元素可以是任意类型,包括基本类型和引用类型。
- 数组的索引从0开始,最大索引为数组长度减1。可以通过索引来访问数组中的元素。
- 数组是一块连续的内存区域,可以通过索引计算元素在内存中的位置,从而快速访问元素。
- 数组可以用于存储一组数据,并且可以对这些数据进行遍历、排序、搜索等操作。
(二)数组的定义与静态初始化
在Java中,数组的定义和静态初始化可以在一行代码中完成。定义和静态初始化数组的基本语法如下:
数据类型[] 数组名 = {元素1, 元素2, ...}
其中,数据类型表示数组中元素的类型,数组名是数组的名称,元素1、元素2等是要存储在数组中的具体数值。在静态初始化中,需要将数组的元素一一列举出来。
下面是一个例子,声明并静态初始化一个整型数组:
int[] numbers = {1, 2, 3, 4, 5};
在上面的代码中,我们定义了一个名为numbers的整型数组,并将1、2、3、4、5这些元素存储在数组中。
静态初始化数组时,可以使用任意多的元素,但是数组的长度会根据元素的个数自动确定。
除了基本类型,还可以使用引用类型进行数组的定义和静态初始化。例如,声明并静态初始化一个字符串数组:
String[] names = {"Alice", "Bob", "Charlie"};
在上面的代码中,我们定义了一个名为names的字符串数组,并将"Alice"、“Bob”、"Charlie"这些字符串存储在数组中。
静态初始化数组的好处是可以在声明数组的同时,为数组赋值,简化了代码的编写。但是静态初始化只适用于已经确定了元素的值的情况,如果需要动态赋值,则需要使用动态初始化的方式。
(三)数组元素访问
在Java中,可以使用索引访问数组中的元素。数组的索引从0开始,依次递增,直到数组的长度减1。
要访问数组中的元素,需要使用数组名和索引值来指定要访问的元素。基本语法如下:
数组名[索引值]
下面是一个例子,访问名为numbers的整型数组中的第三个元素:
int[] numbers = {1, 2, 3, 4, 5};
int element = numbers[2];
在上面的代码中,我们通过numbers[2]访问了整型数组numbers中的第三个元素,即数字3。将其赋值给了变量element。
需要注意的是,索引值必须在有效的范围内,即大于等于0且小于数组的长度。如果使用了无效的索引值,会导致数组越界异常(ArrayIndexOutOfBoundsException)。
此外,可以使用循环结构遍历数组中的所有元素。例如,使用for循环遍历整型数组numbers中的所有元素:
for (int i = 0; i < numbers.length; i++) {
System.out.println(numbers[i]);
}
在上面的代码中,通过循环逐个访问数组中的元素,并使用System.out.println()方法将其打印出来。需要注意的是,数组的长度可以通过数组名后跟.length来获取。
(四)数组变量
在Java中,数组是一种特殊类型的变量,用于存储相同类型的多个值。数组变量用于引用数组对象,可以通过数组变量来访问和操作数组中的元素。
声明一个数组变量的基本语法如下:
数据类型[] 变量名;
例如,声明一个整型数组变量numbers:
int[] numbers;
在上述例子中,我们声明了一个名为numbers的整型数组变量。
要使用一个数组变量,需要先创建一个实际的数组对象,并将其赋值给数组变量。可以使用关键字new来创建数组对象。
例如,创建一个长度为5的整型数组,并将其赋值给numbers变量:
numbers = new int[5];
在上述例子中,我们使用new int[5]创建了一个长度为5的整型数组对象,并将其赋值给numbers变量。
也可以在声明数组变量的同时创建数组对象,并将其赋值给数组变量。例如:
int[] numbers = new int[5];
上述语句将声明一个整型数组变量numbers,并创建一个长度为5的整型数组对象,并将其赋值给numbers变量。
在声明数组变量后,可以使用数组变量来访问和操作数组中的元素。例如,将元素赋值给数组中的某个位置:
numbers[0] = 1;
在上述例子中,将值1赋给数组numbers的第一个元素。
需要注意的是,数组变量只是一个引用,它并没有实际的数据。数据存储在数组对象中。
(五)数组动态初始化
在Java中,数组的动态初始化是指在创建数组对象时指定数组的长度。动态初始化允许我们在运行时确定数组的大小。
动态初始化数组的基本语法如下:
数据类型[] 变量名 = new 数据类型[长度];
例如,创建一个动态初始化的整型数组numbers,长度为5:
int[] numbers = new int[5];
上述语句将创建一个长度为5的整型数组对象,并将其赋值给变量numbers。
在动态初始化数组时,可以使用变量或表达式来指定数组的长度。例如:
int size = 5;
int[] numbers = new int[size];
在上述例子中,通过变量size来指定数组的长度。
动态初始化数组后,数组中的每个元素都会被默认初始化为其数据类型的默认值。例如,整型数组中的元素会被初始化为0,布尔型数组中的元素会被初始化为false。
可以通过索引和数组变量来访问和操作数组中的元素。例如,给数组中的某个位置赋值:
numbers[0] = 1;
在上述例子中,将值1赋给数组numbers的第一个元素。
需要注意的是,动态初始化数组时,长度必须是一个非负整数。否则会抛出NegativeArraySizeException异常。
(六)数组内存图
Java中的数组是一段连续的内存空间,用于存储相同类型的元素。每个数组都在内存中有一个地址,可以通过数组变量来访问。
下面是一个示例的Java数组的内存图示例,用于说明数组的组成和访问:
int[] numbers = new int[5];
内存图示意图如下:
┌─────────────────────┐
numbers ──────>│ 数组变量 │
└─────────────────────┘
│
▼
┌─────────────────────┐
│ 数组对象 │
├─────────────────────┤
│ 长度:5 │
├─────────────────────┤
│ 0 │ 0 │ 0 │ 0 │ 0 │
└─────────────────────┘
在上面的内存图中,numbers
是一个数组变量,指向数组对象。数组对象是一个长度为5的整型数组,每个元素默认初始化为0。
可以使用索引来访问数组中的元素。例如,numbers[0]
表示数组中的第一个元素,numbers[1]
表示数组中的第二个元素,依此类推。
访问数组元素时,Java会根据索引找到相应位置的内存地址,然后读取或修改该位置上的值。例如,numbers[0] = 1;
将把值1存储到数组的第一个元素上。
需要注意的是,数组的索引从0开始,到数组长度减1结束。如果访问超出数组范围的索引,将会抛出ArrayIndexOutOfBoundsException异常。
(七)数组常见问题
在Java中使用数组时,常见的问题有:
-
如何声明和初始化一个数组?
你可以使用以下语法来声明和初始化一个数组:dataType[] arrayName = new dataType[arrayLength];
例如:
int[] numbers = new int[5];
声明了一个包含5个整数的数组。 -
数组的长度是固定的吗?
是的,一旦数组被创建,它的长度就是固定的,无法改变。如果需要存储更多的元素,你需要创建一个新的数组。 -
如何访问数组中的元素?
数组的元素可以通过索引来访问,索引从0开始。例如,对于一个数组int[] numbers = {1, 2, 3};
,你可以通过numbers[0]
来访问第一个元素。 -
如何遍历数组?
可以使用循环结构(如for循环)来遍历数组中的元素。例如:for(int i = 0; i < array.length; i++){ // 访问array[i] }
-
数组越界是什么意思?
数组越界指的是访问数组时使用了一个超出数组长度范围的索引。这将导致运行时错误(ArrayIndexOutOfBoundsException)。 -
数组元素可以是任何类型吗?
数组元素可以是任何数据类型,包括基本类型和引用类型。 -
如何使用多维数组?
可以使用多个方括号来声明和访问多维数组。例如,int[][] matrix = new int[3][3];
声明了一个3x3的二维数组。 -
数组和ArrayList有什么区别?
数组是一块连续的内存空间,长度固定。而ArrayList是基于数组实现的动态数组,长度可以动态扩展。 -
如何在方法中传递数组?
你可以将数组作为方法的参数传递。例如,public void printArray(int[] array){ ... }
可以接受一个整数数组作为参数。 -
数组有哪些常用的方法?
数组类(java.util.Arrays)提供了一些常用的方法,如排序(sort)、查找(binarySearch)、复制(copyOf)等。可以通过该类来操作数组。
(八)数组常见操作
在Java中,数组有许多常见的操作,包括:
-
声明和初始化数组:
dataType[] arrayName = new dataType[arrayLength];
-
访问数组元素:
数组元素可以通过索引来访问,索引从0开始。例如,arrayName[index]
。 -
修改数组元素:
数组元素可以通过索引来修改。例如,arrayName[index] = value;
。 -
获取数组的长度:
数组的长度可以使用arrayName.length
来获取。 -
遍历数组:
可以使用循环结构(如for循环或foreach循环)来遍历数组中的元素。 -
复制数组:
可以使用Arrays.copyOf()
或System.arraycopy()
方法来复制一个数组。 -
数组排序:
可以使用Arrays.sort()
方法对数组进行排序,默认按升序排序。 -
数组查找:
可以使用Arrays.binarySearch()
方法在已排序的数组中查找特定元素。 -
数组填充:
可以使用Arrays.fill()
方法将数组的所有元素设置为指定的值。 -
数组比较:
可以使用Arrays.equals()
方法检查两个数组是否相等。 -
数组转换为字符串:
可以使用Arrays.toString()
方法将数组转换为字符串。 -
多维数组操作:
可以使用多个方括号来声明和访问多维数组的元素。
这些是Java数组的一些常见操作,可以根据需要选择适合的方法来操作数组。