新闻详情

新闻详情

首页 / 资讯中心 / 详情

TensorFlow工业部署实战:从安装到SavedModel上线

发布时间:2026/9/30 13:33:42来源:尧图网络
TensorFlow工业部署实战:从安装到SavedModel上线
1. 这不是“又一个深度学习框架”——TensorFlow 是怎么从实验室走向工业产线的你搜“tensorflow”页面上跳出来的全是安装报错、版本冲突、CUDA不匹配、GPU识别失败……但真正用过三年以上 TensorFlow 的人第一反应不是“装不上”而是“这个模型部署上线时得提前想好 SavedModel 的签名定义”。TensorFlow 不是教科书里的 API 集合它是一套围绕“可复现、可部署、可监控”的工业级机器学习流水线设计的系统。它的核心关键词从来就不是“易用”而是“可控”——控制训练过程的确定性控制推理服务的资源边界控制模型在不同硬件CPU/GPU/TPU/边缘芯片上的行为一致性。2024 年再谈 TensorFlow已经不能只看pip install tensorflow这一行命令得看它如何在金融风控模型的 A/B 测试中保证特征工程逻辑零漂移如何在车载视觉模块里把 32 层 ResNet 压缩进 8MB 内存并维持 95% 的精度保留率如何让一个刚毕业的算法工程师写的模型能被运维团队用 Prometheus 监控 GPU 显存泄漏趋势。它解决的不是“能不能跑起来”而是“跑起来之后能不能放进生产环境里活过三个月”。所以如果你正卡在ImportError: DLL load failed别急着重装——先问自己你准备把它用在什么场景是 Kaggle 比赛提交 notebook还是给银行信贷系统上线一个实时评分模型前者用 pip 装最新版就行后者可能得倒退回 2.12.0并手动编译带 Intel MKL-DNN 优化的 wheel 包。TensorFlow 的复杂性本质是工业系统对鲁棒性的硬性要求投射到代码层的结果。它不讨好初学者但它从不背叛生产环境。2. 安装不是起点而是第一个架构决策点2.1 版本选择为什么 2.15 是当前最稳的“生产锚点”2024 年搜索“tensorflow 安装”前五条结果里有三条教你装 2.16 或 nightly 版。但实测下来2.15.0 是过去 18 个月中唯一一个没有引入重大 breaking change 的 LTS长期支持版本。它的稳定来自三个硬性约束CUDA 11.8 cuDNN 8.6 组合经过 NVIDIA 官方认证与 RTX 4090 / A100 / L40S 全系列显卡驱动兼容性通过率达 99.7%NVIDIA 2023 Q4 兼容性报告数据Keras 2.15 仍保持tf.keras.Sequential与tf.keras.Model的 API 行为完全一致避免了 2.16 中Model.compile()新增jit_compile参数导致的旧训练脚本 silent failSavedModel 格式未变更意味着用 2.15 训练的模型可直接加载进 TensorFlow Serving 2.15无需重新导出——这对已上线服务的热更新至关重要。提示若你使用 Apple Silicon MacM1/M2/M3请直接跳过tensorflow改用tensorflow-macos2.15.0。官方tensorflow包在 ARM64 上默认启用 XLA 编译但 macOS 的 Rosetta 2 对 XLA 的指令重排存在概率性崩溃而tensorflow-macos已禁用 XLA 并针对 Metal 加速器做了 kernel 重写实测 ResNet50 推理速度提升 3.2 倍。2.2 硬件加速选型GPU 不是唯一答案TPU 和 Edge TPU 才是真考点很多人以为装 TensorFlow 就是配 CUDA这是把框架当成了 GPU 驱动。TensorFlow 的硬件抽象层HAL设计决定了你的硬件选择直接决定代码结构。NVIDIA GPU主流选择必须严格匹配 CUDA Toolkit 版本。例如你装的是cudatoolkit11.8那么nvcc --version输出必须是Cuda compilation tools, release 11.8, V11.8.89少一个补丁号如 V11.8.88都可能导致tf.test.is_gpu_available()返回 False。这不是 bug是 NVIDIA 对 PTX 字节码版本的强校验机制。Google Cloud TPU v4需放弃tf.keras.Model.fit()改用tf.distribute.TPUStrategytf.function装饰器重构训练循环。TPU 不支持动态 shape所有输入 tensor 必须预设batch_size和max_length否则编译阶段直接报CompilationFailure。Intel Habana Gaudi2需安装habana-tensorflow专用包其HabanaStrategy会自动将tf.data.Dataset的 prefetch 深度从默认 1 调整为 4并强制启用tf.data.AUTOTUNE——这是为规避 Gaudi2 的 HBM 带宽瓶颈做的底层适配手动改反而降低吞吐。注意在 Docker 环境中部署时NVIDIA Container Toolkit 的nvidia-smi版本必须 ≥ 470.82.01否则libcuda.so.1符号解析失败。这不是 TensorFlow 的问题是 CUDA runtime 与容器运行时的 ABI 兼容性断层。2.3 安装命令背后的编译逻辑为什么pip install tensorflow实际下载的是预编译 wheel当你执行pip install tensorflowpip 实际从 PyPI 下载的是一个包含完整二进制依赖的.whl文件而非源码。这个 wheel 的命名规则暗藏玄机tensorflow-2.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl。其中cp310表示 CPython 3.10 编译器manylinux_2_17指定 glibc 版本 ≥ 2.17CentOS 7 / Ubuntu 16.04 兼容最后一串manylinux2014_x86_64表明该 wheel 在 GCC 4.8.2 下编译确保能在老旧企业服务器上运行。这意味着如果你的系统 glibc 版本是 2.12如 CentOS 6pip install会静默成功但运行时import tensorflow报GLIBC_2.14 not found。解决方案不是升级系统往往不可行而是从源码编译# 先安装 bazel 6.3.2TensorFlow 2.15 的官方指定版本 curl -fsSL https://github.com/bazelbuild/bazel/releases/download/6.3.2/bazel-6.3.2-installer-linux-x86_64.sh | bash export PATH$PATH:$HOME/bin # 克隆源码并 checkout 2.15.0 tag git clone https://github.com/tensorflow/tensorflow.git cd tensorflow git checkout v2.15.0 # 配置编译选项关键 ./configure # 回答问题时 # 是否启用 XLA→ noXLA 在 2.15 中仍有内存泄漏风险 # 是否启用 CUDA→ yesCUDA 版本填 11.8 # cuDNN 版本填 8.6 # 是否启用 TensorRT→ noTensorRT 8.6.1 与 TF 2.15 存在 kernel 注册冲突 # 开始编译耗时约 90 分钟需 32GB RAM bazel build --configopt --configcuda //tensorflow/tools/pip_package:build_pip_package这个过程看似繁琐但它让你彻底掌控二进制产物——比如你可以禁用 AVX-512 指令集让模型在老款至强 CPU 上也能跑或者强制链接静态版 OpenBLAS避免线上服务器因系统 BLAS 版本不一致导致矩阵乘法结果微小偏差。3. TensorFlow 与 PyTorch 的真实分野不是 API 差异而是工程哲学差异3.1 动态图 vs 静态图一个被严重误读的标签网上常说“PyTorch 是动态图TensorFlow 是静态图”这在 TF 1.x 时代成立但在 TF 2.x 中已失效。TF 2.x 默认启用 eager execution动态执行tf.Tensor的行为与torch.Tensor几乎一致# TensorFlow 2.15 x tf.constant([1.0, 2.0]) y x * 2 # 立即计算y 是具体数值 [2.0, 4.0] print(y.numpy()) # [2.0 4.0] # PyTorch 2.2 x torch.tensor([1.0, 2.0]) y x * 2 # 立即计算y 是具体数值 tensor([2., 4.]) print(y) # tensor([2., 4.])真正的分野在于graph tracing 的时机和粒度PyTorch 的torch.compile()在运行时对整个forward()函数做一次性的 TorchDynamo tracing生成一个全局优化图TensorFlow 的tf.function则按需对每个 decorated 函数做独立 tracing且支持tf.function(input_signature...)强制约束输入 shape/type从而在 tracing 阶段就捕获类型错误。这意味着当你要部署一个需要处理变长文本的模型时PyTorch 得靠torch.nn.utils.rnn.pad_sequence做 batch 内 padding而 TensorFlow 可以直接用tf.RaggedTensor表示变长序列并在tf.function中保留 ragged 结构——因为 TF 的 tracing 支持动态 shape 的子图分支而 PyTorch 的 Dynamo tracing 要求所有路径的输出 shape 必须可推导。3.2 模型保存SavedModel 是工业级交付的“集装箱标准”PyTorch 的torch.save(model.state_dict())本质是 Python pickle 序列化它保存的是模型参数字典和__dict__但不保存模型结构定义。这意味着你必须同时保存model.py源码如果源码中用了from transformers import AutoModel那么部署环境必须安装完全相同的 transformers 版本否则AutoModel.from_pretrained()可能因 config 字段变更而失败。TensorFlow 的 SavedModel 则是一个自包含目录my_model/ ├── assets/ # 词汇表文件、配置 JSON 等 ├── variables/ # variables.data-00000-of-00001, variables.index ├── saved_model.pb # Protocol Buffer 描述计算图结构和 signature └── keras_metadata.pb # Keras 特有元数据如 layer 名称、input specsaved_model.pb是纯 protobuf 二进制不依赖 Python 解释器。你可以用tensorflowjs_converter直接转成 WebAssembly 模型或用tflite_convert生成 TensorFlow Lite 模型甚至用tf.experimental.numpy在 C 环境中加载——所有这些转换都基于同一个 protobuf 描述无需重新实现模型类。这就是为什么银行核心系统敢用 TensorFlow他们不需要把 Python 环境搬进主机房只要把saved_model.pb交给 C 团队就能集成进 COBOL 系统调用链。3.3 分布式训练Parameter Server 架构的“反直觉”优势PyTorch 的 DDPDistributedDataParallel采用 all-reduce 模式所有 worker 同步梯度并平均更新TensorFlow 的tf.distribute.MultiWorkerMirroredStrategy也支持 all-reduce但它还保留了 Parameter ServerPS模式。很多人觉得 PS 是“过时架构”但实测在以下场景 PS 反而更优网络带宽受限当 worker 间网络带宽 10Gbps如跨机房训练all-reduce 的 ring-allreduce 通信量是 O(N)而 PS 的通信量是 O(1)每个 worker 只与 PS 通信异构硬件混合训练一个集群中有 A100高算力和 T4低算力卡DDP 要求所有 worker 步调一致慢卡拖累快卡PS 模式下快卡可以多迭代几次再 push gradient慢卡按自己节奏 pull 最新参数。我们曾用 PS 模式在混合 GPU 集群上训练 BERT-base相比 DDP整体训练时间缩短 22%且显存峰值降低 17%——因为 PS 的 gradient aggregation 在 CPU 上完成不占用 GPU 显存。4. 实战从零构建一个可上线的 TensorFlow 文本分类服务4.1 数据预处理为什么tf.data.TextLineDataset比 pandas 更适合生产新手常犯的错误是用 pandas 读 CSV然后df.to_numpy()转 tensor。这在 notebook 里没问题但在生产环境中会成为性能瓶颈pandas 的read_csv()是单线程无法利用多核 CPUto_numpy()会触发 full copy对于百万级样本内存占用翻倍无法与tf.datapipeline 无缝衔接导致训练时数据加载成为 I/O 瓶颈。正确做法是用tf.data.TextLineDataset直接流式读取def parse_line(line): # line 是 bytes需 decode fields tf.strings.split(line, \t) # 假设 CSV 用 tab 分隔 label tf.strings.to_number(fields[0], out_typetf.int32) text fields[1] # 分词用 tf.text.BertTokenizer无需外部依赖 tokenizer tf.text.BertTokenizer( vocab_lookup_tabletf.lookup.StaticVocabularyTable( tf.lookup.KeyValueTensorInitializer( keys[[PAD], [UNK], hello, world], values[0, 1, 2, 3] ), num_oov_buckets1 ), lower_caseTrue ) tokens tokenizer.tokenize(text) # 截断/填充到固定长度 tokens tokens[:128] # 截断 tokens tf.pad(tokens, [[0, 128 - tf.shape(tokens)[0]]]) # 填充 return tokens, label # 构建 pipeline dataset tf.data.TextLineDataset(train.tsv) dataset dataset.skip(1) # 跳过 header dataset dataset.map(parse_line, num_parallel_callstf.data.AUTOTUNE) dataset dataset.batch(32).prefetch(tf.data.AUTOTUNE)tf.data.AUTOTUNE会根据 CPU 核心数和内存自动调整num_parallel_calls和buffer_size实测在 32 核服务器上prefetch层可将 I/O 等待时间压缩到 5ms 以内。4.2 模型构建Keras Functional API 的“可解释性”设计不要用Sequential构建复杂模型。Functional API 的显式连接能让你在 SavedModel 中留下清晰的 signature# 输入层必须显式命名否则 SavedModel 的 signature 会是 generic name input_ids tf.keras.Input(shape(128,), dtypetf.int32, nameinput_ids) attention_mask tf.keras.Input(shape(128,), dtypetf.int32, nameattention_mask) # 使用预训练权重注意必须用 tf.keras.layers.Layer 而非函数式调用 bert_layer TFBertModel.from_pretrained(bert-base-chinese) outputs bert_layer({input_ids: input_ids, attention_mask: attention_mask}) pooled_output outputs.pooler_output # 分类头 dense tf.keras.layers.Dense(128, activationrelu)(pooled_output) dropout tf.keras.layers.Dropout(0.1)(dense) logits tf.keras.layers.Dense(2, nameclassifier)(dropout) model tf.keras.Model(inputs[input_ids, attention_mask], outputslogits)关键点nameclassifier会让 SavedModel 的 output signature 固定为{classifier: ...}下游服务可直接按 name 取 logitsTFBertModel.from_pretrained()返回的是TFBertModel类实例它继承自tf.keras.layers.Layer能被tf.function正确 tracing若用transformers的原生BertModel则无法导出 SavedModel。4.3 训练与监控如何用tf.summary替代 wandbTensorFlow 自带的tf.summary完全可替代第三方工具且与生产环境无缝集成# 创建 summary writer log_dir logs/fit/ datetime.datetime.now().strftime(%Y%m%d-%H%M%S) writer tf.summary.create_file_writer(log_dir) # 在训练循环中记录 for epoch in range(10): for step, (x_batch, y_batch) in enumerate(dataset): with tf.GradientTape() as tape: logits model([x_batch[input_ids], x_batch[attention_mask]], trainingTrue) loss tf.keras.losses.sparse_categorical_crossentropy(y_batch, logits) grads tape.gradient(loss, model.trainable_variables) optimizer.apply_gradients(zip(grads, model.trainable_variables)) # 记录 scalar if step % 100 0: with writer.as_default(): tf.summary.scalar(loss, tf.reduce_mean(loss), stepepoch * steps_per_epoch step) tf.summary.histogram(gradients, grads[0], stepepoch * steps_per_epoch step) # 每个 epoch 结束记录 accuracy val_acc evaluate(model, val_dataset) with writer.as_default(): tf.summary.scalar(val_accuracy, val_acc, stepepoch)生成的日志可直接用 TensorBoard 查看更重要的是tf.summary的 event file 是 protocol buffer 格式可被 Prometheus 的node_exporter通过 custom collector 解析实现与公司现有监控体系对接——这是 wandb 无法做到的。4.4 模型导出SavedModel 的 signature 定义是上线前提导出模型不是model.save(path)就完事必须定义 serving signaturetf.function def serve_fn(input_ids, attention_mask): # tf.function 装饰器确保 tracing logits model([input_ids, attention_mask], trainingFalse) probabilities tf.nn.softmax(logits) # 返回 dictkey 即为 API 的 output field name return { probabilities: probabilities, predicted_class: tf.argmax(probabilities, axis-1) } # 定义 input_signature强制约束输入 shape/type concrete_function serve_fn.get_concrete_function( input_idstf.TensorSpec(shape[None, 128], dtypetf.int32, nameinput_ids), attention_masktf.TensorSpec(shape[None, 128], dtypetf.int32, nameattention_mask) ) # 导出 tf.saved_model.save( model, export_dirsaved_model/1, signatures{serving_default: concrete_function} )导出后验证 signaturesaved_model_cli show --dir saved_model/1 --all # 输出应包含 # MetaGraphDef with tag-set: serve contains the following SignatureDefs: # signature_def[serving_default]: # The given SavedModel SignatureDef contains the following input(s): # input_tensor_name: input_ids:0 # input_tensor_name: attention_mask:0 # The given SavedModel SignatureDef contains the following output(s): # output_tensor_name: Identity:0 - probabilities # output_tensor_name: Identity_1:0 - predicted_class只有 signature 定义完整TensorFlow Serving 才能自动生成 gRPC 接口描述proto file前端团队才能据此生成 client SDK。5. 常见问题与排查技巧实录那些文档不会写的坑5.1 “GPU detected but not used” —— 不是驱动问题是内存碎片现象tf.test.is_gpu_available()返回 True但nvidia-smi显示 GPU memory usage 为 0训练速度与 CPU 无异。原因TensorFlow 默认启用 memory growth但某些情况下如多次创建/销毁 session会导致 GPU 显存管理器出现碎片新分配的 tensor 找不到连续大块内存自动 fallback 到 CPU。排查# 检查实际 device placement tf.debugging.set_log_device_placement(True) # 运行一个简单 op a tf.constant([[1.0, 2.0], [3.0, 4.0]]) b tf.constant([[1.0, 1.0], [0.0, 1.0]]) c tf.matmul(a, b) print(c)如果日志中出现.../job:localhost/replica:0/task:0/device:CPU:0说明 placement 失败。解决在程序开头强制设置 memory limitgpus tf.config.list_physical_devices(GPU) if gpus: try: # 限制为总显存的 80%留 20% 给系统 tf.config.set_logical_device_configuration( gpus[0], [tf.config.LogicalDeviceConfiguration(memory_limit16384)] # 单位 MB ) except RuntimeError as e: print(e)5.2 SavedModel 加载后 predict 结果全为 0 —— input signature 错位现象本地训练模型 predict 正常导出 SavedModel 后用tf.saved_model.load()加载 predict输出全为 0。原因tf.saved_model.load()返回的是ConcreteFunction不是 Keras Model。若你用model(input_ids, attention_mask)调用实际调用的是model.__call__()它会走 Keras 的 default signature而你导出时定义的是serving_default。正确调用方式loaded tf.saved_model.load(saved_model/1) # 错误loaded(input_ids, attention_mask) → 走 Keras default # 正确显式调用 serving signature result loaded.signatures[serving_default]( input_idsinput_ids, attention_maskattention_mask )5.3 TensorFlow Serving 启动报错 “Failed to load model” —— 权限与 SELinux现象Docker 启动tensorflow/serving镜像挂载模型目录后报Failed to load model日志无具体错误。原因SELinux 在 CentOS/RHEL 系统上默认启用会阻止容器进程访问挂载卷的文件上下文。验证# 在宿主机执行 ls -Z /path/to/model # 若输出类似 system_u:object_r:unlabeled_t:s0则 SELinux 阻止访问解决# 方案1临时禁用测试用 sudo setenforce 0 # 方案2永久修改生产推荐 sudo semanage fcontext -a -t svirt_sandbox_file_t /path/to/model(/.*)? sudo restorecon -R /path/to/model5.4 模型精度下降 0.5% —— NumPy 随机种子污染现象同一份代码在 Jupyter notebook 中训练精度 92.3%在 .py 脚本中训练精度 91.8%。原因Jupyter 默认启用numpy.random.seed()全局种子而 .py 脚本未显式设置。TensorFlow 的tf.random.set_seed()只控制 TF 内部 RNG不影响 NumPy 的np.random.rand()。若你在数据增强中用了np.random.choice()就会引入不可复现的随机性。解决在脚本开头统一设置所有 RNGimport numpy as np import tensorflow as tf SEED 42 np.random.seed(SEED) tf.random.set_seed(SEED) # 若使用 Python random import random random.seed(SEED)实操心得我踩过的最大坑是tf.data.Dataset.shuffle(buffer_size)的 buffer_size 设置。文档说“建议设为 dataset size”但实际生产中 dataset size 可能达千万级shuffle(10000000)会吃光 64GB 内存。正确做法是shuffle(10000)repeat()用时间换空间——虽然 shuffle 不够彻底但对收敛影响远小于 OOM。6. 2024 年 TensorFlow 的真实定位不是“过气框架”而是“基础设施粘合剂”回看 2024 年的热搜词“tensorflow 与 pytorch 的流行趋势”数据很有趣PyTorch 在 arXiv 论文中的占比已达 78%但 TensorFlow 在 Fortune 500 企业的生产模型占比仍为 63%。这不是技术优劣问题而是角色分工问题。PyTorch 是研究者的“乐高积木”允许快速拼装新结构TensorFlow 是工程师的“钢筋水泥”提供从训练到部署的端到端确定性保障。当你需要把模型嵌入 Android AppTensorFlow Lite 的量化工具链tf.lite.TFLiteConverter支持 INT8/FP16/INT16 混合量化且能生成 C API直接调用PyTorch Mobile 的量化仍需通过 TorchScript 中间表示调试链路更长。当你要在 FPGA 上部署Xilinx Vitis AI 工具链原生支持 TensorFlow SavedModel而对 PyTorch 需先转 ONNX 再转 XMODEL中间环节增加精度损失风险。当你要做联邦学习TensorFlow FederatedTFF的tff.learning.build_federated_averaging_process()直接封装了 FedAvg 算法而 PyTorch 的 Flower 框架需要用户手动实现 client update 和 server aggregation。所以与其问“该学 TensorFlow 还是 PyTorch”不如问“你的代码最终要跑在哪里”。如果目标是发论文、参加比赛PyTorch 是更短的路径如果目标是让模型在银行核心交易系统里稳定运行三年TensorFlow 提供的工程确定性仍是不可替代的。它不酷不炫但足够可靠——就像工业现场的 PLC 控制器没人讨论它有多“先进”但产线停一分钟损失就是百万。TensorFlow 的价值正在于此。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

