12、编程中的数值提升与命名规则解析

编程中的数值提升与命名规则解析

在编程领域,数值的处理和命名规范是非常基础且重要的内容。下面我们将详细探讨二进制数值提升以及命名相关的规则。

二进制数值提升

二进制数值提升是指在操作符对一对操作数进行运算时,根据一定规则对操作数进行类型转换的过程。操作数必须能转换为数值类型,具体规则如下:
1. 拆箱转换 :若操作数为引用类型,先进行拆箱转换。
2. 类型转换规则
- 若任一操作数为 double 类型,另一个操作数转换为 double 类型。
- 若任一操作数为 float 类型,另一个操作数转换为 float 类型。
- 若任一操作数为 long 类型,另一个操作数转换为 long 类型。
- 否则,两个操作数都转换为 int 类型。

类型转换完成后,还会对每个操作数进行值集转换。

以下这些操作符会对操作数进行二进制数值提升:
- 乘法运算符 * / %
- 数值类型的加法和减法运算符 + -
- 数值比较运算符 < <= > >=
- 数值相等运算符 == !=
- 整数按位运算符 & ^ |
- 在某些情况下,条件运算符 ? :

下面是一个二进制数值提升的示例代码:

class Test {
    public static void main(String[] args) {
        int i = 0;
        float f = 1.0f;
        double d = 2.0;
        // First int*float is promoted to float*float, then
        // float==double is promoted to double==double:
        if (i * f == d)
            System.out.println("oops");

        // A char&byte is promoted to int&int:
        byte b = 0x1f;
        char c = 'G';
        int control = c & b;
        System.out.println(Integer.toHexString(control));

        // Here int:float is promoted to float:float:
        f = (b==0) ? i : 4.0f;
        System.out.println(1.0/f);
    }
}

该代码的输出结果为:

7
0.25

这个示例将ASCII字符 G 转换为ASCII控制字符 G (BEL) ,通过屏蔽字符的低5位以外的所有位实现。 7 是这个控制字符的数值。

为了更清晰地展示二进制数值提升的流程,我们可以用mermaid流程图表示:

graph TD;
    A[操作符对操作数运算] --> B{操作数是否为引用类型};
    B -- 是 --> C[进行拆箱转换];
    B -- 否 --> D{是否有操作数为double类型};
    C --> D;
    D -- 是 --> E[另一操作数转换为double类型];
    D -- 否 --> F{是否有操作数为float类型};
    E --> G[进行值集转换];
    F -- 是 --> H[另一操作数转换为float类型];
    F -- 否 --> I{是否有操作数为long类型};
    H --> G;
    I -- 是 --> J[另一操作数转换为long类型];
    I -- 否 --> K[两个操作数都转换为int类型];
    J --> G;
    K --> G;
命名规则

在编程中,命名用于引用程序中声明的实体。声明的实体包括包、类类型、接口类型、引用类型的成员、类型参数、参数或局部变量等。

声明

声明会引入一个实体到程序中,并包含一个标识符,用于在名称中引用该实体。声明的实体有多种类型,具体如下表所示:
| 实体类型 | 具体说明 |
| ---- | ---- |
| 包 | 在包声明中声明 |
| 导入类型 | 在单类型导入声明或按需类型导入声明中声明 |
| 类 | 在类类型声明中声明 |
| 接口 | 在接口类型声明中声明 |
| 类型变量 | 作为泛型类、接口、方法或构造函数的形式类型参数声明 |
| 引用类型的成员 | 包括成员类、成员接口、枚举常量、字段(类类型中声明的字段、接口类型中声明的常量字段、数组类型隐式的 length 字段)、方法(类类型中声明的方法、接口类型中声明的抽象方法) |
| 参数 | 方法、构造函数或异常处理程序的参数 |
| 局部变量 | 在块或 for 语句中声明的局部变量 |

构造函数虽然也通过声明引入,但使用的是其所在类的名称,而不是引入新名称。

名称和标识符

名称用于引用程序中声明的实体,有简单名称和限定名称两种形式。简单名称是单个标识符,限定名称由名称、“.”标记和标识符组成。

在确定名称的含义时,会考虑名称出现的上下文。并非所有标识符都是名称的一部分,标识符还用于以下情况:
- 声明中,指定声明实体的名称。
- 字段访问表达式中,指示对象的成员。
- 某些方法调用表达式中,指示要调用的方法。
- 限定类实例创建表达式中,指示类型。
- 作为标签出现在带标签的语句以及 break continue 语句中。

