一道“过时”的面试题:HashMap 和 Hashtable 到底差在哪?

Qt-无标题窗口         今天学习了下无标题窗口,于是来记录下我的学习过程首先建立一个Qt Widgets Application继承QWidget类创建完后直接运行就得到了如下效果那么,既然是无标题窗口就要去掉窗口栏啊,于是加上setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint);去掉标题栏,但是这样整个窗口就不能移动... 阅读详情

一道“过时”的面试题:HashMap 和 Hashtable 到底差在哪?

Hashtable 是 1996 年 JDK 1.0 的产物。1998 年 JDK 1.2 引入集合框架后,它就被官方标注为过时的遗留类,但面试官几乎每次都问。

因为它能一口气串起四条主线:线程安全的实现方式、null 语义的取舍、容量与索引算法、迭代器的 fail-fast 机制。答得出来是及格,答得出“为什么这么设计”才是加分。

0. 先给面试答案(30 秒版)

HashMap 和 Hashtable 最核心的区别就是线程安全性。 Hashtable 的方法基本都加了 synchronized,是线程安全的,但代价是性能差;HashMap 没加锁,单线程下跑得快,但多线程环境得自己保证同步。

其他几个关键区别:

  1. 对 null 的处理不一样。HashMap 允许一个 null 键和多个 null 值,Hashtable 不让存 null,往里塞就抛 NullPointerException;
  2. 继承体系不同。HashMap 继承 AbstractMap,是正经的 Map 实现;Hashtable 继承的是古早的 Dictionary 类,虽然后来也实现了 Map 接口,但 Dictionary 早就被官方标注为过时(obsolete);
  3. 迭代器机制有差别。HashMap 用的是 fail-fast 的 Iterator,迭代时改结构直接抛 ConcurrentModificationException;Hashtable 的 keys()/elements() 返回的是老式 Enumerator,不做校验,改了结构也不一定报错——不过要注意,它的 keySet().iterator() 是 fail-fast 的(第 5 节有实测)。

容量算法(16 vs 11、位与 vs 取模)、hash 扰动这些也常被追问,扫一眼下面的速查表即可:

维度HashMapHashtable
引入版本JDK 1.2JDK 1.0
父类AbstractMapDictionary(官方标注已废弃)
线程安全❌ 不安全✅ 安全(方法级 synchronized,锁 this)
null 支持1 个 null key + 任意 null valuekey 和 value 都不允许
默认容量1611
扩容策略2 倍(保持 2 的幂)2n + 1(保持奇数)
索引计算(n - 1) & hash(hash & 0x7FFFFFFF) % length
hash 扰动有(h ^ (h >>> 16))无,直接用 key.hashCode()
迭代器fail-fastkeySet() 视图 fail-fast,keys()/elements() 不是

一句话记住:Hashtable 用一把锁把整个表锁住,安全但慢;HashMap 不锁所以快,但并发要自己管。

下面把每一条拆开,最后给几个实测数据。


1. 出身不同:一个 1998 年的遗留类

Hashtable 是 JDK 1.0 就有的类,比 Collection 框架还早两年。等到 JDK 1.2 引入集合框架时,官方才补了 HashMap,并顺手把 Hashtable 归入“不推荐使用”的历史遗留。

证据在 Dictionary 的 javadoc 里:

NOTE: This class is obsolete. New implementations should implement the Map interface, rather than extending this class.

Hashtable 恰恰继承了 Dictionary,所以它的位置很尴尬:

  • 它没有被 @Deprecated 标注(实测 Hashtable.class.isAnnotationPresent(Deprecated.class) 返回 false),所以编译不报警;
  • 但文档明确说“新实现应该实现 Map 接口,而不是继承这个类”。

命名也不规范。 按 Java 命名约定应该是 HashTable,而 Hashtable 把 t 写成了小写——这是 JDK 1.0 时代命名规范尚未定型留下的历史包袱。

方法名更让人困惑:

Hashtable<String, String> ht = new Hashtable<>();
ht.put("a", "v");
System.out.println(ht.contains("v"));    // true —— 它其实是 containsValue!

contains(Object) 判断的是值是否存在,和直觉完全相反。HashMap 干脆删掉了这个方法,只保留 containsKey 和 containsValue,从 API 设计上消灭了歧义。


