Java入门到超神(全网整理的复习资料)

 本人非常感谢各位突如其来的关注,这是你们对我整理的内容的一种认可,我将全心认真的持续整理更新,让各位对Java感兴趣的同伴阅读起来的时候通俗易懂,当然小弟有写的不好的地方,还望大家多多留言,我将不断更新。

注意:转载请标明出处,如承担法律责任本人概不负责。

目录

第一章:Java语言概述

1.1:软件开发的介绍

1.2:软件开发介绍

1.3:计算机编程语言介绍

1.4:Java语言的概述

1.5:Java语言的概述:简史

1.6 :Java技术体系平台

1.7:Java在各个平台的应用

1.8:Java语言的诞生

1.9:Java语言的主要特性

2.0:Java程序运行机制及运行过程

2.1:Java语言的环境搭建

2.1.1:什么是JDK,JRE

2.1.3:下载并安装JDK

2.2:注释

2.3:Java API的文档

第2章:基础语法

 1:关键字和保留字

2:标识符(Identifier)

3:变量

3.1:变量的分类按数据类

3.2:整数类型:byte、short、int、long

3.3:浮点类型:float、double

3.4:字符类型:char

3.5:布尔类型:boolean

3.6:基本数据类型转换

3.7:字符串类型:String

3.8:强制类型转换

3.9:变量之进制

4:运算符

4.1:算术运算符的注意问题

4.2:赋值运算符

4.3:比较运算符

4.3:逻辑运算符

4.4:位运算符

5:程序流程控制

5.1:程序流程控制:顺序结构

5.2:程序流程控制:if-else结构

5.3:switch-case结构

5.4:程序流程控制:循环结构

5.4.1:for循环

5.4.2:while循环

5.4.3:do...while

 5.4.4:嵌套循环(多重循环)

5.4.4:特殊关键字的使用:break、continue

5.4.5:程序流程控制:课后项目

第3章:数组

3.1:数组的概述

3.2:一堆数组的使用

3.2.1:数组声明方式

3.2.2:一维数组的使用:初始化

3.3:多维数组的使用

3.4:数组中涉及到的常见算法

3.4.2:冒泡算法

3.5:Arrays工具类的使用

3.6:数组使用中的常见异常

第4章:面向对象编程(上)

4.1学习路线

4.1.1面向过程与面向对象

4.1.2面向对象的思想概述

4.1.3:java的基本元素:类和对象

4.1.4:对象创建和使用

4.1.5:类的成员之一:属性

4.1.6:类的成员之二:方法

4.1.7:再谈方法

4.1.8:OOP特征一:封装与隐藏

4.1.8.1四种访问权限修饰符

4.1.9:类的成员之三:构造器

4.1.9:关键字:this

4.1.10关键字:package,import

4.1.11:本节面试题

第5章:面向对象编程(中)

5.1:面向对象特征二:继承性

5.2:方法的重写(override)

5.3:四种访问权限修饰符

5.4:关键字:super

5.5:子类对象实例化过程

5.6:面向对象特征三:多态性

5.6.1:虚拟方法调用(Virtual Method Invocation)

5.6.2:小结:方法的重载与重写

5.6.3:多态小结

5.6.4:面试题

5.6.5:子类对象实例化过程

5.8:Object类的使用

5.8.1:==操作符与equals方法

5.8.2面试题

5.8.3:toString()使用

5.8.4:JUnit单元测试

5.9:包装类的使用

5.9.1:总结:基本类型、包装类与String类间的转换

5.9.3:面试题



第一章:Java语言概述

1.1:软件开发的介绍

  1. 软件开发

    1. 软件即一系列按照特定顺序组织的计算机数据和指令的集合。有系统软件应用软件之分

  2. 人机交互方式

    1. 图形化界面(Graphical User Interface GUI)这种方式简单直观,使用者易于接受,容易操作上手

    2. 命令行方式(Command Line Interface CLI):需要有一个控制台,输入特定的指令,让计算机完成一些操作。较为麻烦,需要记录住一些命令。

1.2:软件开发介绍

  1. 常用的DOS命令

    1. dir:列出当前目录下的文件以及文件夹

    2. md:创建目录

    3. rd:删除目录

    4. cd:进入指定目录

    5. cd..:返回上一级目录

    6. cd\:退回根目录

    7. del:删除文件

    8. exit:退出dos命令行

1.3:计算机编程语言介绍

  1. 什么是计算机语言

    1. 语言:是人与人之间用于沟通的一种方式。例如:中国人与中国人用普通话沟通。而中国人要和英国人交流,就要学习英语。

  2. 计算机语言:人与计算机交流的方式。

    1. 如果人要与计算机交流,那么就要学习计算机语言。

  3. 计算机语言有很多种。如:C ,C++ ,Java ,PHP , Kotlin,Python,Scala等。

  4. 第一代语言

    1. 机器语言。指令以二进制代码形式存在。

  5. 第二代语言

    1. 汇编语言。使用助记符表示一条机器指令。

  6. 第三代语言:高级语言**

    1. C、Pascal、Fortran面向过程的语言

    2. C++面向过程/面向对象

    3. Java跨平台的纯面向对象的语言

    4. .NET跨语言的平台

    5. Python、Scala…

1.4:Java语言的概述

  • 是SUN(Stanford University Network,斯坦福大学网络公司 ) 1995年推出的一

门高级编程语言。

  • 是一种面向Internet的编程语言。Java一开始富有吸引力是因为Java程序可以

在Web浏览器中运行。这些Java程序被称为Java小程序(applet)。applet使

用现代的图形用户界面与Web用户进行交互。 applet内嵌在HTML代码中。

  • 随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。

后台开发:Java、PHP、Python、Go、Node.js

1.5:Java语言的概述:简史

​​​​​

  • 1991年 Green项目,开发语言最初命名为Oak (橡树)

  • 1994年,开发组意识到Oak 非常适合于互联网

  • 1996年,发布JDK 1.0,约8.3万个网页应用Java技术来制作

  • 1997年,发布JDK 1.1,JavaOne会议召开,创当时全球同类会议规模之最

  • 1998年,发布JDK 1.2,同年发布企业平台J2EE

  • 1999年,Java分成J2SE、J2EE和J2ME,JSP/Servlet技术诞生

  • 2004年,发布里程碑式版本:JDK 1.5,为突出此版本的重要性,更名为JDK 5.0

  • 2005年,J2SE -> JavaSE,J2EE -> JavaEE,J2ME -> JavaME

  • 2009年,Oracle公司收购SUN,交易价格74亿美元

  • 2011年,发布JDK 7.0

  • 2014年,发布JDK 8.0,是继JDK 5.0以来变化最大的版本

  • 2017年,发布JDK 9.0,最大限度实现模块化

  • 2018年3月,发布JDK 10.0,版本号也称为18.3

  • 2018年9月,发布JDK 11.0,版本号也称为18.9

1.6 :Java技术体系平台

  1. Java SE(Java Standard Edition)标准版

    1. 支持面向桌面级应用(如Windows下的应用程序)的Java平台,提供了完整的Java核心API,此版本以前称为J2SE

  2. Java EE(Java Enterprise Edition)企业版

    1. 是为开发企业环境下的应用程序提供的一套解决方案。该技术体系中包含的技术如Servlet 、Jsp等,主要针对于Web应用程序开发。版本以前称为J2EE

  3. Java ME(Java Micro Edition)小型版

    1. 支持Java程序运行在移动终端(手机、PDA)上的平台,对Java API有所精简,并加

  4. 入了针对移动终端的支持,此版本以前称为J2ME
  5. Java Card

    1. 支持一些Java小程序(Applets)运行在小内存设备(如智能卡)上的平台

1.7:Java在各个平台的应用

从Java的应用领域来分,Java语言的应用方向主要表现在以下几个方面:

  • 企业级应用:主要指复杂的大企业的软件系统、各种类型的网站。Java的安全机制以及

它的跨平台的优势,使它在分布式系统领域开发中有广泛应用。应用领域包括金融、电

信、交通、电子商务等。

  • Android平台应用:Android应用程序使用Java语言编写。Android开发水平的高低

很大程度上取决于Java语言核心能力是否扎实。

  • 大数据平台开发:各类框架有Hadoop,spark,storm,flink等,就这类技术生态

圈来讲,还有各种中间件如flume,kafka,sqoop等等 ,这些框架以及工具大多数

是用Java编写而成,但提供诸如Java,scala,Python,R等各种语言API供编程。

  • 移动领域应用:主要表现在消费和嵌入式领域,是指在各种小型设备上的应用,包括手

机、PDA、机顶盒、汽车通信设备等。

1.8:Java语言的诞生

java之父James Gosling团队在开发”Green”项目时,发现C缺少垃圾回收系统,还有可移植的安

全性、分布程序设计和多线程功能。最后,他们想要一种易于移植到各种设备上的平台。

Java确实是从C语言和C++语言继承了许多成份,甚至可以将Java看成是类C语言发展和衍生的产物。比如Java语言的变量声明,操作符形式,参数传递,流程控制等方面和C语言、C++语言完全相同。但同时,Java是一个纯粹的面向对象的程序设计语言,它继承了C++语言面向对象技术的核心。Java舍弃了C语言中容易引起错误的指针(以引用取代)、运算符重载(operator overloading)、多重继承(以接口取代)等特性,增加了垃圾回收器功能用于回收不再被引用的对象所占据的内存空间。JDK1.5又引入了泛型编程(Generic Programming)、类型安全的枚举、不定长参数和自动装/拆箱。

1.9:Java语言的主要特性

  • Java语言是易学的。

  • Java语言的语法与C语言和C++语言很接近,使得大多数程序员很容易学习和使用Java。

  • Java语言是强制面向对象的。

  • Java语言提供类、接口和继承等原语,为了简单起见,只支持类之间的单继承,但支持接口之间的多继承,并支持类与接口之间的实现机制(关键字为implements)。

  • Java语言是分布式的。

  • Java语言支持Internet应用的开发,在基本的Java应用编程接口中有一个网络应用编程接口(java net),它提供了用于网络应用编程的类库,包括URL、URLConnection、Socket、ServerSocket等。Java的RMI(远程方法激活)机制也是开发分布式应用的重要手段。

  • Java语言是健壮的。

    • Java的强类型机制、异常处理、垃圾的自动收集等是Java程序健壮性的重要保证。对指针的丢弃是Java的明智选择。

  • Java语言是安全的。

    Java通常被用在网络环境中,为此,Java提供了一个安全机制以防恶意代码的攻击。如:安全防范机制(类ClassLoader),如分配不同的名字空间以防替代本地的同名类、字节代码检查。

  • Java语言是体系结构中立的。

    • Java程序(后缀为java的文件)在Java平台上被编译为体系结构中立的字节码格式(后缀为class的文件),然后可以在实现这个Java平台的任何系统中运行。

  • Java语言是解释型的

    • 如前所述,Java程序在Java平台上被编译为字节码格式,然后可以在实现这个Java平台的任何系统的解释器中运行。

  • Java是性能略高的

    • 与那些解释型的高级脚本语言相比,Java的性能还是较优的。

  • Java语言是原生支持多线程的。

    • 在Java语言中,线程是一种特殊的对象,它必须由Thread类或其子(孙)类来创建。

2.0:Java程序运行机制及运行过程

  • Java语言的特点

    • 特点一:面向对象

      • 两个基本概念:类、对象

      • 三大特性:封装、继承、多态

    • 特点二:健壮性

      • 吸收了C/C++语言的优点,但去掉了其影响程序健壮性的部分(如指针、内存的申请与释放等),提供了一个相对安全的内存管理和访问机制

    • 特点三:跨平台性

      • 跨平台性:通过Java语言编写的应用程序在不同的系统平台上都可以运行。Writeonce , Run Anywhere

      • 原理:只要在需要运行 java 应用程序的操作系统上,先安装一个Java虚拟机 (JVM JavaVirtual Machine) 即可。由JVM来负责Java程序在该系统中的运行。

  • Java两种核心机制

    • Java虚拟机 (Java Virtal Machine)

      • 核心机制**—Java虚拟机JVM是一个虚拟的计算机,具有指令集并使用不同的存储区域。负责执行指令,管理数据、内存、寄存器。

      • 对于不同的平台,有不同的虚拟机。

      • 只有某平台提供了对应的java虚拟机,java程序才可在此平台运行

      • Java虚拟机机制屏蔽了底层运行平台的差别,实现了“一次编译,到处运行”

      • 垃圾收集机制 (Garbage Collection)

        • 不再使用的内存空间应回收—— 垃圾回收。

          • 在C/C++等语言中,由程序员负责回收无用内存。

          • Java 语言消除了程序员回收无用内存空间的责任:它提供一种系统级线程跟踪存储空间的分配情况。并在JVM空闲时,检查并释放那些可被释放的存储空间。

        • 垃圾回收在Java程序运行过程中自动进行,程序员无法精确控制和干预。

        • Java程序还会出现内存泄漏和内存溢出问题吗?Yes!

2.1:Java语言的环境搭建

  • 明确什么是JDK, JRE

  • 下载 JDK

  • 安装 JDK

  • 配置环境变量

    • path:windows系统执行命令时要搜寻的路径。

  • 验证是否成功:javac java

  • 选择合适的文本编辑器或 IDE 开发

2.1.1:什么是JDK,JRE

  • JDK(Java Development Kit Java开发工具包)

  • JDK是提供给Java开发人员使用的,其中包含了java的开发工具,也包括了JRE。所以安装了JDK,就不用在单独安装JRE了。

    • 其中的开发工具:编译工具(javac.exe) 打包工具(jar.exe)等

  • JRE(Java Runtime Environment Java运行环境)

    • 包括Java虚拟机(JVM Java Virtual Machine)和Java程序所需的核心类库等,如果想要运行一个开发好的Java程序,计算机中只需要安装JRE即可。

 

 

2.1.3:下载并安装JDK

官方网址:

www.oracle.com

java.sun.com

安装JDK

傻瓜式安装,下一步即可。

建议:安装路径不要有中文或者空格等特殊符号。

如果操作系统是64位的,软件尽量选择支持64位的(除非软件本身不区分)。

当提示安装 JRE 时,正常在JDK安装时已经装过了,但是为了后续使用Eclipse等开发

工具不报错,建议也根据提示安装JRE

具体安装查看教程

JDK安装&&环境配置(小白详细教程)_不_yu的博客-CSDN博客

2.2:注释

  • 用于注解说明解释程序的文字就是注释。

  • Java中的注释类型:

    • 单行注释

    • 多行注释

    • 文档注释 (java特有)

  • 提高了代码的阅读性;调试程序的重要方法。

  • 注释是一个程序员必须要具有的良好编程习惯。

  • 将自己的思想通过注释先整理出来,再用代码去体现

  • 单行注释

    • 格式: //注释文字

  • 多行注释

    • 格式: /* 注释文字 */

  • 注:

    • 对于单行和多行注释,被注释的文字,不会被JVM(java虚拟机)解释执行。

    • 多行注释里面不允许有多行注释嵌套。

  • 文档注释(Java特有)

    • 格式:/*

      @author 指定java程序的作者

      @version 指定源文件的版本*/

  • 注释内容可以被JDK提供的工具 javadoc 所解析,生成一套以网页文件形式体现的该程序的说明文档。

  • 操作方式

  • Java入门到超神(全网整理的复习资料)_第1张图片

     

    2.3:Java API的文档

  • API (Application Programming Interface,应用程序编程接口)是 Java 提供的基本编程接口。

  • Java语言提供了大量的基础类,因此 Oracle 也为这些基础类提供了相应的API文档,用于告诉开发者如何使用这些类,以及这些类里包含的方法。

  • 下载API:

    • Java Downloads | Oracle

    • Additional Resources-Java SE 8 Documentation下载。

    • 详见:JDK8的下载-安装-配置.doc。

第2章:基础语法

 1:关键字和保留字

  • 关键字(keyword)的定义和特点

    • 定义:被Java语言赋予了特殊含义,用做专门用途的字符串(单词)

    • 特点:关键字中所有字母都为小写

    • 官方地址: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html

    • Java入门到超神(全网整理的复习资料)_第2张图片

    • 保留字(reserved word)

      • Java保留字:现有Java版本尚未使用,但以后版本可能会作为关键字使用。自己命名标识符时要避免使用这些保留字。goto 、const

2:标识符(Identifier)

  • 标识符:

    • Java 对各种变量方法等要素命名时使用的字符序列称为标识符

    • 技巧:凡是自己可以起名字的地方都叫标识符。

  • 定义合法标识符规则:

    • 由26个英文字母大小写,0-9 ,_ $ 组成

    • 数字不可以开头。

    • 不可以使用关键字和保留字,但能包含关键字和保留字。

    • Java中严格区分大小写,长度无限制。

    • 标识符不能包含空格。

  • Java中的名称命名规范:

    • 包名:多单词组成时所有字母都小写:xxxyyyzzz

    • 类名、接口名:多单词组成时,所有单词的首字母大写:XxxYyyZzz

    • 变量名、方法名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写:xxxYyyZzz

    • 常量名:所有字母都大写。多单词时每个单词用下划线连接:XXX_YYY_ZZZ

  • 注意1:在起名字时,为了提高阅读性,要尽量有意义,“见名知意”。

  • 注意2:java采用unicode字符集,因此标识符也可以使用汉字声明,但是不建议使用。

3:变量

  • 变量的概念。

    • 内存中的一个存储区域

    • 该区域的数据可以在同一类型范围内不断变化

    • 变量是程序中最基本的存储单元。包含变量类型、变量名和存储的值

  • 变量的作用:

    • 用于在内存中保存数据

  • 使用变量注意:

    • Java中每个变量必须先声明,后使用

    • 使用变量名来访问这块区域的数据

    • 变量的作用域:其定义所在的一对{ }内

    • 变量只有在其作用域内才有效

    • 同一个作用域内,不能定义重名的变量

  • 声明变量

    • 语法:<数据类型> <变量名称>

    • 例如:int var;

  • 变量的赋值

    • 语法:<变量名称> = <值>

    • 例如:var = 10;

  • 声明和赋值变量

    • 语法: <数据类型> <变量名> = <初始化值>

    • 例如:int var = 10;

3.1:变量的分类按数据类型

  • 对于每一种数据都定义了明确的具体数据类型(强类型语言),在内存中分配了不同大小的内存空间。

 

补充:变量的分类-按声明的位置的不同

  • 在方法体外,类体内声明的变量称为成员变量

  • 在方法体内部声明的变量称为局部变量

3.2:整数类型:byte、short、int、long

  • Java各整数类型有固定的表数范围和字段长度,不受具体OS的影响,以保证java程序的可移植性。

  • java的整型常量默认为 int 型,声明long型常量须后加‘l’或‘L’

  • java程序中变量通常声明为int型,除非不足以表示较大的数,才使用long

500MB 1MB = 1024KB 1KB= 1024B B= byte ? bit?

bit: 计算机中的最小存储单位。byte:计算机中基本存储单元。

public class VariableTest {

 public static void main(String[] args) {

	int number1;
	number1 = 10;
	int number2;
	number2 = 20;
	int number3;
	number3 = number1 + number2;
	System.out.println("Number3 = " + number3);
	int number4 = 50;
	int number5 = number4 - number3;
	System.out.println("Number5 = " + number5);
	}

}

3.3:浮点类型:float、double

  • 与整数类型类似,Java 浮点类型也有固定的表数范围和字段长度,不受具体操作系统的影响。

  • 浮点型常量有两种表示形式:

    • 十进制数形式:如:5.12 512.0f .512 (必须有小数点)

    • 科学计数法形式:如:5.12e2 512E2 100E-2

  • float:单精度,尾数可以精确到7位有效数字。很多情况下,精度很难满足需求。

  • double:双精度,精度是float的两倍。通常采用此类型。

Java 的浮点型常量默认为double型声明float型常量,须后加‘f’或‘F’。

Java入门到超神(全网整理的复习资料)_第3张图片

3.4:字符类型:char

  • char 型数据用来表示通常意义上“字符”(2字节)

  • Java中的所有字符都使用Unicode编码,故一个字符可以存储一个字母,一个汉字,或其他书面语的一个字符。

  • 字符型变量的三种表现形式:

    • 字符常量是用单引号(‘ ’)括起来的单个字符。例如:char c1 = 'a'; char c2 = '中'; char c3 = '9';

    • Java中还允许使用转义字符‘\’来将其后的字符转变为特殊字符型常量。例如:char c3 = ‘\n’; // '\n'表示换行符

    • 直接使用 Unicode 值来表示字符型常量:‘\uXXXX’。其中,XXXX代表一个十六进制整数。如:\u000a 表示 \n。

  • char类型是可以进行运算的。因为它都对应有Unicode码。

3.5:布尔类型:boolean

  • boolean 类型用来判断逻辑条件,一般用于程序流程控制:

    • if条件控制语句;

    • while循环控制语句;

    • do-while循环控制语句;

    • for循环控制语句;

  • boolean类型数据只允许取值true和false,无null。

    • 不可以使用0或非 0 的整数替代false和true,这点和C语言不同。

    • Java虚拟机中没有任何供boolean值专用的字节码指令,Java语言表达所操作的boolean值,在编译之后都使用java虚拟机中的int数据类型来代替:true用1表示,false用0表示。———《java虚拟机规范 8版》

3.6:基本数据类型转换

  • 自动类型转换:容量小的类型自动转换为容量大的数据类型。数据类型按容量大小排序为:

  • 有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的那种数据类型,然后再进行计算。

  • byte,short,char之间不会相互转换,他们三者在计算时首先转换为int类型。

  • boolean类型不能与其它数据类型运算。

  • 当把任何基本数据类型的值和字符串(String)进行连接运算时(+),基本数据类型的值将自动转化为字符串(String)类型。

3.7:字符串类型:String

  • String不是基本数据类型,属于引用数据类型

  • 使用方式与基本数据类型一致。例如:String str = “abcd”;

  • 一个字符串可以串接另一个字符串,也可以直接串接其他类型的数据。例如:

str = str + “xyz” ; 
int n = 100;
str = str + n;

//示 例—StringTest类
public class StringTest {
 public static void main(String[] args) {
 int no = 10;
 String str = "abcdef";
 String str1 = str + “xyz” + no;
 str1 = str1 + "123";
 char c = '国';
 double pi = 3.1416;
 str1 = str1 + pi;
 boolean b = false;
 str1 = str1 + b;
 str1 = str1 + c;
 System.out.println("str1 = " + str1);
 }
}

//练习1
String str1 = 4; //判断对错:no
String str2 = 3.5f + “”; //判断str2对错:yes
System.out.println(str2); //输出:”3.5”
System.out .println(3+4+“Hello!”); //输出:7Hello!
System.out.println(“Hello!”+3+4); //输出:Hello!34
System.out.println(‘a’+1+“Hello!”); //输出:98Hello!
System.out.println(“Hello”+‘a’+1); //输出:Helloa1

3.8:强制类型转换

  • 自动类型转换的逆过程,将容量大的数据类型转换为容量小的数据类型。使用时要加上强制转换符:(),但可能造成精度降低或溢出,格外要注意。

  • 通常,字符串不能直接转换为基本类型,但通过基本类型对应的包装类则可以实现把字符串转换成基本类型。

    • 如: String a = “43”; int i = Integer.parseInt(a);

    • boolean类型不可以转换为其它的数据类型。

  • 练习2 
    1)short s = 5;
    	s = s-2; //判断:no
    2) byte b = 3;
    	b = b + 4; //判断:no
    	b = (byte)(b+4); //判断:yes
    3)char c = ‘a’;
        int i = 5;
        float d = .314F;
        double result = c+i+d; //判断:yes
    4) byte b = 5;
        short s = 3;
        short t = s + b; //判断:no.9:

3.9:变量之进制

关于进制

  • 所有数字在计算机底层都以二进制形式存在。

  • 对于整数,有四种表示方式:

    • 二进制(binary):0,1 ,满2进1.以0b或0B开头。

    • 十进制(decimal):0-9 ,满10进1。

    • 八进制(octal):0-7 ,满8进1. 以数字0开头表示。

    • 十六进制(hex):0-9及A-F,满16进1. 以0x或0X开头表示。此处的A-F不区分大小写。

    • 如:0x21AF +1= 0X21B0

    • 二进制

    • Java整数常量默认是int类型,当用二进制定义整数时,其第32位是符号位;当是long类型时,二进制默认占64位,第64位是符号位

    • 二进制的整数有如下三种形式:

      • 原码:直接将一个数值换成二进制数。最高位是符号位

      • 负数的反码:是对原码按位取反,只是最高位(符号位)确定为1。

      • 负数的补码:其反码加1。

    • 计算机以二进制补码的形式保存所有的整数。

      • 正数的原码、反码、补码都相同

      • 负数的补码是其反码+1

    • 为什么要使用原码、反码、补码表示形式呢?

      计算机辨别“符号位”显然会让计算机的基础电路设计变得十分复杂! 于是人们想出了将符号位也参与运算的方法. 我们知道, 根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法, 这样计算机运算的设计就更简单了。

    •  

    • 4:运算符

      运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等。

    • 算术运算符

    • 赋值运算符

    • 比较运算符(关系运算符)

    • 逻辑运算符

    • 位运算符

    • 三元运算符

  • 4.1:算术运算符的注意问题

  • 如果对负数取模,可以把模数负号忽略不记,如:5%-2=1。 但被模数是负数则不可忽略。此外,取模运算的结果不一定总是整数。

  • 对于除号“/”,它的整数除和小数除是有区别的:整数之间做除法时,只保留整数部分而舍弃小数部分。 例如:int x=3510;x=x/1000*1000; x的结果是?

  • “+”除字符串相加功能外,还能把非字符串转换成字符串.例如:System.out.println(“5+5=”+5+5); //打印结果是? 5+5=55 ?

    //练习1:算术运算符:自加、自减
    public class SignTest{
    public static void main(String[] args){
        int i1 = 10;
        int i2 = 20;
        int i = i1++;
        System.out.print(“i=”+i);
        System.out.println(“i1=”+i1);
        i = ++i1;
        System.out.print(“i=”+i);
        System.out.println(“i1=”+i1);
        i = i2--;
        System.out.print(“i=”+i);
        System.out.println(“i2=”+i2);
        i = --i2;
        System.out.print(“i=”+i);
        System.out.println(“i2=”+i2);
    } }
    //练习2
    /*随意给出一个整数,打印显示它的个位数,十位数,百位数的值。
    格式如下:
    数字xxx的情况如下:
    个位数:
    十位数:
    百位数:
    例如:
    数字153的情况如下:
    个位数:3
    十位数:5
    百位数:1
    */
    
    public class AriExrr{
    public static void main(String[] args){
        int number = 153;
       	int bai = num/100;
        int shi = num%100/10;
        int ge  = num%10;
        System.out.print(“百位为:”+bai);
        System.out.println(“十位为:”+shi);
        System.out.println(“个位为:”+ge);
    	} 
    }

