Java 程序设计基础
Java 程序设计基础
程序设计风格和文档
程序设计风格决定程序的外观呈现,文档则是包含程序解释性评注与注释的结构化说明。良好的设计风格与规范文档能显著降低代码出错概率,提升代码可读性与可维护性,是团队协作和长期项目开发的基础。
正确的注释和注释风格
Java 支持三种注释类型,需根据使用场景选择合适的注释方式:
- 单行注释:以
//开头,注释范围仅当前行,适用于简短说明(如代码功能、变量含义)。
示例:// 计算圆的面积(公式:面积 = 半径 × 半径 × π) - 多行注释:以
/*开头、*/结尾,可跨多行,适用于代码块功能说明(如方法作用、逻辑思路)。
示例:/* * 从控制台读取用户输入的半径 * 步骤:1. 创建Scanner对象 2. 调用nextDouble()方法获取输入值 */ - 文档注释:以
/**开头、*/结尾,支持通过javadoc工具生成 HTML 格式文档,适用于类、方法、接口的结构化说明(需包含作者、参数、返回值、功能描述等)。
示例:/** * 计算圆的面积 * @param radius 圆的半径(double类型,需大于0) * @return 圆的面积(double类型) * @author 开发者姓名 */ public static double calculateArea(double radius) { return radius * radius * 3.14; }
正确的缩进和空白
缩进与空白的规范能让代码结构更清晰,便于快速理解代码层级关系:
- 缩进:使用
4 个空格作为一级缩进(不推荐使用 Tab 键,避免不同编辑器显示不一致),适用于类体、方法体、条件语句(if/for/while)等代码块内部。
示例:public class ComputeArea { // 一级缩进:方法体在类体内部 public static void main(String[] args) { // 二级缩进:变量声明在方法体内部 double radius; // 二级缩进:条件语句块 if (radius > 0) { // 三级缩进:条件满足时的执行代码 double area = radius * radius * 3.14; } } } - 空白:
- 运算符两侧加空格(如
=、+、*),增强可读性,示例:area = radius * radius * 3.14(而非area=radius*radius*3.14)。 - 逗号后加空格,示例:
int a, b, c(而非int a,b,c)。 - 方法参数列表中,参数之间加空格,示例:
public static void printInfo(String name, int age)。
- 运算符两侧加空格(如
块的风格
代码块(类块、方法块、条件块等)需用 {} 包裹,且遵循统一的格式规范,常见风格有两种:
- K&R 风格(推荐):左花括号
{与代码块起始语句同行,右花括号}与代码块起始语句对齐,适用于 Java 官方推荐规范。
示例:public class ComputeArea { // 左花括号与类声明同行 public static void main(String[] args) { // 左花括号与方法声明同行 double radius = 5.0; if (radius > 0) { // 左花括号与条件语句同行 double area = radius * radius * 3.14; } // 右花括号与if语句对齐 } // 右花括号与main方法声明对齐 } // 右花括号与类声明对齐 - Allman 风格:左花括号
{单独占一行,右花括号}与左花括号对齐,适用于代码块层级较多的场景。
示例:public class ComputeArea { // 左花括号单独占一行 public static void main(String[] args) { // 左花括号单独占一行 double radius = 5.0; if (radius > 0) { // 左花括号单独占一行 double area = radius * radius * 3.14; } // 右花括号与左花括号对齐 } // 右花括号与左花括号对齐 } // 右花括号与左花括号对齐
注意:同一项目中需统一块风格。
编写简单的程序
编写简单程序的核心是“设计解决问题的算法”与“用编程语言实现算法”,需先明确问题目标、拆解步骤,再通过代码落地。以下以“计算圆面积”为例,完整演示程序编写流程。
算法设计
算法是解决问题的“步骤集合”,需明确“做什么”和“按什么顺序做”,可通过自然语言或伪代码描述。
计算圆面积的算法(自然语言描述):
- 读取用户输入的圆的半径(需确保半径为正数)。
- 使用公式
面积 = 半径 × 半径 × π(π 取 3.14)计算面积。 - 在控制台显示计算结果。
代码实现步骤
搭建程序框架
Java 程序以类为基础,每个可执行程序需包含一个 public 类和 main 方法(程序入口):
// 步骤1:声明public类(类名与文件名一致,此处为ComputeArea)
public class ComputeArea {
// 步骤2:定义main方法(程序入口,JVM从这里开始执行)
public static void main(String[] args) {
// 后续代码将在此处编写(读取半径、计算面积、显示结果)
}
}
声明变量
变量是存储数据的“内存区域”,需指定 数据类型 和 变量名(见下文“变量”)。
计算圆面积需存储“半径”和“面积”,二者均为带小数点的数值,故使用 double 类型(双精度浮点型):
public class ComputeArea {
public static void main(String[] args) {
// 声明double类型变量:radius(半径)、area(面积)
double radius;
double area;
// 后续:读取半径、计算面积、显示结果
}
}
读取用户输入(见下文“从控制台读取输入”)
计算面积并显示结果(见下文“赋值语句”“控制台输出”)
从控制台读取输入
Java 中可通过 java.util.Scanner 类实现控制台输入,需先导入该类,再调用其方法读取不同类型的数据(如 nextDouble() 读取浮点型、nextInt() 读取整型)。
完整示例:读取半径并计算圆面积
package com.basic;
// 步骤1:导入Scanner类(Scanner在java.util包中,需显式导入)
import java.util.Scanner;
/**
* @Author Jing61
*/
public class ComputeArea {
public static void main(String[] args) {
// 步骤2:提示用户输入(友好交互)
System.out.println("请输入圆的半径:");
// 步骤3:创建Scanner对象(System.in表示从控制台输入)
Scanner input = new Scanner(System.in);
// 步骤4:调用nextDouble()方法读取用户输入的半径,赋值给radius变量
double radius = input.nextDouble();
// 步骤5:计算面积(π取3.14)
double area = radius * radius * 3.14;
// 步骤6:显示结果(使用+拼接字符串和变量)
System.out.println("半径为:" + radius + "的圆的面积为:" + area);
// 步骤7:关闭Scanner(可选,避免资源泄漏)
input.close();
}
}
Scanner 类核心方法
| 方法名 | 功能 | 示例 |
|---|---|---|
| nextDouble() | 读取 double 类型数据(适用于小数) | double radius = input.nextDouble(); |
| nextInt() | 读取 int 类型数据(适用于整数) | int age = input.nextInt(); |
| nextLong() | 读取 long 类型数据(适用于大整数) | long phone = input.nextLong(); |
| nextByte() | 读取 byte 类型数据(适用于小范围整数) | byte score = input.nextByte(); |
| nextShort() | 读取 short 类型数据(适用于中等范围整数) | short num = input.nextShort(); |
| nextFloat() | 读取 float 类型数据(适用于单精度小数) | float weight = input.nextFloat(); |
| nextBoolean() | 读取 boolean 类型数据(仅识别 true/false) | boolean isActive = input.nextBoolean(); |
| next() | 读取字符串(以空格/回车为分隔符,不含分隔符) | String name = input.next(); |
| nextLine() | 读取一行字符串(以回车为分隔符,含空格) | String address = input.nextLine(); |
| next(String pattern) | 读取匹配指定正则表达式的字符串 | String code = input.next("[A-Z0-9]+"); |
导入语句的两种类型
- 明确导入:指定导入单个类,格式为
import 包名.类名;,示例:import java.util.Scanner;(仅导入Scanner类)。 - 通配符导入:导入一个包中的所有类,格式为
import 包名.*;,示例:import java.util.*;(导入java.util包下的所有类,如Scanner、ArrayList等)。
注意:两种导入方式在性能上无差异,编译器仅会加载程序中实际使用的类;推荐优先使用明确导入,避免类名冲突(如不同包下有同名类)。
练习:读取三个数值并计算平均值
package com.basic;
import java.util.Scanner;
/**
* @Author Jing61
*/
public class CalculateAverage {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// 提示用户输入三个数值
System.out.println("请输入第一个数值:");
double num1 = input.nextDouble();
System.out.println("请输入第二个数值:");
double num2 = input.nextDouble();
System.out.println("请输入第三个数值:");
double num3 = input.nextDouble();
// 计算平均值
double average = (num1 + num2 + num3) / 3;
// 显示结果
System.out.println("三个数值的平均值为:" + average);
input.close();
}
}
标识符
标识符是 Java 中为 包、类、方法、参数、变量 命名的符号,需严格遵循语法规则,同时建议使用具有描述性的名称(提升代码可读性)。
标识符语法规则
- 可由 大小写字母(A-Z、a-z)、数字(0-9)、下划线(_)、美元符号($) 组成。
- 不能以数字开头(如
123name不合法)。 - 不能是 Java 关键字(如
class、int、public等,见下表)。 - 区分大小写(如
radius和Radius是两个不同的标识符)。
合法与不合法标识符示例
| 类型 | 示例 | 说明 |
|---|---|---|
| 合法 | username、user_name、_userName、$username |
符合语法规则,名称具有描述性 |
| 不合法 | class |
是 Java 关键字 |
| 不合法 | 3.14 |
以数字开头,且包含非法字符 . |
| 不合法 | user name |
包含空格(非法字符) |
Java 常用关键字(部分)
| 关键字 | 用途 | 关键字 | 用途 |
|---|---|---|---|
public |
访问修饰符(公开) | class |
声明类 |
static |
静态修饰符 | void |
表示无返回值 |
int/double |
基本数据类型 | if/for/while |
流程控制 |
final |
声明常量或不可变对象 | return |
方法返回值 |
变量
变量是内存中用于存储数据的“命名区域”,具有 名称、类型、值 三个核心属性,其值可在同一类型范围内修改。
变量的核心概念
- 数据类型:决定变量存储的数据类型(如
int存整数、double存小数),编译器根据类型分配合适的内存空间(如int占 4 字节、double占 8 字节)。 - 变量名:遵循标识符规则,需具有描述性(如用
age表示年龄,而非x)。 - 值:变量存储的具体数据,需与数据类型匹配(如
int age = 20合法,int age = 20.5不合法)。
变量声明与初始化
声明变量
语法:数据类型 变量名;
示例:
int count; // 声明int类型变量count(整数)
double radius; // 声明double类型变量radius(小数)
String name; // 声明String类型变量name(字符串)
声明并初始化变量
变量在使用前必须初始化(赋值),推荐“声明时直接初始化”,避免未赋值导致的错误:
- 语法:
数据类型 变量名 = 初始值; - 示例:
int count = 1; // 声明并初始化int变量count(值为1) double radius = 5.0; // 声明并初始化double变量radius(值为5.0) String name = "Alice"; // 声明并初始化String变量name(值为"Alice")
批量声明同一类型变量
多个同类型变量可在一行声明,用逗号分隔,支持部分变量初始化:
int a = 1, b = 2, c; // 声明int变量a(值1)、b(值2)、c(未初始化)
double x = 3.14, y = 2.5; // 声明double变量x(值3.14)、y(值2.5)
变量的作用域
变量的作用域是指“变量可被引用的程序范围”,超出范围后变量将被销毁(内存释放),主要分为:
- 局部变量:在方法、代码块(如
if/for块)内部声明的变量,作用域仅限于当前方法/代码块,示例:public static void main(String[] args) { // 局部变量:作用域为main方法内部 int a = 10; if (a > 5) { // 局部变量:作用域为if代码块内部,外部无法访问 int b = 20; System.out.println(b); // 合法(在if块内) } // System.out.println(b); // 不合法(b的作用域已结束) } - 成员变量:在类内部、方法外部声明的变量,作用域为整个类(后续详细讲解)。
注意事项
- 方法内的局部变量必须初始化后才能使用(否则编译报错)。
- 变量名需遵循命名习惯(见下文“命名习惯”),如
radius(小写驼峰)表示半径。
赋值语句和赋值表达式
赋值语句用于将“表达式的结果”赋值给变量,= 是赋值运算符(而非“等于”,等于用 == 表示);在 Java 中,赋值语句本身也属于表达式(可嵌套使用)。
赋值语句语法
语法:变量 = 表达式;
- 变量:需与表达式的结果类型匹配(或支持自动类型转换)。
- 表达式:由值、变量、运算符组成,最终计算出一个结果(如
1 + 2、radius * 2)。
示例
// 1. 基本赋值:将常量值赋值给变量
int i = 1;
double radius = 1.0;
// 2. 表达式赋值:将表达式结果赋值给变量
int ret = 5 * (3 / 2); // 表达式5*(3/2)=5*1=5,ret值为5
ret = i + 1; // 表达式i+1=1+1=2,ret值更新为2
// 3. 变量参与表达式:变量可在表达式中使用
double area = radius * radius * 3.14; // radius为变量,表达式结果赋值给area
// 4. 赋值表达式嵌套(赋值语句本身是表达式,结果为赋值后变量的值)
int a = (b = 5); // 先将5赋值给b,再将b的值(5)赋值给a,最终a=5、b=5
注意事项
- 赋值运算符是“右结合”的,即从右往左执行,示例:
a = b = c = 10(先将10赋值给c,再赋值给b,最后赋值给a,最终a=b=c=10)。 - 变量类型需与表达式结果类型兼容,如
int a = 3.14不合法(double类型无法直接赋值给int类型,需强制转换)。
命名常量
常量是“值在程序执行过程中不可改变”的特殊变量,需用 final 关键字声明,通常用于存储固定值(如 π、最大值、配置参数等)。
常量声明语法
语法:final 数据类型 常量名 = 初始值;
final:Java 关键字,标记变量为常量,赋值后不可修改(若尝试修改,编译报错)。- 常量名:遵循“全大写,多单词用下划线连接”的命名习惯(如
PI、MAX_VALUE)。 - 必须在声明时初始化:常量不能先声明后赋值,需在同一行完成声明和赋值。
示例:使用常量计算圆面积
package com.basic;
import java.util.Scanner;
/**
* @Author Jing61
*/
public class ComputeAreaWithConstant {
public static void main(String[] args) {
// 声明常量PI(值为3.14,不可修改)
final double PI = 3.14;
// 读取用户输入的半径
System.out.println("请输入圆的半径:");
Scanner input = new Scanner(System.in);
double radius = input.nextDouble();
// 使用常量PI计算面积(PI的值不可修改)
double area = PI * radius * radius;
// 显示结果
System.out.println("半径为:" + radius + "的圆的面积为:" + area);
input.close();
}
}
使用常量的好处
- 避免重复输入:频繁使用的固定值(如 π)只需声明一次,无需重复编写,减少输入错误。
- 便于维护:若需修改常量值(如 π 更精确为 3.14159),仅需在声明处修改一次,无需逐个修改所有引用处。
- 提升可读性:描述性的常量名(如
PI)比直接写3.14更易理解代码含义。
命名习惯
Java 有严格的命名规范(由 Oracle 官方推荐),遵循规范能让代码风格统一,便于团队协作和后期维护。
| 标识符类型 | 命名规则 | 示例 |
|---|---|---|
| 变量、方法、参数 | 小写驼峰命名法:首字母小写,后续单词首字母大写 | 变量:radius、userName;方法:calculateArea()、printInfo();参数:inputRadius |
| 类、接口 | 大写驼峰命名法:每个单词首字母大写 | 类:ComputeArea、UserInfo;接口:Shape、DataService |
| 常量 | 全大写命名法:所有字母大写,多单词用下划线连接 | PI、MAX_AGE、DB_URL |
| 包 | 全小写命名法:通常为公司/个人域名反转,多层级用点分隔 | java.util(官方包)、edu.cduestc.charpter1(自定义包) |
注意:命名需具有描述性,避免使用无意义的名称(如 x、a1),示例:用 age 表示年龄,而非 a;用 calculateArea 表示计算面积,而非 func1。
数值数据类型和操作
Java 提供两种数值数据类型:整型(存储整数)和 浮点型(存储小数),不同类型的存储范围和精度不同,需根据业务场景选择。
整型(存储整数)
整型用于存储无小数部分的数值,分为 4 种类型,核心区别是 存储范围(由占用字节数决定):
| 类型 | 占用字节 | 存储范围(二进制推导) | 取值范围示例 | 说明 |
|---|---|---|---|---|
byte |
1 字节(8 位) | -2^7 ~ 2^7 - 1 |
-128 ~ 127 | 最小整型,适用于存储小范围整数(如状态码、年龄) |
short |
2 字节(16 位) | -2^15 ~ 2^15 - 1 |
-32768 ~ 32767 | 适用于中等范围整数 |
int |
4 字节(32 位) | -2^31 ~ 2^31 - 1 |
-2147483648 ~ 2147483647 | 默认整型(整数常量默认是 int 类型),最常用 |
long |
8 字节(64 位) | -2^63 ~ 2^63 - 1 |
-9223372036854775808 ~ 9223372036854775807 | 适用于大范围整数(如时间戳、身份证号) |
整型使用注意事项
- 给
long类型赋值时,需在数值后加L或l(推荐L,避免与数字1混淆),否则数值默认是int类型,超出int范围会报错:
示例:long num1 = 10000000000L;(合法);long num2 = 10000000000;(不合法,超出int范围)。 - 整型支持多种进制表示:
- 十进制(默认):
int a = 10; - 二进制:以
0b或0B开头,int b = 0b1010;(表示十进制 10) - 八进制:以
0开头,int c = 012;(表示十进制 10) - 十六进制:以
0x或0X开头,int d = 0xA;(表示十进制 10)
- 十进制(默认):
- Java 7+ 支持数字间用
_分隔,提升可读性(编译器会忽略_):
示例:int e = 1_000_000;(表示 1000000)。
浮点型(存储小数)
浮点型用于存储带小数部分的数值,分为 2 种类型,核心区别是 精度 和 存储范围:
| 类型 | 占用字节 | 精度(有效数字) | 说明 |
|---|---|---|---|
float |
4 字节(32 位) | 6~7 位有效数字 | 单精度浮点型,赋值时需在数值后加 F 或 f(否则默认是 double 类型) |
double |
8 字节(64 位) | 15~17 位有效数字 | 双精度浮点型,默认浮点型(小数常量默认是 double 类型),精度更高,更常用 |
浮点型使用注意事项
- 给
float类型赋值时,必须加F或f:
示例:float f1 = 3.14F;(合法);float f2 = 3.14;(不合法,3.14 默认是double类型)。 - 浮点型支持科学计数法:
- 格式:
数值 e 指数(e表示 10 的幂),示例:double d1 = 3.14e2;(表示 3.14 × 10² = 314);double d2 = 3.14e-2;(表示 3.14 × 10⁻² = 0.0314)。
- 格式:
- 浮点型精度问题:
float和double均为“近似存储”,无法精确表示所有小数(如 0.1、1.3),会存在微小误差,示例:
若需精确计算(如金融场景),需使用double a = 0.1 + 0.2; System.out.println(a); // 输出 0.30000000000000004(而非 0.3)java.math.BigDecimal类(而非浮点型)。
数值操作符
数值操作符用于对数值类型变量/常量进行运算,主要包括 算术运算符、赋值运算符、自增自减运算符 等。
算术运算符
| 运算符 | 功能 | 示例(a=5, b=2) | 结果 |
|---|---|---|---|
+ |
加法 | a + b |
7 |
- |
减法 | a - b |
3 |
* |
乘法 | a * b |
10 |
/ |
除法 | a / b(整数除法) |
2(仅保留整数部分,舍弃小数) |
% |
取模(求余数) | a % b |
1(5 ÷ 2 的余数) |
算术运算符注意事项:
+运算符的特殊用途:除加法外,还可用于 字符串拼接,若+两侧有一个是字符串,结果为字符串:
示例:"x" + 123→"x123";1 + 2 + "x"→"3x";"x" + 1 + 2→"x12"。- 整数除法(
/):若两个操作数均为整数,结果仅保留整数部分,舍弃小数(而非四舍五入):
示例:5 / 2 = 2;3510 / 1000 = 3(而非 3.51)。 - 取模(
%):结果的符号与 被除数 一致,示例:5 % -2 = 1;-5 % 2 = -1;-5 % -2 = -1。
示例1:计算秒数对应的分钟和剩余秒数
package com.basic;
import java.util.Scanner;
/**
* @Author Jing61
*/
public class DisplayTime {
public static void main(String[] args) {
// 读取用户输入的总秒数
Scanner input = new Scanner(System.in);
System.out.println("请输入一个整数来代表秒数:");
int seconds = input.nextInt();
// 计算分钟数(总秒数 ÷ 60)
int minutes = seconds / 60;
// 计算剩余秒数(总秒数 % 60)
int remainingSeconds = seconds % 60;
// 显示结果
System.out.println(seconds + "秒包含" + minutes + "分钟" + remainingSeconds + "秒");
input.close();
}
}
示例2:显示当前时间(基于毫秒数)
package com.basic;
/**
* 显示当前时间(基于1970年1月1日午夜到现在的毫秒数)
* @author Jing61
*/
public class ShowCurrentTime {
public static void main(String[] args) {
// 1. 获取当前时间的总毫秒数(System.currentTimeMillis())
long totalMilliseconds = System.currentTimeMillis();
// 2. 换算成总秒数(毫秒数 ÷ 1000)
long totalSeconds = totalMilliseconds / 1000;
// 3. 计算当前秒数(总秒数 % 60)
long seconds = totalSeconds % 60;
// 4. 换算成总分钟数(总秒数 ÷ 60)
long totalMinutes = totalSeconds / 60;
// 5. 计算当前分钟数(总分钟数 % 60)
long minutes = totalMinutes % 60;
// 6. 换算成总小时数(总分钟数 ÷ 60),加8(东八区)
long totalHours = totalMinutes / 60 + 8;
// 7. 计算当前小时数(总小时数 % 24)
long hours = totalHours % 24;
// 显示当前时间(格式:时:分:秒)
System.out.println(hours + ":" + minutes + ":" + seconds);
}
}
增强赋值操作符
增强赋值操作符是“算术运算符 + 赋值运算符”的简写形式,用于简化“变量自操作后赋值”的代码,支持 +、-、*、/、% 等算术运算符。
增强赋值操作符列表
| 增强赋值运算符 | 等价表达式 | 示例(a=5) | 结果(a的值) |
|---|---|---|---|
+= |
a = a + 表达式 |
a += 3 |
5 + 3 = 8 |
-= |
a = a - 表达式 |
a -= 3 |
5 - 3 = 2 |
*= |
a = a * 表达式 |
a *= 3 |
5 * 3 = 15 |
/= |
a = a / 表达式 |
a /= 3 |
5 / 3 = 1(整数除法) |
%= |
a = a % 表达式 |
a %= 3 |
5 % 3 = 2 |
示例
int count = 10;
count += 5; // 等价于 count = count + 5 → count = 15
count *= 2; // 等价于 count = count * 2 → count = 30
count -= 8; // 等价于 count = count - 8 → count = 22
double price = 19.9;
price /= 2; // 等价于 price = price / 2 → price = 9.95
注意事项
增强赋值操作符会自动处理类型转换(若需要),示例:
byte b = 5;
b += 3; // 等价于 b = (byte)(b + 3) → 结果为 8(无需手动强转)
// 若直接写 b = b + 3,会报错(b+3 结果为 int 类型,需强转)
自增和自减操作符
自增(++)和自减(--)操作符用于让变量“自增 1”或“自减 1”,分为 前缀 和 后缀 两种形式,核心区别是“操作与运算的顺序”。
自增操作符(++)
| 形式 | 语法 | 执行顺序 | 示例(a=5) | 结果(a的值) | 表达式结果 |
|---|---|---|---|---|---|
| 前缀自增 | ++a |
先自增 1,再参与运算 | int b = ++a; |
6 | 6(b=6) |
| 后缀自增 | a++ |
先参与运算,再自增 1 | int b = a++; |
6 | 5(b=5) |
自减操作符(--)
| 形式 | 语法 | 执行顺序 | 示例(a=5) | 结果(a的值) | 表达式结果 |
|---|---|---|---|---|---|
| 前缀自减 | --a |
先自减 1,再参与运算 | int b = --a; |
4 | 4(b=4) |
| 后缀自减 | a-- |
先参与运算,再自减 1 | int b = a--; |
4 | 5(b=5) |
示例
// 自增示例
int x = 3;
int y = ++x; // 前缀自增:x先变成4,再赋值给y → x=4,y=4
int z = x++; // 后缀自增:x先赋值给z(z=4),再变成5 → x=5,z=4
// 自减示例
int m = 5;
int n = --m; // 前缀自减:m先变成4,再赋值给n → m=4,n=4
int p = m--; // 后缀自减:m先赋值给p(p=4),再变成3 → m=3,p=4
// 输出结果
System.out.println(x); // 5
System.out.println(y); // 4
System.out.println(z); // 4
System.out.println(m); // 3
System.out.println(n); // 4
System.out.println(p); // 4
注意事项
- 自增/自减操作符仅适用于变量(如
++5、10--不合法)。 - 避免在复杂表达式中多次使用自增/自减(如
a = ++a + a--),可能导致代码可读性差且结果难以预测。
数值类型转换
当不同类型的数值变量进行运算时,会发生类型转换,确保运算在同一类型下进行。类型转换分为 自动类型转换 和 强制类型转换。
自动类型转换(隐式转换)
规则
当“小范围类型”变量赋值给“大范围类型”变量时,编译器自动完成转换(无精度损失),转换顺序如下:
byte → short → char → int → long → float → double
- 注意1:
byte、short、char之间运算时,结果自动转为int类型(即使运算结果在原类型范围内):
示例:byte a = 10; byte b = 20; int c = a + b;(a+b 结果为int类型,需用int接收)。 - 注意2:
boolean类型不能与任何其他类型转换。
示例
byte b = 127;
short s = b; // 自动转换:byte → short(无精度损失)
int i = s; // 自动转换:short → int
long l = i; // 自动转换:int → long
float f = l; // 自动转换:long → float(float范围比long大)
double d = f; // 自动转换:float → double
char c = 'A'; // 'A' 的 ASCII 码为 65
int i2 = c; // 自动转换:char → int → i2=65
强制类型转换(显式转换)
规则
当“大范围类型”变量赋值给“小范围类型”变量时,需手动使用 (目标类型) 强制转换(可能导致精度损失或数据溢出),语法:
小范围类型 变量名 = (小范围类型) 大范围类型值;
示例
// 1. 浮点型转整型(丢失小数部分,非四舍五入)
double d = 3.9;
int i = (int)d; // 强制转换:double → int → i=3(丢失小数 0.9)
// 2. 大范围整型转小范围整型(可能溢出)
long l = 1000000;
byte b = (byte)l; // 强制转换:long → byte → b=16(1000000 超出 byte 范围,溢出)
// 3. 类型不兼容,强制转换也报错(如 boolean 与 int)
// boolean flag = true;
// int x = (int)flag; // 编译报错:不兼容的类型
注意事项
强制转换会“截断高位数据”,导致精度损失或数据溢出,需谨慎使用,示例:
int a = 257;
byte b = (byte)a; // byte 范围是 -128~127,257 超出范围,结果为 1(二进制截断后的值)
变量与字符串的运算(+ 连接符)
当变量与字符串通过 + 运算时,+ 表示“字符串连接符”,结果为字符串类型,示例:
int age = 20;
String info = "年龄:" + age; // 结果为 "年龄:20"(int 转字符串)
double score = 95.5;
String result = "分数:" + score + "分"; // 结果为 "分数:95.5分"(double 转字符串)
// 混合运算:先计算数值,再拼接字符串
String mix = "1 + 2 = " + (1 + 2); // 结果为 "1 + 2 = 3"(括号内先计算 1+2=3)
String mix2 = "1 + 2 = " + 1 + 2; // 结果为 "1 + 2 = 12"(先拼接 "1 + 2 = 1",再拼接 "2")
软件开发过程
软件开发生命周期是软件开发的标准化流程,涵盖从“需求分析”到“维护”的全阶段,确保软件产品满足用户需求、质量可靠、易于维护。
软件开发生命周期阶段
| 阶段 | 核心任务 | 输出物 |
|---|---|---|
| 需求规范 | 理解用户需求,明确软件功能、性能、安全等要求,形成规范化文档 | 需求规格说明书 |
| 系统分析 | 分析数据流(输入→处理→输出),明确系统边界和业务逻辑 | 系统分析报告、数据流图 |
| 系统设计 | 将问题分解为子系统,设计技术方案(如架构设计、数据库设计、接口设计) | 系统设计文档、架构图、数据库表结构 |
| 实现(编码) | 将设计方案翻译成程序代码,完成模块开发和集成 | 源代码、可执行程序 |
| 测试 | 验证软件是否符合需求,排查功能错误、性能问题、兼容性问题 | 测试用例、测试报告 |
| 部署 | 将软件安装到生产环境,交付用户使用 | 部署文档、用户手册 |
| 维护 | 修复用户反馈的bug,根据需求变更优化功能,保障软件长期稳定运行 | 维护记录、版本更新日志 |
示例:设计“计算贷款支付”程序
以“计算贷款月支付额和总支付额”为例,演示核心阶段的落地过程。
需求规范
程序需满足以下要求:
- 允许用户输入 贷款利率(年利率,如 4.5 表示 4.5%)、贷款额度(如 100000 元)、贷款年限(如 30 年)。
- 计算并显示 月支付额度 和 总支付额度。
系统分析
- 输入:贷款利率(double)、贷款额度(double)、贷款年限(int)。
- 输出:月支付额(double)、总支付额(double)。
- 核心公式(月支付额):
月利率 = 年利率 / 1200(年利率转月利率,除以 100 转为小数,再除以 12 转为月利率)
月支付额 = 贷款额度 × 月利率 / (1 - 1 / (1 + 月利率)ⁿ)(n 为贷款总月数,n = 年限 × 12)
总支付额 = 月支付额 × 年限 × 12。
系统设计
分解步骤:
- 提示用户输入贷款利率、贷款额度、贷款年限。
- 转换利率:将年利率(百分比)转为月利率(小数)。
- 计算贷款总月数(年限 × 12)。
- 使用公式计算月支付额(需调用
Math.pow()方法计算幂次)。 - 计算总支付额(月支付额 × 总月数)。
- 显示计算结果。
实现(编码)
package com.basic;
import java.util.Scanner;
/**
* @Author Jing61
*/
public class ComputeLoan {
public static void main(String[] args) {
// 1. 创建Scanner对象,读取用户输入
Scanner input = new Scanner(System.in);
// 2. 提示并读取贷款额度
System.out.println("请输入贷款额度:");
double loanAmount = input.nextDouble();
// 3. 提示并读取贷款年限
System.out.println("请输入贷款年限:");
int years = input.nextInt();
// 4. 提示并读取贷款利率(年利率,格式如4.5表示4.5%)
System.out.println("请输入贷款利率,格式为:4.5,代表年利率为4.5%");
double interestRate = input.nextDouble();
// 5. 计算月利率(年利率/1200)
double monthlyInterestRate = interestRate / 1200;
// 6. 计算贷款总月数
int totalMonths = years * 12;
// 7. 计算月支付额(使用Math.pow(a, b)计算a的b次方)
double monthlyPayment = loanAmount * monthlyInterestRate /
(1 - 1 / Math.pow(1 + monthlyInterestRate, totalMonths));
// 8. 计算总支付额
double totalPayment = monthlyPayment * totalMonths;
// 9. 显示结果
System.out.println("月支付额:" + monthlyPayment);
System.out.println("总支付额:" + totalPayment);
// 10. 关闭Scanner
input.close();
}
}
测试


浙公网安备 33010602011771号