2. 线程安全:一把锁锁住整张表

实证数据: 反射统计 Hashtable 的 36 个 public 方法,其中 26 个带 synchronized。

public synchronized V put(K key, V value) { ... }
public synchronized V get(Object key) { ... }
public synchronized V remove(Object key) { ... }

锁对象是 this,也就是说整张表共用一把锁。带来三个后果:

  1. 读也被阻塞:线程 A 在 put,线程 B 的 get 必须等——哪怕它们操作的是完全不同的桶;
  2. 单线程也要付锁开销:synchronized 在无竞争时虽然已优化到偏向锁/轻量级锁,但仍有对象头操作和内存屏障的成本;
  3. 并发吞吐极差:线程数一上来,全部退化成串行。

但它是“线程安全”的吗?打引号

if (!ht.containsKey(key)) {     // ① 检查
    ht.put(key, value);         // ② 写入
}

①和②是两个独立的原子操作,中间完全可能被其他线程插入。「先检查再操作」的复合逻辑,Hashtable 保证不了。

想要真正的原子性,因为锁就是 this,可以自己再套一层:

synchronized (ht) {
    if (!ht.containsKey(key)) {
        ht.put(key, value);
    }
}

这算 Hashtable 的一个便利:它的锁对象就是容器本身(this),所以外部可以直接 synchronized (ht) 把多个操作打包成一个原子块。Collections.synchronizedMap 同理——锁就是包装后返回的那个对象,遍历时同样要 synchronized (syncMap)。

但这也是把双刃剑:任何持有该引用的代码都能锁住整张表,一旦有人写了 synchronized (ht) { 耗时操作 },全表都会被拖住。这是“锁对象公开”的代价。


3. null 语义:为什么 Hashtable 一个都不让放

Hashtable<String, String> ht = new Hashtable<>();
ht.put("k", null);    // NullPointerException
ht.put(null, "v");    // NullPointerException

实测两者的 NPE 来源还不一样:

调用异常位置原因
put("k", null)Hashtable.put:476显式检查:if (value == null) throw new NullPointerException();
put(null, "v")Hashtable.put:481隐式:执行 key.hashCode() 时空指针

而 HashMap 允许 1 个 null key + 任意多个 null value:

HashMap<String, String> hm = new HashMap<>();
hm.put(null, null);
hm.put("a", null);
System.out.println(hm.size());   // 2

为什么 HashMap 允许 null key? 因为它的 hash 计算对 null 做了特殊处理:

static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

null key 的 hash 恒为 0,固定落在 0 号桶。putVal 里的判断也随之兼容:

if (p.hash == hash &&
    ((k = p.key) == key || (key != null && key.equals(k))))

当 key == null 时,p.key == key 直接命中(null == null 为 true),equals 根本不会被调用,不会 NPE。

那 ConcurrentHashMap 为什么也不允许 null?

这是这道题最能拉开差距的追问:

并发场景下,get(key) 返回 null 会产生二义性——无法区分是“这个 key 不存在”,还是“这个 key 存在但值是 null”。

单线程下可以用 containsKey 再确认一次,但在并发环境里,containsKey 和 get 之间状态可能已经变了,两次调用不具备原子性,这个确认本身不可靠。

ConcurrentHashMap 的设计从源头上拒绝 null,就是为了避免这种“看起来能判断、实际判断不准”的陷阱——它的 javadoc 也明确写着:与 Hashtable 一样,不允许 null key 和 null value。

引申的实践建议: 业务代码里也尽量别用 null 当值。如果必须表达“空”,用 Optional 或空对象模式,比 map.get(k) == null 安全得多。


4. 容量与扩容:11 和 16,差的不是数字而是算法

HashMapHashtable
默认初始容量1611
负载因子0.750.75
扩容公式newCap = oldCap * 2newCap = oldCap * 2 + 1
扩容后容量16 → 32 → 6411 → 23 → 47

实测扩容序列(反射读取 table 数组长度):

HT default table   : 11
HT table after put : 11
HT table grown     : 47 (size=31)

为什么 HashMap 坚持 2 的幂