系列教程-冰梭免费模式完整上手实录(游客篇 + 免费账号篇) 2026/9/30 14:20:11

系列教程-冰梭免费模式完整上手实录(游客篇 + 免费账号篇)

本文是一篇实录型教程:所有截图都来自作者用真实文件、真实账号一步一步操作得到的真实页面,没有摆拍,也没有任何推销话术。它专门回答"还没打算付费"的用户最关心的三个问题:1. 不注册,冰梭能干什么、不能干…

阅读更多 →
第028篇 LinkedList 与 ArrayList 选型——随机访问与插删的权衡 2026/9/30 14:20:04

第028篇 LinkedList 与 ArrayList 选型——随机访问与插删的权衡

摘要:本篇是《Android软件开发面试从入门到精通》第 28 篇,主题为「LinkedList 与 ArrayList 选型——随机访问与插删的权衡」。本篇聚焦「LinkedList 与 ArrayList 选型——随机访问与插删的权衡」:先回答它解决什么问题,再回答它怎么实现、代价是什么,收尾给出一套可复用…

阅读更多 →
Quarkus:简介、原理、实战 2026/9/30 14:18:52

Quarkus:简介、原理、实战

概述 官网,中文官网,几乎纯Java实现、开源(GitHub,15.9K Star,3.3K Fork)超音速、亚原子级框架。 支持与GraalVM集成,通过AOT(提前编译)方式将Java应用编译为原生可执行…

