目录
第1章 成为程序员 1.1 选择编程语言 1.2 告诉计算机做什么 1.3 程序的工作原理 1.4 为什么程序不能正常工作 1.5 选择 Java编程工具 1.6 安装 Java开发工具 1.7 总结 1.8 问与答 1.9 测验 1.9.1 问题 1.9.2 答案 1.10 练习 第2章 编写第一个程序 2.1 编写程序所需的工具 2.2 创建 Saluton 程序 2.3 开始输入程序 2.3.1 class语句 2.3.2 main语句的作用 2.3.3 大括号 2.4 在变量中存储信息 2.5 保存编写好的程序 2.6 将程序编译为 class文件 2.7 修复错误 2.8 运行 Java程序 2.9 总结 2.10 问与答 2.11 测验 2.11.1 问题 2.11.2 答案 2.12 练习 第3章 Java之旅 3.1 第一站:Oracle 3.2 去 Java学校 3.3 在 JavaWorld 用午餐 3.4 在 NASA仰望天穹 3.5 回归正题 3.6 到 Java Boutique 去问路 3.7 在手机上运行 Java 3.8 总结 3.9 问与答 3.10 测验 3.10.1 问题 3.10.2 答案 3.11 练习 第4章 理解Java程序的工作原理 4.1 创建应用程序 4.2 向应用程序传递参数 4.3 创建 applet 4.4 总结 4.5 问与答 4.6 测验 4.6.1 问题 4.6.2 答案 4.7 练习 第5章 在程序中存储和修改信息 5.1 语句和表达式 5.2 指定变量类型 5.2.1 整数和浮点数 5.2.2 字符和字符串 5.2.3 其他数值类型的变量 5.2.4 布尔型变量 5.3 给变量命名 5.4 在变量中存储信息 5.5 运算符 5.5.1 变量的递增与递减 5.5.2 运算符优先级 5.6 使用表达式 5.7 总结 5.8 问与答 5.9 测验 5.9.1 问题 5.9.2 答案 5.10 练习 第6章 使用字符串来交流 6.1 在字符串中存储文本 6.2 在程序中显示字符串 6.3 在字符串中使用特殊字符 6.4 拼接字符串 6.5 将其他变量用于字符串中 6.6 字符串的高级处理 6.6.1 比较两个字符串 6.6.2 确定字符串的长度 6.6.3 改变字符串的大小写 6.6.4 查找字符串 6.7 导演及演员名单 6.8 总结 6.9 问与答 6.10 测验 6.10.1 问题 6.10.2 答案 6.11 练习 第7章 使用条件测试进行判断 7.1 if语句 7.1.1 小于和大于的比较 7.1.2 相等和不等 7.1.3 使用块语句组织程序 7.2 if-else 语句 7.3 switch语句 7.4 条件运算符 7.5 观察时钟 7.6 总结 7.7 问与答 7.8 测验 7.8.1 问题 7.8.2 答案 7.9 练习 第8章 使用循环重复执行操作 8.1 for循环 8.2 while 循环 8.3 do-while 循环 8.4 退出循环 8.5 给循环命名 8.6 测试计算机的运行速度 8.7 总结 8.8 问与答 8.9 测验 8.9.1 问题 8.9.2 答案 8.10 练习 第9章 使用数组存储信息 9.1 创建数组 9.2 使用数组 9.3 多维数组 9.4 对数组进行排序 9.5 对字符串中的字符计数 9.6 总结 9.7 问与答 9.8 测验 9.8.1 问题 9.8.2 答案 9.9 练习 第10章 创建第一个对象 10.1 面向对象编程的工作原理 10.2 对象示例 10.3 什么是对象 10.4 理解继承 10.5 建立继承层次 10.6 转换对象和简单变量 10.6.1 简单变量的类型转换 10.6.2 对象类型转换 10.6.3 在简单变量和对象之间进行转换 10.6.4 自动封装和拆封 10.7 创建对象 10.8 总结 10.9 问与答 10.10 测验 10.10.1 问题 10.10.2 答案 10.11 练习 第11章 描述对象 11.1 创建变量 11.2 创建类变量 11.3 用方法来创建行为 11.3.1 声明方法 11.3.2 参数不同的类似方法 11.3.3 构造函数 11.3.4 类方法 11.3.5 方法中变量的作用域 11.4 将一个类放在另一个类中 11.5 使用关键字this 11.6 使用类方法和类变量 11.7 总结 11.8 问与答 11.9 测验 11.9.1 问题 11.9.2 答案 11.10 练习 第12章 充分利用现有对象 12.1 继承的威力 12.1.1 继承行为和属性 12.1.2 覆盖方法 12.2 建立继承 12.3 使用现有的对象 12.4 将相同类型的对象存储到 Vector 中 12.5 创建子类 12.6 总结 12.7 问与答 12.8 测验 12.8.1 问题 12.8.2 答案 12.9 练习 第13章 创建简单的用户界面 13.1 Swing 和抽象窗口工具包 13.2 使用组件 13.2.1 窗口和框架 13.2.2 按钮 13.2.3 标签和文本框 13.2.4 复选框 13.2.5 组合框 13.2.6 文本区域 13.2.7 面板 13.3 创建自己的组件 13.4 总结 13.5 问与答 13.6 测验 13.6.1 问题 13.6.2 答案 13.7 练习 第14章 用户界面的布局 14.1 使用布局管理器 14.1.1 GridLayout管理器 14.1.2 BorderLayout管理器 14.1.3 BoxLayout管理器 14.1.4 使用Insets将组件隔开 14.2 应用程序的界面布局 14.3 总结 14.4 问与答 14.5 测验 14.5.1 问题 14.5.2 答案 14.6 练习 第15章 响应用户输入 15.1 让程序监听 15.2 设置要监听的组件 15.3 处理用户事件 15.3.1 复选框和组合框事件 15.3.2 键盘事件 15.3.3 启用和禁用组件 15.4 完善图形应用程序 15.5 总结 15.6 问与答 15.7 测验 15.7.1 问题 15.7.2 答案 15.8 练习 第16章 创建复杂的用户界面 16.1 滚动窗格 16.2 滑块 16.3 变更监听器 16.4 使用图像图标和工具栏 16.5 总结 16.6 问与答 16.7 测验 16.7.1 问题 16.7.2 答案 16.8 练习 第17章 创建交互式Web程序 17.1 标准applet方法 17.1.1 在applet窗口中绘画 17.1.2 初始化applet 17.1.3 启动和停止applet 17.1.4 销毁applet 17.2 将applet放到Web页面中 17.3 创建applet 17.3.1 在applet窗口中绘画 17.3.2 测试SalutonApplet程序 17.4 从Web页面传递参数 17.5 在applet中接收参数 17.6 在applet中处理参数 17.7 使用object标记 17.8 总结 17.9 问与答 17.10 测验 17.10.1 问题 17.10.2 答案 17.11 练习 第18章 处理程序中的错误 18.1 异常 18.1.1 在try-catch块中捕获异常 18.1.2 捕获多种不同的异常 18.1.3 出现异常后进行处理 18.1.4 抛出异常 18.1.5 忽略异常 18.2 抛出和捕获异常 18.3 总结 18.4 问与答 18.5 测验 18.5.1 问题 18.5.2 答案 18.6 练习 第19章 创建线程程序 19.1 线程 19.1.1 降低程序的速度 19.1.2 创建线程 19.2 使用线程 19.2.1 声明类 19.2.2 创建变量 19.3 从init( )开始 19.4 在创建URL时捕获错误 19.5 在paint( )方法中处理屏幕更新 19.6 启动线程 19.6.1 运行线程 19.6.2 停止线程 19.7 处理鼠标单击 19.8 循环显示链接 19.9 总结 19.10 问与答 19.11 测验 19.11.1 问题 19.11.2 答案 19.12 练习 第20章 读写文件 20.1 流 20.1.1 文件 20.1.2 从流中读取数据 20.1.3 缓冲输入流 20.2 将数据写入流中 20.3 读写配置属性 20.4 总结 20.5 问与答 20.6 测验 20.6.1 问题 20.6.2 答案 20.7 练习 第21章 读写XML数据 21.1 创建XML文件 21.2 读取XML文件 21.3 读取 RSS 聚合内容(Syndication Feeds) 21.4 总结 21.5 问与答 21.6 测验 21.6.1 问题 21.6.2 答案 21.7 练习 第22章 利用JAX-WS开发Web服务 22.1 定义服务端点接口 使用注解来简化Java代码 22.2 创建服务实现Bean 22.3 发布Web服务 22.4 使用Web服务描述语言文件 22.5 创建Web服务客户端 22.6 总结 22.7 问与答 22.8 测验 22.8.1 问题 22.8.2 答案 22.9 练习 第23章 创建Java2D图形 23.1 使用Font类 23.2 使用Color类 23.3 创建自定义颜色 23.4 绘制直线和形状 23.4.1 绘制直线 23.4.2 绘制矩形 23.4.3 绘制椭圆和圆 23.4.4 绘制弧线 23.5 绘制饼图 23.6 总结 23.7 问与答 23.8 测验 23.8.1 问题 23.8.2 答案 23.9 练习 第24章 编写Android app 24.1 Android简介 24.2 创建 Android app 24.2.1 剖析一个Android新项目 24.2.2 创建app 24.2.3 安装Android模拟器 24.2.4 创建调试配置 24.3 运行app 24.4 设计真实的app 24.4.1 组织资源 24.4.2 配置app的Manifest文件 24.4.3 设计用户界面 24.4.4 编写Java代码 24.5 总结 24.6 问与答 24.7 测验 24.7.1 问题 24.7.2 答案 24.8 练习 附录A 使用NetBeans IDE A.1 安装NetBeans A.2 创建新项目 A.3 创建新的Java类 A.4 运行应用程序 A.5 修复错误 附录B Java资源 B.1 可以考虑的其他书 B.2 Oracle公司的 Java官方站点 B.3 其他Java站点 B.3.1 本书英文版的配套网站 B.3.2 Café au Lait B.3.3 Workbench B.3.4 Java 7 Developer Blog B.3.5 其他Java博客 B.3.6 InformIT B.3.7 Stack Overflow B.3.8 Java Review Service B.3.9 JavaWorld杂志 B.3.10 Developer.com’s Java Directory 附录C 本书站点 附录D 设置Android开发环境 D.1 起步 D.2 安装Eclipse D.3 安装 Android SDK D.4 安装在Eclipse中使用的Android插件 D.5 设置你的手机 其他 版权