4.2:赋值运算符

  • 符号:=

    • 当“=”两侧数据类型不一致时,可以使用自动类型转换或使用强制类型转换原则进行处理。

    • 支持连续赋值。

  • 扩展赋值运算符: +=, -=, *=, /=, %=

思考1:
short s = 3; 
s = s+2; ①
s += 2; ② 
①和②有什么区别?
①:编译不通过
② :编译通过

思考2:
int i = 1;
i *= 0.1;
System.out.println(i);//0
i++;
System.out.println(i);//1


思考3:
int m = 2;
int n = 3;
n *= m++; //n= n * m++;
System.out.println("m=" + m);//3
System.out.println("n=" + n)//7

思考4:
int n = 10;
n += (n++) + (++n);// n = n+(n++)+(++n) 10+10+12 
System.out.println(n);

4.3:比较运算符

  • 比较运算符的结果都是boolean型,也就是要么是true,要么是false。

  • 比较运算符“==”不能误写成“=” 。

4.3:逻辑运算符

&—逻辑与

| —逻辑或

!—逻辑非

&& —短路与

|| —短路或

^ —逻辑异或

 

思考1:
boolean b1 = false;
//区分好==和=的区别。
if(b1==true)
System.out.println("结果为真");
else
System.out.println("结果为假");
//== 是判断两个元素是否相等,=则是将右边的元素赋值给左边

  • 逻辑运算符用于连接布尔型表达式,在Java中不可以写成33 & x<6 。

  • “&”和“&&”的区别:

    • 单&时,左边无论真假,右边都进行运算;

    • 双&时,如果左边为真,右边参与运算,如果左边为假,那么右边不参与运算。

  • “|”和“||”的区别同理,||表示:当左边为真,右边不参与运算。

  • 异或( ^ )与或( | )的不同之处是:当左右都为true时,结果为false。

    • 理解:异或,追求的是“异”!

//练习:请写出每题的输出结果
int x = 1;
int y=1;
if(x++==2 & ++y==2){
	x =7;
}
System.out.println("x="+x+",y="+y);	//x =2,y =2

int x = 1,y = 1;
if(x++==2 && ++y==2){
x =7;
}
System.out.println("x="+x+",y="+y); //x=2,y=2

int x = 1,y = 1;
if(x++==1 | ++y==1){
x =7;
}
System.out.println("x="+x+",y="+y);

int x = 1,y = 1;
if(x++==1 || ++y==1){
x =7;
}
System.out.println("x="+x+",y="+y);

//【面试题】程序输出
class Test {
 public static void main (String [] args) {
 boolean x=true;
 boolean y=false;
 short z=42;
 //if(y == true)
 if((z++==42)&&(y=true))z++;
 if((x=false) || (++z==45)) z++;

 System. out.println(“z=”+z);
  }
}
//结果为:46

4.4:位运算符

 

 

 

 

 

 

 

  • 位运算是直接对整数的二进制进行的运算

  • 运算符有不同的优先级,所谓优先级就是表达式运算中的运算顺序。如下表,上一行运算符总优先于下一行。

  • 只有单目运算符、三元运算符、赋值运算符是从右向左运算的。

 

  /**
         * 运算符:三目运算符
         * 1.结构:(表达式)1 ? 表达式1:表达式2
         * 2.说明
         *  1:条件表达式的结果为boolean类型
         *  2:根据条件表达式真或假,决定执行表达式1,还是表达式2
         *      如果表达式为true,则执行表达式1
         *      如果表达式为false,则执行表达式2
         */
        //获取两个数最大的值
        int m = 12;
        int n = 5;
        int max = (m>n) ? m : n ;
        System.out.println(max);

5:程序流程控制

  • 顺序结构

    • 程序从上到下逐行地执行,中间没有任何判断和跳转。

  • 分支结构

    • 根据条件,选择性地执行某段代码。

    • 有if…else和switch-case两种分支语句。

  • 循环结构

    • 根据循环条件,重复性的执行某段代码。

    • 有while、do…while、for三种循环语句。

    • 注:JDK1.5提供了foreach循环,方便的遍历集合、数组元素。

5.1:程序流程控制:顺序结构

 

5.2:程序流程控制:if-else结构

 

分支结构:if-else使用说明

  • 条件表达式必须是布尔表达式(关系表达式或逻辑表达式)、布尔变量

  • 语句块只有一条执行语句时,一对{}可以省略,但建议保留

  • if-else语句结构,根据需要可以嵌套使用

  • 当if-else结构是“多选一”时,最后的else是可选的,根据需要可以省略

  • 当多个条件是“互斥”关系时,条件判断语句及执行语句间顺序无所谓

  • 当多个条件是“包含”关系时,“小上大下 / 子上父下”

if-else语句应用举例
public class AgeTest{
public static void main(String args[]){
    int age = 75;
    if (age< 0) {
        System.out.println("不可能!");
    } else if (age>250) {
        System.out.println("是个妖怪!");
    } else {
        System.out.println(“人家芳龄 " + age +" ,马马乎乎啦!");
    }
 } 
}
/*if语句例题1
岳小鹏参加Java考试,他和父亲岳不群达成承诺:
如果:
成绩为100分时,奖励一辆BMW;
成绩为(80,99]时,奖励一台iphone xs max;
当成绩为[60,80]时,奖励一个 iPad;
其它时,什么奖励也没有。
请从键盘输入岳小鹏的期末成绩,并加以判断*/
                     //用户输入成绩
        Scanner scanner = new Scanner(System.in);
        double nextDouble = scanner.nextDouble();
        System.out.println("请输入你的学习成绩");
        //double yuexiappeng = scanner;
        System.out.println(nextDouble);
        if (nextDouble == 100){
            System.out.println("奖励一辆BMW");
        }else if (nextDouble < 99 || nextDouble <= 80){
            System.out.println("奖励一台iphone xs max");
        }else if (nextDouble < 80 || nextDouble <= 60){
            System.out.println("奖励一个 iPad");
        }else if (nextDouble < 59){
            System.out.println("啥也没有");
        }
 //if语句例题2 编写程序:由键盘输入三个整数分别存入变量num1、num2、num3,对它们进行排序(使用 if-else if-else),并且从小到大输出。
        Scanner scanner = new Scanner(System.in);
        int num1 = scanner.nextInt();
        System.out.println("用户输入:"+num1);
        int num2 = scanner.nextInt();
        System.out.println("用户输入:"+num2);
        int num3 = scanner.nextInt();
        int max = 0;
        System.out.println("用户输入:"+num3);

        if(num1 >= num2 ){
            if(num3 >= num1){
                System.out.println(num2+","+num1+","+num3);
            }else if (num3 <= num1){
                System.out.println(num3+","+num1+","+num2);
            }else {
                System.out.println(num1+","+num3+","+num2);
            }
        }else{
            if (num3 >= num2){
                System.out.println(num1+","+num2+","+num3);
            }else if (num3 <= num1){
                System.out.println(num3+","+num1+","+num2);
            }else{
                System.out.println(num1+","+num3+","+num2);
            }
        }
                   
                   
1)//对下列代码,若有输出,指出输出结果。
    int x = 4;
    int y = 1;
    if (x > 2) {
	    if (y > 2) 
		System.out.println(x + y);
	    System.out.println("atguigu");
    } else{
	System.out.println("x is " + x);
}
2) 
    boolean b = true;
//如果写成if(b=false)能编译通过吗?如果能,结果是?
if(b == false) 
System.out.println("a");
else if(b)
System.out.println("b");
else if(!b)
System.out.println("c");
else
System.out.println("d");

/**    if语句练习2
1) 编写程序,声明2个int型变量并赋值。判断两数之和,如果大于等
于50,打印“hello world!”
2) 编写程序,声明2个double型变量并赋值。判断第一个数大于10.0,
且第2个数小于20.0,打印两数之和。否则,打印两数的乘积。
3) 我家的狗5岁了,5岁的狗相当于人类多大呢?其实,狗的前两年每
一年相当于人类的10.5岁,之后每增加一年就增加四岁。那么5岁的狗
相当于人类多少年龄呢?应该是:10.5 + 10.5 + 4 + 4 + 4 = 33岁。
编写一个程序,获取用户输入的狗的年龄,通过程序显示其相当于人
类的年龄。如果用户输入负数,请显示一个提示信息。*/
    //1
     int a = 20;
     int b = 39;
     if(a+b >=50){
         System.out.println("helloword");
       }
    //2
    //        double dou1 = 19.2;
	//        double dou2 = 15.2;
        double dou1 = 9.2;
        double dou2 = 20.2;
        if (dou1 > 10.0 && dou2 <20.0){
            System.out.println(dou1+dou2);
        }else{
            System.out.println(dou1 * dou2);
        }
    //3
     Scanner scanner = new Scanner(System.in);
        int dogAge = scanner.nextInt();

        if(dogAge >= 0 && dogAge <= 2 ){
            System.out.println("相当于人的年龄:"+dogAge*10.5);
        }else if(dogAge>2){
            System.out.println("相当于人的年龄:"+(dogAge*10.5+(dogAge-2)*4));
        }else{
            System.out.println("狗狗还没出身");
        }
    
/** if语句练习3
假设你想开发一个玩彩票的游戏,程序随机地产生一个两位数的彩票,提示用户输入
一个两位数,然后按照下面的规则判定用户是否能赢。
1)如果用户输入的数匹配彩票的实际顺序,奖金10 000美元。
2)如果用户输入的所有数字匹配彩票的所有数字,但顺序不一致,奖金 3 000美元。
3)如果用户输入的一个数字仅满足顺序情况下匹配彩票的一个数字,奖金1 000美元。
4)如果用户输入的一个数字仅满足非顺序情况下匹配彩票的一个数字,奖金500美元。
5)如果用户输入的数字没有匹配任何一个数字,则彩票作废。
提示:使用(int)(Math.random() * 90 + 10)产生随机数。
Math.random() : [0,1) * 90 [0,90) + 10 [10,100)  [10,99]
*/
       //随机生成一个random随机数
        int i = (int) (Math.random() * 90 + 10);
        //System.out.println(i);
        int iShi = i / 10;
        int iGe = i % 10;
        //用户输入
        Scanner scanner = new Scanner(System.in);
        int nextInt = scanner.nextInt();
        System.out.println("您本次输入的中奖号码为:"+nextInt);

        int nextIntShi = nextInt/10;
        int nextIntGe = nextInt%10;

        if (nextInt == i ){
            System.out.println("奖励10000美金");
        }else if(nextIntShi == iGe && nextIntGe == iShi){
            System.out.println("奖励3000美金");
        }else if(nextIntShi == iShi || nextIntGe == iGe){
            System.out.println("奖励1000美金");
        }else if(nextIntShi == iGe || nextIntGe == iShi){
            System.out.println("奖励500美金");
        }else{
            System.out.println("没有中奖");
        }
        System.out.println("本期中奖号码为:"+i);
/**
if语句练习4
大家都知道,男大当婚,女大当嫁。那么女方家长要嫁女儿,当然要提出
一定的条件:高:180cm以上;富:财富1千万以上;帅:是。
 如果这三个条件同时满足,则:“我一定要嫁给他!!!”  如果三个条件有为真的情况,则:“嫁吧,比上不足,比下有余。”
 如果三个条件都不满足,则:“不嫁!”
Sysout(“身高: (cm))
scanner.nextInt();
Sysout(“财富: (千万))
scanner.nextDouble();
Sysout(“帅否: (true/false)) (是/否)
scanner.nextBoolean(); scanner.next(); “是”.equals(str)
*/
       Scanner scanner = new Scanner(System.in);
        System.out.println("请输入你的身高(cm)");
        int height = scanner.nextInt();

        System.out.println("请输入你的财富(千万)");
        double wealth = scanner.nextDouble();

        System.out.println("请输入你是否帅(false/true)");
        boolean isHandsome = scanner.nextBoolean();

        if (height >= 180 && wealth >=1 && isHandsome ==  true){
            System.out.println("我非你不嫁");
        }else if(height >= 180 || wealth >=1 || isHandsome ==  true){
            System.out.println("凑活算求");
        }else{
            System.out.println("我们不合适");
        }

5.3:switch-case结构

//switch语句应用举例
public class SwitchTest {
	public static void main(String args[]) {
        int i = 1;
        switch (i) {
            case 0:
            System.out.println("zero");
            break;
            case 1:
            System.out.println("one");
            break;
            default:
            System.out.println("default");
            break; 
		}
	} 
}
//switch语句应用举例
    String season = "summer";
    switch (season) {
        case "spring":
        System.out.println("春暖花开");
        break;
    case "summer":
        System.out.println("夏日炎炎");
        break;
    case "autumn":
        System.out.println("秋高气爽");
        break;
    case "winter":
        System.out.println("冬雪皑皑");
        break;
    default:
        System.out.println("季节输入有误");
        break; 
    }

 switch语句有关规则

  • switch(表达式)中表达式的值必须是下述几种类型之一:byte,short,char,int,枚举 (jdk 5.0),String (jdk 7.0);

  • case子句中的值必须是常量,不能是变量名或不确定的表达式值;

  • 同一个switch语句,所有case子句中的常量值互不相同;

  • break语句用来在执行完一个case分支后使程序跳出switch语句块;如

  • 果没有break,程序会顺序执行到switch结尾

  • default子句是可任选的。同时,位置也是灵活的。当没有匹配的case时,

  • 执行default

/*
		例 题
    1.使用 switch 把小写类型的 char型转为大写。只转换 a, b, c, d, e. 其它的输
    出 “other”。
    提示:String word = scan.next(); char c = word.charAt(0); switch(c){}
    2.对学生成绩大于60分的,输出“合格”。低于60分的,输出“不合格”。
    
    3.根据用于指定月份,打印该月份所属的季节。    
    3,4,5 春季 6,7,8 夏季 9,10,11 秋季 12, 1, 2 冬季
    
    4. 编写程序:从键盘上输入2019年的“month”和“day”,要求通过程序
    输出输入的日期为2019年的第几天。
*/
 Scanner scanner = new Scanner(System.in);
        System.out.println("请输入2019年的month:");
        int month = scanner.nextInt();

        System.out.println("请输入2019年的day:");
        int day = scanner.nextInt();

        //定义一个变量来保存总天数
        int sumDays = 0;
        switch (month){
            case 12:
                sumDays += 30;
            case 11:
                sumDays += 31;
            case 10:
                sumDays += 30;
            case 9:
                sumDays += 31;
            case 8:
                sumDays += 31;
            case 7:
                sumDays += 30;
            case 6:
                sumDays += 31;
            case 5:
                sumDays += 30;
            case 4:
                sumDays += 31;
            case 3:
                sumDays += 28;
            case 2:
                sumDays += 30;
            case 1:
                sumDays += day;

        }
        System.out.println("2019年"+month+"月"+day+"日是当年的第:"+sumDays+"天");

/*switch语句练习1
从键盘分别输入年、月、日,判断这一天是当年的第几天
注:判断一年是否是闰年的标准:
1)可以被4整除,但不可被100整除
或 
2)可以被400整除
*/
		Scanner scanner = new Scanner(System.in);
        System.out.println("请输入year:");
        int year = scanner.nextInt();
        System.out.println("请输入month");
        int month = scanner.nextInt();
        System.out.println("请输入day");
        int day = scanner.nextInt();
        //定义一个变量保存总天数
        int sumDays = 0;
        switch (month){
            case 12:
                sumDays += 30;
            case 11:
                sumDays += 31;
            case 10:
                sumDays += 30;
            case 9:
                sumDays += 31;
            case 8:
                sumDays += 31;
            case 7:
                sumDays += 30;
            case 6:
                sumDays += 31;
            case 5:
                sumDays += 30;
            case 4:
                sumDays += 31;
            case 3:
                if((year%4 == 0 && year%100 != 0 ) || year % 400 ==0 ){
                    sumDays += 29;
                }else{
                    sumDays += 28;
                }
            case 2:
                sumDays += 30;
            case 1:
                sumDays += day;
        }
        System.out.println(year + "年" + month + "月" + day + "日,截止共有:" +sumDays+"天" );