因为它的索引是 (n - 1) & hash。只有 n 是 2 的幂时,n - 1 的二进制才是全 1,位与运算才等价于取模,且能完整保留低位信息。传非 2 的幂进去,构造器也会用 tableSizeFor 向上取整。

为什么 Hashtable 用 11 和 2n+1

因为它用的是取模,不需要 2 的幂:

int index = (hash & 0x7FFFFFFF) % tab.length;

(& 0x7FFFFFFF 是为了把负的 hash 变成正数,否则 % 会得到负索引。)

  • 初始容量选 11:11 是质数,取模后分布更均匀,减少冲突;
  • 扩容选 2n+1:保持容量始终是奇数,避免 hash % n 在 n 为偶数时产生的规律性聚集。

性能对比: 位与(&)确实比取模(%)快,但这点差异在现代 CPU 上微乎其微。Hashtable 真正的性能问题不在容量算法,而在锁——即使索引算得再快,26 个 synchronized 方法也会把并发性能卡死。


5. 一个实测出来的意外:两个迭代器行为不同

这是写这篇文章时最有意思的发现。

Hashtable<String,String> ht = new Hashtable<>();
for (int i = 0; i < 5; i++) ht.put("k" + i, "v" + i);

// 方式一:keySet().iterator()
for (String k : ht.keySet()) { ht.put("x" + k, "y"); }

// 方式二:keys() 返回的 Enumeration
Enumeration<String> en = ht.keys();
while (en.hasMoreElements()) {
    String k = en.nextElement();
    ht.put("x" + k, "y");
}

JDK 21 实测输出:

keySet()  + 遍历中修改 : java.util.ConcurrentModificationException
keys()    + 遍历中修改 : 无异常,size = 12

同一个类,两种迭代方式,行为完全相反。

原因在 Hashtable.Enumerator 的构造参数:

// 简化示意
Enumerator(Hashtable<K,V> table, boolean iterator) {
    ...
    this.expectedModCount = iterator ? table.modCount : 0;  // 只有 iterator 模式才记录
}
  • keySet() / entrySet() 走的是 Iterator 模式(iterator = true),每次 next() 校验 modCount,改了结构就抛 CME —— 这就是 fail-fast;
  • keys() / elements() 返回的是老式 Enumeration(iterator = false),不做校验,遍历期间修改不报错,但可能读到重复或已删除的元素,结果不确定。

这个差异的实际影响:

老项目里用 keys() 遍历 Hashtable 一直相安无事,某天重构把它改成 keySet(),突然开始偶发 ConcurrentModificationException——这不是 bug,是行为变了。

正确姿势(两种都一样):遍历 Hashtable 必须自己加锁。

synchronized (ht) {
    for (String k : ht.keySet()) { ... }
}

因为迭代器本身不持有锁,它只是在读 table 数组,其他线程随时可能 rehash 把数组换掉。

最后一句话记住:fail-fast 是“尽力检测”,不是“并发安全保障”。 它只能帮你尽早发现误用,不能替代同步。


6. 三个容易踩的 API 陷阱

6.1 contains() 判的是值

ht.contains("v")    // 等价于 containsValue("v")

想知道 key 在不在,用 containsKey。这个命名坑在维护老代码时很常见。

6.2 putAll 可能半途失败

Hashtable<String,String> ht = new Hashtable<>();
Map<String,String> src = new HashMap<>();
src.put("a", "1");
src.put("b", null);      // 这一条会让 putAll 中途抛 NPE
ht.putAll(src);          // 结果:ht 里有 "a",没有 "b"

部分写入成功——putAll 没有事务性。从 HashMap 迁移数据到 Hashtable 时,如果源数据里有 null 值,就会遇到这种“半个表”的状态。

6.3 Dictionary 不是 Map

Hashtable 实现的是 Map 接口(JDK 1.2 后补的),但它同时继承了 Dictionary。所以它能被当成 Map 用,但 Dictionary 类型本身没有 entrySet()、keySet() 这些现代 API。老代码里如果变量声明成 Dictionary,能调的方法非常有限。


7. 现在到底该怎么选