Java初级教程

Java入门经典
第9章 使用数组存储信息

本章介绍如下内容:

创建数组;

设置数组的大小;

为数组元素赋值;

修改数组中的信息;

创建多维数组;

数组排序。

在计算机的发展历程之中,圣诞老人从中获得的便利要比所有人都多。几个世纪以来,人们要求他收集并处理大量的信息。年事已高的圣诞老人还必须记录下列信息:

淘气的孩子;

好孩子;

需要的礼物;

带无通路烟囱的家;

希望圣诞老人(而不是圣诞老人的老婆)满足她们愿望的妇女;

先对其坐骑拍照留念,然后再提需求的国家。

在北极,计算机是最实用的东西,它非常适合用于对信息进行存储、分类和研究。

在计算机程序中存储信息的最基本方式是,将它放在变量中。淘气孩子的名单就是一组类似的信息。可以使用数组来记录这种名单。

数组是一组类型相同的相关变量,可以在数组中存储任何类型的信息,就像在变量中存储信息一样。与单个变量相比,数组可记录更复杂的信息,但创建和使用数组同变量一样简单。

9.1 创建数组

数组是名称相同的一组变量,读者可能熟悉术语“数组”,读者应该很熟悉数组——想象一个销售人员展示的一系列产品,或者是具有一系列令人眼花的奖品的游戏。与变量一样,创建数组也要指出存放在数组中的变量类型以及数组名,不同之处在于多加了一对方括号:“[”和“]”。

