目录
第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入门经典
第6章 使用字符串来交流

本章介绍如下内容:

使用字符串来存储文本;

在程序中显示字符串;

在字符串中包含特殊的字符;

拼接字符串;

在字符串中包含变量;

比较字符串;

判断字符串的长度。

在电影《钢琴》中,Holly Hunter 扮演的 Ada 是一位年轻的苏格兰妇女,她从 6 岁起就是哑巴,只能通过弹钢琴来表达自己。

同Ada一样,计算机程序能够安静地工作,从来不停下来聊天或演奏钢琴。然而如果《钢琴》告诉了我们什么,那就是交流和食物、水和住所一样,是人类的基本需求(这部电影还告诉我们,演员 Harvey Keitel 对自己的肢体表达能力很自信,但这不是本书讨论的内容)。

Java 程序将字符串作为与用户交流的主要方式。字符串是一组文本,可以包含字母、数字、标点符号及其他字符。本章将介绍如何在Java程序中使用字符串。

6.1 在字符串中存储文本

字符串用来存储文本并显示给用户。字符串中最基本的元素是字符。字符可以是一个字母、数字、标点符号,或者是其他符号。

在Java程序中,字符是可存储到变量中的信息类型之一,字符型变量是在语句中使用char来创建的,如下所示:

这条语句创建了一个名为keyPressed的变量,可用于存储字符。当创建字符型变量时,可以设置其初始值,如下所示:

字符值必须用单引号括起来。

字符串是一组字符,可以使用String和变量名来创建存储字符串值的变量,如下所示:

这条语句创建了一个名为 fullName 的字符串变量,并在其中存储了文本“Ada McGrath Stewart”,这是Hunter的钢琴家的全名。在Java语句中,字符串用双引号括起,但双引号不是字符串的一部分。

不同于你前面使用过的其他类型变量:int、float、char、boolean,表示字符串类型的String的首字母必须大写。

这样做的原因是,字符串类型与Java中的其他类型有些不同。字符串是一种称为对象的特殊信息,而所有对象类型名的首字母都必须大写。有关对象的知识将在第 10 章介绍。在本章需要注意的是,字符串与其他变量类型不同,由于这种差别,在语句中指定字符串类型时, String的首字母必须大写。

6.2 在程序中显示字符串

在 Java 程序中,显示字符串的最基本方法是使用 System.out.println( )语句。该语句可在括号中接收字符串和其他变量,并将它们显示在系统输出设备中,即计算机监视器。下面是一个例子。

上述语句将显示下列文本:

在屏幕上显示文本通常称为打印,这就是 println( )代表的意思:打印该行。你可以使用System.out.println( )语句显示用双引号括起的文本和变量(稍后你将会看到)。将所有要显示的内容都放在括号内。

另一种显示文本的方法是调用 System.out.print( ),该语句显示括号中的字符串和其他变量,但不同于 System.out.println( ),它让接下来的语句在同一行显示文本。

可以连续使用 System.out.print( )多次,将内容显示在同一行,如下例所示:

这些语句输出的文本如下:

6.3 在字符串中使用特殊字符

创建或显示字符串时,其文本必须用双引号括起。这些双引号不会显示出来,这就提出了一个很好的问题:如果要显示双引号该怎么办呢?

为显示双引号,Java 创建了一个特殊编码\",可放到字符串中。在字符串中遇到该编码时,将其替换为双引号。例如,请看下面的例子:

这段代码显示如下内容:

可以采用这种方式在字符串中插入多个特殊字符,下面列表出了这些特殊字符,注意到每个都是以反斜线(\)打头。

换行符的作用是在下一行行首显示换行符后面的文本,请看下面的例子:

这条语句将显示如下内容:

6.4 拼接字符串

使用 System.out.println( )语句以及用其他方式处理字符串时,可以使用加号(+)将两个字符串拼接起来。这里用到的加号和用来对数值进行求和的加号相同。

将运算符+用于字符串,其含义与原来不同:不是执行数学运算,而是将两个字符串拼接起来。这导致字符串显示在一起,或使用两个小字符串组合成一个长字符串。

这种行为用拼接(concatenation)来描述,因为它的意思是将两样东西连接起来。

注意:

读者在学习编程技巧时,可能会在其他书中看到 concatenation 这个术语。但是,本书在讲解字符串和字符串结合时,用的是pasting这个术语。

下面的语句使用+运算符来显示一个长字符串:

这里不是将整个字符串放在单独一行(如果这样,以后查看程序时将更难理解),而是使用运算符+将文本文件分成两行。执行这条语句时,输出结果如下:

在该字符串中使用了几个特殊字符:\"、\'、\n 和\t。为更好地熟悉这些字符,请将输出和生成输出的 System.out.println( )语句进行比较。

6.5 将其他变量用于字符串中

虽然可以使用+运算符将两个字符串拼接起来,但更常见的是使用它将字符串和变量拼接起来。请看下面的例子:

