"A".substring(1)不报异常的分析

本文解析了Java中字符串“A”.substring(1)的行为,解释为何没有引发异常而是返回空字符串,并深入探讨了substring方法的实现机制。
今天收到网友 不懂装懂 的来信

您好,讨论个问题
我看到代码"A".substring(1);我第一眼觉得应该越界,因为我基础不好,但是结果没有问题,是个空,我想请您指点迷津

我第一眼也是有问题,因为字符串的长度只有1,而且是从0开始编号的。

还是去看看源代码吧
  1. public String substring(int beginIndex) {
  2.     return substring(beginIndex, count);
  3. }
其中的count没有悬念,是字符串的字符长度,对于我们的例子,长度就是1.

  1.   public String substring(int beginIndex, int endIndex) {
  2.     if (beginIndex < 0) {
  3.       throw new StringIndexOutOfBoundsException(beginIndex);
  4.     }
  5.     if (endIndex > count) {
  6.       throw new StringIndexOutOfBoundsException(endIndex);
  7.     }
  8.     if (beginIndex > endIndex) { // 注意看这里
  9.       throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
  10.     }
  11.     return ((beginIndex == 0) && (endIndex == count)) ? this : new String(offset + beginIndex,
  12.         endIndex - beginIndex, value);
  13.   }
可见,系统是起始的位置如果大于结束的位置,此处结束位置就是字符串的长度1
而我们写的起始位置等于字符串长度,没有大于结束位置,所以不会报异常。

如果写成
  1. "A".substring(2)
则由于超过了字符串的长度1,报

StringIndexOutOfBoundsException