像变量一样,可以创建存放任何类型信息的数组。例如,下面的语句创建一个字符串数组:

下面是另外两个例子:

注意:

在创建数组时,Java 在方括号的位置方面比较灵活,可以将方括号放在变量名后面,而不是放在变量类型的后面,如下所示:

String niceChild[];

为了使程序中的数组更容易理解,应在程序中统一使用一种格式,而不是两种格式都用。在本书的示例中,都是将方括号放在变量类型的后面。

前面的例子创建了数组,但是其中没有存储任何值。为此,可以使用包含变量类型名的new语句,或者将初始值放在大括号“{”和“}”之间。当使用new关键字时,还必须指定数组包含多少项,数组中的项被称为元素。下面的语句创建一个数组,并为其将存储的值预留空间:

该例子创建了一个名为elfSeniority的整型数组,该数组包含250个元素,这些元素用于存储圣诞老人的每个淘气孩子到北极的月份。如果圣诞老人运营一个联盟商店,记录这个信息将很重要。

使用new语句创建数组时,必须指定元素的个数。而且数组中的每个元素都将赋给初始值,初始值取决于数组的类型。对于所有数值型数组,初始值为 0,字符型数组的初始值为‘\0’,布尔型数组的初始值为false,字符串数组和所有其他对象数组的初始值为null。