这段代码的输出如下:

这个例子说明了将+运算符用于字符串的独特之处:导致不是字符串的变量作为字符串显示出来。length是一个整型变量,其值为121,它显示在字符串“Running time:”和“minutes”之间。System.out.println( )语句用于显示一个字符串加上一个整数再加上一个字符串。这条语句之所以能够正常运行,是因为至少开头的部分是字符串。Java语言通过提供这种功能使信息更容易显示。

读者可能想做的一件事情是,将字符串拼接多次,如下例如示:

这段代码导致变量 searchKeywords被设置为“drama romance New Zealand”。第1行创建变量 searchKeywords 并将其设置为空字符串,因为双引号之间为空。第 2 行将变量 search Keywords设置为其当前值加上字符串drama;接下来的两行用相同的方式再加上ramance和New Zealand。

可以看到,在变量后面拼接文本时,变量名将出现两次。Java提供了一种快捷方式来简化该过程,这就是+=运算符。+=运算符将=和+运算符的功能融为一体。对于字符串,它用于在当前字符串后面加上其他字符串。上述SearchKeywords示例可以使用+=运算符简化为如下所示:

这段代码的效果与前面相同:将 searchKeywords设置为“drama romance New Zealand”。

6.6 字符串的高级处理

还有多种其他方式可用于查看字符串变量和修改其值。之所以有这些高级功能,是因为字符串在Java语言中是对象。通过处理字符串对象获得的知识,也适用于其他对象。

6.6.1 比较两个字符串

在程序中经常要比较两个字符串是否相等,为此可在带有两个字符串的语句之中使用equals( ),如下所示:

这里使用了两个字符串变量,一个是变量favorite,用于存储Ada最喜欢的乐器名称:钢琴;另一个变量是guess,用于存储对其最喜欢的乐器的猜测,该猜测是Ada最喜欢尤克里里琴。

第 3 行显示文本“Is Ada’s favorite instrument a”、变量 guess 的值和问号。第4 行显示文本“Answer:”以及下面的新内容:

语句中的这部分称为方法,方法是在Java程序中完成任务的一种方式,这里的方法要完成的任务是,比较字符串favorite和字符串guess的值是否相等。如果这两个字符串的值相等,就显示true,否则显示false。下面是该示例的输出结果:

Output

6.6.2 确定字符串的长度

有时确定字符串的长度很有用,为此可使用方法 length( )。该方法的工作原理与 equals( )相似,但只涉及一个字符串变量。请看下面的例子:

该示例将整型变量 nameLength 的值设置为 15,方法 cinematographer.length( )计算字符串变量cinematographter包含的字符数,并将结果赋给整型变量nameLength。

6.6.3 改变字符串的大小写

计算机很不灵活,不能识别明显相同的东西。虽然人很容易识别出文本 Harvey keitel 和HARVEY KEITEL是一回事,但大多数计算机不这么认为。例如,在本章前面介绍的equals( )方法将果断地认为 Harvey keitel 不等于 HARVEY KEITEL。

为了克服这些障碍,Java 提供了将字符串变量全部转换为大写的方法(toUpperCase( ))和全部转换为小写的方法(toLowerCase( ))。下面的例子演示了如何使用方法 toUpper Case( ):

这段代码将字符串变量 change 设置为字符串变量 baines 的大写形式,即 HARVEY KEITEL。ToLowerCase( )方法的用法相同,但返回的是字符串的小写。

注意,toUpperCase( )方法不改变调用它时使用的字符串变量的大小写。在上述示例中,变量 baines的值仍为 Harvey keitel。

6.6.4 查找字符串

处理字符串时,另一项常见的任务是,确定在一个字符串中能否找到另一个字符串。要在字符串中查找,可使用方法 indexof( ),并将要查找的字符串放在括号中。如果没有找到指定的字符串,indexof( )返回−1;如果找到,indexof( )返回一个整数,指出该字符串的起始位置。字符串中字符位置从 0 开始编号,即第一个字符的位置为 0。在字符串 The Piano 中,文本Piano的起始位置为4。

警告:

indexof( )方法是区分大小写的,这也就意味着只有当目标字符串和搜索字符串的大小写完全相同时,才算查找成功。否则,indexof( )返回−1。

indexof( )方法的一种用法是,在电影《钢琴》的剧本中,搜索 Ada 盛气凌人的丈夫跟她的女儿 Flora的谈话:“You are greatly shamed and you have shamed those trunks”。

如果《钢琴》的剧本存储在变量script中,可以使用下面的语句从中搜索前面引用的部分:

如果在 script 中找到文本“you have shamed those trunks”,变量position 将等于该文本在script中的起始位置,否则将等于−1。

6.7 导演及演员名单

在电影《钢琴》中,Ada McGrath Stewart 从苏格兰搬到新西兰,来到一片陌生的土地并嫁给了一个不懂得欣赏钢琴的人。对于本章介绍的有些主题,读者可能与她一样有种失落感。