例如,在以下代码中:

class Test {
    public static void main(String[] args) {
        Class c = System.out.getClass();
        System.out.println(c.toString().length() +
                args[0].length() + args.length);
    }
}

Test main 以及 args c 的首次出现不是名称,而是用于声明中指定声明实体的名称。 String Class System.out.getClass 等是名称。 length 的两次出现是标识符,用于方法调用表达式。

带标签语句及其相关的 break continue 语句中使用的标识符与声明中使用的标识符是完全分开的。例如:

class TestString {
    char[] value;
    int offset, count;
    int indexOf(TestString str, int fromIndex) {
        char[] v1 = value, v2 = str.value;
        int max = offset + (count - str.count);
        int start = offset + ((fromIndex < 0) ? 0 : fromIndex);
        i:
        for (int i = start; i <= max; i++)
        {
            int n = str.count, j = i, k = str.offset;
            while (n-- != 0) {
                if (v1[j++] != v2[k++])
                    continue i;
            }
            return i - offset;
        }
        return -1;
    }
}

这里将标签改为与局部变量 i 同名,不会影响标签在 i 声明作用域内的使用。

声明的作用域

声明的作用域是程序中可以使用简单名称引用该声明实体的区域。不同构造的作用域规则如下:
1. :可观察的顶级包的声明作用域是所有可观察的编译单元;不可观察的包声明永远不在作用域内;子包声明也不在作用域内。
2. 导入类型 :单类型导入声明或按需类型导入声明导入的类型,其作用域是导入声明所在编译单元中的所有类和接口类型声明。
3. 顶级类型 :顶级类型的作用域是其所在包中的所有类型声明。
4. 类或接口的成员 :类或接口中声明或继承的成员的作用域是该类或接口的整个主体,包括任何嵌套类型声明。
5. 方法或构造函数的参数 :其作用域是方法或构造函数的整个主体。
6. 接口、方法或构造函数的类型参数 :其作用域是整个声明,包括类型参数部分本身。
7. 局部变量
- 在块中声明的局部变量,作用域是声明所在块的其余部分,从其初始化器开始。
- 在基本 for 语句的 ForInit 部分声明的局部变量,作用域包括其初始化器、 ForInit 部分中右侧的其他声明符、 for 语句的表达式和 ForUpdate 部分以及包含的语句。
- 在增强 for 语句的 FormalParameter 部分声明的局部变量,作用域是包含的语句。
8. 异常处理程序的参数 :其作用域是 catch 关联的整个块。

这些规则意味着类和接口类型的声明不必出现在使用这些类型之前。例如:

package points;
class Point {
    int x, y;
    PointList list;
    Point next;
}
class PointList {
    Point first;
}

Point 类中使用 PointList 是正确的,因为 PointList 类声明的作用域包括 Point 类和 PointList 类,以及 points 包中其他编译单元的任何其他类型声明。

声明的遮蔽

某些声明在其部分作用域内可能会被另一个同名声明遮蔽,此时不能使用简单名称引用被声明的实体。具体的遮蔽规则如下:
1. 类型声明 :名为 n 的类型声明 d 会遮蔽在 d 出现点作用域内的任何其他同名类型声明,在 d 的整个作用域内都是如此。
2. 字段、局部变量、参数声明 :名为 n 的字段、局部变量、方法参数、构造函数参数或异常处理程序参数的声明 d ,会遮蔽在 d 出现点作用域内的任何其他同名声明,在 d 的整个作用域内都是如此。
3. 方法声明 :名为 n 的方法声明 d 会遮蔽在 d 出现点的封闭作用域内的任何其他同名方法声明,在 d 的整个作用域内都是如此。
4. 包声明 :包声明不会遮蔽任何其他声明。
5. 单类型导入声明 :在包 p 的编译单元 c 中导入名为 n 的类型的单类型导入声明 d ,会遮蔽 p 的另一个编译单元中声明的任何顶级类型 n c 中按需类型导入声明导入的任何类型 n 以及 c 中按需静态导入声明导入的任何类型 n ,在 c 中都是如此。
6. 单静态导入声明
- 导入名为 n 的字段的单静态导入声明 d ,会遮蔽 c 中按需静态导入声明导入的任何静态字段 n ,在 c 中都是如此。
- 导入具有签名 s 的名为 n 的方法的单静态导入声明 d ,会遮蔽 c 中按需静态导入声明导入的任何具有相同签名的静态方法 n ,在 c 中都是如此。
- 导入名为 n 的类型的单静态导入声明 d ,会遮蔽 c 中按需静态导入声明导入的任何静态类型 n p 的另一个编译单元中声明的任何顶级类型 n 以及 c 中按需类型导入声明导入的任何类型 n ,在 c 中都是如此。

