Android14 Log.isLoggable判断的分析
Android14 Log.isLoggable判断的分析
文章目录
- Android14 Log.isLoggable判断的分析
- 一、前言
- 二、答案和分析
- 1、Log.isLoggable 设置成true
- 2、Log.isLoggable 分析
- (1)Log.java
- (2)android_util_Log.cpp
- (3)properties.cpp
- (4)logd_write.c
- 三、其他
- 1、Log.isLoggable(TAG, Log.DEBUG) 小结
- 设置Log.isLoggable 方法为true
- 设置Log.isLoggable的应用场景
- 2、Log.java 打印等级的值
- 3、Log.java 旧版本的代码
- 4、系统的Log.isLoggable(TAG, Log.DEBUG) 验证
- 5、在cmd窗口查看手机的Log日志相关命令
一、前言
Android系统代码或者系统应用代码中经常有一些Dug打印,是可以在调试模式中查看的;
比如:if(Log.isLoggable(TAG, Log.DEBUG)) {XXX}
或者定义 boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
后面有些打印使用这个DEBUG属性来决定是否打印某些日志。
之前我不太懂,也有看过源码,但是看到了native再后面就追不下去了,就没管了。
后面各种搜索和研究后又有了新的发现。
本文介绍一下如何查看这个默认关闭的DEBUG信息日志。
其实不难,就是prop属性的设置和读取;
但是估计要调试模式才能手动设置这个日志开关;
系统权限应用也可以设置这个属性进行控制。
二、答案和分析
1、Log.isLoggable 设置成true
因为分析的过程比较麻烦,所以直接先说答案了。
private static final String TAG = "WifiTracker";private static final boolean DBG() {return Log.isLoggable(TAG, Log.DEBUG);}//有些写成这样,比较简便:private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
如何让这个DBG() 方法或者 DEBUG 为true 呢?
下面两种方法:
1、在源码里面,把 Log.isLoggable(TAG, Log.DEBUG) 内容替换成 true,重新编译apk或者模块代码进行替换。2、设置prop属性,log.tag.<TAG> 属性设置成D
比如上面这个类设置:setprop log.tag.WifiTracker D
重新加载这个类的时候,就会获取到 Log.isLoggable(TAG, Log.DEBUG) 为 true
第一种方法是最笨的方法,我之前经常是这样搞的。
第二种方法比较灵活,可以动态开启打印,关闭打印。
如果只要看Log.isLoggable的开启,那么到这里就可以了。
但是想看看系统代码是如何判断的可以往后看看。
Log.isLoggable开启后如何关闭?后面会提到!
2、Log.isLoggable 分析
下面分析的是Android14 的代码,不同系统版本可能有差异。
(1)Log.java
framework\base\core\java\android\util\Log.java
public final class Log {.../*** Checks to see whether or not a log for the specified tag is loggable at the specified level.** The default level of any tag is set to INFO. This means that any level above and including* INFO will be logged. Before you make any calls to a logging method you should check to see* if your tag should be logged. You can change the default level by setting a system property:* 'setprop log.tag.<YOUR_LOG_TAG> <LEVEL>'* Where level is either VERBOSE, DEBUG, INFO, WARN, ERROR, or ASSERT.* You can also create a local.prop file that with the following in it:* 'log.tag.<YOUR_LOG_TAG>=<LEVEL>'* and place that in /data/local.prop.*/@FastNativepublic static native boolean isLoggable(@Nullable String tag, @Level int level);
}
居然是native方法,那就就要看cpp代码了!
但是看上面注释的英文其实是有大致的说明了。
/**
*检查指定标记的日志是否可在指定级别记录。
*
*任何标签的默认级别都设置为INFO。这意味着,任何高于并包括以下级别的
*将记录信息。在调用日志方法之前,您应该检查以下内容
*如果你的标签应该被记录下来。您可以通过设置系统属性来更改默认级别:
*'setprop log.tag<;YOUR_LOG_TAG><;级别>'
*其中级别为VERBOSE、DEBUG、INFO、WARN、ERROR或ASSERT。//从小到大
*您还可以创建一个local.prop文件,其中包含以下内容:
*'log.tag<;YOUR_LOG_TAG>=<;级别>'
*并将其放置在/data/local.prop中。
*/
上面大致的意思:
1、可以设置prop属性 setprop log.tag.XXTAG 设置打印等级
TAG一般是当前类,也有可能是其他字符串,有些是整个应用使用某个TAG。2、setprop log.tag<;YOUR_LOG_TAG ><;级别>
当你设置的打印属性等级 >= 定义的等级,日志就会记录,也就是返回true
这里定义了DEBUG(缩写D),如果prop属性设置成DEBUG(D)或者ERRORE(缩写成V),Java代码就会返回true3、属性文件位置:/data/local.prop
这个估计是很旧的代码目录了,Android14 上没看到这个文件!
总的来说就是设置属性:setprop log.tag.XXTAG 设置成D就可以看到打印。
但是第2个>=就有点问题了:
实际代码中尝试prop属性设置成 "E" 是不会显示日志的,设置成 "V" 会显示日志;
难道是注释里面写错了,实际要prop属性的打印等级 <= level级别 ?
继续往下追代码看看!
(2)android_util_Log.cpp
framework\base\core\jni\android_util_Log.cpp
static jboolean isLoggable(const char* tag, jint level) {return __android_log_is_loggable(level, tag, ANDROID_LOG_INFO);
}
这个就很难追下去了,__android_log_is_loggable 找不到实现?!
Android 源码framework、device下面搜了找不到 __android_log_is_loggable的实现,后面使用grep -nr 查看system目录下找到了!
(3)properties.cpp
system\logging\liblog\properties.cpp
int __android_log_is_loggable(int prio, const char* tag, int default_prio) {auto len = tag ? strlen(tag) : 0;//tag字符串的长度//四个参考://1、传入的等级,这里是 Log.DEBUG//2、tag字符串//3、tag的字符串长度//4、默认等级,LOG_INFO,Ireturn __android_log_is_loggable_len(prio, tag, len, default_prio);
}//具体实现判断是在这里:
int __android_log_is_loggable_len(int prio, const char* tag, size_t len, int default_prio) {//1、获取最小日志优先级和属性日志级别int minimum_log_priority = __android_log_get_minimum_priority();//2、这个级别通过系统属性prop配置的,过程在本类看起来很麻烦int property_log_level = __android_log_level(tag, len);if (property_log_level >= 0 && minimum_log_priority != ANDROID_LOG_DEFAULT) {//3、判断传入的 Log.DEBUG 是否大于 prop或者minimum_log_priority 最小值return prio >= std::min(property_log_level, minimum_log_priority);} else if (property_log_level >= 0) {//4、判断传入的 Log.DEBUG 是否大于 prop 值return prio >= property_log_level;} else if (minimum_log_priority != ANDROID_LOG_DEFAULT) {return prio >= minimum_log_priority;} else {return prio >= default_prio;}
}
上面第3点和第4点 都是有判断prop属性的值是否小于或者等于传入的等级值。
所以最终的实现是要prop定义的TAG值小于或者等于传入的Log.DEBUG 才会返回true。
所以对于isLoggable的示例判断:
Log.isLoggable(TAG, Log.DEBUG); 是否返回为true的判断是:
1、判断prop属性: log.tag.TAG 的 Log等级是否小于或者等于 Log.DEBUG;
2、Log的等级从小到大:VERBOSE、DEBUG、INFO、WARN、ERROR或ASSERT
3、所以 log.tag.TAG 等于 V 或者D 就会返回true
到这里简单代码就分析完了,很多复杂的过程在同级目录的其他文件,有兴趣的可以自己看看。
后面我从网上搜到的__android_log_is_loggable具体实现是在 logd_write.c;
但是我在Android13/14的代码上没有看到这个文件,发现是Android11 之前的代码才有;
(4)logd_write.c
但是Android9 和Android11 的代码 system/core/liblog/logd_write.c 文件中,以下是简化后的逻辑分析:
int __android_log_is_loggable(int prio, const char* tag, int default_log_level) {if (prio >= ANDROID_LOG_WARN) {return 1;}char value[PROP_VALUE_MAX];if (tag != NULL) {char key[PROP_NAME_MAX];snprintf(key, sizeof(key), "log.tag.%s", tag);if (__system_property_get(key, value) > 0) {int prop_level = android_log_priority_to_int(value);if (prop_level >= 0) {//这里是判断出入的proi <= prop定义的等级,和最新的是相反的!return prio <= prop_level;} else if (strcmp(value, "SUPPRESS") == 0) {return 0;}}}//最新的系统代码是去除 log.default 的判断的!if (__system_property_get("log.default", value) > 0) {int prop_level = android_log_priority_to_int(value);if (prop_level >= 0) {return prio <= prop_level;}}return prio <= default_log_level;
}
从上面旧系统的代码逻辑看确实是判断 prop属性 log.tag. >= 传入的Log.DEBUG等级。
所以说旧系统代码和新系统代码逻辑是相反的;
Java代码里面的注释并没有进行修改!这个算是Google的一个小错误了。
三、其他
1、Log.isLoggable(TAG, Log.DEBUG) 小结
(1)Log.isLoggable默认都是返回false的
(2)Android 11 之前的版本设置prop属性 log.tag.TAG >= D 为true;
(3)Android 13 之后的版本设置prop属性 log.tag.TAG =< D 为true;
(4)不管什么系统版本设置成一样的等级最保险
(5)如果Android13 或者更新版本要关闭isLoggable的打印,设置大一点就行,比如E
(6)重启后设置的prop属性是不记忆的,要看打印要重新设置一次
设置Log.isLoggable 方法为true
串口设置:
setprop log.tag.XXTAG D //有些要这种V系统/签名应用代码设置:
import android.os.SystemProperties;
SystemProperties.set("log.tag.XXXTAG", "V");
注意设置的属性,重启后是失效的,要重新设置。
如果prop属性是乱设置呢,比如 setprop log.tag.XXTAG XX
这个要看系统代码实现了,因为我试出了两种不同的结果:
Android14 的mtk方案,随便设置,isLoggable 是返回false的
Android13 的rk方案,随便设置,isLoggable 是返回true的
有兴趣的可以自己看看具体实现的cpp代码。
设置Log.isLoggable的应用场景
系统代码里面是有些 Log.isLoggable 的判断,可以用来查看某些默认隐藏的日志;
我们自己开发的系统应用也是可以这样操作:
普通的关键流程日志用Log.i正常打印,如果是比较多的数据,
比如wifi列表所有信息或者某个对象的具体信息,这种详细日志就用调试模式显示。
2、Log.java 打印等级的值
framework\base\core\java\android\util\Log.java
部分代码如下:
public final class Log {/** @hide */@IntDef({ASSERT, ERROR, WARN, INFO, DEBUG, VERBOSE})@Retention(RetentionPolicy.SOURCE)public @interface Level {}/*** Priority constant for the println method; use Log.v.*/public static final int VERBOSE = 2;/*** Priority constant for the println method; use Log.d.*/public static final int DEBUG = 3;/*** Priority constant for the println method; use Log.i.*/public static final int INFO = 4;/*** Priority constant for the println method; use Log.w.*/public static final int WARN = 5;/*** Priority constant for the println method; use Log.e.*/public static final int ERROR = 6;/*** Priority constant for the println method.*/public static final int ASSERT = 7;
...
}
这里可以看到 VERBOSE, DEBUG, INFO, WARN, ERROR, or ASSERT.
打印等级是2到7。越大表示越严重,V是最小的2,A 是最大的7.
ASSERT, ERROR, WARN, INFO, DEBUG, VERBOSE 翻译过来分别对应:
断言、错误、警告、信息、调试、详细,
断言是可能导致系统崩溃的日志,错误可能导致应用崩溃的日志;
3、Log.java 旧版本的代码
网招的,不清楚是哪个安卓版本的,这个版本的prop判断逻辑都在一个Java代码里面
/*** Checks to see whether or not a log for the specified tag is loggable at the specified level.* <p>* The default level of any tag is set to INFO. This means that any level above and including* INFO will be logged. Before you make any calls to a logging method you should check to see* if your tag should be logged. You can change the default level by setting a system property:* 'setprop log.tag.<YOUR_LOG_TAG> <LEVEL>'* Where level is either VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT, or SUPPRESS. SUPPRESS will* turn off all logging for your tag. You can also create a local.prop file that with the* following in it:* 'log.tag.<YOUR_LOG_TAG>=<LEVEL>'* and place that in /data/local.prop.* </p>** @param tag The tag to check.* @param level The level to check.* @return Whether or not that this is allowed to be logged.* @throws IllegalArgumentException is thrown if the tag.length() > 23.*/
public static boolean isLoggable(String tag, int level) {if (tag.length() > LOG_TAG_MAX_LENGTH) {throw new IllegalArgumentException("Log tag " + tag + " exceeds limit of " + LOG_TAG_MAX_LENGTH + " characters");}// 如果级别大于等于 WARN ,直接返回 trueif (level >= Log.WARN) {return true;}// 获取系统属性 log.tag.<TAG> 的值String key = "log.tag." + tag;String value = SystemProperties.get(key);if (value != null) {value = value.toUpperCase();// 解析系统属性值对应的日志级别int i = LogLevel.levelToInt(value, -1); //获取prop属性对应的调试等级int值if (i >= 0) {//这里也是prop属性的级别,大于或者等于输入的定义基本返回truereturn level <= i; } else if (value.equals("SUPPRESS")) {return false;}}// 如果没有设置系统属性,则检查全局的日志级别value = SystemProperties.get("log.default");if (value != null) {value = value.toUpperCase();int i = LogLevel.levelToInt(value, -1);if (i >= 0) {return level <= i;}}return false;
}
上面的代码逻辑熟悉Java的大致可以看懂。
上面的Java代码逻辑大致和Android11 之前的系统Log等级判断是一致的。
不同系统的Log.isLoggable 后面具体逻辑有差异是正常的;
4、系统的Log.isLoggable(TAG, Log.DEBUG) 验证
Android系统中有很多这样的代码,比如热点开关打印的代码:
Settings\src\com\android\settings\network\TetherEnabler.java
public class TetherEnabler implements... {private static final String TAG = "TetherEnabler";private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);void updateState(@Nullable String[] tethered) {int state = getTetheringState(tethered);if (DEBUG) {Log.d(TAG, "updateState: " + state);//热点开关状态打印,0关闭,1开启}
...}
这个热点开关状态的打印是在:原生Settings一级界面刚进入二级界面"WLAN、热点"显示界面会执行updateState方法;
三级界面返回二级界面也是会执行updateState方法;
后续热点开关这里是没有执行updateState方法;
console:/ # logcat | grep TetherEnabler
//没日志!
console:/ # setprop log.tag.TetherEnabler D //设置prop属性
console:/ #
console:/ # logcat | grep TetherEnabler
03-18 20:12:40.290 1006 1006 D TetherEnabler: updateState: 0 //热点关闭状态
03-18 20:12:40.374 1006 1006 D TetherEnabler: updateState: 0
上面日志可以看到设置prop属性后就可以看到 DEBUG 的日志。
上面这个TetherEnabler 的打印是 Settings 的wifi服务正常启动才会进入 TetherEnabler的逻辑,否则不会调用 TetherEnabler 的方法。
有些类设置了prop属性,但是还是没有相关的打印日志,有可能是:
1、prop属性未设置正确
2、等级未设置正确
Log.isLoggable(TAG, Log.VERBOSE) 的等级,prop只能设置成V
3、代码逻辑确实不经过那里
5、在cmd窗口查看手机的Log日志相关命令
//格式1:打印默认日志数据
adb logcat //格式2:需要打印日志详细时间的简单数据
adb logcat -v time//格式3:需要打印级别为Error的信息
adb logcat *:E//格式4:需要打印时间和级别是Error的信息
adb logcat -v time *:E//格式5:将日志保存到电脑固定的位置,比如D:\log.txt
adb logcat -v time >D:\log.txt
https://blog.csdn.net/wenzhi20102321/article/details/81058196
相关文章:
Android14 Log.isLoggable判断的分析
Android14 Log.isLoggable判断的分析 文章目录 Android14 Log.isLoggable判断的分析一、前言二、答案和分析1、Log.isLoggable 设置成true2、Log.isLoggable 分析(1)Log.java(2)android_util_Log.cpp(3)pro…...
Mac:JMeter 下载+安装+环境配置(图文详细讲解)
📌 下载JMeter 下载地址:https://jmeter.apache.org/download_jmeter.cgi 📌 无需安装 Apache官网下载 JMeter 压缩包,无需安装,下载解压后放到自己指定目录下即可。 按我自己的习惯,我会在用户 jane 目…...
Python IP解析器 ip2region使用
说明:最近需要在python项目内使用IP定位所在城市的需求,没有采用向外部ISP服务商API请求获取信息的方案,则翻了翻,在搞Java时很多的方案,在Python端反而可选择范围很小。 # 示例查询 ips ["106.38.188.214"…...
labview与西门子1500plc进行S7通讯(仿真效果)
环境: 1.博图V16 2.S7-PLCSIM Advanced V3.0 3.labview2020 4.HslCommunication的dll文件 运行效果图 通过使用HslCommunication的库文件来对西门子plc进行通讯 labview代码 代码打包 通过网盘分享的文件:labview进行s7通讯测试.rar 链接: https:/…...
Oracle 公布 Java 的五大新功能
Java 增强提案包括语言增强和性能优化,从 JDK 25 中的稳定值 API 开始。 随着JDK(Java 开发工具包)24刚刚全面上市,Oracle 提前透露了不久的将来即将推出的 Java 功能,包括增强原始装箱到空限制值类类型。 3 月 18 日…...
台式机电脑组装---电脑机箱与主板接线
台式机电脑组装—电脑机箱与主板接线 1、机箱连接主板的跳线一般主要有USB 2.0、USB 3.0、前置音频接口(HD_AUDIO)以及POWER SW、RESET SW、POWER LED、HDD LED四个主板跳线,这些跳线分别的含义如下。 RESET SW:机箱重启按键;注:…...
ubuntu高并发内核参数调优 - (压测客户端调优)
业务上要求集群提供10w并发,10w并发听上去不是很难,但10w并发持续1小时呢 在业务上线之前还需要我们自己对业务进行压测,俗称benchmark。 压测的服务器也是需要进行性能调优的,以下列出调优前后的参数对比,更直观的分析…...
动作捕捉手套如何让虚拟现实人机交互 “触手可及”?
在虚拟与现实逐渐交融的当下,动作捕捉技术正以前所未有的速度革新着多个领域。 动作捕捉技术,简称“动捕”,已经从早期的影视特效制作,逐步拓展到游戏开发、虚拟现实、机器人控制等多个领域。 而mHandPrO数据手套作为这一领域的…...
笔记本电脑关不了机是怎么回事 这有解决方法
在快节奏的现代生活中,笔记本电脑已成为我们工作、学习和娱乐的得力助手。在使用电脑的过程中,笔记本电脑突然关不了机了,怎么回事?下面驱动人生就来讲一讲笔记本电脑不能正常关机的解决方法,有需要的可以来看看。 一、…...
数据库:一文掌握 MongoDB 的各种指令(MongoDB指令备忘)
文章目录 入门连接 MongoDB Shell显示数据库切换数据库显示集合运行 JavaScript 文件 CRUD创建寻找文件使用运算符查找文档读取更新删除 数据库和集合Drop创建集合其他采集功能 索引列表索引创建索引删除索引隐藏/取消隐藏索引 方便的命令 其它改变流分片集群副本集 MongoDB 此…...
麒麟操作系统作为服务器,并且需要在浏览器上调试 MATLAB
在内网环境下,使用麒麟操作系统作为服务器,并且需要在浏览器上调试 MATLAB 程序,这确实复杂,但仍然有可行的解决方案。麒麟操作系统是国产化的 Linux 发行版(如基于 Ubuntu Kylin 或银河麒麟),因…...
给管理商场消防安全搭建消防安全培训小程序全过程
一、需求沟通 “我是管理商场消防安全的嘛,做这个的作用呢,1是商场的所有商户员工可以看平面或者视频随时自学, 2是我们定期培训必修课程、考试,这个需要留存他们的手签字的签到表确认我们讲给他们听了(免责很重要&am…...
Flutter:页面滚动,导航栏背景颜色过渡动画
记录:导航默认透明,页面发生滚动后,导航背景色由0-1,过渡到白色背景。 view import package:ducafe_ui_core/ducafe_ui_core.dart; import package:flutter/material.dart; import package:get/get.dart; import package:redo…...
VSCode + CMake
参考文献: 如何用 GCC, CMake 和 Make 编译C/C代码Windows 上的 Linux 子系统:WSLWSL:桌面 UI 远程连接 RDP 配置 VScode 文章目录 CMake 配置VSCode 配置launch.jsontask.jsonc_cpp_properties.json CMake 配置 编写如下的 CmakeLists.t…...
Docker进阶篇1:什么是Docker数据卷?为什么需要Docker数据卷?Docker数据卷3种类型介绍
大家好我是木木,在当今快速发展的云计算与云原生时代,容器化技术蓬勃兴起,Docker 作为实现容器化的主流工具之一,为开发者和运维人员带来了极大的便捷 。下面我们一起开始进阶第1篇:什么是Docker数据卷?为什…...
(2025|ICLR|华南理工,任务对齐,缓解灾难性遗忘,底层模型冻结和训练早停)语言模型持续学习中的虚假遗忘
Spurious Forgetting in Continual Learning of Language Models 目录 1. 引言 2. 动机:关于虚假遗忘的初步实验 3. 深入探讨虚假遗忘 3.1 受控实验设置 3.2 从性能角度分析 3.3 从损失景观角度分析 3.4 从模型权重角度分析 3.5 从特征角度分析 3.6 结论 …...
从两指到三指:Robotiq机器人自适应夹持器技术解析
工业自动化离不开高效工具的支持。Robotiq机器人工具凭借其模块化设计和智能化编程技术,提升了设备的灵活性和操作效率。Robotiq机器人工具精准的传感器和自适应夹持器技术,能够满足多样化的应用需求,为制造业、物流和科研等领域提供可靠的解…...
【css酷炫效果】纯CSS实现悬浮弹性按钮
【css酷炫效果】纯CSS实现悬浮弹性按钮 缘创作背景html结构css样式完整代码效果图 想直接拿走的老板,链接放在这里:https://download.csdn.net/download/u011561335/90492020 缘 创作随缘,不定时更新。 创作背景 刚看到csdn出活动了&…...
力扣222. 完全二叉树的节点个数(Java实现)
222. 完全二叉树的节点个数 1. 思路 这个题最简单的做法就是暴力遍历,时间复杂度为O(n)。 我们现在用低于O(n)的做法解决问题。 对于一棵满二叉树,它的节点数 2 h - 1 (h 是指树一共有多少层) 头节点不断遍历左孩子直至为null,得到树高…...
MySQL函数大全(持续更新)
MySQL常用函数 一、字符串函数 函数功能 CONCAT(s1, s2, ...) 拼接字符串 CONCAT_WS(sep, s1, s2, ...) 指定分隔符拼接字符串 SUBSTRING(str, start, length) 截取字符串 LEFT(str, length) 从左边截取指定长度字符串 RIGHT(str, length) 从右边截取指定长度字符串 LENGTH(s…...
Django系列教程(13)——Cookie和Session应用场景及案例
目录 什么是cookie,cookie的应用场景及缺点 Django中如何使用cookie Cookie使用示例 什么是session及session的工作原理 Django中如何使用会话session Session使用示例 小结 HTTP协议本身是”无状态”的,在一次请求和下一次请求之间没有任何状态保…...
element-ui pagination 组件源码分享
pagination 分页组件源码分享,主要从以下三个方面: 1、pagination 组件页面结构。 2、pagination 组件属性。 3、pagination 组件方法。 一、组件页面结构。 二、组件属性。 2.1 small 是否使用小型分页样式,类型为 boolean,…...
【css酷炫效果】纯CSS实现火焰文字特效
【css酷炫效果】纯CSS实现火焰文字特效 缘创作背景html结构css样式完整代码基础版进阶版(冰霜版) 效果图 想直接拿走的老板,链接放在这里:https://download.csdn.net/download/u011561335/90492005 缘 创作随缘,不定时更新。 创作背景 刚…...
【java面型对象进阶】------继承实例
继承结构下的标准Javabean 代码如下: package demo10;//定义员工父类 public class Employee {private String id;private String name;private double salary;//构造方法public Employee(){}public Employee(String id,String name,double salary){this.idid;thi…...
Oracle 19c 子分区表索引测试
一、建表语句放在最后,方便查看 二、创建各类索引 --创建本地的主键约束,但必须加上分区键、子分区键MT_O_CODE,M_YMD alter table MS_DMG.A_RED drop constraint MGR_PK_AREAD ; alter table MS_DMG.A_RED add constraint MGR_PK_AREAD primary key …...
【数据分享】1999—2023年地级市固定资产投资和对外经济贸易数据(Shp/Excel格式)
在之前的文章中,我们分享过基于2000-2024年《中国城市统计年鉴》整理的1999-2023年地级市的人口相关数据、染物排放和环境治理相关数据、房地产投资情况和商品房销售面积相关指标数据、社会消费品零售总额和年末金融机构存贷款余额、各类用地面积、地方一般公共预算…...
Spring Boot 与 Couchbase 整合教程
精心整理了最新的面试资料和简历模板,有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 Spring Boot 与 Couchbase 整合教程 环境要求 JDK 8Spring Boot 2.7.xCouchbase Server 7.xMaven/Gradle 步骤 1:创建Spring Boot项目 使用 st…...
数据结构——串、数组和广义表
串、数组和广义表 1. 串 1.1 串的定义 串(string)是由零个或多个字符组成的有限序列。一般记为 S a 1 a 2 . . . a n ( n ≥ 0 ) Sa_1a_2...a_n(n\geq0) Sa1a2...an(n≥0) 其中,S是串名,单引号括起来的字符序列是串的值, a i a_i a…...
Spring中DI与IOC的关系解析
在Spring框架中,DI(依赖注入)和IOC(控制反转)是两个核心概念,它们密切相关但有不同的侧重点。 IOC(控制反转) IoC 是一种设计原则,将对象的创建和依赖管理交给框架或容…...
pycharm-python國際象棋遊戲代碼
嗯,用户的问题是“pycharm寫關於python國際象棋遊戲代碼”,也就是要用PyCharm来写一个Python的国际象棋游戏代码。我需要先整理一下用户提供的搜索结果,看看有什么相关的信息可以利用。 首先看搜索结果中的各个网页内容。网页1主要讲的是象棋…...