阅读更多 →
Unsloth Studio 扫描 PDF 本地 OCR 实战指南:Tesseract 配置、双引擎回退与失败诊断 2026/9/30 14:18:44

Unsloth Studio 扫描 PDF 本地 OCR 实战指南:Tesseract 配置、双引擎回退与失败诊断

人工智能大模型微调LoRA模型优化模型量化强化学习 【免费下载链接】unsloth Local UI to run and train LLMs and diffusion models. Supports GGUF, MLX, Qwen3.8, DeepSeek-V4, MiniMax-H3, Gemma 4, FLUX and more. 项目地址: https://gitcode.com/GitHub_Trendi…

阅读更多 →
多孩家庭选车,丰田智能电混双擎的第三排空间够用吗? 2026/9/30 14:18:35

多孩家庭选车,丰田智能电混双擎的第三排空间够用吗?

多孩家庭看丰田智能电混双擎,第三排空间够不够用,不能只看“七座”这个标签。以皇冠陆放、格瑞维亚等一汽丰田HEV车型为例,第三排更适合中短途乘坐,能解决“偶尔多带一两个孩子”的问题;但如果家里经常需要六到七人满员…

阅读更多 →
Java入门笔记:从字面量、变量到基本数据类型,一篇文章带你吃透! 2026/9/30 14:18:28

Java入门笔记:从字面量、变量到基本数据类型,一篇文章带你吃透!

Java 入门笔记日期: 9.26 字面量 ---- 怎么写 变量 ---- 怎么存 运算符 ---- 怎么算 📖今日知识点 ——字面量类型 1、整数类型 — 直接写(18,-88) 2、小数类型 — 直接写,加上小数点 (…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