《Head First Java》笔记(2)

2024-08-24 09:08
文章标签 java 笔记 head first

本文主要是介绍《Head First Java》笔记(2),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

2.1 面向过程与面向对象之间的战争

面向过程与面向对象之间的战争是由下面一则小故事引起的。

从前,有一个软件小铺,该小铺的老板娘(同时也是项目经历)手下有两个小兵:阿朱和阿娇。有一天,老板娘故意刁难两个兵,并且让她两进行比赛,看谁的程序写的好。要求:在图形接口画出正方形、圆形与三角形。当用户点选某个图形时,图形要顺时针旋转360度,并且根据形状的不同而播放不同的AIF音效的音乐文件。 最终赢的人会坐上象征身份地位的宝座!

当接到这个任务的时候,阿朱首先想到的是:这个程序要执行什么动作?会需要什么样的程序?一会她就想到了,需要旋转(rotate)和播放音乐(playSound)这两个动作。于是,阿朱就迫不及待的写下了下面的程序:
这里写图片描述

当接到这个任务的时候,阿娇首先想到的是:这个程序有什么样的事物?有什么关键角色?她首先想到的时候形状体(shape)。当然,她还想到了用户、声响等对象与点击等事件。但是这些对象早就已经建立好了,而她只需要专注于创建形状体就ok了。于是,她就写下了如下程序:
这里写图片描述

此时,当阿朱看到阿娇的代码这么长的时候,心里已经乐开花了,心想,这次赢定了,那个宝座是自己的了!!!

然而,万恶的老板娘此时却又说规格需要有点改动。在原有的基础上,加上阿米巴原虫形状(不规则形状体),用户点选时也是旋转并播放.hif声音的文件。

听到这个改动后,阿朱心想rotate这个程序还可以接着用,但是playSound这个就得需要修改了,于是,她奋笔写下了如下程序:
这里写图片描述

听到这个改动后,阿娇苦笑一下,在原有的基础上又增加了一个类,如下:
这里写图片描述

当她们两把各自的程序拿给老板娘看时,老板娘失望的说:“唉呀,不对呀,阿米巴原虫不是这样旋转的…..”。
原来两个人都把旋转部分写成了这样:
1) 找出指定形状的外接四边形
2) 计算出外接四边形的中心点,以此点为中心进行旋转。
但是老板娘认为阿米巴原虫是这样旋转的:绕着一端进行旋转。
听到这里,阿朱一脸的懵逼,最后奋力的在rotate函数中加上“if/else”,于是写下了下面的程序:
这里写图片描述

这样做之后,就会造成其有一堆程序需要修改,从而本来已经测试号的东西全部又要重来一遍。

而阿娇仅仅在Amoeda这类上作了相应的修改,其他已经测试通过的部分完全不需要修改。其实现如下:
这里写图片描述

此时,阿朱看到阿娇的改动非常小,心有不甘。于是,就质问道:“阿娇,你写的代码中,冲的部分太多,而且设计的时候需要同时维护4个不同的rotate方法,效率有点低”。面对阿朱的质疑。阿娇不紧不慢的回答道:“阿朱,让我告诉你什么叫做面向对象的继承(inheritance)”。

第一步:找出4个类中的共同部分
这里写图片描述

第二步:它们都是形状(Shape),而且都有rotate和playSound这两个方法,因此可以提取出新的类
这里写图片描述

第三步:将上面的4个不同的形状体以继承的关系连接到Shape这个新类中,如下:
这里写图片描述

我们可以称“Square继承自Shape”,“Circle继承自Shape”,“Triangle继承自Shape”,“Amoeda继承自Shape”,而rotate和playSound这两个方法已经移出了Square、Circle、Triangle和Amoeda这四个类了。这里,我们称Shape这个类为父类(基类),称Square、Circle、Triangle和Amoeda这四个类为子类(派生类)。

到这里,阿朱还不死心,继续提出了质疑:“你这样设计,岂不是阿米巴原虫也是继承自Shape,那旋转的功能不就是都变成一样的了吗?”
阿娇说:“问的号。Amoeda这个类可以覆盖(override)Shape的方法。Java虚拟机会知道在遇到Amoeda时会使用不同的rotate方法。”

第四步:让Amoeda这个类去覆盖Shape这个父类中的rotate()和playSound()的两个方法。
这里写图片描述