场景选择理由
单线程HashMap无锁开销,性能最好
多线程读写ConcurrentHashMap桶级锁 + CAS,读几乎无锁
需要存 null 值HashMapHashtable 和 CHM 都不允许
已有 Map 要加同步Collections.synchronizedMap能包装任意 Map,但同样是全表锁
遍历时要强一致自己加锁或用快照任何并发 Map 的迭代器都是弱一致
遗留代码保持,逐步替换直接换会踩 null 和 contains 的坑

为什么 Collections.synchronizedMap 也不推荐? 它和 Hashtable 本质相同——都是对整张表加同一把锁,并发性能和 Hashtable 一个水平,只是锁对象可由你指定。

ConcurrentHashMap 的迭代器是弱一致的:遍历时不阻塞、不抛 CME,但不保证看到最新的写入。这是并发容器“用一致性换吞吐”的典型设计。


8. 高频追问 10 连

Q1:Hashtable 是线程安全的吗?
单个方法是(synchronized),但复合操作不是。“先判断再操作”必须自己 synchronized (ht) 包起来。

Q2:为什么初始容量是 11?
历史遗留 + 取模算法需要质数。11 是质数,hash % 11 分布均匀。换成 16 也不会错,只是冲突率略变。

Q3:为什么扩容是 2n + 1?
保持容量始终为奇数,避免偶数容量在取模时产生的规律性聚集。

Q4:ConcurrentHashMap 为什么比 Hashtable 快?
Hashtable 是整表一把锁;CHM 在 JDK 7 是分段锁,JDK 8 起是 CAS + synchronized 锁单个桶的头节点,锁粒度细化到桶级别,读操作基本无锁。

Q5:HashMap 的 null key 存在哪个桶?
0 号桶,因为 hash(null) 返回 0。

Q6:为什么 ConcurrentHashMap 不允许 null?
并发下 get 返回 null 无法区分“键不存在”和“值为 null”,而 containsKey 与 get 之间没有原子性,这个判断不可靠,会产生隐蔽的并发 bug。

Q7:把 Hashtable 换成 HashMap 要注意什么?
三件事:① null 语义变了(Hashtable 拒绝,HashMap 接受,可能把原本的 NPE 变成“悄悄存入”);② contains(v) 要改成 containsValue(v);③ 同步要靠调用方自己保证。

Q8:Dictionary 和 Map 什么区别?
Dictionary 是抽象类,Map 是接口。Dictionary 已被官方标注 obsolete,新的实现都应该实现 Map。

Q9:为什么现在还会被问到 Hashtable?
因为它是一道“活化石题”——由它引出线程安全、null 语义、扩容算法、fail-fast 四个知识点,考察成本低、区分度高。

Q10:HashMap 线程不安全的具体表现是什么?
并发 put 丢数据、JDK 7 扩容头插法成环导致 get 死循环、size 计数不准。这三点展开就是下一篇的内容。


9. 3 分钟答题模板

  1. 结论:Hashtable 是 JDK 1.0 的遗留类,方法级 synchronized,整表一把锁;HashMap 是 JDK 1.2 的替代品,不保证线程安全但性能好得多;
  2. 差异:分四条讲——线程安全(全表锁 vs 无锁)、null(都不允许 vs 允许 1 个 null key)、容量(11 取模 vs 16 位与)、迭代器(Enumeration vs fail-fast Iterator);
  3. 为什么淘汰:全表锁导致并发退化成串行,现代场景用 ConcurrentHashMap;
  4. 加分:提一句“Hashtable 的 keys() 不是 fail-fast,keySet() 才是”,以及“CHM 拒绝 null 是为了避免并发二义性”。

小结

Hashtable          → JDK 1.0,继承 Dictionary,全表 synchronized
HashMap            → JDK 1.2,AbstractMap,无锁但高性能
null               → HT 全拒绝;HM 允许 1 个 null key(0 号桶)
容量               → HT: 11 起步,2n+1,取模;HM: 16 起步,2 倍,位与
迭代器             → HT: keys() 不 fail-fast,keySet() fail-fast
现代替代           → ConcurrentHashMap

实测环境:JDK 21.0.8(Windows),反射部分通过 --add-opens java.base/java.util=ALL-UNNAMED 读取内部 table 字段。

下一篇拆 「synchronized 和 ReentrantLock 的区别」——一个关键字一个类,为什么 ReentrantLock 能中断、能超时、能公平,以及为什么 JDK 6 之后「synchronized 慢」这个结论已经过期了。