按需类型导入声明和按需静态导入声明不会导致任何其他声明被遮蔽。

以下是一个字段声明被局部变量声明遮蔽的示例:

class Test {
    static int x = 1;
    public static void main(String[] args) {
        int x = 0;
        System.out.print("x=" + x);
        System.out.println(", Test.x=" + Test.x);
    }
}

该代码的输出为:

x=0, Test.x=1

在这个例子中,类变量 x main 方法的主体内被局部变量 x 的声明遮蔽。 print 调用中的表达式 x 引用的是局部变量 x 的值,而 println 调用使用限定名称 Test.x 来访问类变量 x ,因为此时 Test.x 的声明被遮蔽,不能使用简单名称引用。

另一个示例展示了一个类型声明被另一个类型声明遮蔽的情况:

import java.util.*;
class Vector {
    int val[] = { 1 , 2 };
}
class Test {
    public static void main(String[] args) {
        Vector v = new Vector();
        System.out.println(v.val[0]);
    }
}

该代码编译并输出:

1

这里使用的是本地声明的 Vector 类,而不是可能按需导入的 java.util.Vector 类。

通过对二进制数值提升和命名规则的详细了解,我们可以在编程中更准确地处理数值和使用合适的命名,从而编写出更健壮、易读的代码。

编程中的数值提升与命名规则解析

遮蔽声明与可见性的深入理解

在前面我们已经了解了声明的遮蔽规则,实际上,理解遮蔽声明对于编写清晰的代码至关重要。当一个声明被遮蔽时,使用简单名称就无法引用到被遮蔽的实体,此时需要使用限定名称来访问。例如,在之前字段声明被局部变量声明遮蔽的例子中, Test.x 就是使用限定名称来访问被遮蔽的类变量 x

声明的可见性与遮蔽密切相关。一个声明在程序中的某一点是可见的,当且仅当该声明的作用域包含该点,并且该声明在该点没有被其他声明遮蔽。当上下文明确时,我们通常简单地说一个声明是可见的。

为了更清晰地展示不同类型声明的遮蔽情况,我们可以用以下表格总结:
| 声明类型 | 遮蔽情况 |
| ---- | ---- |
| 类型声明 | 名为 n 的类型声明会遮蔽作用域内同名的其他类型声明 |
| 字段、局部变量、参数声明 | 名为 n 的此类声明会遮蔽作用域内同名的其他声明 |
| 方法声明 | 名为 n 的方法声明会遮蔽封闭作用域内同名的其他方法声明 |
| 包声明 | 不会遮蔽任何其他声明 |
| 单类型导入声明 | 会遮蔽特定范围内同名的类型声明 |
| 单静态导入声明 | 会遮蔽特定范围内同名的字段、方法或类型声明 |

下面我们用一个 mermaid 流程图来展示声明可见性的判断流程:

graph TD;
    A[判断声明在某点是否可见] --> B{声明的作用域是否包含该点};
    B -- 否 --> C[声明不可见];
    B -- 是 --> D{声明是否被其他声明遮蔽};
    D -- 是 --> C;
    D -- 否 --> E[声明可见];
命名规则的实际应用建议

在实际编程中,遵循良好的命名规则可以提高代码的可读性和可维护性。以下是一些具体的应用建议:
1. 使用有意义的名称 :无论是变量、方法还是类,都应该使用能够清晰表达其用途的名称。例如,使用 userName 而不是 u 来表示用户的名称。
2. 遵循命名约定 :不同的编程语言通常有自己的命名约定,如 Java 中类名使用大驼峰命名法(如 UserInfo ),变量和方法名使用小驼峰命名法(如 getUserName )。
3. 避免使用保留字 :不要使用编程语言的保留字作为名称,以免引起语法错误。
4. 保持一致性 :在整个项目中保持命名风格的一致性,这样可以让代码看起来更加统一和规范。

二进制数值提升在实际编程中的应用

二进制数值提升在很多实际场景中都有应用,下面我们通过一个简单的示例来说明。