对于不是非常大的数组,可以在创建数组时指定初始值。下面的例子创建一个字符串数组并指定初始值:

要存储到数组元素中的信息放在“{”和“}”之间,之间用逗号隔开。数组中元素的个数也就是用逗号隔开的元素数。数组中的每个元素必须有相同的类型,上述例子用字符串定义每种驯鹿的名称。

在数组创建之后,就不能增大其空间,进而增加其他的元素。即使又想起了一种最著名的驯鹿的名称,也不能将Rudolph作为第9个元素加入到数组reindeerNames中,Java编译器不允许这样做。

9.2 使用数组

在程序中使用数组就像使用变量一样,只是需要在靠近数组名的方括号内指定元素编号。你可以在允许使用变量的任何地方使用数组元素。下面的语句使用的都是本章前面定义的数组:

数组的第1个元素的编号为0,而不是1。这意味着最大的元素编号比你想象的小1。请看下面的语句:

这条语句创建一个字符串数组,其元素编号为0~9,如果在程序的其他地方使用topGifts[10],将会得到一个与ArrayIndexOutOfBoundsException相关的错误消息。

在Java程序中,异常是错误的另外一个名称。这里的异常是一个“数组越界”错误,这表示程序试图使用一个预定义边界之外的数组元素。第18章将详细讲解异常。

如果你想检测数组的上界,以避免在引用数组元素时超越上界,可以使用length变量,它与数组紧密相关。length 是一个整型变量,包含数组能容纳的元素数。下面的例子创建一个数组,然后报告其长度:

在这个例子中,reindeerNames.length的值为 9,也就是说可以指定的最大元素编号为8。

在Java中有两种处理文本的主要方式:字符串和字符数组。使用字符串时,一种有用的技巧是将字符串中的每个字符放在字符数组的一个元素中。为此,可使用字符串的 toChar Array()方法,它生成一个字符数组,该数组包含的元素数与字符串长度相同。

本章的第一个程序使用了本节介绍的两种方法。程序SpaceRemover将显示一个字符串,并将其中所有的空格字符(‘ ’)替换为句点字符(‘.’)。

在 NetBeans 中打开 Java24 项目,然后选择 File->New File,创建一个新的空 Java 文件,将其命名为SpaceRemover。然后在源代码编辑器窗口中输入程序清单9.1中的文本,并保存。

程序清单9.1 SpaceRemover.java程序

在 NetBeans中选择 Run->Run File 命令,运行该程序来查看其输出,如图 9.1 所示。

应用程序 SpaceRemover 将文本“Rudolph the Red - Nosed Reindeer”存储在两个地方:一个是字符串变量 mostFamous,另一个是字符数组mfl。数组是在第4 行通过调用 mostFamous的toCharArray( )方法创建的,该方法将文本中的每个字符存储到数组的一个元素中,字符R存储在元素0中,字符u在元素1中,字符d在元素2中,依此类推,最后将字符r存储到元素29中。

图9.1 SpaceRemover程序的输出

第5~12行的for循环检查数组mfl中的每个字符,如果字符不是空格,就直接显示它,如果是空格,就显示句点字符(.)。

9.3 多维数组

目前为止,本章介绍的都是一维数组,可以使用0到数组元素数之间的数字检索元素。有些类型的信息需要使用多维数组来存储,如(x, y)坐标系的点,其中一维用于存储 x 坐标,另一维用于存储y坐标。

要创建二维数组,必须在创建和使用数组时多加一对方括号。请看下面的例子:

这个例子创建了一个名为selectedPoint的布尔数组,该数组的第一维有50个元素,第二维也有50个元素,因此总共有2500(50×50)个元素。该数组创建后,每个元素的默认值为false。接下来,将其中的3个元素设置为true,它们在数组中的位置分别是(4, 13)、(7, 6)和(11, 22)。

