公司网站建设 阿里,安居客二手房出售信息,984网站建设项目,网站建设基本流程规范本文分享至华为云社区《CodeNavi 中代码语句的节点和节点属性》。作者#xff1a;Uncle_Tom 1. 前期回顾 《寻找适合编写静态分析规则的语言》 根据代码检查中的一些痛点#xff0c;提出了希望寻找一种适合编写静态分析规则的语言。 可以满足用户对代码检查不断增加的各种需求…本文分享至华为云社区《CodeNavi 中代码语句的节点和节点属性》。作者Uncle_Tom 1. 前期回顾 《寻找适合编写静态分析规则的语言》 根据代码检查中的一些痛点提出了希望寻找一种适合编写静态分析规则的语言。 可以满足用户对代码检查不断增加的各种需求使用户能够通过增加或减少对检查约束条件的控制实现快速调整检查中出现的误报和漏报这种检查语言能够有较低的使用门槛使用户更专注于检查业务而不需要关注工具是如何实现的。我们称这种检查规则语言为CodeNavi。文中给出了这种检查规则语言的两个应用场景以此来说明这种检查规则语言如何满足用户在编写静态检查规则时的期望。 《CodeNavi 规则的语法结构》 介绍 CodeNavi 检查规则语言在编写规则的基本语法格式。CodeNavi 检查规则语言通过对代码节点和节点属性的逻辑条件的组合来完成检查的约束条件从而完成代码检查中需要满足的缺陷模式适配找到满足要求的代码点。 《CodeNavi 规则的基础节点和节点属性》 介绍 CodeNavi 检查规则语言在编写时需要使用基础节点和节点属性这些基础节点包括节点类型、字面量、一般变量、枚举、成员变量字段以及数组。 《CodeNavi 中代码表达式的节点和节点属性》 介绍 CodeNavi 检查规则语言如何描述代码中的表达式。这些节点主要包括对象创建表达式、强制类型转换、类型判断表达式、一元表达式、二元表达式、条件表达式/三目运算、方法引用表达式、lambda表达式以及匿名内部类表达式。 本篇将继续介绍 CodeNavi 中代码里语句和代码块的节点和节点属性。 语句节点包括赋值语句控制流语句包括跳转语句、条件控制、Switch控制、循环控制、异常处理、静态语句、同步代码块。
2. CodeNavi 中的节点和节点属性
程序是由空格分隔的字符串组成的序列。在程序分析中这一个个的字符串被称为token是源代码中的最小语法单位是构成编程语言语法的基本元素。
Token可以分为多种类型常见的有关键字如if、while、标识符变量名、函数名、字面量如数字、字符串、运算符如、-、*、/、分隔符如逗号,、分号;等。
我们只需要给代码的不同节点给出一个定义然后通过条件语句来描述对这些节点的要求使之符合缺陷检查的模式就可以完成检查规则的定义。
2.1. 规则节点和节点属性图例
程序是由空格分隔的字符串组成的序列。在程序分析中这一个个的字符串被称为token是源代码中的最小语法单位是构成编程语言语法的基本元素。
Token可以分为多种类型常见的有关键字如if、while、标识符变量名、函数名、字面量如数字、字符串、运算符如、-、*、/、分隔符如逗号,、分号;等。
我们只需要给代码的不同节点给出一个定义然后通过条件语句来描述对这些节点的要求使之符合缺陷检查的模式就可以完成检查规则的定义。
2.1.1. 节点 图例 节点和子节点都使用个图例 规则语言中使用节点的 “英文名”这样便于规则的编写。
2.2. 节点集 图例 节点的集合。
2.3. 属性 图例 规则语言中使用属性的 “英文名”这样便于规则的编写。
3. 语句
程序语言中包含多种语句每种语句都有其特定的作用。
样例代码
// 表达式语句
// 用于执行表达式如赋值、方法调用等。int a 10; // 赋值表达式
System.out.println(Hello, CodeNavi!); // 方法调用表达式// 条件语句
// 用于基于条件执行不同的代码分支。// if 语句
int score 75;
if (score 70) {System.out.println(Pass);
}// if-else 语句
if (score 70) {System.out.println(Pass);
} else {System.out.println(Fail);
}// switch 语句
int month 4;
switch (month) {case 1: System.out.println(January); break;case 2: System.out.println(February); break;// ...default: System.out.println(Invalid month);
}// 循环语句
// 用于重复执行一段代码。// for 循环
for (int i 0; i 10; i) {System.out.println(i);
}// while 循环
int i 0;
while (i 10) {System.out.println(i);
}// do-while 循环
int i 0;
do {System.out.println(i);
} while (i 10);// 跳转语句
// 用于控制程序流程如跳过循环的迭代或退出循环。// break 语句
for (int i 0; i 10; i) {if (i 5) break;System.out.println(i);
}// continue 语句
for (int i 0; i 10; i) {if (i % 2 0) continue; // 跳过偶数System.out.println(i);
}// 异常处理语句
// 用于处理程序运行时可能出现的异常。// try-catch 语句
try {int result 10 / divisor;
} catch (ArithmeticException e) {System.out.println(Cannot divide by zero);
}// try-catch-finally 语句
try {// 可能抛出异常的代码
} catch (Exception e) {// 异常处理
} finally {// 无论是否发生异常都会执行的代码
}// 返回语句
// 用于从方法返回一个值或退出方法。public int max(int a, int b) {return (a b) ? a : b;
}3.1. 赋值语句(assignStatement)
赋值语句是编程中最基本的操作之一几乎所有的编程语言都支持赋值操作。
赋值语句用于将一个值或表达式的结果存储到一个变量中。赋值语句的基本形式是将一个表达式的结果赋给一个变量名。
其作用主要包括 初始化变量 在程序开始时使用赋值语句给变量赋予初始值。 存储数据 将计算结果或常量值存储到一个变量中以便在程序的后续部分使用。 更新变量值 在程序执行过程中可能需要更新变量的值以反映程序状态的变化。 简化代码 通过将复杂表达式的结果赋值给变量可以简化代码提高可读性。 样例代码
int a 10;String b string a;图例 节点属性
名称描述值类型示例DSL 规则lhs左值valueAccess类节点a 10;assignStatement ass where ass.lhs.name “a”;rhs右值literal类节点、valueAccess类节点、functionCall类节点a 10;assignStatement ass where ass.rhs.value 10;
4. 控制流语句
控制流语句是编程语言中用于控制程序执行流程的语句它们决定了程序中代码的执行顺序。 代码块分组 使用大括号 {} 可以将多条语句组织在一起作为一个整体来执行。 条件执行 允许程序根据条件判断来选择不同的执行路径。例如if 语句可以根据条件为真或假来执行不同的代码块。 多路径选择 使用 switch 语句可以根据变量值选择多个执行路径之一。 循环执行 允许程序重复执行一段代码直到满足特定条件。例如for 和 while 循环可以在满足循环条件时不断迭代。 异常处理 使用 try、catch 和 finally 块可以捕获和处理程序运行时发生的异常。 跳转语句 程序中的跳转语句允许改变程序的执行流程使得程序可以跳过某些代码块或直接跳到程序的其他部分执行。包括break、continue、return、throw。
4.1. 跳转语句
程序中的跳转语句允许改变程序的执行流程使得程序可以跳过某些代码块或直接跳到程序的其他部分执行。
跳转语句
break 语句立即终止最近的 for 或 while 循环。continue 语句跳过当前循环的剩余部分开始下一次迭代。return 语句从当前函数返回并可以携带一个值。throw 语句用于抛出一个异常可以是预定义的异常类型或用户自定义的异常类型。
4.1.1. continue语句(continueStatement)
continue 语句用于跳过当前循环的剩余部分并开始执行下一次循环的迭代。这通常用于在满足某个特定条件时不想执行循环体中剩余的代码块。
以下是一些使用 continue 语句的场景 跳过不符合条件的元素 处理一个集合比如数组或列表并且只想对满足特定条件的元素执行操作时可以使用 continue 来跳过不满足条件的元素。 避免重复处理 如果循环中检测到某个元素已经被处理过可以使用 continue 跳过对它的进一步处理。 减少嵌套循环的复杂性 在嵌套循环中如果外层循环的某个条件满足可能就不需要执行内层循环的任何迭代这时可以使用 continue 来跳过内层循环。 样例代码
for (int i 0; i 10; i) {// 跳过偶数if (i % 2 0) {continue;}// 只打印奇数System.out.println(i);
}图例 4.1.2. break语句(breakStatement)
break 语句的作用是立即终止最内层的 for、while 或其他循环结构的执行。当执行到 break 语句时程序会跳出当前的循环体继续执行循环之后的代码。
break 语句的一些主要作用 提前退出循环 当满足特定条件时你可能希望立即退出循环而不是等待循环自然结束。 避免无限循环 在某些情况下循环的条件可能依赖于循环体内部的某些操作结果使用 break 可以避免无限循环。 搜索和查找 在搜索或查找任务中一旦找到所需的元素或满足特定条件使用 break 可以立即退出循环。 错误处理 在循环中进行某些操作时如果发生错误或异常情况可以使用 break 来退出循环。 控制复杂循环逻辑 在嵌套循环中break 可以用来从外层循环中退出而不仅仅是内层循环。 样例代码
// break 语句
for (int i 0; i 10; i) {if (i 5) {break;}System.out.println(i);
}图例 4.1.3. return语句(returnStatement)
return 语句的作用是从一个函数或子程序中返回一个值并终止该函数的执行。
return 语句是函数实现其目的的关键它允许函数将结果传递给调用者并在必要时提前退出函数的执行。
以下是 return 语句的一些关键作用 返回结果 函数通常用于执行某些计算或操作并返回结果。使用 return 语句可以将这些结果传递回调用函数的地方。 提前退出函数 如果函数在执行过程中遇到某些条件可能需要立即退出并返回一个值或不返回任何值。 控制函数的流程 在复杂的函数中return 可以用于控制程序的执行流程例如从嵌套的逻辑结构中返回。 错误处理 在函数中检测到错误或异常情况时可以使用 return 语句返回错误代码或错误信息。 简化代码 通过使用 return可以在满足特定条件时简化代码逻辑避免使用多个 if 语句或条件判断。 样例代码
// 返回语句
// 用于从方法返回一个值或退出方法。public int max(int a, int b) {return (a b) ? a : b;
}图例 节点属性
名称描述值类型示例DSL 规则returnValue返回值任意节点return a;returnStatement rs where rs.returnValue.name “a”;
4.1.4. 异常抛出语句(throwStatement)
使用 throw 语句抛出异常是异常处理机制的一部分它允许开发者明确地指出程序中可能出现的错误并提供一种机制来处理这些错误。 throw 语句用于在代码的特定位置手动抛出一个异常。这个异常可以是预定义的异常类型也可以是用户自定义的异常类型。
throw 语句的一些主要作用 异常处理 当程序检测到一个错误或异常情况时可以使用 throw 抛出一个异常从而中断正常的程序流程。 错误传播 在方法中抛出的异常可以被方法的调用者捕获和处理或者继续向上传播直到被捕获或导致程序终止。 强制方法实现 在的接口或抽象类中可以使用 throw 语句来强制实现某些方法尽管这些方法没有具体的实现代码。 方法签名中的异常声明 当一个方法声明它可能会抛出特定的异常时这些异常需要在方法的签名中声明。如果这些异常是必须被调用者处理的可以使用 throw 语句来抛出。 样例代码
throw new Exception(Get exception!);图例 节点属性
名称描述值类型示例DSL 规则operand抛出异常nodethrow new Exception();throwStatement tr where tr.operand is objectCreationExpression;
4.2. 条件控制(ifBlock)
条件控制语句的作用是允许程序根据不同的条件来决定执行哪些代码块。
以下是条件控制语句的主要作用 决策制定 条件控制语句允许程序基于特定的条件通常是变量或表达式的值来做出决策。 功能开关 在开发过程中条件控制语句可以用于临时启用或禁用某些功能。 状态管理 在需要根据程序的状态来执行不同操作时条件控制语句可以检查状态并做出相应的响应。 避免错误 通过检查条件可以避免执行可能导致错误的代码例如除以零或访问未初始化的变量。 逻辑选择 条件控制语句允许程序在多个选项中选择一个执行例如使用 if 语句来选择两个不同的操作之一。 代码分支 它们可以创建代码的分支路径使得程序可以根据不同的条件执行不同的代码段。 增强程序的灵活性 允许程序根据不同的输入或状态来动态调整其行为。 实现复杂的逻辑 多个条件控制语句可以嵌套使用以实现更复杂的逻辑判断。 控制循环的执行 在循环中使用条件控制语句可以决定何时开始或结束循环的迭代。 资源管理 条件控制语句可以用于在满足特定条件时分配或释放资源。 错误处理 它们可以用于检测错误条件并执行错误处理代码比如记录日志或向用户报告错误。 样例代码
if(num 10) { // if block// then blockSystem.out.println(m 10);
} else {// else block System.out.println(m 10);
} 图例 节点属性
名称描述值类型示例DSL 规则conditionif条件binaryOperation节点if (m 10) { System.out.println(“m 10”); } else { System.out.println(“m 10”); }ifBlock ib where ib.condition contain binaryOperation bo where bo.operator “”;thenBlockif条件为true执行的语句block语句块if (m 10) { System.out.println(“m 10”); } else { System.out.println(“m 10”); }ifBlock ib where ib.thenBlock contain stringLiteral ss where ss.value “m 10”;elseBlockif条件为false执行的语句block语句块if (m 10) { System.out.println(“m 10”); } else { System.out.println(“m 10”); }ifBlock ib where ib.elseBlock contain stringLiteral ss where ss.value “m 10”;
4.3. Switch控制
switch 语句是一种选择控制流语句它允许程序根据不同的条件执行不同的代码块。switch 语句的主要作用是提供一个替代多个 if…else if…else 语句的方法使得代码更加清晰和易于管理。
以下是 switch 语句的一些关键特点和作用 多条件选择 switch 语句允许你根据不同的变量值或表达式结果来选择执行不同的代码块。 默认行为 switch 语句通常包含一个 default 子句用于处理没有匹配到任何 case 的情况类似于 if…else if…else 语句中的 else 部分。 减少嵌套 相比使用多个 if…else if…else 语句switch 语句可以减少代码的嵌套层次使代码结构更清晰。 可中断性 在 switch 语句中可以使用 break 语句来中断当前 case 的执行防止代码继续执行到下一个 case。 提高可读性 switch 语句通过明确的 case 标签使得代码的意图更加明显便于阅读和理解。 易于维护 当需要添加或修改条件分支时switch 语句提供了一种更直观的方式有助于维护和扩展代码。 样例代码
switch (m) {case 12:System.out.println(hello);break;case 10:case 15:System.out.println(CodeNavi);break; default:System.out.println(default value);
}
4.3.1. switch语句块(switchBlock) 图例 节点属性
名称描述值类型示例DSL 规则selectorswitch语句的判断条件任意节点switch (m) {}switchBlock swb where swb.selector.name “m”; 4.3.2. case语句块(caseStatement) 图例 规则样例
caseStatement cs where cs contain literal;4.3.3. default语句块(defaultStatement) 图例 规则样例
switchBlock swb where swb contain defaultStatement;4.4. 循环控制
循环控制语句是程序设计中非常基础且强大的工具它们使得程序能够以一种高效和灵活的方式处理重复性任务。常见的循环控制语句包括 for 循环、while 循环和 do…while 循环等。
以下是循环控制语句的一些关键特点和作用 重复执行 循环控制语句允许代码块在满足循环条件时重复执行这使得处理大量数据或执行重复任务变得简单高效。 条件控制 循环控制语句通常与条件语句结合使用根据条件的变化来决定是否继续执行循环或退出循环。 迭代操作 循环控制语句常用于迭代数据结构如数组、列表、集合等中的元素执行对每个元素的操作。 控制执行流程 循环控制语句中的 break 和 continue 可以用来改变循环的执行流程。break 用于立即退出循环而 continue 用于跳过当前迭代直接进入下一次循环。 实现算法逻辑 许多算法和数据处理任务需要循环结构来实现例如排序、搜索、遍历等。 资源管理 在处理文件、网络连接等资源时循环可以用来重复读取或写入数据直到达到预期的条件。 模拟时间延迟 在某些情况下循环可以用来模拟时间延迟例如通过循环等待某个事件发生。 减少代码冗余 通过循环可以避免编写重复的代码块使得程序更加简洁和易于维护。
4.4.1. 循环语句块(loopBlock)
包括forBlock, forEachBlock, doWhileBlock, whileBlock 图例 节点属性
名称描述值类型示例DSL 规则condition循环条件任意节点while(i list.size()) { i; }whileBlock wb where wb.condition contain binaryOperation bo where bo.lhs.name “i”;body循环体body语句块while(i list.size()) { i; }whileBlock wb where wb.body contain unaryOperation;body.statementNumbody语句块的语句数量数值while(i list.size()) { i; System.out.print(“xxx”); }whileBlock wb where wb.body.statementNum 2;firstStatementloopBlock的第一条语句任意节点while(i list.size()) { i; System.out.print(“xxx”); }whileBlock wb where wb.firstStatement contain unaryOperation;lastStatementloopBlock的最后一条语句任意节点while(i list.size()) { i; System.out.print(“xxx”); }whileBlock wb where wb.lastStatement contain functionCall;
4.4.2. for循环代码块(forBlock)
样例代码
for (int i 0; i list.size(); i) {i
} 图例 节点属性
名称描述值类型示例DSL 规则initialization变量初始化variableDeclaration、 variableAccess节点for (int i 0; i list.size(); i) {}forBlock fb where fb.initialization.name “i”;condition循环条件binaryOperationfor (int i 0; i list.size(); i) {}forBlock fb where fb.condition.rhs is functionCall;iteration迭代操作unaryOperation节点for (int i 0; i list.size(); i) {}forBlock fb where fb.iteration.operator “”;body循环体body语句块for (int i 0; i list.size(); i) { i; }forBlock fb where fb.body contain variableAccess vs where vs.name “i”;body.statementNumbody语句块的语句数量数值for (int i 0; i list.size(); i) { i; }forBlock fb where fb.body.statementNum 1;firstStatementforBlock的第一条语句任意节点for (int i 0; i list.size(); i) { i; }forBlock fb where fb.firstStatement contain unaryOperation;lastStatementforBlock的最后一条语句任意节点for (int j1 1; j1 50 k1 50; j1, k1) { System.out.println(j1) k1; }forBlock fb where fb.lastStatement contain unaryOperation;
4.4.3. forEach循环代码块(forEachBlock)
样例代码
ListString list Arrays.asList(1,2,3);for (String str : list) {System.out.println(str)
} 图例 节点属性
名称描述值类型示例DSL 规则variable循环变量variableDeclaration节点for (String str : list) { System.out.println(str); }forEachBlock fb where and( fb.variable is variableDeclaration, fb.variable.name “str” );iterable被循环的变量任意节点for (String str : list) { System.out.println(str); }forEachBlock fb where fb.iterable.name “list”;body循环体body语句块for (String str : list) { System.out.println(str); }forEachBlock fb where fb.body contain functionCall;body.statementNumbody语句块的语句数量数值for (String str : list) { System.out.println(str); }forEachBlock fb where fb.body.statementNum 1;firstStatementforEachBlock的第一条语句任意节点for (String str : list) { System.out.println(str); }forEachBlock fb where fb.body contain functionCall;lastStatementforEachBlock的最后一条语句任意节点for (String str : list) { System.out.println(str “1”); System.out.println(str “2”); }forEachBlock fb where fb.lastStatement contain functionCall;
4.4.4. while循环语句块(whileBlock)
样例代码
int i 0;
while(i 10) {i i 1;
} 图例 节点属性
名称描述值类型示例DSL 规则condition循环条件任意节点while(i list.size()) { i; }whileBlock wb where wb.condition contain binaryOperation bo where bo.lhs.name “i”;body循环体body语句块while(i list.size()) { i;}whileBlock wb where wb.body contain unaryOperation;body.statementNumbody语句块的语句数量数值while(i list.size()) { i; System.out.print(i); }whileBlock wb where wb.body.statementNum 2;firstStatementwhileBlock的第一条语句任意节点while(i list.size()) { i; System.out.print(i); }whileBlock wb where wb.firstStatement contain unaryOperation;lastStatementwhileBlock的最后一条语句任意节点while(i list.size()) { i; System.out.print(i); }whileBlock wb where wb.lastStatement contain functionCall;
4.4.5. do-while语句块(doWhileBlock)
样例代码
int i 0;
do { i;System.out.print(i);
} while (i 10);图例 节点属性
名称描述值类型示例DSL 规则condition循环条件任意节点do { i; } while (i 10);doWhileBlock wb where wb.condition contain binaryOperation bo where bo.lhs.name “i”;body循环体body语句块do { i; } while (i 10);doWhileBlock wb where wb.body contain unaryOperation;body.statementNumbody语句块的语句数量数值do { i; System.out.print(i); } while (i 10);whileBlock wb where wb.body.statementNum 2;firstStatementforBlock的第一条语句任意节点do { i; System.out.print(i); } while (i 10);doWhileBlock wb where wb.firstStatement contain unaryOperation;lastStatementforBlock的最后一条语句任意节点do { i; System.out.print(i); } while (i 10);doWhileBlock wb where wb.lastStatement contain functionCall;
4.5. 异常处理
程序中的异常处理是一种错误检测和响应机制它有助于编写更加健壮、可靠和易于维护的软件。
它的作用包括但不限于以下几点 错误检测 异常处理允许程序在运行时检测到错误或异常情况并采取相应的措施。 防止程序崩溃 通过捕获和处理异常程序可以在遇到错误时继续运行而不是直接崩溃或终止。 支持自定义异常 开发者可以定义自己的异常类型以更精确地表达特定错误情况。 资源管理 异常处理确保即使在发生错误的情况下程序也能够正确地释放或管理资源如文件句柄、网络连接等。 提供错误信息 异常处理允许程序在发生错误时提供有用的错误信息帮助开发者或用户诊断问题。 分离错误处理代码 通过将错误处理逻辑与正常业务逻辑分离可以使代码更加清晰和易于维护。 支持多级错误处理 异常处理允许程序在不同级别上捕获和处理错误例如在函数内部捕获异常然后在调用者中进一步处理。 控制程序流程 异常处理提供了一种控制程序流程的方式允许程序在特定错误发生时跳转到特定的错误处理代码。 维护程序的健壮性 通过合理地使用异常处理可以增强程序的健壮性使其能够优雅地处理各种意外情况。 样例代码
try {int num 1/0;
} catch (Exception e) {throw new RuntimeException(e);
} finally {System.out.println(finally);
}
4.5.1. 异常捕捉代码块(exceptionBlock)
包括: tryBlock、catchBlock、finallyBlock 图例 节点属性
名称描述值类型示例DSL 规则tryBlocktry语句块tryBlock节点try { int num 1/0; } catch (Exception e) { throw new RuntimeException(e); } finally { System.out.println(“finally”); }exceptionBlock eb where eb.tryBlock contain variableDeclaration;catchBlocks所有的catch语句块集catchBlock节点的集合try { int num 1/0; } catch (Exception e) { throw new RuntimeException(e); } finally { System.out.println(“finally”); }exceptionBlock eb where eb.catchBlocks contain cb where cb contain throwStatement;finallyBlockfinally语句块finallyBlock节点try { int num 1/0; } catch (Exception e) { throw new RuntimeException(e); } finally { System.out.println(“finally”); }exceptionBlock eb where eb.finallyBlock contain functionCall fc where fc.name “println”;
4.5.3. catch语句块(catchBlock)
节点属性
名称描述值类型示例DSL 规则parameters参数集node listtry { int num 1/0; } catch (Exception e) { throw new RuntimeException(e); } finally { System.out.println(“finally”); }catchBlock cb where cb.parameters contain p where p.name “e”;
4.5.4. tryWithResources异常捕捉代码块(tryWithResources)
样例代码
try (Statement stmt con.createStatement()) {System.out.println(try-with-resources block);
} catch (SQLException e1) {System.out.println(e1);
} catch (Exception e2) {System.out.println(e2);
} 图例 节点属性
名称描述值类型示例DSL 规则tryBlocktry语句块tryBlock节点try (Statement stmt con.createStatement()) { System.out.println(“try-with-resources block”); } catch (SQLException e1) { System.out.println(e1); } catch (Exception e2) { System.out.println(e2); }tryWithResources eb where eb.tryBlock contain variableDeclaration;catchBlocks所有的catch语句块catchBlock节点的集合try (Statement stmt con.createStatement()) { System.out.println(“try-with-resources block”); } catch (SQLException e1) { System.out.println(e1); } catch (Exception e2) { System.out.println(e2); }tryWithResources eb where eb.catchBlocks contain cb where cb contain throwStatement;finallyBlockfinally语句块finallyBlock节点try (Statement stmt con.createStatement()) { System.out.println(“try-with-resources block”); } catch (SQLException e1) { System.out.println(e1); } catch (Exception e2) { System.out.println(e2); }tryWithResources eb where eb.finallyBlock contain functionCall fc where fc.name “println”;resources任意节点若干statements节点的集合try (Statement stmt con.createStatement()) { System.out.println(“try-with-resources block”); } catch (SQLException e1) { System.out.println(e1); } catch (Exception e2) { System.out.println(e2); }tryWithResources twr where twr.resources contain re where re contain functionCall fc where fc.name “createStatement”;
4.6. 静态语句块(staticBlock)
静态语句块也称为静态初始化块是一种特殊的代码块它使用关键字 static 标记。
静态语句块在类或接口的主体中定义并且在任何对象被创建之前或者任何静态方法被调用之前执行。由于静态语句块的执行时机和作用域在类的初始化和资源管理方面扮演着重要的角色。
静态语句块的作用主要包括以下几点 初始化静态变量 静态语句块在类加载时执行可以用来初始化类的静态变量。 静态常量赋值 静态语句块可以用来给静态常量赋值虽然通常静态常量直接赋值更为常见。 静态初始化顺序 静态语句块的执行顺序是在类变量声明之后构造函数之前这可以用来控制类的初始化顺序。 延迟初始化 静态语句块可以用于延迟初始化即只有在类被实际使用时才进行初始化。 类级别的条件判断 静态语句块可以包含逻辑判断根据条件来执行不同的初始化代码。 执行一次性操作 静态语句块在类第一次被加载到JVM时执行并且只执行一次。这使得它适合执行那些只需要执行一次的操作。 静态资源分配 静态语句块可以用来分配静态资源如加载配置文件、初始化数据库连接等。 静态工厂方法 静态语句块可以与静态工厂方法结合使用以提供类的实例化逻辑。 静态代码复用 在某些情况下静态语句块可以用于复用静态代码避免在多个构造函数或方法中重复相同的初始化代码。 样例代码
static {int n 5;
}图例 规则样例
staticBlock sb where sb contain variableDeclaration;4.7. 同步代码块(synchronizedBlock)
同步代码块的作用主要是确保多线程环境下的线程安全。
以下是同步代码块的几个关键作用 确保原子性 同步代码块确保了代码块内的一系列操作作为一个整体执行不可被其他线程中断从而保证了操作的原子性。 防止数据竞争 当多个线程尝试同时访问和修改共享资源时同步代码块可以防止出现数据竞争Race Condition的问题。 实现线程互斥 同步机制通过锁定机制实现线程互斥即在同一时刻只允许一个线程执行同步代码块。 避免死锁 虽然同步本身可能导致死锁但正确使用同步代码块可以避免或减少死锁的发生。 提高数据一致性 通过同步代码块可以确保对共享数据的所有访问都是有序的从而维护数据的一致性。 控制并发访问 同步代码块可以用来控制对特定资源的并发访问例如限制同时访问数据库连接的线程数量。 实现线程通信 同步代码块可以与wait()、notify()和notifyAll()方法一起使用实现线程间的协调和通信。 保护关键资源 同步代码块可以用来保护那些不应该被多个线程同时修改的关键资源。 提高程序的可维护性 通过集中管理对共享资源的访问同步代码块可以提高程序的可维护性。 实现线程安全的单例模式 同步代码块常用于实现延迟加载的线程安全的单例模式。 样例代码
// 使用对象锁任意对象synchronized(Object) {// 同步代码块
}// 使用类锁当前类的Class对象synchronized(ClassName.class) {// 同步代码块
} 图例 节点属性
名称描述值类型示例DSL 规则lock锁任意节点synchronized (i) { System.out.println(“hello”); }synchronizedBlock sy where sy.lock contain variableAccess va where va.name “i”;body同步块block语句块synchronized (i) { System.out.println(“hello”); }synchronizedBlock sy where sy.body contain functionCall fc where fc.name “println”;body.statementNumbody语句块的语句数量数值synchronized (i) { System.out.println(“hello”);}synchronizedBlock sb where sb.body.statementNum 1;firstStatementsynchronizedBlock的第一条语句任意节点synchronized (i) { System.out.println(“hello”); }synchronizedBlock sb where sb.firstStatement contain unaryOperation;lastStatementsynchronizedBlock的最后一条语句任意节点synchronized (i) { System.out.println(“hello”); }synchronizedBlock sb where sb.lastStatement contain functionCall;
5. CodeNavi插件 在Vscode 的插件中查询:codenavi并安装。 使用插件的链接安装 https://marketplace.visualstudio.com/items?itemNameHuaweiCloud.codenavi