接下来,为了加深读者对前面介绍的字符串处理功能的理解,将编写一个Java程序,显示一部电影的导演和演员名单。你应该能够猜到该电影的名字。

返回NetBeans中的Java24项目,然后创建一个名为Credits的新Java类,在源代码编辑器中输入程序清单6.1中的所有文本,输入完毕之后存盘。

程序清单6.1 Credits程序

编译程序前先浏览一遍程序,看是否能够明白各条语句的功能。对该程序的详细分析如下。

第1行将该Java程序命名为Credits。

第 2 行是 main( ) 块语句的开头,程序的所有功能都是在该块语句中完成的。

第 4~14 行创建用于存储导演和演员以及影片信息的变量。其中一个变量 year,它是一个整型变量,其他变量都是字符串变量。

第 16~21 行是长语句System.out.println( )。在第16行和第21行的括号之间的信息都将显示到屏幕上。换行符\n的作用将其后面的文本在下一行的行首显示。制表符\t的作用是在输出信息中插入制表符。其他要显示的内容要么是文本,要么是字符串变量。

第 22 行结束main( )块语句。

第23行结束整个程序。

如果提示有错误,可以修改程序中的输入错误,然后重新保存。NetBeans将自动编译程序。当运行程序时,将会看到类似于图6.1所示的输出窗口。

图6.1 Credits程序的输出

注意:

如果你对本章提到的电影《钢琴》、电影中的主人公,以及该电影的导演 Jane Campion 感兴趣,可以访问 Magnus Hjelstuen的非官方网站,地址为www.cadenhead.org/piano。

6.8 总结

如果你的Credits程序运行正常,输出结果与图6.1相同,你的信心也应该增加。通过本书前6章的学习,你现在可以编写一个比较长的Java程序,而且也可以处理一些比较复杂的问题了。字符串是你在每次编程时都会用到的东西。

在影片《钢琴》的开头,Ada的丈夫不允许其毛利人劳工将她的钢琴搬回家,她失去了钢琴。你很幸运,你在Java程序中使用字符串的技能不会其他任何人夺走,你可以通过多种方式使用使用字符串来与用户交流。

6.9 问与答

问:如何将字符串变量的值设置为空?

答:一对双引号之间没有任何文本就表示空字符串。下面的代码创建一个名为 adaSays的字符串变量,并将其值设置为空:

问:使用 toUpperCase( )方法好像不能将字符串中的字母全部转换为大写,我哪里操作不正确?

答:调用字符串对象的 toUpperCase( )方法时,实际上它并未修改该字符串对象,而是创建一个字母全部大写的新字符串,请看下面的语句:

这些语句的输出结果为“First Name: Nessie”,因为变量 firstName 包含的是原来的字符串。如果将最后一条语句改为显示变量 changeName,输出结果将为“First Name: NESSIE”。

当字符串在Java中创建之后,它们的值不会发生改变。

问:在 Java 中,所有方法都像 equals( )那样返回true 或 false吗?

答:方法被调用后,可以有不同的方式来进行响应。如果方法像 equals( )那样发回一个值,则被称为返回一个值。方法 equals( )方法返回一个布尔值,其他方法可能返回字符串、整数、其他类型的值,也可能什么都不返回(使用void来表示)。

6.10 测验

回答下列问题,以测试对字符串理解和掌握的程度。

6.10.1 问题

1.我的朋友要执行拼接操作,需要向权威部门报告吗?

a.不,仅在冬季这才是非法的。

b.是的,但要等到我将故事卖给TMZ.com再说。

c.不,他所做的只是在程序中将两个字符串连接起来。

2.为什么String的首字母要大写,而int等类型名的首字母不需要大写?

a.String是一个完整的单词,而int不是。

b.和Java中所有的对象一样,String的首字母必须大写。

c.Oracle的质量控制做得很糟糕。

3.下列那项在字符串中添加一个单引号?

a.<quote>。

b.\’。

c.‘。

6.10.2 答案

1.c.拼接(Concatenation)指的是将两个字符串连接起来,它使用运算符+或+=。

2.b.在Java中,所有的对象类型名的首字母都要大写,因此变量名的首字母都是小写,这样就不容易将变量和对象搞混。

3.b.在字符串中插入特殊字符时,总是以单个反斜杠开头。

6.11 练习

通过下列练习来复习本章介绍的主题:

编写一个名为Favorite的小型Java程序,将本章中“比较两个字符串”一节的代码放在 main( )块语句中。测试该程序,确认其输出就像正文中描述的那样,Ada 最喜欢的乐器不是尤克里里琴。测试完毕后,将变量guess的初始值从ukelele改为piano,再看看如果如何。

修改程序Credits,将导演和全部演员的名字都用大写字母显示。

有关完成这些练习需要编写的Java程序,请访问本书的配套网站www.java24hours.com。

没有精选讨论主题。

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

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