《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

相关文章

使用SpringBoot+InfluxDB实现高效数据存储与查询

《使用SpringBoot+InfluxDB实现高效数据存储与查询》InfluxDB是一个开源的时间序列数据库,特别适合处理带有时间戳的监控数据、指标数据等,下面详细介绍如何在SpringBoot项目... 目录1、项目介绍2、 InfluxDB 介绍3、Spring Boot 配置 InfluxDB4、I

基于Java和FFmpeg实现视频压缩和剪辑功能

《基于Java和FFmpeg实现视频压缩和剪辑功能》在视频处理开发中,压缩和剪辑是常见的需求,本文将介绍如何使用Java结合FFmpeg实现视频压缩和剪辑功能,同时去除数据库操作,仅专注于视频处理,需... 目录引言1. 环境准备1.1 项目依赖1.2 安装 FFmpeg2. 视频压缩功能实现2.1 主要功

使用Java读取本地文件并转换为MultipartFile对象的方法

《使用Java读取本地文件并转换为MultipartFile对象的方法》在许多JavaWeb应用中,我们经常会遇到将本地文件上传至服务器或其他系统的需求,在这种场景下,MultipartFile对象非... 目录1. 基本需求2. 自定义 MultipartFile 类3. 实现代码4. 代码解析5. 自定

Spring-DI依赖注入全过程

《Spring-DI依赖注入全过程》SpringDI是核心特性,通过容器管理依赖注入,降低耦合度,实现方式包括组件扫描、构造器/设值/字段注入、自动装配及作用域配置,支持灵活的依赖管理与生命周期控制,... 目录1. 什么是Spring DI?2.Spring如何做的DI3.总结1. 什么是Spring D

spring AMQP代码生成rabbitmq的exchange and queue教程

《springAMQP代码生成rabbitmq的exchangeandqueue教程》使用SpringAMQP代码直接创建RabbitMQexchange和queue,并确保绑定关系自动成立,简... 目录spring AMQP代码生成rabbitmq的exchange and 编程queue执行结果总结s

Java调用Python脚本实现HelloWorld的示例详解

《Java调用Python脚本实现HelloWorld的示例详解》作为程序员,我们经常会遇到需要在Java项目中调用Python脚本的场景,下面我们来看看如何从基础到进阶,一步步实现Java与Pyth... 目录一、环境准备二、基础调用:使用 Runtime.exec()2.1 实现步骤2.2 代码解析三、

聊聊springboot中如何自定义消息转换器

《聊聊springboot中如何自定义消息转换器》SpringBoot通过HttpMessageConverter处理HTTP数据转换,支持多种媒体类型,接下来通过本文给大家介绍springboot中... 目录核心接口springboot默认提供的转换器如何自定义消息转换器Spring Boot 中的消息

Springboot项目构建时各种依赖详细介绍与依赖关系说明详解

《Springboot项目构建时各种依赖详细介绍与依赖关系说明详解》SpringBoot通过spring-boot-dependencies统一依赖版本管理,spring-boot-starter-w... 目录一、spring-boot-dependencies1.简介2. 内容概览3.核心内容结构4.

Spring Boot 整合 SSE(Server-Sent Events)实战案例(全网最全)

《SpringBoot整合SSE(Server-SentEvents)实战案例(全网最全)》本文通过实战案例讲解SpringBoot整合SSE技术,涵盖实现原理、代码配置、异常处理及前端交互,... 目录Spring Boot 整合 SSE(Server-Sent Events)1、简述SSE与其他技术的对

Spring Security 前后端分离场景下的会话并发管理

《SpringSecurity前后端分离场景下的会话并发管理》本文介绍了在前后端分离架构下实现SpringSecurity会话并发管理的问题,传统Web开发中只需简单配置sessionManage... 目录背景分析传统 web 开发中的 sessionManagement 入口ConcurrentSess