C# 移动无标题栏无边框窗体的3种方法 目录 第一种:手工移动 第二种:调用系统API 1.引入下面代码 前提需要引入命名空间using System.Runtime.InteropServices 2.增加鼠标按下事件发送消息,让系统误以为按下是标题栏 第三种,重写 WndProc 第一种:手工移动 直接通过修改窗体位置从而达到移动窗体的效果 //定义一个位置信息Point用于存储鼠标位置 private Point mPoint; /// <summary> 阅读详情

相关推荐

从‘炼丹’到‘讲理’:物理信息神经网络(PINN)的硬约束 vs 软约束,我该选哪个?

本文深入探讨了物理信息神经网络(PINN)中硬约束与软约束的选择策略,帮助研究者在深度学习中有效融入物理先验知识。通过对比两种约束方法的实现复杂度、数据效率和计算性能,提供了针对材料科学和流体动力学等领域的实用决策指南,并介绍了自适应约束和混合约束等前沿技术。

weixin_42535703的博客 519

Delphi无标题窗体增强功能实现:让无标题窗体更具交互性

Delphi无标题窗体增强功能实现:让无标题窗体更具交互性 去发现同类优质开源项目:https://gitcode.com/ 项目介绍 在软件开发领域,Delphi 语言因其高效的执行速度和清晰的语法结构,一直受到开发者的喜爱。然而,在使用无标题窗体(borderstyle=bsnone)时,开发者常常面临一个问题:用户无法通过常规方式来移动或调整窗体大小。本项目正是为了解决这一难题而诞生,它提供...

gitblog_06708的博客 992

电脑的kernelbase.dll故障怎么处理?kernelbase.dll是什么文件

kernelbase.dll​是一个系统文件,属于Microsoft Windows操作系统的一部分。该DLL(动态链接库)文件包含了许多基本且低级的系统函数,这些函数被Windows上运行的各种程序和进程调用。kernelbase.dll通常与Kernel32.dll紧密相关,它是实现许多Windows API(应用程序编程接口)的封装。这些API涉及到内存管理、输入输出操作、进程和线程管理以及其他许多核心的操作系统功能。

电脑修复君的博客 4520

无标题栏窗口拖动的实现

普通的Windows应用程序窗口都具有统一的窗口风格,它们一般都包括:用户区和非用户区两部分。非用户区包括标题条、窗口边框、最大化按钮、最小化按钮、关闭按钮和系统默认的快捷键及鼠标支持等。利用鼠标的左键通过拖动窗口的标题条可以在屏幕上任意移动整个窗口,当光标停止在窗口边框上时可以改变窗口的大小。在一些比较经典的软件中,有一类特殊的无标题条的窗口。这种窗口不需要改变窗口的大小,但必须具有窗口客户区域

ArduousBonze的专栏 4036

adams案例分析_案例1(麦弗逊悬架子系统创建)

本文字数3292字83图,建议阅读时间26分钟首先看下案例1的麦弗逊悬架数模结构就不细讲了,从数模上主要是获取硬点坐标(铰接点、安装点、参考点)及大部件结构(副车架、摆臂、转向节等实际运动过程中会产生变形的部件,在ADAMS Car中我们就可以用柔性体来搭建)再来回顾下上一篇讲到的模型元素1、Hardpoint——硬点(只有位置没有方向)2、Parameter Variable——参数...

weixin_39609407的博客 6459

threejs加载3dtiles(倾斜摄影)数据

1、安装3dTilesRenderer 插件 使用npm 安装 npm install 3d-tiles-renderer --save 或者去官网下载都行 GitHub - NASA-AMMOS/3DTilesRendererJS: Renderer for 3D Tiles in Javascript using three.js 2、使用 首先引入,在填入3dtiles数据的地址,可以是文件路径也可以是网站路径 const tilesRenderer = new TilesRend..

weixin_39481659的博客 1万+

无标题窗口的拖动