/*
switch语句练习
2 使用switch语句改写下列if语句:
    int a = 3;
    int x = 100;
    if(a==1)
    	x+=5;
    else if(a==2)
        x+=10;
    else if(a==3)
    	x+=16;
    else
    	x+=34;
*/
 		int a = 3;
        int x = 100;
        switch (a){
            case 1:
                System.out.println(x+=5);
                break;
            case 2:
                System.out.println(x+=10);
                break;
            case 3:
                System.out.println(x+=16);
                break;
            default:
                System.out.println(x+=34);
/*switch语句练习3
编写程序:从键盘上读入一个学生成绩,存放在变量score中,根据score的
值输出其对应的成绩等级:
score>=90 等级: A
70<=score<90 等级: B 
60<=score<70 等级: C
score<60 等级: D
方式一:使用if-else
方式二:使用switch-case: score / 10: 0 - 10
*/
 		int a = 3;
        int x = 100;
        switch (a){
            case 1:
                System.out.println(x+=5);
                break;
            case 2:
                System.out.println(x+=10);
                break;
            case 3:
                System.out.println(x+=16);
                break;
            default:
                System.out.println(x+=34);
                
                 System.out.println("请输入你的成绩");
        Scanner scanner = new Scanner(System.in);
        int score = scanner.nextInt();
        int scoreShi = score/10;
        switch (scoreShi){
            case 10:
                System.out.println("成绩非常优秀为A");
                break;
            case 9:
            case 8:
            case 7:
                System.out.println("成绩B等");
                break;
            case 6:
            case 5:
            case 4:
            case 3:
            case 2:
            case 1:
            case 0:
                System.out.println("成绩为D");
                break;
            default:
                System.out.println("输入不合法");
        }
 /**
 	switch语句练习4
    编写一个程序,为一个给定的年份找出其对应的中国生肖。中国的生肖基于12年一个周期,
    每年用一个动物代表:rat、ox、tiger、rabbit、dragon、snake、horse、sheep、monkey、
    rooster、dog、pig
*/

5.4:程序流程控制:循环结构

  • 循环结构

  • 在某些条件满足的情况下,反复执行特定代码的功能

  • 循环语句分类

    • for 循环

    • while 循环

    • do-while 循环

  • 循环语句的四个组成部分

    • 初始化部分(init_statement)

    • 循环条件部分(test_exp)

    • 循环体部分(body_statement)

    • 迭代部分(alter_statement)

    5.4.1:for循环

  • 语法格式

    for (①初始化部分; ②循环条件部分; ④迭代部分){

    ③循环体部分;

  • 执行过程:

    ①-②-③-④-②-③-④-②-③-④-.....-②

  • 说明:

    ②循环条件部分为boolean类型表达式,当值为false时,退出循环

    ①初始化部分可以声明多个变量,但必须是同一个类型,用逗号分隔

    ④可以有多个变量更新,用逗号分隔

 

//应用举例
public class ForLoop {
	public static void main(String args[]) {
    int result = 0;
    for (int i = 1; i <= 100; i++) {
    result += i; }
    System.out.println("result=" + result);
	} 
}
//for语句例题1
/*
编写程序从1循环到150,并在每行打印一个值,另外在每个3的倍数行
上打印出“foo”,在每个5的倍数行上打印“biz”,在每个7的倍数行上打印
输出“baz”。
*/
for (int i = 1; i <=150 ; i++) {
            System.out.print(i);
            if (i%3==0){
                System.out.print(" foo");
            }
            if (i%5==0){
                System.out.print(" biz");
            }
            if(i%7 == 0){
                System.out.print(" baz");
            }
            System.out.println();
        }
/**for语句例题2
题目:输入两个正整数m和n,求其最大公约数和最小公倍数。
比如:12和20的最大公约数是4,最小公倍数是60。
说明:break关键字的使用
*/
		Scanner scanner = new Scanner(System.in);
        System.out.println("请输入第一个正整数");
        int m = scanner.nextInt();
        System.out.println("请输入第二个正整数");
        int n = scanner.nextInt();
        //获取最大公约数
        //获取两个数中的较小值
        int min = (m <= n) ? m : n;
        for (int i = min ; i >= 1; i--){
            if (m%i == 0 && n%i == 0){
                System.out.println("最大公约数为:"+i);
                break;//一旦在循环中执行到break,就跳出
            }
        }

        //获取最小公倍数
        //1.获取两个数中的较大值
        int max = (m >= n) ? m : n ;
        //2.遍历
        for (int i = max; i < m * n; i++) {
            if (i%m == 0 && i%n == 0){
                System.out.println("最小公倍数:" +i);
                break;
            }
        }
/*for语句练习
1.打印1~100之间所有奇数的和
2.打印1~100之间所有是7的倍数的整数的个数及总和(体会设置计数
器的思想)
3.输出所有的水仙花数,所谓水仙花数是指一个3位数,其各个位上数
字立方和等于其本身。
例如: 153 = 1*1*1 + 3*3*3 + 5*5*5
*/
       // 1.打印1~100之间所有奇数的和
        //2.定义一个变量存储奇数之和
        int qiShu = 0;
        for (int i = 0; i <=100 ; i++) {
            if (i%2!=0){
                qiShu += i;
            }
        }
        System.out.println(qiShu);
		//2.打印1~100之间所有是7的倍数的整数的个数及总和(体会设置计数器的思想)
        //1:设置存储7的倍数
        int beiShu = 0;
        for (int i = 0; i <= 100 ; i++) {
            if (i % 7 == 0) {
                beiShu += i;
            }
        }
        System.out.println(beiShu);
 		//3.输出所有的水仙花数,所谓水仙花数是指一个3位数,其各个位上数
        // 字立方和等于其本身。
        for (int i = 100; i <1000 ; i++) {
            //提取百位
            int bai = i / 100;
            //提取十位
            int shi = i / 10 % 10;
            //提取个位
            int gei = i % 10;

            if (i ==(bai*bai*bai+shi*shi*shi+gei+gei+gei)){
                System.out.println("水仙花数为:"+i);

5.4.2:while循环

语法格式

①初始化部分

while(②循环条件部分){

③循环体部分;

④迭代部分;

}

执行过程:

①-②-③-④-②-③-④-②-③-④-...-②

说明:

注意不要忘记声明④迭代部分。否则,循环将不能结束,变成死循环。

for循环和while循环可以相互转换

//应用举例
public class WhileLoop {
	public static void main(String args[]) {
    int result = 0;
    int i = 1;
    while (i <= 100) {
    	result += i; 
        i++;
    }
    System.out.println("result=" + result);
	} 

5.4.3:do...while

  • 语法格式

    ①初始化部分;

    do{

    ③循环体部分

    ④迭代部分

    }while(②循环条件部分);

  • 执行过程:

    ①-③-④-②-③-④-②-③-④-...②

  • 说明:

    do-while循环至少执行一次循环体。

//应用举例
public class DoWhileLoop {
	public static void main(String args[]) {
    	int result = 0, i = 1;
        do {
        result += i; i++;
        } while (i <= 100);
    	System.out.println("result=" + result);
	} 
}
/*循环语句综合例题
题目:
从键盘读入个数不确定的整数,并判断读入的正数和负数的个数,输入
为0时结束程序。
最简单“无限” 循环格式:while(true) , for(;;),无限循环存在的原因是并不
知道循环多少次,需要根据循环体内部某些条件,来控制循环的结束。
		Scanner scanner = new Scanner(System.in);*/
        //记录正数的个数
        int positiveNumber = 0;
        //记录负数的个数
        int negetiveNumber = 0;
        while(true){
            int number = scanner.nextInt();
            //判断number的正负情况
            if(number > 0 ){
                positiveNumber++;
            }else if (number < 0){
                negetiveNumber++;
            }else{
                //一旦执行break,跳出循环
                break;
            }

        }
        System.out.println("正数的个数:"+positiveNumber);
        System.out.println("负数的个数:"+negetiveNumber);

 5.4.4:嵌套循环(多重循环)

  • 将一个循环放在另一个循环体内,就形成了嵌套循环。其中,for ,while ,do…while均可以作为外层循环或内层循环。

  • 实质上,嵌套循环就是把内层循环当成外层循环的循环体。当只有内层循环的循环条件为false时,才会完全跳出内层循环,才可结束外层的当次循环,开始下一次的循环。

  • 设外层循环次数为m次,内层为n次,则内层循环体实际上需要执行m*n次。

/*
例题:
1)九九乘法表
2)100以内的所有质数
*/
 for (int i = 1; i <= 9; i++) {
            for (int j = 1; j <= i ; j++) {
                System.out.print(j+"*"+i+"="+j*i+" ");
            }
            System.out.println();
        }

5.4.4:特殊关键字的使用:break、continue

特殊流程控制语句

  • break语句

    • break语句用于终止某个语句块的执行

      { ……

      break;

      ……

      }

    • break语句出现在多层嵌套的语句块中时,可以通过标签指明要终止的是哪一层语句块

      label1:{ ……

      label2: {……

      label3: { ……

      break label2;

      ……

      }

      }

      }

5.4.5:程序流程控制:课后项目

综合练习

项目一:家庭收支记账软件

public class FamilyAccount {
    public static void main(String[] args) {
        boolean isFlag = true;
        //用于记录用户的收入和支出的详情
        String dateils = "";
        //初始金额
        int balance = 10000;
        while (true){
            System.out.println("----------------------家庭收支记账软件----------------------------");
            System.out.println("                       1:收支明细");
            System.out.println("                       2:登记收入");
            System.out.println("                       3:登记支出");
            System.out.println("                       4:退   出 /n");
            System.out.println("                       请选择<1-4>");
            //获取用户的选择
            char selection = Utility.readMenuSelection();
            switch (selection){
                case '1':
                    System.out.println("当前收支明细记录");
                    System.out.println("收支\t账户金额\t收支金额\t说明");
                    System.out.println(dateils);
                    System.out.println("---------------------------------------------------------------");
                    break;
                case '2':
                    System.out.print("本次收入金额:");
                    int minusMoney = Utility.readNumber();
                    System.out.print("本次收入说明:");
                    String info = Utility.readString();
                    System.out.println("------------------------------登记完成-------------------------");
                    //处理余额 balance
                    balance += minusMoney;
                    //处理datails
                    dateils += ("收入\t"+balance+"\t\t"+minusMoney+"\t"+info+"\t"+"\n");

                    break;
                case '3':
                    System.out.println("本次支出金额: ");
                    int readNumber = Utility.readNumber();
                    System.out.println("本次支出说明: ");
                    String infoZhichu = Utility.readString();
                    //处理支出余额 balance
                    if (balance >=readNumber) {
                        balance -= readNumber;
                        //处理datails
                        dateils += ("收入\t"+balance+"\t\t"+readNumber+"\t"+info+"\t"+"\n");
                    }else {
                        System.out.println("你没有多余的钱了" );
                    }
                    break;
                case '4':
                    System.out.println("是否确认退出(Y/N)");
                    char isExit = Utility.readConfirmSelection();
                    if (isExit == 'Y') {
                        isFlag = false;
                    }
            }
        }
    }
}

--------------------------------------------------------------------------------------
import java.util.Scanner;
/**
 Utility工具类:
 将不同的功能封装为方法,就是可以直接通过调用方法使用它的功能,而无需考虑具体的功能实现细节。
 */
public class Utility {
    private static Scanner scanner = new Scanner(System.in);
    /**
     用于界面菜单的选择。该方法读取键盘,如果用户键入’1’-’4’中的任意字符,则方法返回。返回值为用户键入字符。
     */
    public static char readMenuSelection() {
        char c;
        for (; ; ) {
            String str = readKeyBoard(1);
            c = str.charAt(0);
            if (c != '1' && c != '2' && c != '3' && c != '4') {
                System.out.print("选择错误,请重新输入:");
            } else {
                break;
            }
        }
        return c;
    }
    /**
     用于收入和支出金额的输入。该方法从键盘读取一个不超过4位长度的整数,并将其作为方法的返回值。
     */
    public static int readNumber() {
        int n;
        for (; ; ) {
            String str = readKeyBoard(4);
            try {
                n = Integer.parseInt(str);
                break;
            } catch (NumberFormatException e) {
                System.out.print("数字输入错误,请重新输入:");
            }
        }
        return n;
    }
    /**
     用于收入和支出说明的输入。该方法从键盘读取一个不超过8位长度的字符串,并将其作为方法的返回值。
     */
    public static String readString() {
        String str = readKeyBoard(8);
        return str;
    }

    /**
     用于确认选择的输入。该方法从键盘读取‘Y’或’N’,并将其作为方法的返回值。
     */
    public static char readConfirmSelection() {
        char c;
        for (; ; ) {
            String str = readKeyBoard(1).toUpperCase();
            c = str.charAt(0);
            if (c == 'Y' || c == 'N') {
                break;
            } else {
                System.out.print("选择错误,请重新输入:");
            }
        }
        return c;
    }


    private static String readKeyBoard(int limit) {
        String line = "";

        while (scanner.hasNext()) {
            line = scanner.nextLine();
            if (line.length() < 1 || line.length() > limit) {
                System.out.print("输入长度(不大于" + limit + ")错误,请重新输入:");
                continue;
            }
            break;
        }

        return line;
    }
}

第3章:数组

3.1:数组的概述

数组(Array),是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。

数组的常见概念

  • 数组名

  • 下标(或索引)

  • 元素

  • 数组的长度

  • 数组本身是引用数据类型,而数组中的元素可以是任何数据类型,包括基本数据类型和引用数据类型。

  • 创建数组对象会在内存中开辟一整块连续的空间,而数组名中引用的是

  • 这块连续空间的首地址。

  • 数组的长度一旦确定,就不能修改。

  • 我们可以直接通过下标(或索引)的方式调用指定位置的元素,速度很快。

  • 数组的分类:

    • 按照维度:一维数组、二维数组、三维数组、…

    • 按照元素的数据类型分:基本数据类型元素的数组、引用数据类型元素的数组(即对象数组)

  • 数据结构:

    • 数据与数据之间的逻辑关系:集合,一对一,一对多,多对多

    • 数据的存储结构

      • 线性表:顺序表(比如:数组),链表,栈,队列

      • 树形结构:二叉树

      • 图形结构:

        3.2:一堆数组的使用

        3.2.1:数组声明方式

        • 一维数组的声明方式:

          type var[] 或 type[] var;

          • 例如:

            int a[];

            int[] a1;

            double b[];

            String[] c; //引用类型变量数组

        • Java语言中声明数组时不能指定其长度(数组中元素的数), 例如: int a[5]; //非法

        3.2.2:一维数组的使用:初始化

        • 动态初始化:数组声明且为数组元素分配空间与赋值的操作分开进行

        int[] arr = new int[3];

        arr[0] = 3;

        arr[1] = 9;

        arr[2] = 8;

        String names[];

        names = new String[3];

        names[0] = “钱学森”;

        names[1] = “邓稼先”;

        names[2] = “袁隆平”;

        • 静态初始化:在定义数组的同时就为数组元素分配空间并赋值。

        int arr[] = new int[]{ 3, 9, 8};

        int[] arr = {3,9,8};

        String names[] = {

        “李四光”,“茅以升”,“华罗庚”

        }

        3.2.3:一维数组的使用:初始化

        • 定义并用运算符new为之分配空间后,才可以引用数组中的每个元素;

        • 数组元素的引用方式:数组名[数组元素下标]

          • 数组元素下标可以是整型常量或整型表达式。如a[3] , b[i] , c[6*i];

          • 数组元素下标从0开始;长度为n的数组合法下标取值范围: 0 —>n-1;如int a[]=new int[3]; 可引用的数组元素为a[0]、a[1]、a[2]

        • 每个数组都有一个属性length指明它的长度,例如:a.length 指明数组a的长度(元素个数)

          • 数组一旦初始化,其长度是不可变的

        3.2.3:一维数组的使用:数组元素的默认初始化

        • 数组是引用类型,它的元素相当于类的成员变量,因此数组一经分配空间,其中的每个元素也被按照成员变量同样的方式被隐式初始化。例如:

          public class Test {

          public static void main(String argv[]){

          int a[]= new int[5];

          System.out.println(a[3]); //a[3]的默认值为0

          }

        }

        • 对于基本数据类型而言,默认初始化值各有不同

        • 对于引用数据类型而言,默认初始化值为null(注意与0不同!)

        • 创建基本类型数组(1)

        • Java中使用关键字new来创建数组

        • 如下是创建基本数据类型元素的一维数组

        public class Test{
        public static void main(String args[]){
        	int[] s;
        	s = new int[10];
        	for ( int i=0; i<10; i++ ) {
        	s[i] =2*i+1;
        	System.out.println(s[i]);
        		} 
        	} 
        }

        Java入门到超神(全网整理的复习资料)_第4张图片

         创建基本数据类型数组 (2)

        public class Test{
        	public static void main(String args[]){
        		int[] s;
        		s = new int[10];
                //int[] s=new int[10];
                //基本数据类型数组在显式赋值之前,
                //Java会自动给他们赋默认值。
                for ( int i=0; i<10; i++ ) {
        			s[i] =2*i+1;
        			System.out.println(s[i]);
        		} 
        	}
        }

         创建基本数据类型数组 (3)

        public class Test{
        	public static void main(String args[]){
                int[] s;
                s = new int[10];
                for ( int i=0; i<10; i++ ) {
                	s[i] =2*i+1;
                	System.out.println(s[i]);
        		} 
        	}
        }

         

         

        //一堆数组的使用
        //练习1:手机号
        public class ArrayTest {
        public static void main(String[] args) {
            int[] arr = new int[]{8,2,1,0,3};
            int[] index = new int[]{2,0,3,2,4,0,1,3,2,3,3};
            String tel = "";
            for(int i = 0;i < index.length;i++){
            	tel += arr[index[i]];
            	}
        		System.out.println("联系方式:"+ tel);
        	}
        }
        
        
        /**
        2. 从键盘读入学生成绩,找出最高分,并输出学生成绩等级。
        成绩>=最高分-10    等级为’A’   
        成绩>=最高分-20    等级为’B’
        成绩>=最高分-30    等级为’C’   
        其余				 等级为’D’
        提示:先读入学生人数,根据人数创建int数组,存放学生成绩。
        */
         public static void main(String[] args) {
                //1.使用Scanner,读取学生个数
                Scanner scanner = new Scanner(System.in);
                System.out.println("请输入学生的人数");
                int number = scanner.nextInt();
                //2.创建数组,存储学生成绩,动态初始化
                int[] scores = new int[number];
                //3.给数组中的元素赋值
                System.out.println("请输入"+number+"学生成绩");
                for (int i = 0; i < scores.length; i++) {
                    scores[i] = scanner.nextInt();
                }
                //4.获取数组中的元素的最大值:最高分
                int maxScore = 0;
                for (int i = 0; i < scores.length; i++) {
                    if (maxScore < scores[i]) {
                        maxScore = scores[i];
                    }
                }
                //5.根据每个学生成绩与最高分的差值,得到每个学生的等级,并输出等级和成绩
                char level ;
                for (int i = 0; i < scores.length; i++) {
                    if (maxScore - scores[i]<=10){
                        level = 'A';
                    }else if (maxScore - scores[i]<=20){
                        level = 'B';
                    }else if (maxScore - scores[i]<=30){
                        level = 'C';
                    }else {
                        level = 'D';
                    }
                    System.out.println("student "+i+"  score is "+scores[i]+",grade is "+level );
                }
        
            }

        3.3:多维数组的使用

        • Java 语言里提供了支持多维数组的语法。

        • 如果说可以把一维数组当成几何中的线性图形,那么二维数组就相当于是一个表格,像右图Excel 中的表格一样。

        • 对于二维数组的理解,我们可以看成是一维数组array1又作为另一个一维数组array2的元素而存在。其实,从数组底层的运行机制来看,其实没有多维数组。

        • Java入门到超神(全网整理的复习资料)_第5张图片

           ​

           

           

           

           Java入门到超神(全网整理的复习资料)_第6张图片

           

           

          /**
          练习2
          获取arr数组中所有元素的和。提示:使用for的嵌套循环即可。
          */
          public static void main(String[] args) {
                  int[][] arr = new int[][]{{3,5,8},{12,9},{7,0,6,4}};
                  //记录总和
                  int sum = 0;
                  for (int i = 0; i 

          3.4:数组中涉及到的常见算法

        1. 数组元素的赋值(杨辉三角、回形数等)

        2. 求数值型数组中元素的最大值、最小值、平均数、总和等

        3. 数组的复制、反转、查找(线性查找、二分法查找)

        4. 数组元素的排序算法

         

        Java入门到超神(全网整理的复习资料)_第7张图片

         Java入门到超神(全网整理的复习资料)_第8张图片

         

         Java入门到超神(全网整理的复习资料)_第9张图片

        /**
        练习5
        定义一个int型的一维数组,包含10个元素,分别赋一些随机整数,
        然后求出所有元素的最大值,最小值,和值,平均值,并输出出来。
        要求:所有随机数都是两位数。
        提示;
        [0,1) * 90 [0,90) + 10  [10,100) [10,99]
        (int)(Math.random() * 90 + 10)
        */
        public class ArrayTest01 {
            public static void main(String[] args) {
                int[] arr = new int[10];
                //给10个动态元素赋值
                for (int i = 0; i  arr[i]){
                        minValue = arr[i];
                    }
                }
                System.out.println("数组元素中的最小值:" +minValue);
        
                //求数组元素中的总和
                int sum = 0;
                for (int i = 0; i dest1){
                        end = middle-1;
                    }else{
                        head = middle+1;
                    }
                }
                if(isFlag1){
                    System.out.println("没有找到指定元素");
                }
        
            }
        }
        

         Java入门到超神(全网整理的复习资料)_第10张图片

         

         Java入门到超神(全网整理的复习资料)_第11张图片

         Java入门到超神(全网整理的复习资料)_第12张图片

        排序:假设含有n个记录的序列为{R1,R2,...,Rn},其相应的关键字序列为{K1,K2,...,Kn}。将这些记录重新排序为{Ri1,Ri2,...,Rin},使得相应的关键字值满足条Ki1<=Ki2<=...<=Kin,这样的一种操作称为排序。

         通常来说,排序的目的是快速查找。

        衡量排序算法的优劣:

        1.时间复杂度:分析关键字的比较次数和记录的移动次数

        2.空间复杂度:分析排序算法中需要多少辅助内存

        3.稳定性:若两个记录A和B的关键字值相等,但排序后A、B的先后次序保持不变,则称这种排序算法是稳定的

        排序算法分类:内部排序和外部排序。

        **内部排序:**整个排序过程不需要借助于外部存储器(如磁盘等),所有排 序操作都在内存中完成。

         **外部排序:**参与排序的数据非常多,数据量非常大,计算机无法把整个排序过程放在内存中完成,必须借助于外部存储器(如磁盘)。外部排序最常见的是多路归并排序。可以认为外部排序是由多次内部排序组成。

        十大内部排序算法

        • 选择排序

          • 直接选择排序、堆排序

        • 交换排序

          • 冒泡排序、快速排序

        • 插入排序

          • 直接插入排序、折半插入排序、Shell排序

        • 归并排序

        • 桶式排序

        • 基数排序

        3.4.2:冒泡算法

        冒泡排序

        介绍:

        冒泡排序的原理非常简单,它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。

        排序思想:

        1. 比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个。

        2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。

        3. 针对所有的元素重复以上的步骤,除了最后一个。

        4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要

        比较为止。

        快速排序

        介绍:

        快速排序通常明显比同为O(nlogn)的其他算法更快,因此常被采用,而且快排采用了分治法的思想,所以在很多笔试面试中能经常看到快排的影子。可见掌握快排的重要性。

        快速排序(Quick Sort)由图灵奖获得者Tony Hoare发明,被列为20世纪十大算法之一,是迄今为止所有内排序算法中速度最快的一种。冒泡排序的升级版,交换排序的一种。快速排序的时间复杂度为O(nlog(n))

        排序思想:

        1. 从数列中挑出一个元素,称为"基准"(pivot),

        2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。

        3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

        4. 递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去

        各种内部排序方法性能比较

        1.从平均时间而言:快速排序最佳。但在最坏情况下时间性能不如堆排序和归并排序。

        2.从算法简单性看:由于直接选择排序、直接插入排序和冒泡排序的算法比较简单,将其认为是简单算法。对于Shell排序、堆排序、快速排序和归并排序算法,其算法比较复杂,认为是复杂排序。

        3.从稳定性看:直接插入排序、冒泡排序和归并排序时稳定的;而直接选择排序、快速排序、 Shell排序和堆排序是不稳定排序

        4.从待排序的记录数n的大小看**,n较小时,宜采用简单排序;而n较大时宜采用改进排序

        public class BubbleSortTest {
            public static void main(String[] args) {
                //冒泡排序算法
                int[] arr = new int[10];
                //随机生成十个元素
                for (int i = 0; i arr[j+1]){
                            //定义一个空的元素保存每次比较的值
                            int temp = arr[j];
                            arr[j] = arr[j+1];
                            arr[j+1] = arr[i];
                        }
                    }
        
                }
        
                for (int i = 0; i < arr.length; i++) {
                    System.out.print(arr[i]+"\t");
                }
        
        
            }
        }
        

        3.5:Arrays工具类的使用

        3.6:数组使用中的常见异常

         

        public class day04 {
            public static void main(String[] args) {
                //1.boolean equals(int[] a,int [] b):判断两个数组是否相等
                int[] arr1 = new int[]{1,2,3,4};
                int[] arr2 = new int[]{1,3,2,4};
                boolean isEquals = Arrays.equals(arr1,arr2);
        
                //2.String toSting(int[] a):输出数组信息
                System.out.println(Arrays.toString(arr1));
        
                //3.void fill(int[],int val):将指定值填充到数组中
                Arrays.fill(arr1,10);
                System.out.println(Arrays.toString(arr1));
        
                //4.void sort(int[] a):对数组进行排序
                Arrays.sort(arr2);
                System.out.println(Arrays.toString(arr2));
        
                //int binarySearch(int[] a,int key)
                int[] arr3 = new int[]{-98,-34,2,34,54,66,79,109,211,333};
                int index = Arrays.binarySearch(arr3,211);
                System.out.println(index);
            }
        }
        

        第4章:面向对象编程(上)

        学习面向对象内容的三条主线

        1.Java类及类的成员

        2.面向对象的三大特征

        3.其它关键字

        4.1学习路线

        ​ 

        4.1.1面向过程与面向对象

        1. 面向过程(POP) 与 面向对象(OOP)

          1. 二者都是一种思想,面向对象是相对于面向过程而言的。面向过程,强调的 是功能行为,以函数为最小单位,考虑怎么做。面向对象,将功能封装进对 象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。

          2. 面向对象更加强调运用人类在日常的思维逻辑中采用的思想方法与原则,如 抽象、分类、继承、聚合、多态等。

        2. 面向对象的三大特征

          1. 封装 (Encapsulation)

          2. 继承 (Inheritance)

          3. 多态 (Polymorphism)

        3. 面向对象:Object Oriented Programming

        4. 面向过程:Procedure Oriented Programmin

        4.1.2面向对象的思想概述

        • 程序员从面向过程的执行者转化成了面向对象的指挥者

        • 面向对象分析方法分析问题的思路和步骤:

          • 根据问题需要,选择问题所针对的现实世界中的实体。

          • 从实体中寻找解决问题相关的属性和功能,这些属性和功能就形成了概念世界中的类。

          • 把抽象的实体用计算机语言进行描述,形成计算机世界中类的定义。即借助某种程序 语言,把类构造成计算机能够识别和处理的数据结构。

          • 将类实例化成计算机世界中的对象。对象是计算机世界中解决问题的最终工具。

        /**
        练习1:
        1. 我要开车去丽江,这句话包含的类有什么?
        2. 体会以下几个经典案例涉及到的类。
        	人在黑板上画圆
         	列车司机紧急刹车
         	售货员统计收获小票的金额
        	你把门关上了
        */

        4.1.3:java的基本元素:类和对象

        面向对象的思想概述

        • 类(Class)和对象(Object)是面向对象的核心概念。

          • 类是对一类事物的描述,是抽象的、概念上的定义

          • 对象是实际存在的该类事物的每个个体,因而也称为实例(instance)。

        • “万事万物皆对象”

          • 可以理解为:类 = 抽象概念的人;对象 = 实实在在的某个人

          • 面向对象程序设计的重点是类的设计

          • 类的设计,其实就是类的成员的设计

        Java类及类的成员

        • 现实世界的生物体,大到鲸鱼,小到蚂蚁,都是由最基本的细胞构成的。同 理,Java代码世界是由诸多个不同功能的类构成的。

        • 现实生物世界中的细胞又是由什么构成的呢?细胞核、细胞质、… 那么, Java中用类class来描述事物也是如此。常见的类的成员有:

          • 属 性:对应类中的成员变量

          • 行 为:对应类中的成员方法

        Field = 属性 = 成员变量,Method = (成员)方法 = 函数

         

        ​ 

         

        4.1.4:对象创建和使用

         Java入门到超神(全网整理的复习资料)_第13张图片

         

         

         

         

         

         Java入门到超神(全网整理的复习资料)_第14张图片

         

         

         

         Java入门到超神(全网整理的复习资料)_第15张图片

         

        4.1.5:类的成员之一:属性

        • 语法格式:

          修饰符 数据类型 属性名 = 初始化值 ;

          • 说明1: 修饰符

            • 常用的权限修饰符有:private、缺省、protected、public

            • 其他修饰符:static、final (暂不考虑)

          • 说明2:数据类型

            • 任何基本数据类型(如int、Boolean) 或 任何引用数据类型。

          • 说明3:属性名

            • 属于标识符,符合命名规则和规范即可。

        • 举例:

        public class Person{
        
        private int age; //声明private变量 age
        
        public String name = “Lila”; //声明public变量 name
        
        }

        4.1.5.1变量的分类:成员变量与局部变量

        • 在方法体外,类体内声明的变量称为成员变量。

        • 在方法体内部声明的变量称为局部变量。

        Java入门到超神(全网整理的复习资料)_第16张图片​ 

        • 注意:二者在初始化值方面的异同:

          • 同:都有生命周期

          • 异:局部变量除形参外,均需显式初始化。

        4.1.5.2:成员变量(属性)和局部变量的区别?

         

        /**
         *类中的属性的使用
         * 属性(成员变量) VS 局部变量
         * 1.相同点:
         *  1.1 定义变量的格式:数据类型 变量名 =变量值
         *  1.2 先声明,后使用
         *  1.3 变量都有其对应的作用域
         *
         *
         * 2.不同点:
         *  2.1 在类中声明的位置不同
         *      属性:直接定义在类的一对{}内
         *      局部变量:声明在方法内,方法形参,代码块内,构造器
         *  2.2 关于权限修饰符不同
         *      属性:可以在声明属性时候,指明其权限修饰符
         *      常用的权限修饰符:private,pulic,缺省,protected
         *  2.3 默认初始化值的情况
         *      属性:类的属性,根据其类型,都有默认初始化值。
         *              整型(byte,short,int,long):0
         *              浮点型(float,double):0.0
         *              字符型(char):0 (或‘\u0000’)
         *              布尔型(boolean) :false
         *              引用数据类型(类,数组,接口):null
         *      局部变量:没有默认初始化值
         *          意味着,我们在调用局部变量之前,一定要显示赋值
         *          特别地:形参在调用时,我们赋值即可
         *     2.4:在内存中加载的位置
         *      属性:加载到对空间中
         *      局部变量:加载到栈空间
         */
        public class UserTest {
            public static void main(String[] args) {
                User u1 = new User();
                System.out.println(u1.age);
                System.out.println(u1.name);
                System.out.println(u1.isMale);
                u1.talk("日语");
                u1.eat();
        
            }
        
        }
        
        class User{
            //属性(或成员变量)
            String name;
            public  int age;
            boolean isMale;
        
            //language 形参
            public void talk(String language){
                System.out.println("我们使用"+language+"进行交流");
            }
        
            //方法
            public void eat(){
                //局部变量
                String food ="烙饼";
                System.out.println("北方人喜欢吃:"+food);
            }
        
        }

        4.1.6:类的成员之二:方法

        什么是方法(method、函数):

        • 方法是类或对象行为特征的抽象,用来完成某个功能操作。在某些语言中 也称为函数或过程。

        • 将功能封装为方法的目的是,可以实现代码重用,简化代码

        • Java里的方法不能独立存在,所有的方法必须定义在类里。

        /**
        举例
        */
        public class Person{
        	private int age;
        	public int getAge() { //声明方法getAge()
        		return age; 
        	}
        	public void setAge(int i) { //声明方法setAge
        		age = i; //将参数i的值赋给类的成员变量age
        	}
        }

        方法的声明格式:

        修饰符 返回值类型 方法名(参数类型 形参1, 参数类型 形参2, ….){

        方法体程序代码

        return 返回值;

        其中: 修饰符:public,缺省,private, protected等 返回值类型:

         没有返回值:void。

         有返回值,声明出返回值的类型。与方法体中“return 返回值”搭配使用。

        方法名:属于标识符,命名时遵循标识符命名规则和规范,“见名知意” 形参列表:可以包含零个,一个或多个参数。多个参数时,中间用“,”隔开 返回值:方法在执行完毕后返还给调用它的程序的数据。

        ​ 

         Java入门到超神(全网整理的复习资料)_第17张图片

        • 注 意:

          • 方法被调用一次,就会执行一次

          • 没有具体返回值的情况,返回值类型用关键字void表示,那么方法体中可 以不必使用return语句。如果使用,仅用来结束方法。

          • 定义方法时,方法的结果应该返回给调用者,交由调用者处理。

          • 方法中只能调用方法或属性,不可以在方法内部定义方法。

        /**
         * 类中方法的声明和使用
         *
         *  方法:描述类应该具有的功能
         *  比如:Math类:sqrt()\random()\
         *      Scanner类:nextXxx()....
         *      Arrays类:sort()\binarySearch()\toString()
         *  1.举例
         *  public void eat(){}
         *  public  void  sleep(int hour){ }
         *  public String getName(){}
         *  public  String getNation(String nation){ }
         *  2.方法的声明:权限修饰符 返回值类型 方法名字(形参列表){
         *      方法体
         *  }
         *  3.说明
         *      3.1 关于权限修饰符:默认方法的权限修饰符先都使用public
         *          java规定的4中权限修饰符:private,public,缺省,protected
         *      3.2 返回值类型:有返回值 VS 没有返回值
         *          3.2.1:如果方法有返回值,则必须在方法声明时,指定返回值类型。同时,方法中,需要使用return关键字来返回指定的变量或者常量
         *          :“return”数据。
         *          如果方法没有返回值,则方法声明时,使用void来表示。通常,没有返回值的方法,就不适用return。但是
         *          如果使用的话,只能“return;”表示结束次方法的意思。
         *          3.2.2 我们定义方法该不该有返回值
         *              ①题目要求
         *              ②凭经验:具体问题具体分析
         *      3.3 方法名:属于标识符,遵循标识符的规则和规范,“见名知意”
         *      3.4 形参列表:方法可以声明0个,1个,或多个形参。
         *          3.4.1 格式:数据类型1,形参1,数据类型2,形参2....
         *          3.4.2 我们定义方法时,该不该定义形参?
         *              ①题目要求
         *              ②凭经验:具体问题具体分析
         *      3.5 方法体
         *          3.5.1 方法的功能实现
         *   4.return关键字的使用
         *      1.使用范围:使用在方法体中
         *      2.作用:①结束方法
         *             ②针对有返回值类型的方法,使用“return”数据方法返回所要的数据类型
         *      3.注意点:return关键字后面不可以声明执行语句。
         *   5.方法的使用中:可以调用当前类的属性或方法
         *      特殊的:方法A中又调用了方法A:递归方法;
         *
         *
         */
        public class CustomerTest {
            public static void main(String[] args) {
                Customer customer = new Customer();
                customer.eat();
                customer.sleep(8);
            }
        }
        
        //客户类
        class Customer{
            //属性
            String name;
            int age ;
            boolean isMale;
        
            //方法
            public void eat(){
                System.out.println("客户吃饭");
            }
            public  void  sleep(int hour){
                System.out.println("休息了"+hour +"个小时");
            }
        
            public String getName(){
                return  name;
            }
        
            public  String getNation(String nation){
                String info = "我的国籍是:"+nation;
                return info;
            }
        }

        public class Person {
            String name;
            int age;
            int sex;
            public void study(){
                System.out.println("studying");
            }
        
            public void showAge(){
                System.out.println("age:"+age);
            }
        
            public int addAge(int i){
                age+=i;
                return age;
            }
        }
        //**********************************************************
        public class PersonTest {
            public static void main(String[] args) {
                Person person= new Person();
                person.name="张三";
                person.age = 18;
                person.sex = 1;
                person.study();
                person.showAge();
                person.addAge(2);
        
                int newAge = person.addAge(2);
                System.out.println(person.name+"的新年龄为:"+newAge);
        
                //**********************
                Person person1 = new Person();
                person1.showAge();//0
                person1.addAge(10);
                person1.showAge();//10
                person1.showAge();
        
        
            }
        }
        /**
        练习3
        3.1 编写程序,声明一个method方法,在方法中打印一个10*8 的*型矩形,在main方法中调用该方法。
        3.2 修改上一个程序,在method方法中,除打印一个10*8的*型矩形外,再计算该矩形的面积,并将其作为方法返回值。在main方法中调用该方法,接收返回的面积值并打印。
        3.3 修改上一个程序,在method方法提供m和n两个参数,方法中打印一个m*n的*型矩形,并计算该矩形的面积, 将其作为方法返回值。在main方法中调用该方法,接收返回的面积值并打印。
        4. 对象数组题目:
        定义类Student,包含三个属性:学号number(int),年级state(int),成绩score(int)。 创建20个学生对象,学号为1到20,年级和成绩都由随机数确定。
        问题一:打印出3年级(state值为3)的学生信息。
        问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息
        提示:
        1) 生成随机数:Math.random(),返回值类型double; 
        2) 四舍五入取整:Math.round(double d),返回值类型long。
        练习3
        5.声明一个日期类型MyDate:有属性:年year,月month,日day。创建2个日期对象,分别赋值为:你的出生日期,你对象的出生日期,并显示信息。
        */
        
        //3.1,3.2,3.3
        public class Exer3Test {
            public static void main(String[] args) {
                Exer3Test exer3Test = new Exer3Test();
                //3.1
        //        exer3Test.method();
                //3.2 测试
        //        int method = exer3Test.method();
        //        System.out.println("面积为:"+method);
        
                //方式二
        //        System.out.println(exer3Test.method());
                //3.3 测试
                int method = exer3Test.method(12,10);
                System.out.println("面积为:"+method);
            }
            //3.1
        //    public  void method(){
        //        for (int i = 0; i < 10; i++) {
        //            for (int j = 0; j < 8; j++) {
        //                System.out.print("* ");
        //            }
        //            System.out.println();
        //        }
        //    }
            //3.2
        //    public  int  method(){
        //        for (int i = 0; i < 10; i++) {
        //            for (int j = 0; j < 8; j++) {
        //                System.out.print("* ");
        //            }
        //            System.out.println();
        //        }
        //        return 10*8;
        //    }
        
            //3.3
            public int method(int m,int n){
                for (int i = 0; i < m; i++) {
                    for (int j = 0; j < n; j++) {
                        System.out.print("*");
                    }
                    System.out.println();
                }
                return m * n;
            }
        
        }
        
        public class StudentTest {
            public static void main(String[] args) {
                //声明Student类型的数组
                Student[] student = new Student[20];
        
                for (int i = 0; i < student.length; i++) {
                    //给数组元素赋值
                    student[i] = new Student();
                    //给Student对象的属性赋值
                    student[i].number = i + 1;
                    //年级:[1,6]
                    student[i].state = (int)(Math.random()*(6-1+1)+1);
                    //成绩[0,100]
                    student[i].socre = (int)(Math.random()*(100-0+1));
                }
                //遍历学生数组
                for (int i = 0; i student[j+1].socre){
                            //如果需要环旭,交换的是数组的元素:Student对象
                            Student temp = student[j];
                            student[j] = student[j+1];
                            student[j+1] = temp;
        
                        }
                    }
                }
                //遍历学生数组
                for (int i = 0; i student1s[j+1].socre){
                            //如果需要环旭,交换的是数组的元素:Student对象
                            Student1 temp = student1s[j];
                            student1s[j] = student1s[j+1];
                            student1s[j+1] = temp;
        
                        }
                    }
                }
        
            }
        }
        class Student1 {
            int number;
            int state;
            int socre;
        
            //显示学生信息的方法
            public String info(){
                return "学号:"+number+",年级:"+state+"学生成绩:"+socre;
            }
        
        }
        

        4.1.7:再谈方法

        4.1.7.1:方法的重载

        重载的概念 在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数 类型不同即可。

        重载的特点: 与返回值类型无关,只看参数列表,且参数列表必须不同。(参数个数或参数类 型)。调用时,根据方法参数列表的不同来区别。

        重载示例:

        //返回两个整数的和

        int add(int x,int y){return x+y;}

        //返回三个整数的和

        int add(int x,int y,int z){return x+y+z;}

        //返回两个小数的和

        double add(double x,double y){return x+y;}

        //示例
        public class PrintStream {
            public static void print(int i) {……}
            public static void print(float f) {……}
            public static void print(String s) {……}
            public static void main(String[] args) {
                print(3);
                print(1.2f);
                print("hello!");
        	}
        }
         使用**重载**方法,可以为编程带来方便。 
        
        例如,System.out.println()方法就是典型的重载方法,其内部的声 明形式如下: 
        
        public void println(byte x) 
        
        public void println(short x) 
        
        public void println(int x) 
        
        public void println(long x) 
        
        public void println(float x) 
        
        public void println(double x) 
        
        public void println(char x) 
        
        public void println(double x)
        
         public void println() ……
        /**
        练习1:
        1.判 断:
        与void show(int a,char b,double c){}构成重载的有:
        a) void show(int x,char y,double z){} // no
        b) int show(int a,double c,char b){} // yes
        c) void show(int a,double c,char b){} // yes
        d) boolean show(int c,char b){} // yes
        e) void show(double c){} // yes
        f) double show(int x,char y,double z){} // no
        g) void shows(){double c} // no
        */
        /**
        2.编写程序,定义三个重载方法并调用。方法名为mOL。
        三个方法分别接收一个int参数、两个int参数、一个字符串参数。分别执行平方运算并输出结果,相乘并输出结果,输出字符串信息。
        在主类的main ()方法中分别用参数区别调用三个方法。
        */
        public class OverLoadExer {
            public static void main(String[] args) {
                OverLoadExer overLoadExer = new OverLoadExer();
                overLoadExer.mOL(2);
                overLoadExer.mOL(1,2);
                overLoadExer.mOL("谢谢");
            }
        
            //1.如下三个方法构成重载
            public void mOL(int i){
                System.out.println(i * i);
            }
        
            public void mOL(int i,int j){
                System.out.println(i * j);
            }
        
            public void mOL(String str){
                System.out.println(str);
            }   
        }
        
        /**
        3.定义三个重载方法max(),第一个方法求两个int值中的最大值,第二个方
        法求两个double值中的最大值,第三个方法求三个double值中的最大值,
        并分别调用三个方法。
        */
        public class OverLoadExer {
            public static void main(String[] args) {
                OverLoadExer overLoadExer = new OverLoadExer();
                System.out.println(overLoadExer.max(2,4));
                System.out.println(overLoadExer.max(2.31,5.12));
                System.out.println(overLoadExer.max(7.77,8.88,9.99));
            }
            //2.如下的三个方法构成重载
            public int max(int i,int j){
                return (i>j) ? i:j;
            }
        
            public double max(double d1, double d2){
                return (d1>d2) ? d1:d2;
            }
            public double max(double d1,double d2,double d3){
                double max = (d1>d2)?d1:d2;
                return (max>d3)?max:d3;
            }
        }

        4.1.7.2:可变形参的方法

        JavaSE 5.0 中提供了Varargs(variable number of arguments)机制,允许直接定 义能和多个实参相匹配的形参。从而,可以用一种更简单的方式,来传递个数可变的实参。

        //JDK 5.0以前:采用数组形参来定义方法,传入多个同一类型变量 public static void test(int a ,String[] books); //JDK5.0:采用可变个数形参来定义方法,传入多个同一类型变量 public static void test(int a ,String…books)

        说明:

        1. 声明格式:方法名(参数的类型名 ...参数名)

        2. 可变参数:方法参数部分指定类型的参数个数是可变多个:0个,1个或多个

        3. 可变个数形参的方法与同名的方法之间,彼此构成重载

        4. 可变参数方法的使用与方法参数部分使用数组是一致的

        5. 方法的参数部分有可变形参,需要放在形参声明的最后

        6. 在一个方法的形参位置,最多只能声明一个可变个数形参

        public void test(String[] msg){
        	System.out.println(“含字符串数组参数的test方法 ");
        }
        public void test1(String book){
        	System.out.println(“****与可变形参方法构成重载的test1方法****");
        }
        public void test1(String ... books){
        	System.out.println("****形参长度可变的test1方法****");
        }
        public static void main(String[] args){
            TestOverload to = new TestOverload();
            //下面两次调用将执行第二个test方法
            to.test1();
            to.test1("aa" , "bb");
            //下面将执行第一个test方法
            to.test(new String[]{"aa"});
        }

        4.1.7.3:方法参数的传递机制(重点)

        • 方法,必须由其所在类或对象调用才有意义。若方法含有参数:

          • 形参:方法声明时的参数

          • 实参:方法调用时实际传给形参的参数值

        • Java的实参值如何传入方法呢?

          • Java里方法的参数传递方式只有一种:值传递。 即将实际参数值的副本 (复制品)传入方法内,而参数本身不受影响。

            • 形参是基本数据类型:将实参基本数据类型变量的“数据值”传递给形参

            • 形参是引用数据类型:将实参引用数据类型变量的“地址值”传递给形参

         Java入门到超神(全网整理的复习资料)_第18张图片

         

         

         

         Java入门到超神(全网整理的复习资料)_第19张图片

        //例题1:方法的参数传递
        public class TransferTest1 {
        	public void swap(int a, int b) {
                int tmp = a;
                a = b;
                b = tmp;
                System.out.println("swap方法里,a的值是" + a + ";b的值是" + b);
        }
        public static void main(String[] args) {
            TransferTest1 test = new TransferTest1();
            int a = 5;
            int b = 10;
            test.swap(a, b);
            System.out.println("交换结束后,变量a的值是" + a + ";变量b的值是" + b);
            }
        }
        

         

        //例题2:方法的参数传递
        class DataSwap {
            public int a;
            public int b;
        }
        public class TransferTest2 {
            public static void swap(DataSwap ds) {
            int temp = ds.a;
            ds.a = ds.b;
            ds.b = temp;
            System.out.println("swap方法里,a Field的值是" + ds.a + ";b Field的值是" + ds.b);
        }
        public static void main(String[] args) {
            DataSwap ds = new DataSwap();
            ds.a = 5;
            ds.b = 10;
            swap(ds);
            System.out.println("交换结束后,a Field的值是" + ds.a + ";b Field的值是" + ds.b);
        	}
        }

        Java入门到超神(全网整理的复习资料)_第20张图片

         

         //例题3:
        public class TransferTest3 {
        public static void main(String args[]) {
            TransferTest3 test = new TransferTest3();
            test.first();
        }
        public void first() {
            int i = 5;
            Value v = new Value();
            v.i = 25;
            second(v, i);
            System.out.println(v.i);
        }
        public void second(Value v, int i) {
            i = 0;
            v.i = 20;
            Value val = new Value();
            v = val;
            System.out.println(v.i + " " + i);
            }
        }
        class Value {
            int i = 15;
        }

        ​ 

        /**
        微软:
        定义一个int型的数组:int[] arr = new int[]{12,3,3,34,56,77,432};
        让数组的每个位置上的值去除以首位置的元素,得到的结果,作为该位置上的
        新值。遍历新的数组。
        */
        
        答案:
        //错误写法
        for(int i= 0;i < arr.length;i++){
        arr[i] = arr[i] / arr[0];
        }
        //正确写法1
        for(int i = arr.length – 1;i >= 0;i--){
        arr[i] = arr[i] / arr[0];
        }
        //正确写法2
        int temp = arr[0];
        for(int i= 0;i < arr.length;i++){
        arr[i] = arr[i] / temp;
        }
        //练习6
        /**
        (1)定义一个Circle类,包含一个double型的radius属性代表圆的半径,一个findArea()方法返回圆的面积。
        (2)定义一个类PassObject,在类中定义一个方法printAreas(),该方法的定义
        	如下:public void printAreas(Circle c, int time)
        	在printAreas方法中打印输出1到time之间的每个整数半径值,以及对应的面积。
        	例如,times为5,则输出半径1,2,3,4,5,以及对应的圆面积。
        (3)在main方法中调用printAreas()方法,调用完毕后输出当前半径值。程序运行结果如图所示
        */
        
        /**
         *	(1)
         * 定义一个Circle类,包含一个double型的radius属性代表圆的半径,一个findArea()方法返回圆的面积。
         */
        public class Circle {
            /**
                圆的半径
             */
            double radius;
        
            /**
             * Circle()方法返回圆的面积
             * @return
             */
            public  double findArea(){
                return  Math.PI * radius * radius;
            }
        
        }
        
        
        /**
         * 考查参数值传递
         * (2)定义一个类PassObject,在类中定义一个方法printAreas(),该方法的定义
         * 	如下:public void printAreas(Circle c, int time)
         * 	在printAreas方法中打印输出1到time之间的每个整数半径值,以及对应的面积。
         * 	例如,times为5,则输出半径1,2,3,4,5,以及对应的圆面积。
         *
         * 	在main方法中调用printAreas()方法,调用完毕后输出当前半径值。程序运行结果如图所示
         */
        public class PassObject {
            public static void main(String[] args) {
                PassObject test = new PassObject();
                Circle c = new Circle();
                test.printAreas(c,5);
                System.out.println("now radius is "+ c.radius);
            }
        
            public void printAreas(Circle c, int time){
                System.out.println("Radius\t\tArea");
                //设置圆的半径
                int i = 1;
                for (; i <=time; i++) {
                    c.radius =i;
                    System.out.println(c.radius+"\t\t"+c.findArea());
                }
                //c.radius = time+1;
                c.radius = i;
            }
        }
        

        4.1.7.1:递归方法

        递归方法:一个方法体内调用它自身。

        • 方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执 行无须循环控制。

        • 递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死 循环。

        //计算1-100之间所有自然数的和

        public int sum(int num){
         	if(num == 1){
         	return 1; 
        }else{
         	return num + sum(num - 1);
         	} 
        }
        /**练习7.1:请用Java写出递归求阶乘(n!)的算法
        练习7.2:已知有一个数列:f(0) = 1,f(1) = 4,f(n+2)=2*f(n+1) + f(n),其中n是大于0的整数,求f(10)的值。
        练习7.3:已知一个数列:f(20) = 1,f(21) = 4,f(n+2) = 2*f(n+1)+f(n),其中n是大于0的整数,求f(10)的值。
        练习7.4:输入一个数据n,计算斐波那契数列(Fibonacci)的第n个值
        	1 1 2 3 5 8 13 21 34 55
        	规律:一个数等于前两个数之和
        	要求:计算斐波那契数列(Fibonacci)的第n个值,并将整个数列打印出来
        */
        public class RecursionTest {
            public static void main(String[] args) {
                RecursionTest test = new RecursionTest();
                int sum = test.getSum(100);
                System.out.println(sum);
        
                //方式二
                RecursionTest test1 = new RecursionTest();
                int sum1 = test1.getSum1(100);
                System.out.println(sum1);
        
                System.out.println("*******************************");
                int value = test1.f(10);
                System.out.println(value);
            }
            //例题1:计算1-n 之间所有自然数的和!
            public  int getSum(int n){
                if (n == 1){
                    return  1;
                }else{
                    return  n+getSum(n-1);
                }
            }
        
            //例题2:计算1-n 之间所有自然数的乘积:n!
            public int getSum1(int n){
                if (n == 1){
                    return 1;
                }else{
                    return  n * getSum(n-1);
                }
            }
        
            //练习.3:已知一个数列:f(20) = 1,f(21) = 4,f(n+2) = 2*f(n+1)+f(n),
            // 其中n是大于0的整数,求f(10)的值。
            public int f(int n){
                if(n == 0){
                    return 1;
                }else if (n == 1){
                    return 4;
                }else{
                    return  f(n+2)-2*f(n+1);
                }
            }
            //例4:斐波那契数列
            package com;
         
        import java.util.Arrays;
         
        //1.递归方法
        public class test2 {
            //1.用递归方法
            public static void main(String[] args) {
                for (int counter = 0; counter <= 10; counter++){
                    System.out.printf("Fibonacci of %d is: %d\n", counter, fibonacci(counter));
                }
            }
            public static long fibonacci(long number) {
                if ((number == 0) || (number == 1))
                    return number;
                else
                    return fibonacci(number - 1) + fibonacci(number - 2);
            }
        }
            
            public class test3{
            public static void main(String[] args) {
                //1.定义三个变量,用来存放第一个第二第三个斐波那契数
                int a1 = 1;
                int a2 = 1;
                int a3 ;
                System.out.print("斐波那契数列前十个是:");
                System.out.print(a1+","+a2);
                for (int i = 3; i <=10;i++) {
                    //2.根据前两个数算出第三个数
                    a3=a2+a1;
                    //3.更新第一第二个数
                    a1=a2;
                    a2=a3;
                    System.out.print(","+a3);
                }
            }
        }
            
            public class test4{
            public static void main(String[] args) {
                //创建一个用来装斐波那契数列的数组,假设只获取前十个数
                int [] arr = new int[10];
                //先将前两个放入数组
                arr[0] = 1;
                arr[1] = 1;
                //循环获得剩下斐波那契数
                for (int i = 2; i 移到->  " + M);
            }
        
            // 递归实现汉诺塔的函数
        
            public static void hanoi(int n, char A, char B, char C) {
        
                if (n == 1)// 圆盘只有一个时,只需将其从A塔移到C塔
        
                    Hanoi2.move(1, A, C);// 将编b号为1的圆盘从A移到C
        
                else
        
                {
                    // 否则
        
                    hanoi(n - 1, A, C, B);// 递归,把A塔上编号1~n-1的圆盘移到B上,以C为辅助塔
        
                    Hanoi2.move(n, A, C);// 把A塔上编号为n的圆盘移到C上
        
                    hanoi(n - 1, B, A, C);// 递归,把B塔上编号1~n-1的圆盘移到C上,以A为辅助塔
        
                }
            }
        
            public static void main(String[] args) {
                Scanner in = new Scanner(System.in);
        
                char A = 'A';
        
                char B = 'B';
        
                char C = 'C';
                System.out.println("******************************************************************************************");
                System.out.println("汉诺塔问题(把A塔上编号从小号到大号的圆盘从A塔通过B辅助塔移动到C塔上去---山东科技大学昝道广");
                System.out.println("******************************************************************************************");
                System.out.print("请输入圆盘的个数:");
                int n = in.nextInt();
                Hanoi2.hanoi(n, A, B, C);
                System.out.println(">>移动了" + m + "次,把A上的圆盘都移动到了C上");
                in.close();
            }
        
        }
            
            //*****************
            import java.util.Scanner;
         
        public class Hanio {
        	static int count=0;//记录移动次数
        	
        	
        	public static void move(int num,char start,char end){
        		//将盘子从小到大编号,每次将编号为num的盘子,从start柱子移动到end柱子
        		
        		System.out.println("第"+(++count)+"次移动,将"+num+"号盘子从"+start+"柱子移动到"+end+"号柱子上");
        	}
        	
        	public static void hanio(int total,char A,char B,char C) {
        		//total为盘子总数
        		//默认A柱子为起始柱子
        		//默认B柱子为辅助柱子
        		//默认C柱子为终点柱子
        		
        		/*
        		思路:
        		将上面total-1个盘子从A移动到B(无需思考移动细节),再将最后一个盘子(最底下最大的)先移动到终点柱C
        		最后只需将B柱子的total-1个盘子借助A柱子移动到C即可
        		*/
        		if (total==1) {
        			Hanio.move(1, A, C);
        			//盘子总数为1时,total-1个盘子已经在C终点柱子,只需将1号(汉诺塔最上面的盘子)直接从起始A柱移动到C即可
        		} else {
        			hanio(total-1, A, C, B);
        			//total-1个盘子从A移动到B,借助C
        			Hanio.move(total, A, C);
        			//将最后一个盘子(最下面最大的盘子)从A移动到C
        			hanio(total-1, B, A, C);
        			//将total-1个盘子从B移动到C,借助A
        		}
        	}
        	public static void main(String[] args) {
        		//主函数
        		Scanner sc=new Scanner(System.in);
        		//定义三根柱子
        		char a='A';
        		char b='B';
        		char c='C';
        		System.out.println("请输入汉诺塔盘子总数:");
        		//初始化盘子总数
        		int total=sc.nextInt();
        		hanio(total, a, b, c);
        		//汉诺塔执行函数(移动细节在函数内部)
        		System.out.println("结束");
        	}
        }
        
            //例6:快排
        public class QuickSort {
         
            public static void main(String[] args) {
                int[] nums=new int[]{23,383,9,84,13,55};
         
                new QuickSort().quickSort(nums,0,nums.length-1);
         
                Arrays.stream(nums).forEach(System.out::println);
            }
         
         
            public void quickSort(int[] nums,int start,int end){
                if(start>=end) return;
         
                int pivot=nums[start];
                int i=start;
                int j=end;
                while(i pivot) {
                        i++;
                    }
                    if (i < j) {
                        nums[j--] = nums[i];
                    }
                }
         
                nums[i]=pivot;
         
                quickSort(nums,start,i-1);
                quickSort(nums,i+1,end);
            }
        }
        }
        
        public class QuickTest {
             public static void sort(int[] a) {
                if (a.length > 0) {
                    sort(a, 0, a.length - 1);
                }
         
            }
         
            public static void sort(int[] a, int low, int height) {
                int i = low;
                int j = height;
                if (i > j) {//放在k之前,防止下标越界
                    return;
                }
                int k = a[i];
         
                while (i < j) {
                    while (i < j && a[j] > k) { //找出小的数
                        j--;
                    }
                    while (i < j && a[i] <= k) { //找出大的数
                        i++;
                    }
                    if (i < j) {//交换
                        int swap = a[i];
                        a[i] = a[j];
                        a[j] = swap;
                    }
         
                }
                 //交换K
                k = a[i];
                a[i] = a[low];
                a[low] = k;
         
                //对左边进行排序,递归算法
                sort(a, low, i - 1);
                //对右边进行排序
                sort(a, i + 1, height);
            }
         
         
            public static void main(String[] args) {
                int[] arr = {5, 9, 7, 4, 5, 7, 6, 1, 9, 9, 7, 4};
                System.out.println(Arrays.toString(arr));
                sort(arr);
                System.out.println(Arrays.toString(arr));
            }
         
        }
        

        4.1.8:OOP特征一:封装与隐藏

        • 为什么需要封装?封装的作用和含义?

          封装的意义,在于明确标识出允许外部使用的所有成员函数和数据项 内部细节对外部调用透明,外部调用无需修改或者关心内部实现

        • 我们程序设计追求“高内聚,低耦合”。

          • 高内聚 :类的内部数据操作细节自己完成,不允许外部干涉;

          • 低耦合 :仅对外暴露少量的方法用于使用。

        • 隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提 高系统的可扩展性、可维护性。通俗的说,把该隐藏的隐藏起来,该暴露 的暴露出来。这就是封装性的设计思想。

        /**使用者对类内部定义的属性(对象的成员变量)的直接操作会导致数据的错误、混乱或安全性问题。
        问题:xb.legs = -1000;
        应该将legs属性保护起来,
        防止乱用。
        保护的方式:信息隐藏
        */
        class Animal {
            public int legs;
            public void eat(){
            System.out.println("Eating");
            }
            public void move(){
            	System.out.println("Moving.");
            }
        }
        public class Zoo {
            public static void main(String args[]) {
                Animal xb = new Animal();
                xb.legs = 4;
                System.out.println(xb.legs);
                xb.eat();
                xb.move();
                }
        }

        信息的封装和隐藏

        Java中通过将数据声明为私有的(private),再提供公共的(public) 方法:getXxx()和setXxx()实现对该属性的操作,以实现下述目的:

        • 隐藏一个类中不需要对外提供的实现细节;

        • 使用者只能通过事先定制好的方法来访问数据,可以方便地加入控制逻辑, 限制对属性的不合理操作;

        • 便于修改,增强代码的可维护性;

        class Animal {
            private int legs;// 将属性legs定义为private,只能被Animal类内部访问
            public void setLegs(int i) { // 在这里定义方法 eat() 和 move()
                if (i != 0 && i != 2 && i != 4) {
                    System.out.println("Wrong number of legs!");
                    return;
                }
                    legs = i;
                }
                public int getLegs() {
                    return legs;
                }
        	}
        public class Zoo {
            public static void main(String args[]) {
            Animal xb = new Animal();
            xb.setLegs(4); // xb.setLegs(-1000);
            //xb.legs = -1000; // 非法
            System.out.println(xb.getLegs());
            }
        }

        4.1.8.1四种访问权限修饰符

         4种权限可以用来修饰类以及类的内部结构:属性,方法,构造器,内部类

        /**
        1.创建程序,在其中定义两个类:Person和PersonTest类。定义如下:
        用setAge()设置人的合法年龄(0~130),用getAge()返回人的年龄。
        在 PersonTest 类 中实例化 Person 类的对象 b , 调 用 setAge() 和
        getAge()方法,体会Java的封装性。
        */
        public class Person {
            private  int age;
        
            public int getAge() {
                return age;
            }
        
            public void setAge(int a) {
                if (a < 0 || a>130){
                    //throw new RuntimeException("传入的数据非法")
                    System.out.println("传入的数据非法");
                }else{
                    age = a;
                }
        
            }
        }
        //
        public class PersonTest {
            public static void main(String[] args) {
                Person person = new Person();
                person.setAge(6);
                System.out.println("年龄为:"+person.getAge());
            }
        }
        

        4.1.9:类的成员之三:构造器

        • 构造器的特征

          • 它具有与类相同的名称

          • 它不声明返回值类型。(与声明为void不同)

          • 不能被static、final、synchronized、abstract、native修饰,不能有 return语句返回值

        • 构造器的作用:创建对象;给对象进行初始化;

          • 如:Order o = new Order(); Person p = new Person(“Peter”,15);

          • 如同我们规定每个“人”一出生就必须先洗澡,我们就可以在“人”的 构造器中加入完成“洗澡”的程序代码,于是每个“人”一出生就会自 动完成“洗澡”,程序就不必再在每个人刚出生时一个一个地告诉他们 要“洗澡”了

        • 语法格式:

          修饰符 类名 (参数列表) {

          初始化语句;

          }

        举例

        • public class Animal {
              private int legs;
              // 构造器
              public Animal() {
             	 legs = 4;
              } 
              public void setLegs(int i) {
             	 legs = i;
              }
              public int getLegs() {
              	return legs;
              }
          }
          

          创建Animal类的实例:Animal a = new Animal();

          调用构造器,将legs初始化为4。

        • 根据参数不同,构造器可以分为如下两类:

          • 隐式无参构造器(系统默认提供)

          • 显式定义一个或多个构造器(无参、有参)

        • 注 意:

          • Java语言中,每个类都至少有一个构造器

          • 默认构造器的修饰符与所属类的修饰符一致

          • 一旦显式定义了构造器,则系统不再提供默认构造器

          • 一个类可以创建多个重载的构造器

          • 父类的构造器不可被子类继承

            /**
            1. 在前面定义的Person类中添加构造器,利用构造器设置所有人的age属性初始值都为18。
            2. 修改上题中类和构造器,增加name属性,使得每次创建Person对象的同时初始化对象的age属性值和name属性值。
            */
            
            /**
             * 1. 在前面定义的Person类中添加构造器,利用构造器设置所有人的age属
             * 性初始值都为18。
             * 2. 修改上题中类和构造器,增加name属性,使得每次创建Person对象的同
             * 时初始化对象的age属性值和name属性值。
             */
            public class Person {
                private int age;
            
                private String name;
            
                //自定义构造器
                public Person(){
                    age = 18;
                }
            
                //声明带参数的构造器
                public Person(String n ,int a){
                    name = n;
                    age = a;
                }
            
                public void  setAge(int a){
                    if( a < 0  || a > 130){
                        //throw new RuntimeException("传入的数据非法");
                        System.out.println("传入的数据非法");
                        return;
                    }
                    age = a;
                }
            
                public int getAge(){
                    return age;
                }
            
                //get 和 set 方法
                public void setName(String n){
                    name = n ;
                }
            
                public  String getName(){
                    return name;
                }
            }
            
            //***********
            public class PersonTest {
                public static void main(String[] args) {
                    Person person = new Person();
                    person.setAge(12);
            
                    System.out.println("年龄为:"+person.getAge());
            
                    Person person1 = new Person("Tom",21);
                    System.out.println("name = " + person1.getName()+" age: "+person1.getAge());
                }
            }
            /**
            3.编写两个类,TriAngle和TriAngleTest,其中TriAngle类中声明私有的底边长base和高height,同时声明公共方法访问私有变量。此外,提供类必要的构造器。另一个类中使用这些公共方法,计算三角形的面积。
            */
            public class TriAngle {
                //底边长
                private  double base;
                //高
                private  double height;
            
                public TriAngle(){
            
                }
            
                public TriAngle(double b ,double h){
                    base = b;
                    height = h;
                }
            
                public void  setBase(double b){
                    base = b;
                }
            
                public double getBase (){
                    return base;
                }
            
                public  void  setHeight(double h){
                    height = h;
                }
            
                public double getHeight() {
                    return height;
                }
            }
            
            public class TriAngleTest {
                public static void main(String[] args) {
                    TriAngle triAngle = new TriAngle();
                    triAngle.setBase(2.0);
                    triAngle.setHeight(2.4);
                    System.out.println("base:"+triAngle.getBase()+" Hetght:"+triAngle.getHeight());
            
            
                    TriAngle triAngle1 = new TriAngle(5.1,6.3);
                    System.out.println("base:"+triAngle1.getBase()+" Hetght:"+triAngle1.getHeight());
            
                }
            }

            构造器(构造方法),构造器重载

        • 构造器一般用来创建对象的同时初始化对象。如

        class Person{ 
            String name; 
            int age; 
            public Person(String n , int a){ 
                name=n; 
                age=a;
                } 
        } 
        • 构造器重载使得对象的创建更加灵活,方便创建各种不同的对象。 构造器重载举例:

        public class Person{
        
             public Person(String name, int age, Date d) {
                this(name,age);
                …
            } 
        
            public Person(String name, int age) {
                …
            } 
        
            public Person(String name, Date d) {
                …
            } 
            public Person(){
                …
            }
        } 

        构造器重载,参数列表必须不同

        //构造器重载举例
        public class Person { 
            private String name;
            private int age;
            private Date birthDate;
            public Person(String n, int a, Date d) {
                name = n;
                age = a;
                birthDate = d;
            }
            public Person(String n, int a) {
                name = n;
                age = a;
            }
            public Person(String n, Date d) {
                name = n;
                birthDate = d;
            }
            public Person(String n) {
                name = n;
                age = 30;
            }
        }
        
        /**
        (1)定义Student类,有4个属性:
            String name; 
            int age; 
            String school; 
            String major;
        (2)定义Student类的3个构造器:
        第一个构造器Student(String n, int a)设置类的name和age属性;
        第二个构造器Student(String n, int a, String s)设置类的name, age 和school属性;
        第三个构造器Student(String n, int a, String s, String m)设置类的name, age ,school和major属性;
        (3)在main方法中分别调用不同的构造器创建的对象,并输出其属性值。
        */

        总结:属性赋值过程

        • 赋值的位置:

          • ① 默认初始化

          • ② 显式初始化

          • ③ 构造器中初始化

          • ④ 通过“对象.属性“或“对象.方法”的方式赋值

        • 赋值的先后顺序:

          • ① - ② - ③ - ④

        拓展知识:JavaBean

        • JavaBean是一种Java语言写成的可重用组件。

        • 所谓javaBean,是指符合如下标准的Java类:

          • 类是公共的

          • 有一个无参的公共的构造器

          • 有属性,且有对应的get、set方法

        • 用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以 用Java代码创造的对象进行打包,并且其他的开发者可以通过内部的JSP 页面、Servlet、其他JavaBean、applet程序或者应用来使用这些对象。用 户可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,而不用关心任何改变。

        /javaBean
        public class JavaBean {
            private String name; // 属性一般定义为private
            private int age;
            public JavaBean() {
            }
            public int getAge() {
            	return age;
            }
            public void setAge(int a) {
           	 	age = a;
            }
            public String getName() {
            	return name;
            }
            public void setName(String n) {
            	name = n;
            }
        }
        
        //练习
        /**
         * 1.JavaBean是一种Java语言写成的可重用组件。
         * 2.所谓javaBean,是指符合如下标准的Java类:
         *   - 类是公共的
         *   - 有一个无参的公共的构造器
         *   - 有属性,且有对应的get、set方法
         *  - 用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以 用Java代码创造的对象进行打包,
         *    并且其他的开发者可以通过内部的JSP 页面、Servlet、其他JavaBean、applet程序或者应用来使用这些对象。
         *    用 户可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,而不用关心任何改变。
         */
        public class Customer {
        
            //提供属性
            private int id;
        
            private String name;
        
            public Customer(){
        
            }
        
            public  void setId(int i){
                id =  i;
            }
        
            public  int getId(){
                return id;
            }
        
            public String getName() {
                return name;
            }
        
            public void setName(String name) {
                this.name = name;
            }
        }

         

        1. 表示 public 类型, - 表示 private 类型,#表示protected类型

        2. 方法的写法: 方法的类型(+、-) 方法名(参数名: 参数类型):返回值类型

        4.1.9:关键字:this

        this是什么?

        • 在Java中,this关键字比较难理解,它的作用和其词义很接近。

          • 它在方法内部使用,即这个方法所属对象的引用;

          • 它在构造器内部使用,表示该构造器正在初始化的对象。

        • this 可以调用类的属性、方法和构造器

        • 什么时候使用this关键字呢?

          • 当在方法内需要用到调用该方法的对象时,就用this。 具体的:我们可以用this来区分属性和局部变量。 比如:this.name = name;

        • 使用this,调用属性、方法

        /**
        1. 在任意方法或构造器内,如果使用当前类的成员变量或成员方法可以在其前面添加this,
        增强程序的阅读性。不过,通常我们都习惯省略this。
        2. 当形参与成员变量同名时,如果在方法内或构造器内需要
        使用成员变量,必须添加this来表明该变量是类的成员变量
        3.使用this访问属性和方法时,如果在本类中未找到,会从父类中查找
        */
        class Person{ // 定义Person类
            private String name ;
            private int age ;
            public Person(String name,int age){
                this.name = name ; 
                this.age = age ; }
            public void getInfo(){
                System.out.println("姓名:" + name) ;
                this.speak();
            }
            public void speak(){
            	System.out.println(“年龄:” + this.age);
            }
        }
        
        //当前正在操作本方法的对象称为当前对象。
        class Person{ // 定义Person类
            String name;
            Person(String name){
            	this.name = name;
            }
            public void getInfo(){
            	System.out.println("Person类 --> " + this.name) ; }
            public boolean compare(Person p){
            	return this.name==p.name;
            } 
        }
            public class PersonTest{
                public static void main(String args[]){
                Person per1 = new Person("张三") ;
                Person per2 = new Person("李四") ;
                per1.getInfo() ; // 当前调用getInfo()方法的对象是per1
                per2.getInfo() ; // 当前调用getInfo()方法的对象是per2
                boolean b = per1.compare(per2);
            }
         }
        
        //实际操作
        **
         * 1.JavaBean是一种Java语言写成的可重用组件。
         * 2.所谓javaBean,是指符合如下标准的Java类:
         *   - 类是公共的
         *   - 有一个无参的公共的构造器
         *   - 有属性,且有对应的get、set方法
         *  - 用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以 用Java代码创造的对象进行打包,
         *    并且其他的开发者可以通过内部的JSP 页面、Servlet、其他JavaBean、applet程序或者应用来使用这些对象。
         *    用 户可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,而不用关心任何改变。
         */
        public class Customer {
        
            //提供属性
            private int id;
        
            private String name;
        
            public Customer(){
        
            }
        
            public  void setId(int i){
                id =  i;
            }
        
            public  int getId(){
                return id;
            }
        
            public String getName() {
                return name;
            }
        
            public void setName(String name) {
                this.name = name;
            }
        }
        • 使用this调用本类的构造器

        //4.this可以作为一个类中构造器相互调用的特殊格式
        class Person{ // 定义Person类
            private String name ;
            private int age ;
            public Person(){ // 无参构造器
                System.out.println("新对象实例化") ;
            }
            public Person(String name){
                this(); // 调用本类中的无参构造器
                this.name = name ;
            }
            public Person(String name,int age){
                this(name) ; // 调用有一个参数的构造器
                this.age = age;
            }
            public String getInfo(){
            	return "姓名:" + name + ",年龄:" + age ;
            } 
        }
        
        //练习
        /**
         * this关键字的使用
         * 1.this可以用来修饰调用:属性,方法,构造器
         * 2.this修饰属性和方法
         *  this理解为:当前对象 或当前正在创建的对象
         * 2.1.在类的方法中,我们可以使用“this.属性”或“this.方法”的方式,调用当前对象属性或方法.但是,
         * 常情况下,我们都选择省略“this.”。特殊情况下,如果方法的形参和类的属性同名时,
         * 我们必须显示的使用“this.变量”的方式,表明此变量时属性,而非形参
         *
         * 3.this 调用构造器
         *  1.我们在类的构造器中,可以显示的使用“this(形参列表)”方式,调用本类中指定的其他构造器
         *  2.构造器中不能通过“this(形参列表)”方式调用自己
         *  3.如果一个类中有n个构造器,则最多有n-1构造器中使用了“this(形参列表)”
         *  4.规定“this(形参列表)”必须声明在当前构造器的首行
         *  5.构造器内部,最多只能声明一个“this(形参列表)”,用来调用其他的构造器
         *
         */
        public class PersonTest01 {
            public static void main(String[] args) {
                Person01 person01 = new Person01();
                person01.setAge(10);
                System.out.println(person01.getAge());
            }
        }
        
        class Person01{
            private String name;
            private int age;
        
            public Person01(){
        
            }
        
            public Person01(String name){
                this.name = name;
            }
        
            public Person01(String name,int age){
                this.name = name ;
                this.age = age;
            }
        
        
            public void setName(String name) {
                this.name = name;
            }
        
            public String getName() {
                return name;
            }
        
            public void setAge(int age) {
                this.age = age;
            }
        
            public int getAge() {
                return age;
            }
            public  void eat(){
                System.out.println("人吃饭");
                this.study();
            }
            public  void study(){
                System.out.println("人学习");
            }
        
        }

        • 注意:

        • 可以在类的构造器中使用"this(形参列表)"的方式,调用本类中重载的其 他的构造器!

        • 明确:构造器中不能通过"this(形参列表)"的方式调用自身构造器

        • 如果一个类中声明了n个构造器,则最多有 n - 1个构造器中使用了 "this(形参列表)"

        • "this(形参列表)"必须声明在类的构造器的首行!

        • 在类的一个构造器中,最多只能声明一个"this(形参列表)"

        Java入门到超神(全网整理的复习资料)_第21张图片​ 

        //Boy
        public class Boy {
            private String name;
            private int age;
        
            //空参构造器
            public Boy(){
        
            }
        
            public Boy(String name) {
                this.name = name;
            }
        
            public Boy(String name,int age){
                this.name = name;
                this.age = age;
            }
        
            public void setName(String name) {
                this.name = name;
            }
        
            public String getName(){
                return name;
            }
        
            public int getAge() {
                return age;
            }
        
            public void setAge(int age) {
                this.age = age;
            }
        
            //方法
            public void marry(Girl girl){
                System.out.println("我想娶:"+girl.getName());
            }
        
            public void shout(){
                int yeas = 22;
                if(this.age >= yeas ){
                    System.out.println("你可以合法登记结婚了");
                }else{
                    System.out.println("先多谈谈恋爱");
                }
            }
        }
        
        
            //方法
            public void marry(Girl girl){
                System.out.println("我想娶:"+girl.getName());
            }
        
            public void shout(){
                int yeas = 22;
                if(this.age >= yeas ){
                    System.out.println("你可以合法登记结婚了");
                }else{
                    System.out.println("先多谈谈恋爱");
                }
            }
        }
        //Girl
        public class Girl {
            private String name;
            private int age ;
        
            public Girl(){
        
            }
        
            public Girl(String name ,int age){
                this.name = name;
                this.age = age;
            }
        
            public String getName() {
                return name;
            }
        
            public void setName(String name) {
                this.name = name;
            }
        
            public void marry(Boy boy){
                System.out.println("我想嫁给你:"+boy.getName());
                boy.marry(this);
            }
        
            /**
             * @Description 比较两个对象的大小
             * @author liheng
             * @date 2021/08/23 20:51
             * @param girl
             * @return 正数:当前对象大; 负数:当前对象小, 0 当前对象与形参对象相等
             */
            public int compare(Girl girl){
        //        if(this.age > girl.age){
        //            return 1;
        //        }else if (this.age < girl.age){
        //            return -1;
        //        }else{
        //            return 0;
        //        }
                return this.age - girl.age;
            }
        }
        //主方法
        public class BoyGirlTest {
            public static void main(String[] args) {
                Boy boy = new Boy("张三男",21);
                boy.shout();
        
                Girl girl = new Girl("李四女", 20);
                girl.marry(boy);
        
                Girl girl1 = new Girl("祝英台", 19);
                int compare = girl.compare(girl1);
                if (compare > 0 ){
                    System.out.println(girl.getName()+" 大");
                }else if(compare < 0 ){
                    System.out.println(girl1.getName()+" 大");
                }else{
                    System.out.println("一样大");
                }
        
            }
        }
        

        //实验1
        
        /**
         *   1、写一个名为 Account 的类模拟账户。该类的属性和方法如下图所示。该类包括的属性:
         * 账号 id,余额 balance,年利率 annualInterestRate;包含的方法:访问器方法(getter 和 setter
         * 方法),取款方法 withdraw(),存款方法 deposit()。
         *
         *
         */
        public class Account {
            /**
             * 账号 id
             */
            private int id;
            /**
             * 余额 balance
             */
            private double balance;
        
            /**
             * 年利率 annualInterestRate
             */
            private double annualInterestRate;
        
            //构造器
            public Account(int id, double balance, double annualInterestRate) {
                this.id = id;
                this.balance = balance;
                this.annualInterestRate = annualInterestRate;
            }
        
            //get、set方法
            public int getId() {
                return id;
            }
        
            public void setId(int id) {
                this.id = id;
            }
        
            public double getBalance() {
                return balance;
            }
        
            public void setBalance(double balance) {
                this.balance = balance;
            }
        
            public double getAnnualInterestRate() {
                return annualInterestRate;
            }
        
            public void setAnnualInterestRate(double annualInterestRate) {
                this.annualInterestRate = annualInterestRate;
            }
        
            //方法
        
            /**
             * 提示:在提款方法 withdraw 中,需要判断用户余额是否能够满足提款数额的要求,如果不
             * 能,应给出提示。
             * @param amount
             */
            public void withdraw (double amount){
                if (balance < amount){
                    System.out.println("余额不足取款失败");
                    return;
                }
                balance -= amount;
                System.out.println("成功取出:"+amount);
            }
        
            /**
             * 存钱
             * @param amount
             */
            public void deposit (double amount){
                if (amount>0){
                    balance += amount;
                    System.out.println("成功存入:"+amount);
                }
            }
        }
        
        
        /**
         * 客户类
         */
        public class Customer {
            /**
             *
             */
            private String firstName;
            /**
             *
             */
            private String lastName;
        
            /**
             *
             */
            private Account account;
        
            //构造器
            public Customer(String f,String l){
                this.firstName = f;
                this.lastName = l;
            }
        
            public String getFirstName() {
                return firstName;
            }
        
            public String getLastName() {
                return lastName;
            }
        
            public Account getAccount() {
                return account;
            }
        
            public void setAccount(Account account) {
                this.account = account;
            }
        }
        
        /**
         * (1) 创建一个 Customer ,名字叫 Jane Smith, 他有一个账号为 1000,余额为 2000 元,
         * 年利率为 1.23% 的账户。
         * (2) 对 Jane Smith 操作。
         * 存入 100 元,再取出 960 元。再取出 2000 元。
         * 打印出 Jane Smith 的基本信息
         *
         * 成功存入 :100.0
         * 成功取出:960.0
         * 余额不足,取款失败
         * Customer [Smith, Jane] has a account: id is 1000, annualInterestRate is 1.23%, balance is
         * 1140.0
         */
        public class CustomerTest {
            public static void main(String[] args) {
                //实例化构造器
                Customer customer = new Customer("Jane" ,"Smith");
        
                Account account = new Account(1000,2000.00,0.0123);
        
                customer.setAccount(account);
        
                customer.getAccount().deposit(100);
                customer.getAccount().withdraw(960);
                customer.getAccount().withdraw(2000);
        
                System.out.println("Customer ["+customer.getFirstName()+","+customer.getLastName()+"] " +
                        "has a account: id is "+customer.getAccount().getId()+
                        ", annualInterestRate is "+customer.getAccount().getAnnualInterestRate()*100+"%, " +
                        "balance is"+customer.getAccount().getBalance());
            }
        }

        4.1.10关键字:package,import

        • package语句作为Java源文件的第一条语句,指明该文件中定义的类所在 的包。(若缺省该语句,则指定为无名包)。它的格式为: package 顶层包名.子包名 ;

        举例:
        
        pack1\pack2\PackageTest.java 
        
        package pack1.pack2; //指定类PackageTest属于包pack1.pack2 
        
        public class PackageTest{ 
        
        	public void display(){ System.out.println("in method display()"); 
        
        	}
        } 

         包的作用:

        • 包帮助管理大型软件系统:将功能相近的类划分到同一个包中。比如:MVC的设计模式

        • 包可以包含类和子包,划分项目层次,便于管理

        • 解决类命名冲突的问题

        • 控制访问权限 例:某航运软件系统包括:一组域对象、GUI和reports子系统

        •   Java入门到超神(全网整理的复习资料)_第22张图片

          MVC设计模式

          MVC是常用的设计模式之一,将整个程序分为三个层次:视图模型层控制器层,与 数据模型层。这种将程序输入输出、数据处理,以及数据的展示分离开来的设计模式 使程序结构变的灵活而且清晰,同时也描述了程序各个对象间的通信方式,降低了程序的耦合性。

        • 模型层 model 主要处理数据

          • 数据对象封装 model.bean/domain

          • 数据库操作类 model.dao

          • 数据库 model.db

        • 控制层 controller 处理业务逻辑

          • 应用界面相关 controller.activity

          • 存放fragment controller.fragment

          • 显示列表的适配器 controller.adapter

          • 服务相关的 controller.service

          • 抽取的基类 controller.base

        • 视图层 view 显示数据

          • 相关工具类 view.utils

          • 自定义view view.ui

        JDK中主要的包介绍

        1. java.lang----包含一些Java语言的核心类,如String、Math、Integer、 System和 Thread,提供常用功能

        2. java.net----包含执行与网络相关的操作的类和接口。

        3. java.io ----包含能提供多种输入/输出功能的类。

        4. java.util----包含一些实用工具类,如定义系统特性、接口的集合框架类、使用与日 期日历相关的函

        5. java.text----包含了一些java格式化相关的类

        6. java.sql----包含了java进行JDBC数据库编程的相关类/接口

        7. java.awt----包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这 些类被用来构建和管理应用程序的图形用户界面(GUI)。 B/S C/S

        关键字—import

        • 为使用定义在不同包中的Java类,需用import语句来引入指定包层次下所需要的类 或全部类(.*)。import语句告诉编译器到哪里去寻找类。

        • 语法格式:

          • import 包名. 类名;

        • 应用举例:

        import pack1.pack2.Test; //import pack1.pack2.*;表示引入pack1.pack2包中的所有结构
        public class PackTest{
        	public static void main(String args[]){
                Test t = new Test(); //Test类在pack1.pack2包中定义
                t.display();
            }
        }

        注意:

        1. 在源文件中使用import显式的导入指定包下的类或接口

        2. 声明在包的声明和类的声明之间

        3. 如果需要导入多个类或接口,那么就并列显式多个import语句即可

        4. 举例:可以使用java.util.*的方式,一次性导入util包下所有的类或接口。

        5. 如果导入的类或接口是java.lang包下的,或者是当前包下的,则可以省略此import语句。

        6. 如果在代码中使用不同包下的同名的类。那么就需要使用类的全类名的方式指明调用的 是哪个类。

        7. 如果已经导入java.a包下的类。那么如果需要使用a包的子包下的类的话,仍然需要导入。

        8. import static组合的使用:调用指定类或接口下的静态的属性或方法

        4.1.11:本节面试题

        //面试题
        /**
         * 1.构造器的作用是什么?使用中有哪些注意点(>=3条)
         *	1.1:创建对象,
         *	1.2:初始化对象结构
         *	注意:	- ava语言中,每个类都至少有一个构造器 
         *		  - 默认构造器的修饰符与所属类的修饰符一致 
         *		  - 一旦显式定义了构造器,则系统不再提供默认构造器 
         *		  - 一个类可以创建多个重载的构造器 
         *		  - 父类的构造器不可被子类继承
         * 2.关于类的属性的赋值,有几种赋值的方式。谈谈赋值先后顺序
         *		-  赋值的位置: 
         *  		- ① 默认初始化 
         *  		- ② 显式初始化 
         *  		- ③ 构造器中初始化
         *  		- ④ 通过“对象.属性“或“对象.方法”的方式赋值 
         *
         *		   -  赋值的先后顺序: 
         * 		   - ① - ② - ③ - ④
         * 3. this关键字可以用来调用哪些结构,简单说明一下。
         *		this可以调用属性,方法,构造器
         *		this:理解为当前对象,当前正在创建的对象
         *
         * 4.java中目前学习设计到的四种权限修饰符都有什么?并说明各自的范围。
         *		4.1: private :当前类下独自使用的
         *		4.2:缺省:当前类,当前包,
         *		4.3:protected :当前类,当前包,不同包的子类
         *		4.4:public :当前类,当前包,不同包的子类,同一个工程
         *
         * 5.创建Circle类,提供私有的radius属性,提供相应的get和set方法,提供求圆的面积。
         */
        import java.util.Scanner;
        
        /**
         * 5.创建Circle类,提供私有的radius属性,提供相应的get和set方法,提供求圆的面积。
         */
        public class Circle {
        
            /**
             *     半径
             */
            private double radius;
        
            /**
             * 提供get和set方法
             */
            public double getRadius() {
                return radius;
            }
        
            public void setRadius(double radius) {
                this.radius = radius;
            }
        
            /**
             * 求圆的面积计算函数
             */
            public void radius(double radius){
                double circle = Math.PI * radius * radius;
                System.out.println("圆的面积为:"+ circle);
            }
        
            public static void main(String[] args) {
                //double v = (int)(Math.random() * 100 - 1);
                System.out.println("请输入圆的半径");
                Scanner scanner = new Scanner(System.in);
                double nextDouble = scanner.nextDouble();
        
        
                Circle circle = new Circle();
                circle.radius(nextDouble);
        
            }
        /**
         * 面向对象特征之一:封装与隐藏
         *	1.为什么要引入封装性?
         * 		我们程序设计追求“高内聚,低耦合”
         *	    “高内聚”:类的内部数据操作细节自己完成,不允许外部干涉
         *	    “低耦合”:仅对外暴露少量的方法用于使用
         *		隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性,可维护性。通俗说,  *   把该隐藏的隐藏起来,把该暴露的暴露出来。 这就是封装设计的思想。
         *
         *
         *	this可以调用:属性,方法,构造器
         *
         *	this调用构造器
         *  1.我们在类的构造器中,可以显示的使用“this(形参列表)”方式,调用本类中指定的其他构造器
         *  2.构造器中不能通过“this(形参列表)”方式调用自己
         *  3.如果一个类中有n个构造器,则最多有n-1构造器中使用了“this(形参列表)”
         *  4.规定“this(形参列表)”必须声明在当前构造器的首行
         *  5.构造器内部,最多只能声明一个“this(形参列表)”,用来调用其他的构造器
         *
         *JDK中主要的包介绍** 
        * 1. java.lang----包含一些Java语言的核心类,如String、Math、Integer、 System和 Thread,提供常用功能 
        * 2. java.net----包含执行与网络相关的操作的类和接口。 
        * 3. java.io ----包含能提供多种输入/输出功能的类。 
        * 4. java.util----包含一些实用工具类,如定义系统特性、接口的集合框架类、使用与日 期日历相关的函
        * 5. java.text----包含了一些java格式化相关的类 
        * 6. java.sql----包含了java进行JDBC数据库编程的相关类/接口 
        * 7. java.awt----包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这 些类被用来构建和管理应用程序的图形用户界面(GUI)。 B/S C/S
         *
         */

         本章节练习小项目

        import java.util.*;
        /**
        CMUtility工具类:
        将不同的功能封装为方法,就是可以直接通过调用方法使用它的功能,而无需考虑具体的功能实现细节。
        */
        public class CMUtility {
            private static Scanner scanner = new Scanner(System.in);
        
            /**
        	用于界面菜单的选择。该方法读取键盘,如果用户键入’1’-’5’中的任意字符,则方法返回。返回值为用户键入字符。
        	*/
        	public static char readMenuSelection() {
                char c;
                for (; ; ) {
                    String str = readKeyBoard(1, false);
                    c = str.charAt(0);
                    if (c != '1' && c != '2' && 
                        c != '3' && c != '4' && c != '5') {
                        System.out.print("选择错误,请重新输入:");
                    } else {
                        break;
                    }
                }
                return c;
            }
        	/**
        	从键盘读取一个字符,并将其作为方法的返回值。
        	*/
            public static char readChar() {
                String str = readKeyBoard(1, false);
                return str.charAt(0);
            }
        	/**
        	从键盘读取一个字符,并将其作为方法的返回值。
        	如果用户不输入字符而直接回车,方法将以defaultValue 作为返回值。
        	*/
            public static char readChar(char defaultValue) {
                String str = readKeyBoard(1, true);
                return (str.length() == 0) ? defaultValue : str.charAt(0);
            }
        	/**
        	从键盘读取一个长度不超过2位的整数,并将其作为方法的返回值。
        	*/
            public static int readInt() {
                int n;
                for (; ; ) {
                    String str = readKeyBoard(2, false);
                    try {
                        n = Integer.parseInt(str);
                        break;
                    } catch (NumberFormatException e) {
                        System.out.print("数字输入错误,请重新输入:");
                    }
                }
                return n;
            }
        	/**
        	从键盘读取一个长度不超过2位的整数,并将其作为方法的返回值。
        	如果用户不输入字符而直接回车,方法将以defaultValue 作为返回值。
        	*/
            public static int readInt(int defaultValue) {
                int n;
                for (; ; ) {
                    String str = readKeyBoard(2, true);
                    if (str.equals("")) {
                        return defaultValue;
                    }
        
                    try {
                        n = Integer.parseInt(str);
                        break;
                    } catch (NumberFormatException e) {
                        System.out.print("数字输入错误,请重新输入:");
                    }
                }
                return n;
            }
        	/**
        	从键盘读取一个长度不超过limit的字符串,并将其作为方法的返回值。
        	*/
            public static String readString(int limit) {
                return readKeyBoard(limit, false);
            }
        	/**
        	从键盘读取一个长度不超过limit的字符串,并将其作为方法的返回值。
        	如果用户不输入字符而直接回车,方法将以defaultValue 作为返回值。
        	*/
            public static String readString(int limit, String defaultValue) {
                String str = readKeyBoard(limit, true);
                return str.equals("")? defaultValue : str;
            }
        	/**
        	用于确认选择的输入。该方法从键盘读取‘Y’或’N’,并将其作为方法的返回值。
        	*/
            public static char readConfirmSelection() {
                char c;
                for (; ; ) {
                    String str = readKeyBoard(1, false).toUpperCase();
                    c = str.charAt(0);
                    if (c == 'Y' || c == 'N') {
                        break;
                    } else {
                        System.out.print("选择错误,请重新输入:");
                    }
                }
                return c;
            }
        
            private static String readKeyBoard(int limit, boolean blankReturn) {
                String line = "";
        
                while (scanner.hasNextLine()) {
                    line = scanner.nextLine();
                    if (line.length() == 0) {
                        if (blankReturn) {
                            return line;
                        }else{
                            continue;
                        }
                    }
        
                    if (line.length() < 1 || line.length() > limit) {
                        System.out.print("输入长度(不大于" + limit + ")错误,请重新输入:");
                        continue;
                    }
                    break;
                }
        
                return line;
            }
        }
        //
        /**
         * Customer为实体类,用来封装客户信息
         */
        public class Custlomer {
        
            /**
             * 客户姓名
             */
            private String name;
        
            /**
             * 性别
             */
            private char gender;
        
            /**
             * 年龄
             */
            private int age;
        
            /**
             * 电话号码
             */
            private String phone;
        
            /**
             * 电子邮箱
             */
            private String email;
        
        
            //提供构造方法
            public Custlomer(){
            }
        
            public Custlomer(String name, char gender, int age, String phone, String email) {
                this.name = name;
                this.gender = gender;
                this.age = age;
                this.phone = phone;
                this.email = email;
            }
        
            public String getName() {
                return name;
            }
        
            public void setName(String name) {
                this.name = name;
            }
        
            public char getGender() {
                return gender;
            }
        
            public void setGender(char gender) {
                this.gender = gender;
            }
        
            public int getAge() {
                return age;
            }
        
            public void setAge(int age) {
                this.age = age;
            }
        
            public String getPhone() {
                return phone;
            }
        
            public void setPhone(String phone) {
                this.phone = phone;
            }
        
            public String getEmail() {
                return email;
            }
        
            public void setEmail(String email) {
                this.email = email;
            }
        
            //显示当前对象的信息
            public String info(){
                return name + "\t" + gender + "\t" + age + "\t" + phone + "\t" + email;
            }
        }
        
        import myproject01.bean.Custlomer;
        
        /**
         * CustlomerList为Custlomer对象的管理模块,内部使用数组管理一组Custlomer对象
         */
        
        public class CustlomerList {
            /**
             * 用来保存客户对象数组
             */
            private Custlomer[] custlomers;
        
            /**
             * 记录已保存客户对象的数量
             */
            private int total;
        
        
            /**
             * 提供构造器以及方法
             */
            /**
             * 用来初始化Custlomer数组的构造器
             * @param totalCustomer 指定数组的长度
             */
            public CustlomerList(int totalCustomer){
                //初始化
                custlomers = new Custlomer[totalCustomer];
            }
        
            /**
             * @Description 将指定的客户添加到数组中
             * @param custlomer
             * @return true:添加成功  false:添加失败
             */
        
            public boolean addCustlomer(Custlomer custlomer){
                //判断添加用户
                if(custlomer != null && total< custlomers.length){
                    // custlomers[total] =custlomer;
                    // total++;
                    custlomers[total++] =custlomer;
                    return true;
                }
                return  false;
        
            }
        
            /**
             * @Description 修改指定位置上的客户信息
             * @param custlomer
             * @return true:修改成功  false:修改失败
             */
            public boolean replaceCustomer(int index,Custlomer custlomer){
                if(index>0 || index < total){
                    custlomers[index] = custlomer;
                    return true;
                }
                return false;
            }
        
            /**
             * @Description 删除指定索引位置上的客户
             * @param index
             * @return  true:删除成功  false:删除失败
             */
            public boolean deleteCustomer(int index){
                if(index>=0 || index < total){
                    for (int i = index; i < total-1 ; i++) {
                        custlomers[i] = custlomers[i+1];
                    }
                    //最后有数据的元素需要置空
        //        custlomers[total - 1] = null;
        //        total--;
                    custlomers[--total] = null;
                    return true;
                }
                return false;
            }
        
            /**
             * @Description 获取所有的客户信息
             * @return
             */
            public  Custlomer[] getAllCustomer(){
                Custlomer[] custl = new Custlomer[total];
                for (int i = 0; i < total; i++) {
                    custl[i] = custlomers[i];
                }
                return custl;
            }
            /**
             * @Description 获取所有的客户信息
             * @return  如果找到了元素,则返回;如果没有找到,则返回null
             */
            public Custlomer getCustlomer(int index){
                if(index >= 0 && index < total){
                    return custlomers[index];
                }
                return null;
            }
        
            /**
             * @Description 获取存储的客户的数量
             * @return
             */
            public int getTotal(){
                return total;
        //        return custlomers.length;//错误的
            }
        
        }
        
        
        
        import myproject01.bean.Custlomer;
        import myproject01.sevice.CustlomerList;
        import myproject01.util.CMUtility;
        
        /**
         * @Descrpition CustlomerView 为主模块,负责菜单的显示和处理用户操作
         */
        public class CustlomerView {
            private CustlomerList custlomerList = new CustlomerList(10);
        
            public CustlomerView(){
                Custlomer custlomer = new Custlomer("张三",'男',23,"15619971100","[email protected]");
                custlomerList.addCustlomer(custlomer);
            }
        
            /**
             * 显示《客户信息管理软件》界面的方法
             * 进入主界面的方法
             */
            public void enterMainMenu(){
                boolean isFlag = true;
                do{
                    System.out.println("\n-----------------客户信息管理软件-----------------\n");
                    System.out.println("                   1 添 加 客 户");
                    System.out.println("                   2 修 改 客 户");
                    System.out.println("                   3 删 除 客 户");
                    System.out.println("                   4 客 户 列 表");
                    System.out.println("                   5 退       出\n");
                    System.out.print("                      请选择(1-5):");
                    // 从键盘获取用户1-5的选择
                    char menu = CMUtility.readMenuSelection();
                    // 使用switch-case对用户的选择,进行区别处理
                    switch (menu){
                        case '1':
                            addNewCustomer();
                            break;
                        case '2':
                            modifyCustomer();
                            break;
                        case '3':
                            deleteCustomer();
                            break;
                        case '4':
                            listAllCustomer();
                        case '5':
                            System.out.println("确认是否退出Y/N:");
                            char isExit = CMUtility.readConfirmSelection();
                            if (isExit == 'Y'){
                                isFlag = false;
                            }
                           break;
                    }
                }while (isFlag);
                
            }
        
            /**
             * 添加客户的操作
             */
            private void addNewCustomer(){
                //System.out.println("添加客户");
        
                System.out.print("姓名:");
                String name = CMUtility.readString(5);
                System.out.print("性别:");
                char gender = CMUtility.readChar();
                System.out.print("年龄:");
                int age = CMUtility.readInt();
                System.out.print("电话:");
                String phone = CMUtility.readString(15);
                System.out.print("邮箱:");
                String email = CMUtility.readString(20);
                //将上述数据封装到对象中
                Custlomer custlomer = new Custlomer(name, gender, age, phone, email);
                boolean isSuccess = custlomerList.addCustlomer(custlomer);
        
                if(isSuccess){
                    System.out.println("---------------------添加客户---------------------");
                }else{
                    System.out.println("---------------------客户目录已满,添加失败---------------------");
                }
        
            }
        
            /**
             *
             */
            private void modifyCustomer(){
                System.out.println("---------------------修改客户---------------------");
                Custlomer custlomer;
                int number;
                for (;;) {
                    System.out.print("请选择待修改客户编号(-1退出):");
                    number = CMUtility.readInt();
                    if(number == -1){
                        return;
                    }
                    // 对于用户来讲,我们让number 默认从1开始。
                    custlomer = custlomerList.getCustlomer(number-1);
                    if (custlomer == null){
                        System.out.println("无法找到指定的客户");
                    }else{
                        //找到了相应编号的客户
                        break;
                    }
                }
                //修改客户信息
                System.out.println("姓名("+custlomer.getName()+"):");
                String name = CMUtility.readString(10, custlomer.getName());
                System.out.println("性别("+custlomer.getGender()+"):");
                char gender = CMUtility.readChar(custlomer.getGender());
                System.out.println("年龄("+custlomer.getAge()+"):");
                int age = CMUtility.readInt(custlomer.getAge());
                System.out.println("电话("+custlomer.getPhone()+"):");
                String phone = CMUtility.readString(13, custlomer.getPhone());
                System.out.println("邮箱("+custlomer.getEmail()+"):");
                String email = CMUtility.readString(30, custlomer.getEmail());
                //将上述数据封装到对象中
                Custlomer newCustlomer = new Custlomer(name, gender, age, phone, email);
                boolean isReplace = custlomerList.replaceCustomer(number - 1, newCustlomer);
                if(isReplace){
                    System.out.println("---------------------修改完成---------------------");
                }else{
                    System.out.println("---------------------修改失败---------------------");
                }
            }
        
            /**
             * 删除用户
             */
            private void deleteCustomer(){
                System.out.println("---------------------删除客户---------------------");
                Custlomer custlomer;
                int number;
                for (;;){
                    System.out.print("请选择待删除客户编号(-1退出):");
                     number = CMUtility.readInt();
                    if (number == -1){
                        return;
                    }
                    custlomer = custlomerList.getCustlomer(number - 1);
                    if (custlomer == null){
                        System.out.println("无法找到指定客户");
                    }else{
                        break;
                    }
                }
                //一旦找到相应的索引位置的customer以后,让用户决定是否确认删除
                System.out.println("是否需要确认删除Y/N");
                char isDelete = CMUtility.readConfirmSelection();
                if(isDelete == 'Y'){
                    boolean deleteSuccess = custlomerList.deleteCustomer(number - 1);
                    if (deleteSuccess) {
                        System.out.println("---------------------删除完成---------------------");
        
                    }else{
                        System.out.println("---------------------删除失败---------------------");
                    }
                }else{
                    return;
                }
            }
        
            /**
             * 显示客户列表的操作
             */
            private void listAllCustomer(){
                //System.out.println("显示客户列表");
                System.out.println("---------------------------客户列表---------------------------");
                int total = custlomerList.getTotal();
                if(total == 0){
                    System.out.println("没有任何客户记录!");
                }else{
                    System.out.println("编号\t姓名\t性别\t年龄\t电话\t\t\t邮箱");
                    Custlomer[] allCustomer = custlomerList.getAllCustomer();
                    for (int i = 0; i < allCustomer.length; i++) {
                        Custlomer cust = allCustomer[i];
                        System.out.println((i+1)+"\t"+cust.getName()+"\t"+cust.getGender()
                                +"\t"+cust.getAge()+"\t"+cust.getPhone()+"\t"+cust.getEmail());
                    }
                }
        
                System.out.println("-------------------------客户列表完成-------------------------");
            }
        
            public static void main(String[] args) {
                CustlomerView view = new CustlomerView();
                view.enterMainMenu();
            }
        
        
        }
        /**
         * CustlomerList为Custlomer对象的管理模块,内部使用数组管理一组Custlomer对象
         */
        
        public class CustlomerList {
            /**
             * 用来保存客户对象数组
             */
            private Custlomer[] custlomers;
        
            /**
             * 记录已保存客户对象的数量
             */
            private int total;
        
        
            /**
             * 提供构造器以及方法
             */
            /**
             * 用来初始化Custlomer数组的构造器
             * @param totalCustomer 指定数组的长度
             */
            public CustlomerList(int totalCustomer){
                //初始化
                custlomers = new Custlomer[totalCustomer];
            }
        
            /**
             * @Description 将指定的客户添加到数组中
             * @param custlomer
             * @return true:添加成功  false:添加失败
             */
        
            public boolean addCustlomer(Custlomer custlomer){
                //判断添加用户
                if(custlomer != null && total< custlomers.length){
                    // custlomers[total] =custlomer;
                    // total++;
                    custlomers[total++] =custlomer;
                    return true;
                }
                return  false;
        
            }
        
            /**
             * @Description 修改指定位置上的客户信息
             * @param custlomer
             * @return true:修改成功  false:修改失败
             */
            public boolean replaceCustomer(int index,Custlomer custlomer){
                if(index>0 || index < total){
                    custlomers[index] = custlomer;
                    return true;
                }
                return false;
            }
        
            /**
             * @Description 删除指定索引位置上的客户
             * @param index
             * @return  true:删除成功  false:删除失败
             */
            public boolean deleteCustomer(int index){
                if(index>=0 || index < total){
                    for (int i = index; i < total-1 ; i++) {
                        custlomers[i] = custlomers[i+1];
                    }
                    //最后有数据的元素需要置空
        //        custlomers[total - 1] = null;
        //        total--;
                    custlomers[--total] = null;
                    return true;
                }
                return false;
            }
        
            /**
             * @Description 获取所有的客户信息
             * @return
             */
            public  Custlomer[] getAllCustomer(){
                Custlomer[] custl = new Custlomer[total];
                for (int i = 0; i < total; i++) {
                    custl[i] = custlomers[i];
                }
                return custl;
            }
            /**
             * @Description 获取所有的客户信息
             * @return  如果找到了元素,则返回;如果没有找到,则返回null
             */
            public Custlomer getCustlomer(int index){
                if(index >= 0 && index < total){
                    return custlomers[index];
                }
                return null;
            }
        
            /**
             * @Description 获取存储的客户的数量
             * @return
             */
            public int getTotal(){
                return total;
        //        return custlomers.length;//错误的
            }
        
        }

        第5章:面向对象编程(中)

        5.1:面向对象特征二:继承性

        • 为什么要有继承?

          • 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中, 那么多个类无需再定义这些属性和行为,只要继承那个类即可。

        • 此处的多个类称为子类(派生类),单独的这个类称为父类(基类 或超类)。可以理解为:“子类 is a 父类”

        • 类继承语法规则: class Subclass extends SuperClass{ }

        • 作用:

          • 继承的出现减少了代码冗余,提高了代码的复用性。 

          • 继承的出现,更有利于功能的扩展。

          • 继承的出现让类与类之间产生了关系,提供了多态的前提。

        • 注意:不要仅为了获取其他类中某个功能而去继承

        • 子类继承了父类,就继承了父类的方法和属性。

        • 在子类中,可以使用父类中定义的方法和属性,也可以创建新的数据和方法。

        • 在Java 中,继承的关键字用的是“extends”,即子类不是父类的子集, 而是对父类的“扩展”。

        • Java只支持单继承和多层继承,不允许多重继承

          • 一个子类只能有一个父类

          • 一个父类可以派生出多个子类

            • class SubDemo extends Demo{ } //ok

            • class SubDemo extends Demo1,Demo2...//error

        • Java只支持单继承和多层继承,不允许多重继承

          • 一个子类只能有一个父类

          • 一个父类可以派生出多个子类

            • class SubDemo extends Demo{ } //ok

            • class SubDemo extends Demo1,Demo2...//error

         

        //案例
        public class Person {
            String name;
            int age;
        
            //提供一个构造方法
            public  Person(){
        
            }
        
            public Person(String name,int age){
                this.name = name;
                this.age = age;
            }
        
            public  void  eat(){
                System.out.println("Person+吃饭");
            }
        
            public void sleep(){
                System.out.println("Person+睡觉");
            }
        
            public int getAge() {
                return age;
            }
        
            public void setAge(int age) {
                this.age = age;
            }
        }
        public class Student extends Person{
        //    String name;
        //    int age;
            String major;
        
            public Student(){
        
            }
            public Student(String name, int age,String major){
                this.name = name;
                this.age = age;
                this.major = major;
            }
        
        //    public void eat(){
        //        System.out.println("吃饭");
        //    }
        //
        //    public void sleep(){
        //        System.out.println("睡觉");
        //    }
        
            public void study(){
                System.out.println("学习");
            }
        }
        
        /**
         * 面向对象特征之二:继承性
         * 一:继承性的好处
         * 1:减少了代码的冗余,提高代码的复用性
         * 2:便于功能的扩展
         * 3:为了之后多态性的使用,提供了前提
         *
         * 二:继承性的格式:class A extends B{}
         *  A:子类,派生类,subclass
         *  B:父类,超类,基类,superclass
         *  2.1体现:一旦子类A继承父类B以后,子类A中获取了父类B中声明的结构。
         *      特别的,父类中声明为private的属性或方法,子类继承父类以后,仍然认为获取父类中私有的结构
         *      只有因为封装性的影响。
         *  2.2 子类继承父类以后,还可以声明自己特有的属性或方法:实现功能的拓展。
         *      子类和父类的关系,不同于子集和集合的关系。
         *      extends :延展,扩展。
         * 三:java关于继承性的规定
         *     1:一个类可以被多个子类继承
         *     2:一个类只能有一个父类
         *     3:子父类是相对的概念
         *     4:子类直接继承的类称为直接父类。间接继承的父类称为:间接弗雷
         *     5:子类继承父类以后,就会直接父类以及所有间接父类中声明的属性和方法
         * 四:1.如果我们没有显示的声明一个类的父类的话,则此类继承与java.lang.Object类
         *     2.所有的java类(除java.lang.Object)都直接或间接的继承与java.lang.Object类
         *     3.意味着,所有的java类都具有java.lang.Object类声明或功能
         */
        public class ExtendsTest {
            public static void main(String[] args) {
                Person person = new Person();
                person.age = 1;
                person.eat();
        
                Student student = new Student();
                student.name = "张三";
                student.eat();
                student.sleep();
            }
        }
        
        复习:继承性
        1:为什么要有类的继承性?
            1:减少了代码的冗余,提高代码的复用性
            2:便于功能的扩展
            3:为了之后多态性的使用,提供了前提
        2:继承性的格式
        	class A extents B{}
        	
        3:子类继承父类有哪些不同?	
        	 2.1体现:一旦子类A继承父类B以后,子类A中获取了父类B中声明的结构。
               特别的,父类中声明为private的属性或方法,子类继承父类以后,仍然认为获取父类中私有的结构
               只有因为封装性的影响。
          	2.2 子类继承父类以后,还可以声明自己特有的属性或方法:实现功能的拓展。
               子类和父类的关系,不同于子集和集合的关系。
               extends :延展,扩展。
               
        4.Java中继承性的说明       
        	1:一个类可以被多个子类继承
        	2:一个类只能有一个父类
           	3:子父类是相对的概念
           	4:子类直接继承的类称为直接父类。间接继承的父类称为:间接父类
           	5:子类继承父类以后,就会直接父类以及所有间接父类中声明的属性和方法
           	
        5.java.lang.Object类的理解
        	1.如果我们没有显示的声明一个类的父类的话,则此类继承与java.lang.Object类
            2.所有的java类(除java.lang.Object)都直接或间接的继承与java.lang.Object类
            3.意味着,所有的java类都具有java.lang.Object类声明或功能
        /练习1
        /**
        (1)定义一个ManKind类,包括
            成员变量int sex和int salary;
            方法void manOrWoman():根据sex的值显示“man”(sex==1)或者“woman”(sex==0);
            方法void employeed():根据salary的值显示“no job”(salary==0)或者“ job”(salary!=0)。
        (2)定义类Kids继承ManKind,并包括
            成员变量int yearsOld;
            方法printAge()打印yearsOld的值。
        (3)定义类KidsTest,在类的main方法中实例化Kids的对象someKid,用该对象访问
        	其父类的成员变量及方法。
        */	
        public class Mankind {
            private int sex;
            private int salary;
        
            public Mankind() {
        
            }
        
            public Mankind(int sex, int salary) {
                this.sex = sex;
                this.salary = salary;
            }
        
            public int getSex() {
                return sex;
            }
        
            public void setSex(int sex) {
                this.sex = sex;
            }
        
            public int getSalary() {
                return salary;
            }
        
            public void setSalary(int salary) {
                this.salary = salary;
            }
        
            public void manOrWoan(){
                if (sex == 1){
                    System.out.println("man");
                }else if(sex == 0){
                    System.out.println("woman");
                }
            }
        
            public void employeed(){
        //        if(salary == 0){
        //            System.out.println("no job");
        //        }else if(salary != 0){
        //            System.out.println("job");
        //        }
                String jobInfo = (salary == 0) ? "nojob" : "job";
                System.out.println(jobInfo);
            }
        }
        public class Kids extends Mankind {
            private int yearsOld;
        
            public Kids() {
            }
        
            public Kids(int yearsOld) {
                this.yearsOld = yearsOld;
            }
        
            public void printAge(){
                System.out.println("I am "+ yearsOld + "yeasOld");
            }
        
            public int getYearsOld() {
                return yearsOld;
            }
        
            public void setYearsOld(int yearsOld) {
                this.yearsOld = yearsOld;
            }
        }
        
        public class KidsTest {
            public static void main(String[] args) {
                Kids somekids = new Kids(12);
                somekids.printAge();
                somekids.manOrWoan();
                somekids.setSalary(0);
                somekids.setSex(1);
                somekids.manOrWoan();
                somekids.employeed();
            }
        }
        
        /** 
        *根据下图实现类。在CylinderTest类中创建Cylinder类的对象,设置圆柱的底面半径和高,并输出圆柱的体积。
        *	Circle (圆)
        * -radius :double
        * Circle(): 构造器,将radius属性初始化为1
        * +setRadius(double radius) : void
        * +getRadius(): double
        * +findArea():double 计算圆的面积
        *----------------------------------
        *	Cylinder (圆柱)
        *-length:double
        * Cylinder(): 构造器,将length属性初始化为1
        * +setLength(double length):void
        * +getLength():double
        * +findVolume() :double 计算圆柱体积
        */
        public class Circle {
            private  double radius;
        
        
            public Circle() {
                radius = 1.0;
            }
        
            public double getRadius() {
                return radius;
            }
        
            public void setRadius(double radius) {
                this.radius = radius;
            }
        
            //返回圆的面积
            public double findArea(){
                return Math.PI * radius *radius;
            }
        }
        public class Cylinder extends Circle{
            private double length;
        
            public Cylinder() {
                length=1.0;
            }
        
            public double getLength() {
                return length;
            }
        
            public void setLength(double length) {
                this.length = length;
            }
        
            public double findVolume(){
              //  return Math.PI * getRadius() * getLength() * getLength();
                return  findArea() * getLength();
            }
        }
        public class CylinderTest {
            public static void main(String[] args) {
                Cylinder cylinder = new Cylinder();
                cylinder.setRadius(2.1);
                cylinder.setLength(3.4);
                double volume = cylinder.findVolume();
                System.out.println("圆柱的体积:" + volume);
        
                double area = cylinder.findArea();
                System.out.println("底面圆的面积:"+ area);
            }
        }

        5.2:方法的重写(override)

        • 定义:在子类中可以根据需要对从父类中继承来的方法进行改造,也称 为方法的重置、覆盖。在程序执行时,子类的方法将覆盖父类的方法。

        • 要求:

        1. 子类重写的方法必须和父类被重写的方法具有相同的方法名称、参数列表

        2. 子类重写的方法的返回值类型不能大于父类被重写的方法的返回值类型

        3. 子类重写的方法使用的访问权限不能小于父类被重写的方法的访问权限

          子类不能重写父类中声明为private权限的方法

        4. 子类方法抛出的异常不能大于父类被重写方法的异常

        • 注意: 子类与父类中同名同参数的方法必须同时声明为非static的(即为重写),或者同时声明为 static的(不是重写)。因为static方法是属于类的,子类无法覆盖父类的方法。

        5.3:四种访问权限修饰符

        //注意看包名称
        package shangxuetang.day10;
        
        /**
         * 体会4中不同的权限修饰
         */
        public class Order {
            private int orderPrivate;
            int orderDefault;
            protected int orderProtected;
            public int orderPublic;
        
            private void metnodPrivate(){
                orderPrivate = 1;
                orderDefault = 2;
                orderProtected = 3;
                orderPublic = 4;
            }
        
            void methodDeafault(){
                orderPrivate = 1;
                orderDefault = 2;
                orderProtected = 3;
                orderPublic = 4;
            }
        
            protected void  methodProtected(){
                orderPrivate = 1;
                orderDefault = 2;
                orderProtected = 3;
                orderPublic = 4;
            }
        
            public void methodPublic(){
                orderPrivate = 1;
                orderDefault = 2;
                orderProtected = 3;
                orderPublic = 4;
            }
        
        }
        public class OrderTest {
            public  static void main(String[] args){
                Order order = new Order();
                order.orderDefault = 1;
                order.orderProtected = 2;
                order.orderPublic = 3;
        
                order.methodDeafault();
                order.methodProtected();
                order.methodPublic();
                //同一个包中的其他类,不可以调用Order类中私有的属性,方法
        //        order.orderPrivate = 4 ;
        //        order.methodPrivate ();
        
        
            }
        }
        
        package shangxuetang.day10.day101;
        
        import shangxuetang.day10.Order;
        
        public class SubOrder extends Order {
            public void method(){
               orderProtected = 1;
               orderPublic = 2;
               methodProtected();
               methodPublic();
        
               //在不同包的子类中,不能调用Order类中声明为private和缺省权限的属性,方法
        //       orderDefault = 3;
        //       orderPrivate = 4;
        //
        //       methodDeafault();
        //       methodPrivate();
            }
        }
        
        package shangxuetang.day10.day101;
        
        import shangxuetang.day10.Order;
        
        public class OrderTest {
            public static void main(String[] args) {
                Order order = new Order();
                order.orderPublic = 1;
                order.methodPublic();
        
                //不同包下的非普通类(非子类)要是用Order类,不可以调用声明为private,缺省,protected权限的属性,方法
        //        order.orderPrivate = 2;
        //        order.orderDefault = 3;
        //        order.orderProtected = 4;
        //
        //        order.methodPrivate = 2;
        //        order.methodDefault = 3;
        //        order.methodProtected = 4;
        
            }
            public void show(Order order){
                order.orderPublic = 1;
                order.methodPublic();
        
                //不同包下的非普通类(非子类)要是用Order类,不可以调用声明为private,缺省,protected权限的属性,方法
        //        order.orderPrivate = 2;
        //        order.orderDefault = 3;
        //        order.orderProtected = 4;
        //
        //        order.methodPrivate = 2;
        //        order.methodDefault = 3;
        //        order.methodProtected = 4;
            }
        
        }

        5.4:关键字:super

        • 在Java类中使用super来调用父类中的指定操作:

          • super可用于访问父类中定义的属性

          • super可用于调用父类中定义的成员方法

          • super可用于在子类构造器中调用父类的构造器

        • 注意:

          • 尤其当子父类出现同名成员时,可以用super表明调用的是父类中的成员

          • super的追溯不仅限于直接父类

          • super和this的用法相像,this代表本类对象的引用,super代表父类的内存 空间的标识

         

        package shangxuetang.day11;
        
        public class Person {
            String name;
            int age;
            //身份证号
            int id = 1001;
        
            public Person() {
                System.out.println("我无处不在");
            }
        
            public Person(String name) {
                this.name = name;
            }
        
            public Person(String name ,int age) {
                this(name);
                this.age = age;
            }
        
            public void eat(){
                System.out.println("人:吃饭");
            }
        
            public void sleep(){
                System.out.println("人:睡觉");
            }
        
            public void walk(){
                System.out.println("人:走路");
            }
        }
        //**********************************************************
        package shangxuetang.day11;
        
        public class Student extends Person{
            String major;
            //学号
            int id = 1002;
        
            public Student() {
            }
        
            public Student(String major) {
                this.major = major;
            }
        
            public Student(String name, int age, String major) {
        //        this.name = name;
        //        this.age = age;
                super(name, age);
                this.major = major;
            }
        
            @Override
            public void eat() {
                System.out.println("学生:多吃有营养的食物");
            }
        
            public void study(){
                System.out.println("学生:学习知识");
                this.eat();
                super.eat();
                this.walk();
            }
        
            public void show(){
                System.out.println("name = " + this.name +","+super.age);
                System.out.println("id = " +id);
                System.out.println("id = " +super.id);
            }
        
        }
        //*********************************************
        package shangxuetang.day11;
        
        /**
         * super关键字的使用
         * 1:super理解为:父类的
         * 2:super可以用来调用:属性,方法,构造器
         * 3:super的使用
         *  3.1 我们可以在子类的方法或构造器中。通过“super.属性” 或“super.方法”,显示的是父类中声明的属性或方法
         *  3.2 特殊情况:当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须显示的使用“super.属性”的方式,
         *      表明调用的是父类中声明的属性。
         *  3.3 特殊情况:当子类重写了父类中的方法以后,们要想在子类中调用父类中声明的属性,则必须显示的使用“super.方法”的方式,
         *      表明调用的是父类中被重写的方法。
         * 4.super调用构造方法
         *  4.1 我们可以在子类的构造器中显示使用"super(形参列表)"的方式,调用父类中声明的指定的构造器
         *  4.2 "super(形参列表)"的使用,必须声明在子类构造器的首行
         *  4.3 我们在类的构造器中,针对与“this(形参列表)”或“super(形参列表)”只能二选一,不能同时出现
         *  4.4 在构造器的首行,没有显示的声明“this(形参列表)”或“super(形参列表)”,则默认调用的是父类中空餐的构造器
         *  4.5 在类的多个构造器中,至少有一个类的构造器中使用了“super(形参列表)”,调用父类中的伪构造器
         */
        public class SuperTest {
            public static void main(String[] args) {
                Student student = new Student();
                student.show();
                System.out.println();
                student.study();
                System.out.println("************************************");
                Student student1 = new Student("李四",24,"计算机科学与技术");
                student1.show();
                System.out.println("************************************");
        
                Student student2 = new Student();
        
            }
        }
        
        

        Java入门到超神(全网整理的复习资料)_第23张图片

         

         

        5.5:子类对象实例化过程

         Java入门到超神(全网整理的复习资料)_第24张图片

         

         Java入门到超神(全网整理的复习资料)_第25张图片

         

        package shangxuetang.exer01;
        
        /**
         * 1:写一个名为 Account 的类模拟账户。该类的属性和方法如下图所示。该类包括的属性:
         * 账号 id,余额 balance,年利率 annualInterestRate;包含的方法:访问器方法(getter 和
         * setter 方法),返回月利率的方法 getMonthlyInterest(),取款方法 withdraw(),存款方法
         * deposit()。
        
         */
        public class Account {
            /**
             * 账号
             */
            private int id;
            /**
             * 余额
             */
            private double balance;
            /**
             * 年利率
             */
            private double annualInterestRate;
        
            public Account(int id, double balance, double annualInterestRate) {
                this.id = id;
                this.balance = balance;
                this.annualInterestRate = annualInterestRate;
            }
        
            public int getId() {
                return id;
            }
        
            public void setId(int id) {
                this.id = id;
            }
        
            public double getBalance() {
                return balance;
            }
        
            public void setBalance(double balance) {
                this.balance = balance;
            }
        
            public double getAnnualInterestRate() {
                return annualInterestRate;
            }
        
            public void setAnnualInterestRate(double annualInterestRate) {
                this.annualInterestRate = annualInterestRate;
            }
        
            //返回月利率
            public double getMonthlyInterest(){
                return  annualInterestRate / 12;
            }
            //取钱
            public void withdraw (double amount){
                if(balance >= amount){
                    balance -= amount;
                    return;
                }
                System.out.println("余额不足");
            }
        
            //存钱
            public void deposit (double amount){
                if(amount > 0){
                    balance += amount;
                }
            }
        
        }
        //******************************************************************************************
        package shangxuetang.exer01;
        
        /**
         * 写一个用户程序测试 Account 类。在用户程序中,创建一个账号为 1122、余额为 20000、
         * 年利率 4.5%的 Account 对象。使用 withdraw 方法提款 30000 元,并打印余额。
         * 再使用 withdraw 方法提款 2500 元,使用 deposit 方法存款 3000 元,然后打印余额和月利
         * 率。
         * 提示:在提款方法 withdraw 中,需要判断用户余额是否能够满足提款数额的要求,如果不
         * 能,应给出提示。
         */
        
        public class AccountTest {
            public static void main(String[] args) {
                Account account = new Account(1122, 20000, 0.045);
                account.withdraw(30000);
                System.out.println("您的账户余额为:"+account.getBalance());
                account.withdraw(2500);
                System.out.println("您的账户余额为:"+account.getBalance());
                account.deposit(3000);
                System.out.println("您的账户余额为:"+account.getBalance());
                System.out.println("月利率为:"+(account.getMonthlyInterest()*100)+"%");
        
            }
        }
        //******************************************************************************************
        package shangxuetang.exer01;
        
        /**
         * 创建 Account 类的一个子类 CheckAccount 代表可透支的账户,该账户中定义一个属性
         * overdraft 代表可透支限额。在 CheckAccount 类中重写 withdraw 方法,其算法如下:
         * 如果(取款金额<账户余额),
         * 可直接取款
         * 如果(取款金额>账户余额),
         * 计算需要透支的额度
         * 判断可透支额 overdraft 是否足够支付本次透支需要,如果可以
         * 将账户余额修改为 0,冲减可透支金额
         * 如果不可以
         * 提示用户超过可透支额的限额
         */
        public class CheckAccunt extends Account{
            /**
             * 可透支限额
             */
            private double overdraft;
        
            public CheckAccunt(int id, double balance, double annualInterestRate,double overdraft) {
                super(id, balance, annualInterestRate);
                this.overdraft = overdraft;
            }
        
            /**
             * 重写父类的方法
             * @param amount
             */
            @Override
            public void withdraw(double amount){
                //余额足够消费
                if(getBalance() >= amount){
                    //方式一
                //    setBalance(getBalance() - amount);
                    //方式二
                    super.withdraw(amount);
        
                }else if(overdraft >= amount-getBalance()){
                    //这个模块就是透支额度进行消费
                    overdraft -= (amount - getBalance());
                 //   setBalance(0);
                    super.withdraw(getBalance());
                }else{
                    System.out.println("超过可透支限额");
                }
            }
        
            public double getOverdraft() {
                return overdraft;
            }
        
            public void setOverdraft(double overdraft) {
                this.overdraft = overdraft;
            }
        }
        //**************************************************************************************
        package shangxuetang.exer01;
        
        /**
         * 要求:写一个用户程序测试 CheckAccount 类。在用户程序中,
         * 创建一个账号为 1122、余额为 20000、年利率 4.5%,可透支限额为 5000 元的 CheckAccount 对象。
         * 使用 withdraw 方法提款 5000 元,并打印账户余额和可透支额。
         * 再使用 withdraw 方法提款 18000 元,并打印账户余额和可透支额。
         * 再使用 withdraw 方法提款 3000 元,并打印账户余额和可透支额。
         * 提示:
         * (1) 子类 CheckAccount 的构造方法需要将从父类继承的 3 个属性和子类自己的属性全
         * 部初始化。
         * (2) 父类Account的属性balance被设置为private,但在子类CheckAccount的withdraw
         * 方法中需要修改它的值,因此应修改父类的 balance 属性,定义其为 protected。
         */
        public class CheckAccuntTest {
            public static void main(String[] args) {
                CheckAccunt checkAccunt = new CheckAccunt(1122,20000,0.045,5000);
                /**
                 * 使用 withdraw 方法提款 5000 元,并打印账户余额和可透支额。
                 */
                checkAccunt.withdraw(5000);
                System.out.println("您的余额为:" + checkAccunt.getBalance());
                System.out.println("您的可透支额度为:" + checkAccunt.getOverdraft());
                /**
                 *再使用 withdraw 方法提款 18000 元,并打印账户余额和可透支额。
                 */
                checkAccunt.withdraw(18000);
                System.out.println("您的余额为:" + checkAccunt.getBalance());
                System.out.println("您的可透支额度为:" + checkAccunt.getOverdraft());
                /**
                 *再使用 withdraw 方法提款 3000 元,并打印账户余额和可透支额。
                 */
                checkAccunt.withdraw(3000);
                System.out.println("您的余额为:" + checkAccunt.getBalance());
                System.out.println("您的可透支额度为:" + checkAccunt.getOverdraft());
            }
        }
        

        5.6:面向对象特征三:多态性

        • 多态性,是面向对象中最重要的概念,在Java中的体现:

          对象的多态性:父类的引用指向子类的对象 。

          可以直接应用在抽象类和接口上

        • Java引用变量有两个类型:编译时类型和运行时类型。编译时类型由声明 该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。简 称:编译时,看左边;运行时,看右边。

          若编译时类型和运行时类型不一致,就出现了对象的多态性(Polymorphism)

          多态情况下, “看左边” :看的是父类的引用(父类中不具备子类特有的方法)

        “看右边” :看的是子类的对象(实际运行的是子类重写父类的方法)

        • 对象的多态 —在Java中,子类的对象可以替代父类的对象使用

          一个变量只能有一种确定的数据类型

          一个引用类型变量可能指向(引用)多种不同类型的对象

          Person p = new Student();

          Object o = new Person();//Object类型的变量o,指向Person类型的对象

          o = new Student(); //Object类型的变量o,指向Student类型的对象

          • 子类可看做是特殊的父类,所以父类类型的引用可以指向子类的对象:向 上转型(upcasting)。

        • 一个引用类型变量如果声明为父类的类型,但实际引用的是子类 对象,那么该变量就不能再访问子类中添加的属性和方法

          • Student m = new Student();

          • m.school = “pku”; //合法,Student类有school成员变量

          • Person e = new Student(); e.school = “pku”;

          • //非法,Person类没有school成员变量

          • 属性是在编译时确定的,编译时e为Person类型,没有school成员变量,因而编 译错误。

        • 方法声明的形参类型为父类类型,可以使用子类的对象作为实参调用该方法

        多态性应用举例
        public class Test {
            public void method(Person e) {
                // ……
                e.getInfo();
            }
            public static void main(Stirng args[]) {
                Test t = new Test();
                Student m = new Student();
                t.method(m); // 子类的对象m传送给父类类型的参数e
            }
        }

        5.6.1:虚拟方法调用(Virtual Method Invocation)

        • 正常的方法调用

          Person e = new Person();

          e.getInfo();

          Student e = new Student();

          e.getInfo();

        • 虚拟方法调用(多态情况下)

          • 子类中定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法称为虚拟方法,父类根据赋给它的不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期是无法 确定的。

            Person e = new Student();

            e.getInfo(); //调用Student类的getInfo()方法

          • 编译时类型和运行时类型 编译时e为Person类型,而方法的调用是在运行时确定的,所以调用的是Student类 的getInfo()方法。——动态绑定

        5.6.2:小结:方法的重载与重写

        1:二者定义的细节:略

        2:从编译和运行的角度看:

        重载,是指允许存在多个同名方法,而这些方法的参数不同。编译器根据方法不 同的参数表,对同名方法的名称做修饰。对于编译器而言,这些同名方法就成了 不同的方法。它们的调用地址在编译期就绑定了。Java的重载是可以包括父类 和子类的,即子类可以重载父类的同名不同参数的方法。 所以:对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法, 这称为“早绑定”或“静态绑定”;

        而对于多态,只有等到方法调用的那一刻,解释运行器才会确定所要调用的具体 方法,这称为“晚绑定”或“动态绑定”。 引用一句Bruce Eckel的话:“不要犯傻,如果它不是晚绑定,它就不是多态。”

        5.6.3:多态小结

        • 多态作用:

          • 提高了代码的通用性,常称作接口重用

        • 前提:

          • 需要存在继承或者实现关系

          • 有方法的重写

        • 成员方法:

          • 编译时:要查看引用变量所声明的类中是否有所调用的方法。

          • 运行时:调用实际new的对象所属的类中的重写方法。

        • 成员变量:

          • 不具备多态性,只看引用变量所声明的类。

        5.6.4:面试题

        1:什么是多态性?什么是虚拟方法?

        对象的多态性:父类的引用指向子类的对象。

        Person p = new Man();

        p.eat();

        调用方法时候,编译时看左边,运行时看右边。

        2.一个类可以有几个直接父类?一个父类可以有多少个子类?子类能获取直接父类的父类中的结构吗?子类能否获取父类中private权限的属性和方法?

        答:只有一个父类。多个子类。可以获取。可以的获取父类中的private属性和方法,因为提供了get和set方法。

        3.方法的重写(override/overwite)的具体规则有哪些?

        方法名/形参列表相同,

        权限修饰符不小于父类的权限修饰符,

        返回值类型不能大于父类的返回值。

        子类的异常抛出不能小于父类的异常。

        开发中经常重写:通过父类粘贴,或者快捷键提示。

        4.super的调用构造器,有哪些具体的注意点。

        this(形参列表):本类重载的其它的构造器

        supper(形参列表)调用父类中指定的构造器

        在构造器的首行必须只能二选一,默认supper空参

        5.6.5:子类对象实例化过程

         

         Java入门到超神(全网整理的复习资料)_第26张图片

        面试题:
        1.多态性的理解
        	一个事务的多种理解
        2.何为多态性?
        	对象的多态性:父类的引用指向子类的对象(或子类的对象覆盖父类的引用)
        	举例:
        		Person p = new Man();
        		Object obj = new Date();
        3:多态性的使用:虚拟方法调用
        	有了对多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期执行的是子类重写父类的方法。
        	编译看左边,运行:看右边
        4:多态性使用的前提:1:类的继承关系(如果没有抽象类,接口,多态性就塌了一半),2:方法的重写

        instanceof操作符

        x instanceof A :检查x是否为A类的对象,返回值为boolean型

        • 要求x所属的类与类A必须是子类和父类的关系,否则编译错误。

        • 如果x属于类A的子类B,x instanceof A值也为true。

        /**
        * 举例
        */
        public class Person extends Object {…}
        public class Student extends Person {…}
        public class Graduate extends Person {…}
        -------------------------------------------------------------------
        public void method1(Person e) {
            if (e instanceof Person) 
            // 处理Person类及其子类对象
            if (e instanceof Student) 
            //处理Student类及其子类对象
            if (e instanceof Graduate)
            //处理Graduate类及其子类对象
        }

         

        //案例
        package shangxuetang.day13.java;
        
        public class Person {
            String name;
            int age;
            int id = 1001;
        
            public  void eat(){
                System.out.println("人:吃饭");
            }
        
            public  void  walk(){
                System.out.println("人:走路");
            }
        
        }
        //*******************************************************************
        package shangxuetang.day13.java;
        
        public class Man extends Person{
            boolean isSomking;
        
            int id  = 1002;
        
            public void earnMoney(){
                System.out.println("男人负责挣钱养家");
            }
        
            @Override
            public void eat(){
                System.out.println("男人多吃肉,长肌肉");
            }
        
            @Override
            public void walk(){
                System.out.println("男人霸气的走路");
            }
        }
        //*******************************************************************
        package shangxuetang.day13.java;
        
        public class Woman extends Person{
            boolean isBeauty;
        
            public  void goShopping(){
                System.out.println("女人喜欢购物");
            }
        
            @Override
            public void eat(){
                System.out.println("女人少吃,为了减肥");
            }
        
            @Override
            public void walk() {
                System.out.println("女人窈窕走路");
            }
        }
        //*******************************************************************
        package shangxuetang.day13.java;
        
        import java.util.Date;
        
        /**
         * 面向对象特征之三:多态性
         * 1:理解多态性:可以理解为一个事务有多个形态
         * 2:何为多态:
         *  对象的多态性:父类的引用指向子类的对象(子类的对象赋给了父类的引用)
         * 3:多态的使用:虚拟方法的使用
         *  有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际调用的是子类重写父类的方法
         *  总结,编译看左边,运行看右边。
         *4:多态性使用的前提:类的继承关系,方法的重写
         *
         *5:对象的多态性,只适用于方法,不适应用于属性(编译和运行都看左边)
         *
         */
        public class PersonTest {
            public static void main(String[] args) {
                Person person1 = new Person();
                person1.eat();
        
                Man man = new Man();
                man.eat();
                man.age = 25;
                man.earnMoney();
        
                System.out.println("*******************************************");
        
                //对象的多态性:父类的引用指向子类的对象
                Person person2 = new Man();
                //多态的使用:当调用子父类同名参数的方法时,实际执行的是子类重写父类的方法---------虚拟方法调用
                person2.eat();
                person2.walk();
        
                System.out.println(person2.id);
                System.out.println("*******************************************");
        
                //不能调用子类所特有的方法,属性:编译时,persopn2是Persopn类型
                person2.name = "Tom";
        //        person2.earnMoney();
        //        person2.isSmonking();
                //有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的,但是由于变量声明的是父类的类型,导致
                //编译时,只能调用父类中你声明的属性和方法。子类特有的属性和方法不能调用。
        
                //如何才能调用子类特有的属性和方法?
                //向下转型:使用强制类型转换符。
                Man man1 = (Man)person2;
                man1.earnMoney();
                man1.isSomking = true;
        
                //使用强制转换时,可能出现ClassCastException
                //Woman woman = (Woman)porson2
                //w1.goShopping();
        
                /**
                 * instanceof 关键字的使用
                 * a instanceof A:判断对象a是否是类A的实例。如果是,返回true;如果不是返回false
                 * 使用情景:为了避免在向下转型时出现ClassCastException的异常,我们在向下转型之前
                 * 使用instanceof的判断,一旦返回true,就进行向下转型。如果返回false则不能进行向下转型
                 *
                 * 如果a instanceof A 返回true,则a instanceof B也返回true
                 * 其中,类B是类A的父类
                 */
        
                if(person2 instanceof Woman){
                    Woman woman1 = (Woman)person2;
                    woman1.goShopping();
                    System.out.println("*********************Woman******************");
                }
        
                if(person2 instanceof Man){
                    Man man2 = (Man)person2;
                    man2.earnMoney();
                    System.out.println("*********************Man******************");
                }
                if(person2 instanceof Person){
                    System.out.println("*********************Person******************");
                }
                if(person2 instanceof Object){
                    System.out.println("*********************Object******************");
                }
        
                //向下转型的几个常见问题,练习
                //问题一:编译时通过,运行时不通过
                //举例一
        //        Person person3 = new Woman();
        //        Man man3 = (Man)person3;
                //举例二
        //        Person person4 = new Person();
        //        Man man4 = (Man)person4;
        
                //问题二:编译通过,运行时也通过
        //        Object obj = new Woman();
        //        Person p = (Person)obj;
                //问题三:编译不通过
        //        Man man5 = new Woman();
        
        //        String str = new Dete();
        //
        //        Object o = new Date();
        //        String str1 = (String)o;
        
        
            }
        
        }
        

        对象类型转换 (Casting )

        • 基本数据类型的Casting:

          • 自动类型转换:小的数据类型可以自动转换成大的数据类型

          • 如long g=20; double d=12.0f

          • 强制类型转换:可以把大的数据类型强制转换(casting)成小的数据类型

          • 如 float f=(float)12.0; int a=(int)1200L

        • 对Java对象的强制类型转换称为造型

          • 从子类到父类的类型转换可以自动进行

          • 从父类到子类的类型转换必须通过造型(强制类型转换)实现

          • 无继承关系的引用类型间的转换是非法的

          • 在造型前可以使用instanceof操作符测试一个对象的类型

        //多态的基本练习
        package shangxuetang.day13.exer;
        
        /**
         * 子类继承父类
         * 若子类重写了父类方法,就意味着子类里定义的方法彻底覆盖了父类里的
         * 同名方法,系统将不可能把父类里的方法转移到子类中。
         * 对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的
         * 实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量
         */
        class Base {
            int count = 10;
        
            public void display() {
                System.out.println(this.count);
            }
        }
        
        class Sub extends Base {
            int count = 20;
            @Override
            public void display() {
                System.out.println(this.count);
            }
        }
        
        public class FieldMethodTest {
            public static void main(String[] args) {
                Sub s = new Sub();
                System.out.println(s.count);//20
                s.display();//20
                //s 赋值给 b  赋值的就是地址值
                Base b = s;
                //== :对于引用数据类型来讲,比较的是两个引用数据类型变量的值是否相等
                System.out.println(b == s);//true
                System.out.println(b.count);//10
                b.display();//20
        
            }
        }
        

        //多态练习 -- 多态的基本操作
        package shangxuetang.day13.exer;
        
        /**
         * 建立InstanceTest 类,在类中定义方法
         * method(Person e);
         * 在method中:
         * (1)根据e的类型调用相应类的getInfo()方法。
         * (2)根据e的类型执行:
         * 如果e为Person类的对象,输出:
         * “a person”;
         * 如果e为Student类的对象,输出:
         * “a student”
         * “a person ”
         * 如果e为Graduate类的对象,输出:
         * “a graduated student”
         * “a student”
         * “a person”
         */
        public class InstanceTest {
        
            public static void main(String[] args) {
                InstanceTest instanceTest = new InstanceTest();
                instanceTest.method(new Student());
            }
        
            public void method(Person e) {
                //虚拟方法调用
                String info = e.getInfo();
                System.out.println(info);
                //方式1
        //        if(e instanceof Graduate){
        //            System.out.println("a graduated student");
        //            System.out.println("a student");
        //            System.out.println("a person");
        //        }else if(e instanceof Student){
        //            System.out.println("a student");
        //            System.out.println("a person");
        //        }else {
        //            System.out.println("a person");
        //        }
        //    }
                if (e instanceof Graduate) {
                    System.out.println("a graduated student");
                }
                if (e instanceof Student) {
                    System.out.println("a student");
                }
        
                if (e instanceof Person) {
                    System.out.println("a person");
                }
            }
        }
        
        class Person {
            protected String name="person";
            protected int age=50;
            public String getInfo() {
                return "Name: "+ name + "\n" +"age: "+ age;
            }
        }
        
        class Student extends Person {
            protected String school="pku";
            @Override
            public String getInfo() {
                return "Name: "+ name + "\nage: "+ age
                        + "\nschool: "+ school;
            }
        }
        class Graduate extends Student{
            public String major="IT";
            @Override
            public String getInfo()
            {
                return "Name: "+ name + "\nage: "+ age
                        + "\nschool: "+ school+"\nmajor:"+major;
            }
        }

        5.8:Object类的使用

        • Object类是所有Java类的根父类

        • 如果在类的声明中未使用extends关键字指明其父类,则默认父类 为java.lang.Object类

        public class Person {

        ...

        }

        等价于:

        public class Person extends Object {

        ...

        }

        • 例:method(Object obj){…}//可以接收任何类作为其参数

        Person o=new Person();

        method(o);

        package shangxuetang.day13.java1;
        
        /**
         * java.lang.Object
         * 1.Object类是所有Java类的根父类
         * 2. 如果在类的声明中未使用extends关键字指明其父类,则默认父类为java.lang.Object类
         * 3.Object类中的功能(属性,方法)就具有通用性
         *  属性:无
         *  方法:equals()/ toString()/getClass()/hashCode()/clone()/finalize()
         *       wait()/notify()/notifyAll()
         *
         * 4.Objetc类只声明了一个空参的构造器
         *
         *  面试题
         *  final,finally,finalize的区别?
         *
         */
        public class ObjectTest {
            public static void main(String[] args) {
                Order order = new Order();
                //获取order的这个类,后面是获取order这个父类
                System.out.println(order.getClass().getSuperclass());
            }
        }
        
        class Order{
        
        }

        5.8.1:==操作符与equals方法

        • = =:

          • 基本类型比较值:只要两个变量的值相等,即为true。

            • int a=5; if(a==6){…}

          • 引用类型比较引用(是否指向同一个对象):只有指向同一个对象时,==才 返回true。

            • Person p1=new Person();

            • Person p2=new Person();

            • if (p1==p2){…}

            • 用“==”进行比较时,符号两边的数据类型必须兼容(可自动转换的基本 数据类型除外),否则编译出错

        • equals():所有类都继承了Object,也就获得了equals()方法。还可以重写。

          • 只能比较引用类型,其作用与“==”相同,比较是否指向同一个对象。

          • 格式:obj1.equals(obj2)

        • 特例:当用equals()方法进行比较时,对类File、String、Date及包装类 (Wrapper Class)来说,是比较类型及内容而不考虑引用的是否是同一个对 象;

          • 原因:在这些类中重写了Object类的equals()方法。

        • 当自定义使用equals()时,可以重写。用于比较两个对象的“内容”是否都 相等

        • 重写equals()方法的原则

          • 对称性:如果x.equals(y)返回是“true” ,那么y.equals(x)也应该返回是 “true”。

          • 自反性:x.equals(x)必须返回是“true”。

          • 传递性:如果x.equals(y)返回是“true” ,而且y.equals(z)返回是“true” , 那么z.equals(x)也应该返回是“true”。

          • 一致性:如果x.equals(y)返回是“true” ,只要x和y内容一直不变,不管你 重复x.equals(y)多少次,返回都是“true”。

          • 任何情况下,x.equals(null),永远返回是“false” ; x.equals(和x不同类型的对象)永远返回是“false”。

        //案例讲解
        //重点==  和 Equals 的区别
        //本人理解的为  String  Date File 等类是Object 重写了equals方法,所以他们比较的是属性是否相同
        //如果由作者定义的某类 去做一个equals 去比较,而是比较的是两个对象的地址值是否相同
        
        import java.util.Date;
        
        /**
         * 面试题:== 和 qualse() 区别
         * 一.回顾== 的使用
         * == : 运算符
         * 1.可以使用在基本数据类型变量和引用数据类型变量中
         * 2.如果比较的是基本数据类型变量:比较两个变量保存的数据是否相等(不一定类型要相同)
         *   如果比较的是引用数据类型:比较的是两个对象的地址值是否相同,即两个引用是否指向同一个对象实体
         *
         * equals
         * 二.equals()方法的使用;
         *  1.是一个方法,而非运算符
         *  2.只能适用于引用类型
         *  3.Objetc类中equals()的定义:
         *      public boolean equals(Object obj) {
         *         return (this == obj);
         *     }
         *     说明:Object类中定义的equals()和==的作用是相同的,比较两个对象的地址值是否相同,即两个引用是否向同一个对象实体
         *
         * 4.像String,Date,File包装类等都重写了Obejct类中的equals()方法。
         *      重写以后,比较的不是两个引用的地址是否相同,而是比较两个对象的“实体内容”是否相同
         */
        
        public class EqualsTest {
            public static void main(String[] args) {
                //基本数据类型
                int i= 10;
                int j = 10;
                double d = 10.0;
                //true
                System.out.println(i==j);
                //false
                System.out.println(i==d);
        
                boolean b = true;
        //        System.out.println(i == b);
                char c = 65;
                //true
                System.out.println( i == c);
        
                char c1 = 'A';
                char c2 = 65;
                System.out.println(c1 == c2);
        
                //引用类型
                Customer customer1 = new Customer("Tom",21);
                Customer customer2 = new Customer("Tom",21);
                //false
                System.out.println(customer1 == customer2);
        
                String string1 = new String("atguigu");
                String string2 = new String("atguigu");
                //false
                System.out.println(string1 == string2);
                System.out.println("***********************************");
                System.out.println(customer1.equals(customer2));
                //true
                System.out.println(string1.equals(string2));
        
                Date date1 = new Date(32432525324L);
                Date date2 = new Date(32432525324L);
                //false
                System.out.println(date1 == date2);
        
                //true
                System.out.println(date1.equals(date2));
        
            }
        }
        

        //探究重写equals()方法

        package shangxuetang.day13.java1;
        
        import java.util.Date;
        
        /**
         * 面试题:== 和 qualse() 区别
         * 一.回顾== 的使用
         * == : 运算符
         * 1.可以使用在基本数据类型变量和引用数据类型变量中
         * 2.如果比较的是基本数据类型变量:比较两个变量保存的数据是否相等(不一定类型要相同)
         *   如果比较的是引用数据类型:比较的是两个对象的地址值是否相同,即两个引用是否指向同一个对象实体
         *
         * equals
         * 二.equals()方法的使用;
         *  1.是一个方法,而非运算符
         *  2.只能适用于引用类型
         *  3.Objetc类中equals()的定义:
         *      public boolean equals(Object obj) {
         *         return (this == obj);
         *     }
         *     说明:Object类中定义的equals()和==的作用是相同的,比较两个对象的地址值是否相同,即两个引用是否向同一个对象实体
         *
         * 4.像String,Date,File包装类等都重写了Obejct类中的equals()方法。
         *      重写以后,比较的不是两个引用的地址是否相同,而是比较两个对象的“实体内容”是否相同
         * 5.通常情况下,我们自定义的类如果使用equals()的话,也通常是比较两个对象的"实体内容"是否相同,
         *      那么我们就需要对Object类中的quals()进行重写
         *     //重写原则:比较两个对象的实体内容是否相同(即:name 和 age)是否相同
         */
        
        public class EqualsTest {
            public static void main(String[] args) {
                //基本数据类型
                int i= 10;
                int j = 10;
                double d = 10.0;
                //true
                System.out.println(i==j);
                //false
                System.out.println(i==d);
        
                boolean b = true;
        //        System.out.println(i == b);
                char c = 65;
                //true
                System.out.println( i == c);
        
                char c1 = 'A';
                char c2 = 65;
                System.out.println(c1 == c2);
        
                //引用类型
                Customer customer1 = new Customer("Tom",21);
                Customer customer2 = new Customer("Tom",21);
                //false
                System.out.println(customer1 == customer2);
        
                String string1 = new String("atguigu");
                String string2 = new String("atguigu");
                //false
                System.out.println(string1 == string2);
                System.out.println("***********************************");
                System.out.println(customer1.equals(customer2));
                //true
                System.out.println(string1.equals(string2));
        
                Date date1 = new Date(32432525324L);
                Date date2 = new Date(32432525324L);
                //false
                System.out.println(date1 == date2);
        
                //true
                System.out.println(date1.equals(date2));
        
            }
        }
        //比较自定义的类
        package shangxuetang.day13.java1;
        
        import java.util.Objects;
        
        public class Customer {
            private  String name;
            private int age;
        
            public Customer() {
            }
        
            public Customer(String name, int age) {
                super();
                this.name = name;
                this.age = age;
            }
        
            public String getName() {
                return name;
            }
        
            public void setName(String name) {
                this.name = name;
            }
        
            public int getAge() {
                return age;
            }
        
            public void setAge(int age) {
                this.age = age;
            }
        
            //重写:比较两个对象的实体内容是否相同(即:name 和 age)是否相同
            //手动实现equals 重写
        //    @Override
        //    public boolean equals(Object obj) {
        //        System.out.println("Customer equals()...");
        //        if(this == obj){
        //            return true;
        //        }
        //        if (obj instanceof Customer){
        //            Customer customer = (Customer)obj;
        //            //比较两个对象的每个属性是否都相同
                    if (this.age == customer.age && this.name.equals(customer.name)){
                        return true;
                    }else {
                        return  false;
                    }
        //           // 或
        //            return this.age == customer.age && this.name.equals(customer.name);
        //        }
        //
        //        return false;
        //    }
        
            /**
             * 自动生成的equals
             * @param o
             * @return
             */
            @Override
            public boolean equals(Object o) {
                if (this == o) {
                    return true;
                }
                if (o == null || getClass() != o.getClass()) {
                    return false;
                }
                Customer customer = (Customer) o;
                return age == customer.age &&
                        Objects.equals(name, customer.name);
            }
        
            @Override
            public int hashCode() {
                return Objects.hash(name, age);
            }
        }
        

        5.8.2面试题

        == 和 equals 的区别
        1.==即可以比较基本类型也可以比较引用类型。对于基本类型就是比较值,对于引用类型来说就是比较内存的地址值是否相同。
        2.equals的话,它是属于java.lang.Objetc类里面的方法,如果该方法没有被重写过默认也是==,我们可以看到String等类的equals方法是被重写过的,而且String类在日常开发中用的比较多,形成了equals是比较值的错误观点。
        3.具体要看自定义类里面有没有重写Object的equals方法来判断
        4.通常情况下,重写equals方法,会比较累中的相应属性是否都相等。

        //练习7
        int it = 65;
        float fl = 65.0f;
        System.out.println(“65和65.0f是否相等?” + (it == fl)); //true
        char ch1 = 'A'; char ch2 = 12;
        System.out.println("65和'A'是否相等?" + (it == ch1));//true
        System.out.println(“12和ch2是否相等?" + (12 == ch2));//true
        String str1 = new String("hello");
        String str2 = new String("hello");
        System.out.println("str1和str2是否相等?"+ (str1 == str2));//false
        System.out.println("str1是否equals str2?"+(str1.equals(str2)));//true
        System.out.println(“hello” == new java.util.Date()); //编译不通过
        练 习8
        1.编写Order类,有int型的orderId,String型的orderName,相应的
        getter()和setter()方法,两个参数的构造器,重写父类的equals()方法:
        public boolean equals(Object obj),并判断测试类中创建的两个对象是否
        相等。
        2.请根据以下代码自行定义能满足需要的MyDate类,在MyDate类中覆盖
        equals方法,使其判断当两个MyDate类型对象的年月日都相同时,结果
        为true,否则为false。 public boolean equals(Object o)
        //练习8.1
        
        import java.util.Objects;
        
        public class Order {
            private  int orderId;
            private String orderName;
        
            public Order() {
            }
        
            public Order(int orderId, String orderName) {
                this.orderId = orderId;
                this.orderName = orderName;
            }
        
            public int getOrderId() {
                return orderId;
            }
        
            public void setOrderId(int orderId) {
                this.orderId = orderId;
            }
        
            public String getOrderName() {
                return orderName;
            }
        
            public void setOrderName(String orderName) {
                this.orderName = orderName;
            }
        
            @Override
            public boolean equals(Object o) {
                if (this == o) {
                    return true;
                }
                if (o == null || getClass() != o.getClass()) {
                    return false;
                }
                Order order = (Order) o;
                return orderId == order.orderId && Objects.equals(orderName, order.orderName);
            }
        
            @Override
            public int hashCode() {
                return Objects.hash(orderId, orderName);
            }
        }
        
        public class OrederTest  {
            public static void main(String[] args) {
                Order order1 = new Order(1001,"tom");
                Order order2 = new Order(1001,"cat");
                System.out.println(order1.equals(order2));
                System.out.println(order1 == order2);
        
                Order order3 = new Order(1001,"cat");
                System.out.println(order3.equals(order2));
            }
        }
        //练习8.2
        public class MyDateTest {
            public static void main(String[] args) {
                MyDate myDate1 = new MyDate(14,3,2019);
                MyDate myDate2 = new MyDate(14,3,2019);
                if (myDate1 == myDate2){
                    System.out.println("myDate1 == myDate2");
                }else{
                    System.out.println("myDate1 != myDate2");
                }
                if (myDate1.equals(myDate2)){
                    System.out.println("myDate1 is equals to myDate2");
                }else{
                    System.out.println("myDate1 is not equal to myDate2");
                }
            }
        }
        class MyDate{
            private int day;
            private int month;
            private int year;
        
            public MyDate() {
            }
        
            public MyDate(int day, int month, int year) {
                this.day = day;
                this.month = month;
                this.year = year;
            }
        
            public int getDay() {
                return day;
            }
        
            public void setDay(int day) {
                this.day = day;
            }
        
            public int getMonth() {
                return month;
            }
        
            public void setMonth(int month) {
                this.month = month;
            }
        
            public int getYear() {
                return year;
            }
        
            public void setYear(int year) {
                this.year = year;
            }
        
            @Override
            public boolean equals(Object o) {
                if (this == o) {
                    return true;
                }
                if (o == null || getClass() != o.getClass()) {
                    return false;
                }
                MyDate myDate = (MyDate) o;
                return day == myDate.day &&
                        month == myDate.month &&
                        year == myDate.year;
            }
        
        }
        

        5.8.3:toString()使用

        • toString()方法在Object类中定义,其返回值是String类型,返回类名和它 的引用地址。

        • 在进行String与其它类型数据的连接操作时,自动调用toString()方法

          Date now=new Date();

          System.out.println(“now=”+now); 相当于

          System.out.println(“now=”+now.toString());

        • 可以根据需要在用户自定义类型中重写toString()方法

          如String 类重写了toString()方法,返回字符串的值。

          s1=“hello”;

          System.out.println(s1);//相当于System.out.println(s1.toString());

        • 基本类型数据转换为String类型时,调用了对应包装类的toString()方法

        • int a=10; System.out.println(“a=”+a);

        package shangxuetang.day13.java1;
        
        import java.util.Date;
        
        /**
         * Object类中的toString()的使用:
         * 1.当我们输出一个对象的引用时,实际上就是调用当前对象的toSring()方法
         * 2.Obejcet类中toString()定义:
         *      public String toString() {
         *         return getClass().getName() + "@" + Integer.toHexString(hashCode());
         *     }
         * 3.像String,Date,File等包装类都重写了Object当中的toString()方法,重写过后就输出的是对象的实体
         *      使得在调用对象toString()时,返回实体对象信息
         * 4.自定义类也乐意重写toString()方法,当调用此方法时候,返回对象的实体内容。
         */
        public class ToStringTest {
            public static void main(String[] args) {
                Customer customer1 = new Customer();
                //输出的是地址值
                //shangxuetang.day13.java1.Customer@3c1
                //包名+类名,类的具体位置@地址值(已经转换为16进制了)
                System.out.println(customer1.toString());
                //直接输出 也调用了toString方法
                System.out.println(customer1);
        
                String str = new String("MM");
                //MM
                System.out.println(str);
        
                Date date = new Date(4534534534543L);
                System.out.println(date.toString());
        
                //在Customer类中重写toString方法之后就可以输出实体对象信息
                System.out.println(customer1);
            }
        }
        

        //练习9
        
        public class GeometricObject {
            protected String color;
            protected double weight;
            public GeometricObject() {
                super();
                this.color = "white";
                this.weight = 1.0;
            }
            public GeometricObject(String color, double weight) {
                super();
                this.color = color;
                this.weight = weight;
            }
            public String getColor() {
                return color;
            }
            public void setColor(String color) {
                this.color = color;
            }
            public double getWeight() {
                return weight;
            }
            public void setWeight(double weight) {
                this.weight = weight;
            }
        }
        
        public class Circle extends GeometricObject {
            private double radius;
        
            public Circle() {
                super();
                radius = 1.0;
        //		color = "white";
        //		weight = 1.0;
            }
        
            public Circle(double radius) {
                super();
                this.radius = radius;
            }
            public Circle(double radius,String color,double weight) {
                super(color,weight);
                this.radius = radius;
            }
        
            public double getRadius() {
                return radius;
            }
        
            public void setRadius(double radius) {
                this.radius = radius;
            }
            //求圆的面积
            public double findArea(){
                return 3.14 * radius * radius;
            }
            //比较两个圆的半径是否相等,如相等,返回true。
            @Override
            public boolean equals(Object obj) {
        
                if(this == obj){
                    return true;
                }
        
                if(obj instanceof Circle){
                    Circle c = (Circle)obj;
                    return this.radius == c.radius;
                }
        
                return false;
        
            }
        
            @Override
            public String toString() {
                return "Circle [radius=" + radius + "]";
            }
        
        }
        /**
         * 写一个测试类,创建两个Circle对象,判断其颜色是否相等;利用equals方法判断其半径是否相等;利用
         * toString()方法输出其半径。
         */
        public class CircleTest {
            public static void main(String[] args) {
                Circle circle1 = new Circle(2.3);
                Circle circle2 = new Circle(3.3, new String("white"), 2.0);
        
                System.out.println("颜色是否相等:" + circle1.getColor().equals(circle2.getColor()));
        
                System.out.println("半径是否相等:" + circle1.equals(circle2));
        
                System.out.println(circle1);
                System.out.println(circle2.toString());
        }

        5.8.4:JUnit单元测试

        package shangxuetang.day13.java2;
        
        import org.junit.Test;
        
        import java.util.Date;
        
        /**
         * Java中的JUnit单元测试
         * 步骤:
         *  1:选中当前工程  -  右键选择:bulid path - add libraries - JUnit 4 - 下一步
         *  2:创建Java类,进行单元测试
         *      此时的java要求:1.此类事public的 2此类提供公共的无参的构造器
         *  3.此类中声明单元测试方法
         *      此时的单元测试方法:方法权限是public,没有返回值,没有形参
         *  4.此单元测试方法上需要声明注释:@Test,并在单元测试类中导入:import org.junit.Test
         *  5.声明好单元测试方法以后,就可以在方法体内测试相关代码
         *  6.写完代码以后,左键双击单元测试方法名,右键 run - as JUnit Test
         *
         *  说明:
         *  1.如果执行结果没有任何异常,绿条
         *  2.如果执行结果出现异常,红条
         */
        public class JUnitTest {
            int number = 10;
        
        
            @Test
            public void testEquals(){
                String s1 = "MM";
                String s2 = "MM";
                System.out.println(s1.equals(s2));
                //ClassCastException的异常
        //        Object obj = new String();
        //        Date date = (Date)obj;
                System.out.println(number);
                show();
            }
        
            public  void  show(){
                number = 20;
                System.out.println("show().....");
            }
        
            @Test
            public void testToString(){
                String s2 = "MM";
                System.out.println(s2.toString());
            }
        }
        

        5.9:包装类的使用

        1:Vactor类中关于添加元素,只定义了形参为Object方法

        • 针对八种基本数据类型定义相应的引用类型—包装类(封装类)

        • 有了类的特点,就可以调用类中的方法,Java才是真正的面向对象

        Java入门到超神(全网整理的复习资料)_第27张图片

         

        • 基本数据类型包装成包装类的实例 ---装箱

          • 通过包装类的构造器实现:

            • int i = 500; Integer t = new Integer(i);

        • 还可以通过字符串参数构造包装类对象:

          • Float f = new Float(“4.56”);

          • Long l = new Long(“asdf”); //NumberFormatException

        • 获得包装类对象中包装的基本类型变量 ---拆箱

          • 调用包装类的.xxxValue()方法:

            • boolean b = bObj.booleanValue();

        • JDK1.5之后,支持自动装箱,自动拆箱。但类型必须匹配。

        • 字符串转换成基本数据类型

          • 通过包装类的构造器实现:

            • int i = new Integer(“12”);

        • 通过包装类的parseXxx(String s)静态方法:

          • Float f = Float.parseFloat(“12.1”);

        • 基本数据类型转换成字符串

          • 调用字符串重载的valueOf()方法:

            • String fstr = String.valueOf(2.34f);

          • 更直接的方式:

            • String intStr = 5 + “”

        5.9.1:总结:基本类型、包装类与String类间的转换

         

        5.9.2:包装类(Wrapper)的使用

        int i = 500;

        Integer t = new Integer(i);

        装箱:包装类使得一个基本数据类型的数据变成了类。

        有了类的特点,可以调用类中的方法。

        String s = t.toString(); // s = “500“,t是类,有toString方法

        String s1 = Integer.toString(314); // s1= “314“ 将数字转换成字符串。

        String s2=“4.56”;

        double ds=Double.parseDouble(s2); //将字符串转换成数字

        用法举例

        • 拆箱:将数字包装类中内容变为基本数据类型。

          • int j = t.intValue(); // j = 500,intValue取出包装类中的数据

        • 包装类在实际开发中用的最多的在于字符串变为基本数据类型。

          • String str1 = "30" ;

          • String str2 = "30.3" ;

          • int x = Integer.parseInt(str1) ; // 将字符串变为int型

          • float f = Float.parseFloat(str2) ; // 将字符串变为int型

        //包装类实体操作代码,自动拆箱,自动装箱
        package shangxuetang.day13.java2;
        
        import org.junit.Test;
        
        /**
         * 包装类的使用
         * 1.java提供了8中基本数据类型对应包装类,使得基本数据类型的变量具有类的特征。
         * 2.重点需要掌握的:基本数据类型,包装类,String三者之间的相互转换。
         *
         */
        public class WrapperTest {
        
            /**
             * Stirng类型---->基本数据类型,包装类: 调用包装类的paresXxx()
             */
            @Test
            public void test5(){
                String str1 = "123";
                //错误的情况:不能强转
        //        int num1 = (int)str1;
        //        Integer in1 = (Integer)num1;
                //可能会报错:NumberFormatException
                int num2 = Integer.parseInt(str1);
                System.out.println("int:"+num2);
                float v = Float.parseFloat(str1);
                System.out.println("float:"+v);
                //布尔类型只要你不是true,就都会报false;
                String string = "true1";
                boolean b = Boolean.parseBoolean(string);
                System.out.println("boolean:"+b);
            }
        
            /**
             * 基本数据类型,包装类---->String类型
             *  1:连接运算
             *  2:调用String重载的valueOf(XXX xxx)
             */
            @Test
            public void test4(){
                int num1 = 10;
                //方式1:连接运算
                String str1 = num1+"";
                //方式2:调用String重载的valueOf(XXX xxx)
                float f1 = 12.3f;
                String str2 = String.valueOf(f1);
        
                Double d1 = new Double(12.4);
                String str3 = String.valueOf(d1);
                System.out.println(str1);
                System.out.println(str2);
                System.out.println(str3);
            }
        
        
        
            @Test
            public void test3(){
                int num1 = 10;
                //基本数据类型--->包装类
                method(num1);
                //自动装箱:基本数据类型--->包装类
                int num2 = 10;
                Integer integer1 = num2;
        
                boolean b1 = true;
                Boolean b2 = b1;
                System.out.println(b2);
        
                //自动拆箱包:装类--->基本数据类型
                System.out.println(integer1.toString());
                //自动拆箱
                int num3 = integer1;
        
            }
        
            public void method(Object obj){
                System.out.println(obj);
            }
        
            /**包装类--->基本数据类型*/
            @Test
            public void test2(){
                Integer integer = new Integer(12);
                int intValue = integer.intValue();
                System.out.println(intValue+5);
        
                Float aFloat = new Float(15);
                float floatValue = aFloat.floatValue();
                System.out.println(floatValue+8);
        
            }
        
        
            /**
             * 基本数据类型--->包装类:调用包装类的构造器
             */
            @Test
            public void test1(){
                int num1 = 10;
        //        System.out.println(num1.toString);
                Integer integer1 = new Integer(num1);
                System.out.println(integer1.toString());
        
                Integer integer2 = new Integer("123");
                System.out.println(integer2.toString());
        
                //数字格式异常:java.lang.NumberFormatException
        //        Integer integer3 = new Integer("123abc");
        //        System.out.println(integer3.toString());
                Float f1 = new Float(12.3f);
                Float f2 = new Float("123.3");
                System.out.println(f1);
                System.out.println(f2);
        
                Boolean b1 = new Boolean(true);
                Boolean b2 = new Boolean("123");
                System.out.println("b2");
                //false
                Boolean b3 = new Boolean("123abc");
                System.out.println(b3);
            }
        }
        
        class Order{
          boolean isMale;
        }
        

        5.9.3:面试题

         

        5.9.4:练习题10

        package shangxuetang.day13.exer4;
        
        import java.util.Scanner;
        import java.util.Vector;
        
        /**
         * 利用Vector代替数组处理:从键盘读入学生成绩(以负数代表输入结束),找出
         * 最高分,并输出学生成绩等级。
         * 提示:数组一旦创建,长度就固定不变,所以在创建数组前就需要知道它的
         * 长度。而向量类java.util.Vector可以根据需要动态伸缩。
         * 创建Vector对象:Vector v=new Vector();
         * 给向量添加元素:v.addElement(Object obj); //obj必须是对象
         * 取出向量中的元素:Object obj=v.elementAt(0);
         * 注意第一个元素的下标是0,返回值是Object类型的。
         * 计算向量的长度:v.size();
         * 若与最高分相差10分内:A等;20分内:B等;
         * 30分内:C等;其它:D等
         */
        public class ScoreTest {
            public static void main(String[] args) {
                //1.实例化Scanner,用于从键盘获取学生成绩
                Scanner scanner = new Scanner(System.in);
        
                //2.创建vector:Vector v = new Vector();相当于原来的数组
                Vector vector = new Vector();
        
                //3.通过for(;;)或while(true)方式,geiCector中添加数组:
                int maxScore = 0;
                for(;;){
                    System.out.println("请输入学生成绩(以负数代表输入结束)");
                    int score = scanner.nextInt();
        
                    //3.2 当输入是负数的时候,跳出循环
                    if (score < 0 ){
                        break;
                    }
                    if (score > 100 ){
                        System.out.println("输入的数据非法:请重新输入");
                        continue;
                    }
                    //3.1 添加操作:v.addElement(Object obj)
                    //jdk5.0之前:是以下写法
        //        Integer inScore = new Integer(score);
                    //因为vector方法接收需要的是一个对象,所有就把score转换为包装类对象
        //        vector.addElement(inScore);//多态
                    //jdk5.0之后:因为自动拆装箱
                    vector.addElement(score);
        
                    //4.获取学生成绩的最大值
                    if (maxScore < score){
                        maxScore = score;
                    }
                }
        
                //5.遍历Vetor,得到每个学生的成绩,并与最大成绩比较,得到每个学生的等级
                char level = 0;
                for (int i = 0; i < vector.size(); i++) {
                    Object object = vector.elementAt(i);
                    //jdk5.0之前:
        //            Integer inScore = (Integer)object;
        //            int score = inScore.intValue();
                    //jdk5.0之后:装箱用
                    int score = (int)object;
                    //比较大小
                    if (maxScore - score <=10){
                        level = 'A';
                    }else if (maxScore - score <= 20){
                        level = 'B';
                    }else if (maxScore - score <= 30){
                        level = 'C';
                    }else if(maxScore - score <= 40){
                        level = 'D';
                    }
                    System.out.println("student - "+i+"socre is :" + score + "  level is: " + level);
                }
            }
        
        }
        

        5.9.5:每日一考

        1.如何实现向下转型?需要注意什么?
        	Person p = new Man();
        	使用强转符:()
        	Man m = (Map)p;
        	强转可能ClassCastException异常
        	使用instanceof在进行向下转型前判断
        	if(p instanceof Man){
        		Man m = (Man)p;
        	}
        	
        2.==和equals()有何区别?
        	==:  
        	equals():
        3.class User{
        	String name;
        	int age;
        	//重写equals方法
        	public boolean equals(Object obj){
        		if(obj == this){
        			return true;
        		}
        		if(obj instanceof User){
        			User u = (User)name
        			return this.age == u.age && this.name.equals(u.name);
        		}
        		return false;
        	}
        }
        4.写出8种基本数据类型以及对应的包装类
        int  Integer
        Char characther
        
        5.基本数据类型,包装类与String三者之间如何转换
        	自动装箱,自动拆箱
        	
        	基本数据类型,包装类----->String: valueOf(Xxx xx)
        	String-----> 基本数据类型,包装类:parseXxx(string xx)
        

你可能感兴趣的:(java,开发语言,后端)