根据需要,数组可以有任意多维数,但别忘了,如果数组的维数很多,将占用大量的内存。创建一个50×50的数组相当于创建2500个变量。

9.4 对数组进行排序

将一系列类似的数据组织为数组后,你可以重新安排它们的序列。下面的语句交换整型数组numbers中两个元素的值:

这些语句导致number[5]和number[6]的值相互交换,整型变量temp在交换时用作临时存储空间。“排序”是指将一组相关内容按指定顺序排列,一个例子是将数字从小到大排列。

圣诞老人可以按照姓氏对接收礼物的人进行重新排序。例如,Willie Aames和Hank Aaron会先于 Dweezil Zappa和 Jim Zorn 收到礼物。

在Java中对数组排序很容易,因为Arrays类提供了这种功能。Arrays类位于java.util中,它可以对任何类型(包括字符串)的数组进行排序。

要在程序中使用Arrays类,可执行下列步骤:

1.使用 import java.util.*语句将所有 java.util 类导入到程序中;

2.创建数组;

3.使用 Arrays 类的方法 sort( )来对数组重新排序。

使用 Arrays 类的 sort ( )方法对数组进行排序后,其中的值将按数字升序排列。字符和字符串将按字母顺序排列。

为了对其验证,创建一个新的空Java文件,名Name,然后在源代码编辑器中输入程序清单9.2中的所有文本。这是一个按照名字进行排序的段程序。

程序清单9.2 Name.java的完整源代码

当运行该Java程序时,它首先按照原来的顺序显示这13个名字,按照名字进行排序后,然后再重新显示名字,其输出结果如下。

Output

如果使用字符串或基本类型(如整数和浮点)变量时,通过Arrays类的方法只可按升序进行排序。如果要按其他顺序排列或希望排序效率比Arrays类高,可以自己编写代码来实现。

9.5 对字符串中的字符计数

在英文中,经常出现的字母依次是E、R、S、T、L、N、M和O,如果你之前看过辛迪加游戏“财富转轮”,就会意识到这一点。

注意:

如果读者不熟悉“财富转轮”这个节目,这里介绍一下:财富转轮游戏有 3 个参赛者,他们猜测组成一个短语、名字或引文的字母。如果猜中一个字母且是辅音字母,就可以通过转动大轮子来确定赢多少钱。为增加娱乐性,参加者与在观众席前排就坐的朋友一起来玩这个游戏,猜中字母时,就发给他们随机数量的钱,并给胜利者一个新的猜测机会。

这里将要创建的程序用来统计字母在不同短语或表达中出现的频率,并使用数组来存放每个字母出现的字数。当程序运行时,它将显示每个字母在短语中出现的次数。

在 NetBeans 中创建一个新的 Java 空文件,将其命名为 Wheel.java,然后输入程序清单9.3中的所有文本,最输入完毕之后保存。你可以在第17行和第18行之间随意输入其他短语,只要格式与第17行相同即可。

程序清单9.3 Wheel.java的完整源代码

如果你没有添加自己的短语,该程序的输出如程序清单9.4所示。

程序清单9.4 Wheel程序的输出结果

Wheel程序中将会发生如下事情。

第3~19行:短语存储在字符串数组phrase中。

第20行:创建整型数组letterCount,它包含26个元素。该数组用来存储每个字母(依次为A~Z)出现的次数。元素letterCount[0]存储字母A出现的次数,元素letterCount[1]存储字母B出现的次数,依此类推,最后,元素letterCount[25]存储字母Z出现的次数。

第21行:开始一个for循环,该循环遍历数组phrase中的所有短语。该for语句使用了变量phrase.length,以便达到最后一个短语时结束循环。

第22行:创建一个名为current的字符串变量,并将数组phrase中当前元素的值赋给它。

第23行:创建一个字符型数组,用于存储当前短语中的所有字符。

第24行:开始一个for循环,该循环遍历当前短语中的所有字符。这里使用了变量letters.length,以确保达到最后一个字符时结束循环。

第25行:创建字符变量lett并将当前字符赋给它。字符除文本值外,还有对应的数值。由于数组中的元素可以编号,因此可以使用每个字符对应的数值来确定其元素号。