普通的Windows应用程序窗口都具有统一的窗口风格,它们一般都包括:用户区和非用户区两部分。非用户区包括标题条、窗口边框、最大化按钮、最小化按钮、关闭按钮和系统默认的快捷键及鼠标支持等。利用鼠标的左键通过拖动窗口的标题条可以在屏幕上任意移动整个窗口,当光标停止在窗口边框上时可以改变窗口的大小。在一些比较经典的软件中,有一类特殊的无标题条的窗口。这种窗口不需要改变窗口的大小,但必须具有窗口客户区域

lianxiao1314的专栏 985

QT+Halcon实现螺纹检测

工业上要检测螺丝的内外直径、内外牙距、内外角度,现在比较好用的图像处理库,开源的opencv,收费的有halcon。为了实现螺纹检测,和对比螺纹检测拿个库比较好。分别用opencv和halcon实现了螺纹检测,通过对比发现用halcon实现的效果比较。现在用博客把实现过程记录下来: 1、需要检测的螺纹数据如下: 2、为了实现检测螺丝以上数据,螺纹内径、螺纹外径、螺纹外牙距、螺纹...

专注现代C++实战,从核心语法到高性能编程,助力开发者深入掌握系统级编程精髓。 7047

C#拖动无标题栏窗体

很长时间没有写博客了,今天又解决并测试通过了一个Delphi很简单的问题——无标题栏窗体的拖动 。其实是个很简单的问题,但是还是想写下来,一方面加深自己的记忆,一方面与朋友们分享!DeviceAnywhere在Ioicn发布了,反响似乎一般,我想是因为.net FrameWork环境的问题吧,希望Microsoft再出sp的时候把.net FrameWorkx.x集成到操作系统里吧,这样大家都方便

Windows Mobile 开发历险 1951

计算机视觉与深度学习 | 2024年至2025年图像匹配算法总结(原理,公式,代码,开源链接)

以上总结覆盖了当前主流和前沿技术,实际选择需结合具体场景(速度/精度/资源限制)评估。

尘世冰封的专栏 1571

使用 MATLAB/Simulink + Simscape Electrical + Simulink Design Optimization,构建一个沙漠环境中光伏组件灰尘积累与效率下降仿真模型

本文通过,构建了沙漠环境中光伏组件灰尘积累与效率下降仿真模型✅ 建立了风速-沙尘-积尘速率的物理关系✅ 仿真了灰尘积累过程及其对Isc 和 Pmax的影响✅ 量化分析了不同清洁策略的经济性✅ 提出了优化设计与智能运维建议。

xiaoheshang_123的博客 114

android设置activity全屏 | 无标题

1.设置activity无标题 方法一: 在Manifest.xml中为activity增加属性:  android:theme="@android:style/Theme.NoTitleBar" 方法二: 在activity的onCreate()中加入:requestWindowFeature(Window.FEATURE_NO_TITLE); 2.设置activity全屏

CNnumen 1万+

微信小程序逆向实战:从HTTPS抓包到API接口全解构

方案原理优点缺点方案一:使用低版本微信+系统代理微信7.0以下版本未强制不走代理操作简单容易被封号,无法使用新版小程序方案二:Hook SSL层(Xposed/Frida)动态Hook Java的TrustManager或系统的SSLContext,绕过证书校验灵活可控需要Root/越狱,技术门槛高方案三:VPN转发抓包(PacketCapture)利用Android VPNService将所有流量转发到本地代理无需Root,兼容性好部分机型存在性能问题。

2201_76125261的博客 261

Android应用设置无标题栏的实现方式

去掉标题栏   第一,在代码中实现; requestWindowFeature(Window.FEATURE_NO_TITLE); 代码要写在setContentView()前。 第二,在xml文件中进行配置; 调用系统自带的样式; 实现全屏效果: android:theme="@android:style/Theme.NoTitleBar.Fullscree

三颗猴面包树 1495

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

C#中的无标题栏窗体

所以谓的无标题栏窗体,与标题无关,看边框设置将窗体的FormBorderStyle属性设置为None就可以了,其它的一些属性只是一些显示样式.关于无标题栏窗体的拖动就用傻办法,至少我看到的都是这样的.关于这一方面的介绍不少,我就不在这里缀述了,如果有想要示例的,可以留下邮箱.

fqlove的专栏 1440

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