覆盖的意思就是由子类重新定义继承下来的方法,以改变或延伸此方法的行为。

到此,你是不是就觉得这场比赛,阿娇大获全胜呢??非也,其实获胜的是阿花(老板娘的侄女)。看到这里,各位看官想必都明白:出来混社会,关系一定要硬啊!!!!

2.2 类与对象

首先要明白:类不是对象,类是用来创建对象的模型

创建对象需要两个类:一个是要被操作于对象的类,另一个是用来测试该类的类。

测试用的类带有main()方法,并且会在其中建立与存取被测的对象。
习惯用法:测试用的类一般命名为“受测类名称”+TestDrive。

下面就来创建第一个对象Dog
第1步:编写被测对象Dog类

class Dog
{//定义实例变量int size;String breed;String name;//定义方法void bark(){System.out.println("Ruff ! Ruff !");}   
}

第2步:编写测试用的类DogTestDrive

class DogTestDrive
{public static void main(String[] args){Dog d = new Dog(); //创建一个Dog对象,对象名为dd.size = 40; //采用圆点运算符存取对象的变量d.bark();  //采用圆点运算符调用对象的方法}
}

命令行中执行命令:(必须在绝对路径下去执行)

>javac DogTestDirve.java
>java DogTestDrive

运行结果:
这里写图片描述

2.3 快离开main

只要还待在main中,你就是游离在对象村之外!因为,对于面向对象应用程序来说,我们需要用对象来与对象交互。

2.3.1 main()的两种用途:

  1. 测试真正的类
  2. 启动Java应用程序

真正的Java程序只会让对象与对象交互。这里所说的交互是指相互调用方法。

2.3.2 猜数字游戏

游戏规则:
游戏开始先产生一个0~9之间的随机数作为谜底,然后由三个玩家进行猜数字,只要有一个玩家猜的数字与谜底数字相同,游戏就结束,否则一直进行下去。

对象设计:
这里涉及到两个对象:Player(玩家)和Game(游戏),针对游戏规则,我们设计三个类:Player、GuessGame、GuessLauncher,如下:
这里写图片描述

程序源码:

class GuessGame
{public void startGame(){//先创建三个玩家Player p1 = new Player();Player p2 = new Player();Player p3 = new Player();//定义三个变量,分别存放玩家所猜的数字int guessP1 = 0;int guessP2 = 0;int guessP3 = 0;//声明三个变量,保存玩家是否猜中boolean p1isRight = false;boolean p2isRight = false;boolean p3isRight = false;//随机产生一个0~9之间的数作为谜底数字int targetNumber = (int)(Math.random() * 10);System.out.println("Target Number is " + targetNumber);while(true){//获取每个玩家所猜的数字p1.guess();guessP1 = p1.number;System.out.println("Player one guessed is " + guessP1);p2.guess();guessP2 = p2.number;System.out.println("Player two guessed is " + guessP2);p3.guess();guessP3 = p3.number;System.out.println("Player three guessed is " + guessP3);if(guessP1 == targetNumber){p1isRight = true;}if(guessP2 == targetNumber){p2isRight = true;}if(guessP3 == targetNumber){p3isRight = true;}if(p1isRight || p2isRight || p3isRight)//只要有一人猜中,游戏就结束{System.out.println("We have a winner !");System.out.println("Player one  guessed right ? " + p1isRight);System.out.println("Player two  guessed right ? " + p2isRight);System.out.println("Player three  guessed right ? " + p3isRight);System.out.println("Game Over");break; //游戏结束,跳出循环}else{System.out.println("No one guess right, and game must be continue");}       }       }
}class Player
{int number = 0; //保存玩家猜的数字public void guess(){number = (int) (Math.random() * 10);        }
}public class GameLauncher
{public static void main(String[] args){GuessGame game = new GuessGame();game.startGame();}
}

编译遇到的问题:
1> 命令行编译java源文件提示“编码GBK的不可映射字符”
解决方法:
在输入 javac 命令时,额外输入 -encoding utf-8, 例如:如果编译的源文件名为 Test.java ,那么编译时原先只需输入javac Test.java,而现在需要输入 javac -encoding utf-8 Test.java

2> 显示错误
1. 类GuessGame是公共的,应在名为GuessGame.java文件中声明。
2. 类Player是公共的,应在名为Player.java文件中声明
解决方法:
产生上面的错误原因是,将三个类都写在了同一个.java文件中了,并且类的前面都用了public修饰符进行了修饰,而一个.java文件里面只能有一个public class XXX{} 。
所以将GuessGame和Player这两个类前面的public修饰符去掉,或者将这两个类写在不同的.java文件中即可。
运行结果:
这里写图片描述

这篇关于《Head First Java》笔记(2)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1102052

相关文章

Java中Arrays类和Collections类常用方法示例详解

《Java中Arrays类和Collections类常用方法示例详解》本文总结了Java中Arrays和Collections类的常用方法,涵盖数组填充、排序、搜索、复制、列表转换等操作,帮助开发者高... 目录Arrays.fill()相关用法Arrays.toString()Arrays.sort()A

Spring Boot Maven 插件如何构建可执行 JAR 的核心配置

《SpringBootMaven插件如何构建可执行JAR的核心配置》SpringBoot核心Maven插件,用于生成可执行JAR/WAR,内置服务器简化部署,支持热部署、多环境配置及依赖管理... 目录前言一、插件的核心功能与目标1.1 插件的定位1.2 插件的 Goals(目标)1.3 插件定位1.4 核

如何使用Lombok进行spring 注入

《如何使用Lombok进行spring注入》本文介绍如何用Lombok简化Spring注入,推荐优先使用setter注入,通过注解自动生成getter/setter及构造器,减少冗余代码,提升开发效... Lombok为了开发环境简化代码,好处不用多说。spring 注入方式为2种,构造器注入和setter

使用zip4j实现Java中的ZIP文件加密压缩的操作方法

《使用zip4j实现Java中的ZIP文件加密压缩的操作方法》本文介绍如何通过Maven集成zip4j1.3.2库创建带密码保护的ZIP文件,涵盖依赖配置、代码示例及加密原理,确保数据安全性,感兴趣的... 目录1. zip4j库介绍和版本1.1 zip4j库概述1.2 zip4j的版本演变1.3 zip4

Java堆转储文件之1.6G大文件处理完整指南

《Java堆转储文件之1.6G大文件处理完整指南》堆转储文件是优化、分析内存消耗的重要工具,:本文主要介绍Java堆转储文件之1.6G大文件处理的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言文件为什么这么大?如何处理这个文件?分析文件内容(推荐)删除文件(如果不需要)查看错误来源如何避

SpringBoot整合Dubbo+ZK注册失败的坑及解决

《SpringBoot整合Dubbo+ZK注册失败的坑及解决》使用Dubbo框架时,需在公共pom添加依赖,启动类加@EnableDubbo,实现类用@DubboService替代@Service,配... 目录1.先看下公共的pom(maven创建的pom工程)2.启动类上加@EnableDubbo3.实

SpringBoot整合(ES)ElasticSearch7.8实践

《SpringBoot整合(ES)ElasticSearch7.8实践》本文详细介绍了SpringBoot整合ElasticSearch7.8的教程,涵盖依赖添加、客户端初始化、索引创建与获取、批量插... 目录SpringBoot整合ElasticSearch7.8添加依赖初始化创建SpringBoot项

JAVA覆盖和重写的区别及说明

《JAVA覆盖和重写的区别及说明》非静态方法的覆盖即重写,具有多态性;静态方法无法被覆盖,但可被重写(仅通过类名调用),二者区别在于绑定时机与引用类型关联性... 目录Java覆盖和重写的区别经常听到两种话认真读完上面两份代码JAVA覆盖和重写的区别经常听到两种话1.覆盖=重写。2.静态方法可andro

SpringBoot中六种批量更新Mysql的方式效率对比分析

《SpringBoot中六种批量更新Mysql的方式效率对比分析》文章比较了MySQL大数据量批量更新的多种方法,指出REPLACEINTO和ONDUPLICATEKEY效率最高但存在数据风险,MyB... 目录效率比较测试结构数据库初始化测试数据批量修改方案第一种 for第二种 case when第三种

Java docx4j高效处理Word文档的实战指南

《Javadocx4j高效处理Word文档的实战指南》对于需要在Java应用程序中生成、修改或处理Word文档的开发者来说,docx4j是一个强大而专业的选择,下面我们就来看看docx4j的具体使用... 目录引言一、环境准备与基础配置1.1 Maven依赖配置1.2 初始化测试类二、增强版文档操作示例2.