第26~28行:使用if语句排除所有非字母字符,如标点符号和空格。依据当前存储在变量lett中的字符对应的数值,决定将数组letterCount中的哪个元素加1。字母对应的数值从65(代表‘A’)到90(代表‘Z’)。由于数组letterCount的元素编号为0~25,因此为确定将哪个数组元素加1,将变量lett与‘A’相减。

第31行:使用for循环从字母‘A’遍历到字母‘Z’。

第32~34行:显示当前字母、冒号,以及该字母在数组phrase中存储的短语中出现的次数。

注意:

与字符‘A’到‘Z’相关联的数值是用于ASCII字符集中的值。ASCII字符集是Unicode的一部分,后者是Java语言支持的完整字符集。Unicode字符集支持全世界的各种书面语言中使用的60000多个字符。而ASCII只有256个字符。

该程序演示了如何使用两个嵌套的for循环,以每次一个字符的方式遍历一组短语。Java给每个字符提供了一个相关联的数值,这个值比数组中的字符更易使用。

9.6 总结

通过使用数组,可以在程序中存储和处理复杂的信息。数组也适合存储列表信息,并可使用第8章介绍的循环语句轻松地进行存取。

说实话,圣诞老人的信息处理需求可能超过了数组的处理能力。每年都有孩子出生,他们要求的礼物越来越复杂和昂贵。

使用变量不方便时,可以在程序中使用数组来存储信息,即使没有创建列表或对其进行复核,也可以使用数组。

9.7 问与答

问:字母的数值范围65(‘A’)到90(‘Z’)是基本Java语言的一部分吗?如果是,1~64留作什么用处?

答:数值1~64对应于数字、标点符号和其他可打印字符(如回车、换行符和退格)。在Java程序中,可以使用与可打印字符及一些不可打印字符相关联的数值。Java使用Unicode字符集,其中前127个字符来自ASCII字符集,读者在其他编程语言可能使用过。

问:为什么有些错误称为异常?

答:该术语的含义是程序正常运行时没有问题,而异常表明必须应对特殊情况。异常是Java程序发出的警告消息,在Java语言中,术语“错误(error)”有时只用于描述在运行程序的解释器中发生的错误状态。第18章将更详细地介绍这两个术语。

问:在多维数组中,可以使用变量length来测量除第一维外的其他维的长度吗?

答:可以测量数组任何维的长度,对于第一维,可使用数组名和length,如x.length;对于其他维,可以使用该维的第1个元素和length。请看使用下面的语句创建的数组data:

该数组第一维的长度可使用data.length来确定;对于第二维,可以通过data[0].length来测量;对于第三维,可以使用data[0][0].length来测量。

9.8 测验

如果读者的脑袋是数组,可以通过回答下列关于数组的问题来测量其长度。

9.8.1 问题

1.数组最适合用于存放什么类型的信息?

a.列表。

b.一对相关的信息。

c.琐碎的东西。

2.什么变量用于检查数组的上界?

a.top。

b.length。

c.limit。

3.包括Rudolph在内,圣诞老人有多少只驯鹿?

a.8。

b.9。

c.10。

9.8.2 答案

1.a.列表包含相同类型的信息,如字符串、数字等,适合用数组存储。

2.b.变量length包含数组的元素数。

3.b.Clement Clark Moore 在其著作的圣诞诗歌《A Visit from St. Nicholas》中提到,圣诞老人有8只小驯鹿,所以加上Rudolph后是9只。

9.9 练习

要获得更多可供以后使用的经验,可通过下面的练习拓展有关本章主题的知识:

创建一个程序,它使用多维数组存储学生的成绩。第一维是学生编号,第二维是每个学生的成绩。显示全部学生的平均成绩以及每个学生的平均成绩。

编写一个程序,将能被13整除的前400个数存储到数组中。

要查看完成这些练习编写出的Java程序,请访问本书的配套网站www.java.24hours.com。

没有精选讨论主题。

全部讨论主题 查看精选主题

没有讨论主题。
😃 😅 😆 😁 😂 😊 😄 😠 😩 😲 😞 😵 😰 😒 😍 😤 😜 😝 😋 😘 😚 😷 😳 😢 😭 😨 😣 😡 😌 😖 😔 😱 😪 😏 😓 😥 😫 😉 👊 👍 👆 👇 👈 👉 👋 👏 👌 👎 👐 💓 💔 💕 💖 💗 💘 💙 💚 💛 💜 💝 💞 💟