delphi技巧——移动无标题窗口

 delphi技巧——移动无标题窗口关键词:移动,消息,无标题                      作者:朱能文   我们都知道windows是通过标题栏来移动窗体的,当我们在标题栏上按下鼠标左键时,windows将发送wM_NCHitTest消息,来告诉系统要移动窗体。但我们在实际编程时,有时为了界面的需要或特殊的要求,窗体没有标题栏,我们必须通过程序来移动窗体。下面我将介

nwen的专栏 1276

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

android 设置为无标题,android无标题全屏的三种设置方式

注意,在设置前把XXX-Activity extends ActionBarActivity 修改成XXX-Activity extends Activity,否则activity无法启动1.在onCreat方法中setContentView()之前插入//设置无标题requestWindowFeature(Window.FEATURE_NO_TITLE);//设置全屏getWindow().s...

weixin_35398679的博客 816

移动无标题栏的窗口-java

import java.awt.Point; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener;

Ymy2011的专栏 588

Delphi 无标题窗体增强功能实现

Delphi 无标题窗体增强功能实现 去发现同类优质开源项目:https://gitcode.com/ 资源简介 本资源提供了一种在 Delphi 开发环境中对无标题窗体(borderstyle=bsnone)进行增强的方法。默认情况下,无标题窗体不显示边框,用户无法通过常规方式移动或调整窗体大小。本资源通过特定的技术手段,为无标题窗体添加了边框,同时实现了窗体的拖拽调整大小和移动位置的功能。 功...

gitblog_06743的博客 423

Android 设置无标题栏(全屏)的两种方式

Android开发中,新建一个Activity默认情况会显示Title栏,如下图状态栏下层的应用图标和应用名。为了美观,我们通常会设置Activity无标题来隐藏Tittle栏。                                                                                             设置Activity无标题的方式

ArielYu's Blog 3522

【无标题】

今天在练习自定义标题栏(Android初级开发(四)——补充3)的过程中遇到了隐藏系统自带标题栏的问题,现将几种去掉系统自带标题栏的方式做一总结。大体上可以分为两种方式,一种是修改xml文件(这种方式产生的效果作用于所有Activity),一种是编码实现(这种方式产生的效果只作用于当前Activity): 方法1-1: 1、查看清单文件AndroidManifest.xml中的theme android:theme="@style/AppTheme"(系统默认的)保...

xujingcheng123的博客 151

android手机设置无标题后,程序挂掉 解决 (如何用最简短语句设置 手机 全屏无标题)

手机设置无标题后,总是挂掉,最初以为是布局的问题,换了还是不中,然后新建一个工程,发现还是不中!怎么回事?我以前是搞过着的啊,原来设置全屏无标题,这些语句一定要设在setContentView前面!谨记啊! 还是对这些知识不熟悉,所以我写到这,复习下! 设置无标题+全屏: requestWindowFeature(Window.FEATURE_NO_TITLE); int flag = Wi

yanzi1225627的专栏 3021

android ActionBarActivity设置全屏无标题

新建的Activity继承自ActionBarActivity,设置全屏无标题本来很简单的事,但是没想到app竟然无缘无故的挂,要么就是白屏一片,要么就是黑屏。坑了我一个多小时!!! 原因是ActionBarActivity设置theme的时候只能使用v7包里的Theme.AppCompat***开头的主题,因此设置全屏无标题的话需要自定义个style: name="ActionBar

奥特曼超人的博客专栏 2268

Android设置无标题窗口

在android中,有的时候要做一个无标题的窗口,包括没状态栏的,有两种方法实现:  1 在XML配置文件中:             package="de.vogella.android.temperature"        android:versionCode="1"        android:versionName="1.0">

Bottle's Blog 6万+

界面_无标题窗口的移动

使用OnNcHitTest消息实现无标题窗口的移动////////////////////////////////////////////////////////////UINT myWnd::OnNcHitTest(CPoint point){ // TODO: 在此添加消息处理程序代码和/或调用默认值 // rect 指定,鼠标点在什么地方时,可以移动窗口 // 其实就是把这部分区域当成是 标

2046
上一篇: 一道必考题讲透:`==` 与 `equals`,以及为什么重写 equals 必须重写 hashCode
上进的XJL
博客等级 码龄2年 0粉丝 2原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值