假设我们要实现一个简单的计算器程序,支持加、减、乘、除运算。代码如下:

import java.util.Scanner;

public class Calculator {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入第一个数字:");
        double num1 = scanner.nextDouble();
        System.out.println("请输入运算符(+、-、*、/):");
        char operator = scanner.next().charAt(0);
        System.out.println("请输入第二个数字:");
        double num2 = scanner.nextDouble();

        double result = 0;
        switch (operator) {
            case '+':
                result = num1 + num2;
                break;
            case '-':
                result = num1 - num2;
                break;
            case '*':
                result = num1 * num2;
                break;
            case '/':
                if (num2 != 0) {
                    result = num1 / num2;
                } else {
                    System.out.println("除数不能为零!");
                    return;
                }
                break;
            default:
                System.out.println("无效的运算符!");
                return;
        }
        System.out.println("计算结果:" + result);
    }
}

在这个计算器程序中, num1 num2 都是 double 类型。当进行加、减、乘、除运算时,就会涉及到二进制数值提升。因为这些运算符都会对操作数进行二进制数值提升,确保操作数类型一致后再进行计算。

下面我们用一个流程图来展示这个计算器程序的流程:

graph TD;
    A[开始] --> B[输入第一个数字];
    B --> C[输入运算符];
    C --> D[输入第二个数字];
    D --> E{运算符是否有效};
    E -- 否 --> F[输出无效运算符信息并结束];
    E -- 是 --> G{是否为除法且除数为零};
    G -- 是 --> H[输出除数不能为零信息并结束];
    G -- 否 --> I[根据运算符进行计算];
    I --> J[输出计算结果];
    J --> K[结束];
总结

通过对二进制数值提升和命名规则的全面学习,我们了解到它们在编程中起着至关重要的作用。二进制数值提升确保了在进行数值运算时操作数类型的一致性,避免了类型不匹配的错误。而命名规则则帮助我们编写出更具可读性和可维护性的代码,使代码更易于理解和修改。

在实际编程中,我们应该熟练掌握二进制数值提升的规则,在需要进行数值运算时,能够准确地预测操作数的类型转换。同时,严格遵循命名规则,使用有意义、符合约定的名称,避免声明的遮蔽带来的混淆。这样,我们就能编写出高质量的代码,提高编程效率和代码质量。

希望本文能帮助你更好地理解编程中的二进制数值提升和命名规则,在实际编程中能够灵活运用这些知识,编写出更加优秀的代码。

标题SpringBoot基层智能化人员调度系统研究AI更换标题第1章引言介绍SpringBoot基层智能化人员调度系统的研究背景、意义、现状以及论文的研究方法和创新点。1.1研究背景意义分析当前基层人员调度的现状和问题,阐述智能化调度的必要性和意义。1.2国内外研究现状概述国内外在基层智能化人员调度系统方面的研究进展和应用情况。1.3论文方法及创新点介绍本文采用的研究方法和实现智能化人员调度系统的创新点。第2章相关理论阐述SpringBoot框架、智能化调度算法和人员调度理论。2.1SpringBoot框架概述介绍SpringBoot框架的特点、优势和应用场景。2.2智能化调度算法总结现有的智能化调度算法,并分析其优缺点。2.3人员调度理论基础阐述人员调度的基本概念、原则和方法。第3章系统需求分析对SpringBoot基层智能化人员调度系统进行需求分析,包括功能性需求和非功能性需求。3.1功能性需求明确系统需要实现的功能,如人员信息管理、任务分配、调度策略制定等。3.2非功能性需求分析系统的性能、安全性、可靠性等非功能性需求。3.3需求优先级划分根据实际需求,对各项需求进行优先级划分。第4章系统设计详细介绍SpringBoot基层智能化人员调度系统的设计方案,包括架构设计、数据库设计和界面设计。4.1架构设计给出系统的整体架构,包括前后端分离、微服务架构等设计理念。4.2数据库设计设计合理的数据库表结构,满足系统的数据存储和查询需求。4.3界面设计设计简洁、易用的用户界面,提升用户体验。第5章系统实现阐述SpringBoot基层智能化人员调度系统的具体实现过程,包括核心代码实现、功能模块实现等。5.1核心代码实现详细介绍系统核心功能的代码实现,如人员信息管理、任务分配算法等。5.2功能模块实现分别介绍各个功能模块的实现过程,如用户登录、人员信息管理、任务管理等。第6章系统
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值