原文地址:http://www.java2000.net/p10866
public async Task BatchGenerateDynamicGeneralLedgerAsync() { // 1. 查询所有状态为“生效”的文件 List<Sys_File_Info> Files = new List<Sys_File_Info>(); Files = _sys_File_InfoRepository.FindAsIQueryable(x => x.file_state == "生效").ToList(); foreach(var result in Files) { //查看已有动态一本账是否有该生效文件 var duibi = await _dynamic_general_ledgerRepository.FindAsyncFirst(x => x.file_code == result.file_code); //查找动态一本账对应参照表的信息 var refer = await _dynamic_general_ledgerReferRepository.FindAsyncFirst(x => x.file_type == result.file_type_name); if (refer != null && duibi is null) { //查找一本账数据库有多少条信息用来生成流水号 int count = _dynamic_general_ledgerRepository.FindAsIQueryable(x => true).Count() + 1; var file_security_level = refer.file_security_level.Substring(0, 1); var sharing_scope = refer.sharing_scope; if (result.projectType.Contains("前瞻") || result.projectType.Contains("预研") || result.projectType.Contains("研究")) { file_security_level = "A"; string referSharingScope = refer.sharing_scope; string targetA = "(文档安全等级为A)"; string targetStart = "厂长"; int startIndex = referSharingScope.IndexOf(targetA); if (startIndex != -1) { // 提取(文档安全等级为A)之前的部分 string partBeforeA = referSharingScope.Substring(0, startIndex); // 找到“+”的位置 int plusIndex = partBeforeA.LastIndexOf('+'); if (plusIndex != -1) { partBeforeA = partBeforeA.Substring(plusIndex + 1).Trim(); } // 找到下一个“厂长”的位置 int nextFactoryIndex = referSharingScope.IndexOf(targetStart, startIndex + targetA.Length); if (nextFactoryIndex != -1) { // 提取从“+”之后到下一个“厂长”之前的部分 string partAfterA = referSharingScope.Substring(startIndex + targetA.Length, nextFactoryIndex - (startIndex + targetA.Length)).Trim(); // 拼接结果 sharing_scope = partBeforeA + partAfterA; Console.WriteLine(sharing_scope); } else { // 如果没有找到下一个“厂长”,则只取“+”之后的部分 sharing_scope = partBeforeA; Console.WriteLine(sharing_scope); } } else { Console.WriteLine("未找到(文档安全等级为A)"); } } else if(result.projectType == null || result.projectType is not null) { string referSharingScope1 = refer.sharing_scope; string targetA1 = "(文档安全等级为A)"; string targetB = "(文档安全等级为B)"; string targetC = "(文档安全等级为C)"; string targetStart1 = "厂长"; int startIndex1 = referSharingScope1.IndexOf(targetA1); if (startIndex1 != -1) { // 找到“(文档安全等级为A)”之后的第一个“厂长”的位置 int nextFactoryIndex = referSharingScope1.IndexOf(targetStart1, startIndex1 + targetA1.Length); if (nextFactoryIndex != -1) { // 提取从“(文档安全等级为A)”之后到下一个“厂长”之前的部分 string partAfterA = referSharingScope1.Substring(startIndex1 + targetA1.Length, nextFactoryIndex - (startIndex1 + targetA1.Length)).Trim(); // 初始化最终结果 sharing_scope = partAfterA; // 从“厂长”开始继续提取,跳过“(文档安全等级为B)”或“(文档安全等级为C)” int currentIndex = nextFactoryIndex; while (currentIndex < referSharingScope1.Length) { // 找到下一个“(文档安全等级为B)”或“(文档安全等级为C)”的位置 int endIndexB = referSharingScope1.IndexOf(targetB, currentIndex); int endIndexC = referSharingScope1.IndexOf(targetC, currentIndex); int endIndex = Math.Min(endIndexB, endIndexC); if (endIndexB == -1 && endIndexC == -1) { endIndex = referSharingScope1.Length; } else if (endIndexB == -1) { endIndex = endIndexC; } else if (endIndexC == -1) { endIndex = endIndexB; } // 提取从“厂长”开始到“(文档安全等级为B)”或“(文档安全等级为C)”之前的部分 string part = referSharingScope1.Substring(currentIndex, endIndex - currentIndex).Trim(); sharing_scope = part + sharing_scope; // 更新currentIndex到“(文档安全等级为B)”或“(文档安全等级为C)”之后 if (endIndexB != -1 && endIndexB < endIndexC) { currentIndex = endIndexB + targetB.Length; } else if (endIndexC != -1 && endIndexC < endIndexB) { currentIndex = endIndexC + targetC.Length; } else { break; } } Console.WriteLine(sharing_scope); } else { Console.WriteLine("未找到下一个'厂长'"); } } else { Console.WriteLine("未找到(文档安全等级为A)"); } } if (refer != null && duibi is null) { var Dynamic_general_ledger = new dynamic_general_ledger { file_id = $"C03-{refer.file_type_code}-{refer.sharing_platform}-{result.effect_time.ToString("yyyyMMdd")}-{count}",//暂时这么设置,待后续确定做更改 file_type = result.file_type_name, business_scenario = refer.business_scenario, belong_stage = refer.belong_stage, model_project = result.projectName, project_type = result.projectType, product_model_number = $"",//所属产品型号暂不设定 file_security_level = file_security_level, file_code = result.file_code, development_tool = refer.development_tool, tool_code = $"",//编制工具代码暂不设定 method = refer.method, collaboration_information = refer.collaboration_information, review_tool_platform = refer.review_tool_platform, review_method = refer.review_method, review_scope = refer.review_scope, review_role = refer.project_role, transfer_tool = refer.transfer_tool, transfer_method = refer.transfer_method, transfer_scope = refer.transfer_scope, transfer_format = refer.transfer_format, publishing_platform = refer.publishing_platform, sharing_platform = refer.sharing_platform, sharing_method = refer.sharing_method, sharing_scope = sharing_scope, integration_platform = refer.integration_platform, storage_platform = refer.storage_platform, retention_period = refer.retention_period, storage_strategy = refer.storage_strategy, backup_requirements = refer.backup_requirements, }; _dynamic_general_ledgerRepository.Add(Dynamic_general_ledger, true); } } } }我这里if (result.projectType.Contains("前瞻") || result.projectType.Contains("预研") || result.projectType.Contains("研究"))总是报抛空异常,但是我下面做了另一个判断if(result.projectType == null || result.projectType is not null)为什么还是会这样
08-23
冷冻低温仓库存明细: SELECT CONCAT(c.Name, c.Code) AS ‘仓库名称’, CASE WHEN e.X4 = 0 THEN CONCAT(‘分拣区’, e.Code) WHEN e.X4 = 1 THEN CONCAT(‘储货区’, e.Code) WHEN e.X4 = 2 THEN CONCAT(‘隔离区’, e.Code) ELSE ‘其他’ END AS ‘库区’, d.Code AS ‘库位’, f.SkuCode AS ‘商品编码’, f.SkuName AS ‘商品名称’, f.Barcode AS ‘商品条码’, f.Unit AS ‘单位’, SUBSTRING(f.Subtitle, 1, 5) AS ‘规格’, b.Qty AS ‘库存数量’, b.Amount AS ‘库存金额’, CASE WHEN a.FnType = 3 THEN ‘拆零’ WHEN a.FnType = 1 THEN ‘整件’ ELSE ‘其他’ END AS ‘分拣类型’, CAST(b.BatchNo AS CHAR) AS ‘批次号’, b.X14 AS ‘生产日期’, f.ExpirationDays AS ‘保质期()’, IF( f.ExpirationDays = 0, ‘N/A’, DATEDIFF( DATE_ADD( b.X14, INTERVAL f.ExpirationDays DAY ), CURDATE() ) ) AS ‘效期剩余天数’, IF( f.ExpirationDays = 0, ‘N/A’, DATE_FORMAT( DATE_ADD( b.X14, INTERVAL f.ExpirationDays DAY ), ‘%Y-%m-%d’ ) ) AS ‘有效期至’, g.no AS ‘供应商编码’, g.Name AS ‘供应商名称’ FROM b2b_wms.st_warestore a LEFT JOIN b2b_wms.st_warestoreitem b ON a.Id = b.WareStoreId LEFT JOIN b2b_wms.st_warehouse c ON a.WarehouseId = c.Id LEFT JOIN b2b_wms.st_wareposition d ON b.WarePositionId = d.Id LEFT JOIN b2b_wms.st_warefield e ON d.WareFieldId = e.Id AND d.WarehouseId = e.WarehouseId LEFT JOIN b2b_wms.st_wares f ON a.WaresId = f.Id LEFT JOIN b2b_wms.st_supplier g ON b.SupplierId = g.Id WHERE a.TenantId IN ( ‘3286299645965762560’, ‘3131897506372599808’ ) AND a.WarehouseId IN ( ‘3370028676427628544’, ‘3353714265942151168’ ) AND b.Qty > 0; 冷冻低温仓出库明细: SELECT CAST(a.Id AS CHAR) AS ‘出库单号’, CASE WHEN a.Type = 1 THEN ‘订单’ WHEN a.Type = 2 THEN ‘参照入库出库’ WHEN a.Type = 3 THEN ‘盘亏’ WHEN a.Type = 4 THEN ‘调拨出库’ WHEN a.Type = 6 THEN ‘报损出库’ WHEN a.Type = 9 THEN ‘退供应商’ ELSE ‘其他出库’ END ‘出库类型’, DATE_FORMAT( a.CreateTime, ‘%Y-%m-%d %H:%i:%s’ ) AS ‘出库单日期’, IF( a.Creator = g.UserName, g.Name, a.Creator ) AS ‘操作人’, CONCAT(c.Name, c.Code) AS ‘仓库名称’, CASE WHEN d.X4 = 0 THEN CONCAT(‘分拣区’, d.Code) WHEN d.X4 = 1 THEN CONCAT(‘储货区’, d.Code) WHEN d.X4 = 2 THEN CONCAT(‘隔离区’, d.Code) ELSE ‘其他’ END AS ‘库区’, e.Code AS ‘库位’, a.X3 AS ‘客户名称’, f.SkuCode AS ‘商品编码’, f.SkuName AS ‘商品名称’, f.Barcode AS ‘商品条码’, f.Unit AS ‘单位’, SUBSTRING(f.Subtitle, 1, 5) AS ‘规格’, b.Qty AS ‘出库数量’, b.F8 AS ‘出库单价’, b.F9 AS ‘出库金额’, CAST(b.BatchNo AS CHAR) AS ‘批次’, h.QtyReview AS ‘复核数量’, IF( h.ReviewUser = i.UserName, i.Name, h.ReviewUser ) AS ‘复核人’, DATE_FORMAT( h.ReviewTime, ‘%Y-%m-%d %H:%i:%s’ ) AS ‘复核时间’, DATE_FORMAT( a.CompletionTime, ‘%Y-%m-%d %H:%i:%s’ ) AS ‘完成时间’ FROM b2b_wms.st_outstockorder a LEFT JOIN b2b_wms.st_outstockorderitem b ON a.Id = b.OutStockOrderId LEFT JOIN b2b_wms.st_warehouse c ON a.WarehouseId = c.Id LEFT JOIN b2b_wms.st_warefield d ON b.WareFieldId = d.Id LEFT JOIN b2b_wms.st_wareposition e ON b.WarePositionId = e.Id LEFT JOIN b2b_wms.st_wares f ON b.WaresId = f.Id LEFT JOIN b2b_wms.st_userprofile g ON a.Creator = g.UserName LEFT JOIN b2b_wms.st_outstockorderitemhis h ON b.Id = h.OutStockOrderItemId AND a.Id = h.OutStockOrderId LEFT JOIN b2b_wms.st_userprofile i ON h.ReviewUser = i.UserName WHERE a.TenantId IN ( ‘3286299645965762560’, ‘3131897506372599808’ ) AND a.WarehouseId IN ( ‘3370028676427628544’, ‘3353714265942151168’ ) AND a.Status = 3 AND a.CreateTime >= @oStartTime AND a.CreateTime <= @oEndTime; 帮我写一个商品出库频次,频率,周转等关键指数的select语句。以上提供的语句,字段waresid不在st_warestoreitem表中,逻辑错误。输出的结果需要保留商品的基本属性: CONCAT(t.`hName`, t.`hCode`) AS '仓库名称', CASE WHEN t.`X4` = 0 THEN CONCAT('分拣区', t.`fCode`) WHEN t.`X4` = 1 THEN CONCAT('储货区', t.`fCode`) WHEN t.`X4` = 2 THEN CONCAT('隔离区', t.`fCode`) ELSE '其他' END AS '库区', t.`pCode` AS '库位', t.`SkuCode` AS '商品编码', t.`SkuName` AS '商品名称', t.`Barcode` AS '商品条码', t.`Unit` AS '单位', SUBSTRING(t.`Subtitle`, 1, 5) AS '规格', t.`Qty` AS '库存数量', t.`Amount` AS '库存金额', CASE WHEN t.`FnType` = 3 THEN '拆零' WHEN t.`FnType` = 1 THEN '整件' ELSE '其他' END AS '分拣类型'
最新发布
11-05
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值