JavaSE语言基础
01java语言概述
* A: java语言概述
* a: Java是sun公司开发的一门编程语言,目前被Oracle公司收购,编程语言就是用来编写软件的。
* b: Java的应用
* 开发QQ、迅雷程序(桌面应用软件)
* 淘宝、京东(互联网应用软件)
* c: Java的擅长
* 互联网:电商、P2P等等
* 企业级应用:ERP、CRM、BOS、OA等等
* d: Java语言平台
* JavaSE(标准版)部分,基础学习JavaSE,JavaSE并不能开发大型项目。
* JavaEE(企业版)部分,就业学习JavaEE,学习完JavaEE部分就可以开发各种大型项目了。
02常用的DOS命令
* A: 常用的DOS命令
* a: 打开Dos控制台
* win+r--cmd--回车
* b: 常用dos命令
* cd.. : 退回到上一级目录
* cd\ : 退回到根目录
* cd tools: 进入tools文件夹
* d: : 回车 盘符切换
* cd d:\234 :进入d盘的234文件夹,再切换盘符(d:)才能进入d:\234
* dir : 列出当前目录下的文件以及文件夹
* cls : 清除屏幕
* ipconfig: 查看本机的相关网络配置
* c: dos控制台运行记事本程序
* D:\>C:\windows\notepad.exe
* 还可以省略“.exe”后缀,例如:D:\>C:\windows\notepad
03java语言开发环境JDK
* A: java语言开发环境JDK
* a: JDK是Java开发环境
* b: 课程中使用的JDK版本是JDK8,当前最新版本是JDK11
04JDK的下载和安装(JDK下载安装教程)
* A: JDK的下载
* B: JDK的安装
* C: 验证安装是否成功
05JDK和JRE跨平台
* A: JDK与JRE的关系
* a: JDK:它是Java开发运行环境,在程序员的电脑上当然要安装JDK;
* b: JRE:Java Runtime Environment它是Java运行环境,如果你不需要开发只需要运行Java程序,那么你可以安装JRE。例如程序员开发出的程序最终卖给了用户,用户不用开发,只需要运行程序,所以用户在电脑上安装JRE即可。
* c: JDK包含了JRE。
* B: 跨平台特性
* a: 平台指的是操作系统 (Windows,Linux,Mac)。
* b: Java程序可以在任意操作系统上运行,一次编写到处运行
* c: 实现跨平台需要依赖Java的虚拟机 JVM (Java Virtual Machine)
06编写HelloWorld程序
* A: 编写步骤(初学者)
* a: 创建一个普通文本文件,将其修改为.java文件。
* b: 完成模板代码:
public class HelloWorld{
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
* B: 实际开发步骤
* a: 定义类
* b: 写main方法
* c: 写输出语句(注意:下面的代码是原代码,是不能运行的)
public class HelloWorld {
public static void main(String[] args) {
System.out.println("HelloWorld");
}
}
* d:注意:
* 不要隐藏文件的扩展名
* 类名和文件名要保持一致
* C: Java代码的编写执行过程
* a: 源文件:编写Java源文件(我们也称之为源代码文件),它的扩展名为.java;
* b: 编译:然后通过编译器把源文件编译成字节码文件,字节码文件扩展名为.class;
* c: 运行:最后使用解释器来运行字节码文件。
07编译Java程序
* A:程序编译
* 作用:将程序员写的java源代码生成可以运行的Java程序(.class文件)
* 过程:
* a:开启DOS窗口并切换到.java文件所在的目录 比如HelloWord.java存放于d:\234\day01\code 中
* b:切换到HelloWorld.java所在目录,但是此目录中没有javac命令,所以在编译时要写出javac命令的全路径
* c: d:>d:\develop\java\jdk1.8.0_72\bin\javac HelloWorld.java 回车
* d:在d:\code文件夹中多了个HelloWorld.class文件(又叫做字节码文件)
08运行Java程序
* A:运行程序
* a: 开启DOS窗口并切换到.class文件所在的目录
* b: 此目录中没有java命令,所以在运行时也要写出java命令的全路径
* c: d:>d:\develop\java\jdk1.8.0_72\bin\java HelloWorld 回车(注意:运行时不用后缀名.class)
* d: 控制台打印显示结果"HelloWorld"
09环境变量的配置
* A: Path环境变量配置方式一
* a: 安装高级文本编辑器notepad++
* b: 配置Windows的path环境变量
* 环境变量的作用:让Java的bin目录下的javac命令可以在任意目录下执行
* 配置方法:
* 右键点击计算机 → 选择属性 → 更改设置 → 点击高级 → 点击环境变量 → 找到系统变量中的path → 将java安装目录下javac所在的bin目录路径配置到path变量中,用;(英文)与其他变量分隔
* 注意:
* 配置path后文件的访问顺序:先访问当前路径,如果当前路径没有该文件,则再访问path配置的路径
* B:配置过程(建议使用这种方式配置)
* a:右键点击计算机 → 选择属性 → 更改设置 → 点击高级 → 点击环境变量 → 创建名为JAVA_HOME的环境变量 → 将jdk所在的目录路径(bin所在的路径)配置到JAVA_HOME变量中
* b: 用;与其他变量分隔 → 在path环境变量中添加%JAVA_HOME%\bin
10notepad软件安装
* A: 安装
* 双击.exe文件安装 即可
11注释
* A: 注释
* a: 定义:用来解释和说明程序的文字,注释是不会被执行的
* b: 分类:
* 1:单行注释 //注释内容
* 2:多行注释 /*注释内容*/
* 3:文档注释 /**注释内容*/
* c: 注意:
* 1:对于单行和多行注释,被注释的文字,不会被JVM解释执行
* 2:对于文档注释,可以被JDK提供的工具 javadoc 所解析,生成一套以网页文件形式体现的该程序的说明文档
* 3:单行注释可以嵌套使用,多行注释不能嵌套使用
* d: 案例代码
/*
实现了一个Java的HelloWorld程序
实现步骤:
1. 定义类
2. 定义主方法
3. 一条命令,控制台输出了HelloWorld
*/
public class HelloWorld{
//main主方法,固定格式,程序的入口点
public static void main(String[] args){
//系统 输出 打印 打印的内容
System.out.println("HelloWorld");
}
}
12关键字
* A: 关键字
* a: 定义
* 是被Java语言赋予特殊含义,具有专门用途的单词,比如之前接触的class,int,double均为Java已经预设好的
* b: 特点
* 组成关键字的字母全部小写(代码中的蓝色部分) ,注意String不是关键字
* c: 常见关键字
* public static void class等
* d: 注意事项
* goto与const是Java中的保留字,即没有赋予特殊含义却仍被Java占用的单词,类似Editplus这样的高级记事本,针对关键字有特殊的颜色标记,非常直观
13标识符
* A: 标识符
* a: 定义
* 就是给类,接口,方法,变量等起名字时使用的字符序列
* b: 组成规则(只能包含下面的内容,不能有其它内容)
* 1: 英文大小写字母
* 2:数字字符
* 3:$和_
* c: 注意事项
* 1:数字不能开头
* 2:不可以使用关键字
* 3:严格区分大小写,不限制长度
* 4:起名时,尽量达到见名知意
* B:标识符中常见的命名规则(这些规定是不受语法约束的)
* a: 包名:多单词组成时所有字母均小写,使用.连接 aaa.bbb.ccc
* b: 类名&接口名:大驼峰式 AaaBbbCcc
* c: 变量名&方法名:小驼峰式 aaaBbbCcc
* d: 常量名:多单词组成是所有字母均大写,使用_连接AAA_BBB_CCC
* C: 案例代码
/*
标识符
Java中,自己定义的内容
自定义类的名字,上一个案例 HelloWorld
标识符的规则:
组成: 字母52个A-Z a-z 数字0-9 _ 下划线 $ 美元符
注意: 不能数字开头,不能是关键字
定义名字:
_abc 0a a0 a#a a$a void
YES NO YES NO YES NO
类的名字: 首字母大写,第二个单词首字母大写
BeiJingShiHaiDianQuYiYuan
MeiGuoJiaLiFuNiYa
方法的名字:首字母小写,每个单词首字母大写
addStudent
*/
public class Demo{
}
14Java中的数据类型
* A:为什么有数据类型
* Java语言是强类型语言,对于每一种数据都定义了明确的具体数据类型
* B:Java中数据类型的分类
* 基本数据类型: 基本数据类型是Java语言中内置的类型,分别是整数类型、小数类型、字符类型、布尔类型。
这四类基本类型是最简单、最基础的类型。
* 整数(byte、short、int、long)、小数(float、double)、字符类型(char)、布尔类型(boolean)
* 引用数据类型: 是强大的数据类型,它是基于基本数据类型创建的。JavaSE中提供了一个超级类库,类库中包含了近万种引用数据类型。
不过现在我们先要学习的是基本类型!
* 数组、类、接口
15Java中的常量
* A: 常量的定义
* 常量就是不变的数据量, 在程序执行的过程中其值不可以发生改变
* B: 常量分类
* a: 整数类型
* 十进制表示方式:正常数字 如 13、25等
* 二进制表示方式:以0b(0B)开头 如0b1011 、0B1001
* 十六进制表示方式:以0x(0X)开头 数字以0-9及A-F组成 如0x23A2、0xa、0x10
* 八进制表示方式:以0开头 如01、07、0721
* b: 小数类型
* 如1.0、-3.15、3.168等
* c: 布尔类型
* true、false
* d: 字符类型
* 如'a','A', '0', '家'
* 字符必须使用’’ 包裹,并且其中只能且仅能包含一个字符。
* e: 字符串类型
* 字符串String类型是一种引用类型,我们先了解作为常量类型的使用方式
* 如“我爱Java”,“0123”,“”,“null”
* 字符串必须使用“”包裹,其中可以包含0~N个字符。
16程序中输出Java中的常量
* A: 案例代码
/*
Demo_1类,演示Java中的所有类型的常量
程序当中输出:
输出整数常量
小数常量
布尔常量
字符常量
字符串常量
*/
public class Demo_1{
public static void main(String[] args){
//输出整数 十进制
System.out.println(50);
//输出整数,二进制, 数字开头0B
System.out.println(0B11);
//输出整数,八进制,数字开头0
System.out.println(051);
//输出整数,十六进制,数组开头0X 0-9 A-F
System.out.println(0XE);
//输出浮点数据
System.out.println(5.0);
//输出布尔数据,只有2个值,true,false 关键字
System.out.println(true);
System.out.println(false);
//输出字符常量,单引号包裹,只能写1个字符
System.out.println('a');
//输出字符串常量,双引号包裹,可以写0-n个字符
System.out.println("HelloWorld");
}
}
01变量概述
* A: 什么是变量?
* a: 变量是一个内存中的小盒子(小容器),容器是什么?生活中也有很多容器,例如水杯是容器,用来装载水;你家里的大衣柜是容器,用来装载衣裤;饭盒是容器,用来装载饭菜。那么变量是装载什么的呢?答案是数据!结论:变量是内存中装载数据的小盒子,你只能用它来存数据和取数据。
02计算机存储单元
* A: 计算机中储存和运算的最小单位是?
* a: 一个字节,也就是一个byte.
* win+r--cmd--回车
* b: 常用储存单位
*1B(字节) = 8bit
*1KB = 1024B
*1MB = 1024KB
*1GB = 1024MB
*1TB = 1024GB
*1PB = 1024TB
03Java中数据类型四类八种
* A: 数据类型四类八种
*四类 八种 字节数 数据表示范围
*整型:
byte 1 -128~127
short 2 -32768~32767
int 4 -2147483648~2147483648
long 8 -263~263-1
*浮点型:
float 4 -3.403E38~3.403E38
double 8 -1.798E308~1.798E308
*字符型
char 2 表示一个字符,如('a','A','0','家')
*布尔型
boolean 1 只有两个值true与false
04常量和数据类型
* A:常量的定义
* a: 整形常量默认是int类型
* b: 小数常量默认是double类型
* c: 定义长整形数据如果值超过int取值范围后面要+"L"
* d: 定义float类型的数据后面要+"f" 否则默认是double
05变量创建的三要素
* A: 定义变量的语法格式:
数据类型 变量名 = 变量值;
* int a = 100;
* B:代码:
public class Variable {
public static void main(String[] args) {
int a = 10;
double b = 3.14;
char c = 'z';
String s = "i love java";
a = 20;
System.out.println(a);
}
}
06定义所有的基本数据类型变量
* A: 案例演示
* a: 八种基本类型数据的创建
07定义字符串变量
* A:案例演示
* 创建字符串数据类型变量
* String 是引用数据类型
08变量定义使用注意事项
* A:变量使用的注意事项
* a: 变量定义后可以不赋值,使用时再赋值。不赋值不能使用。
public static void main(String[] args) {
int x;
x = 20; //为x赋值20
System.out.println(x);//读取x变量中的值,再打印
}
* c: 变量使用时有作用域的限制。
public static void main(String[] args) {
int x = 20;
{
int y = 20;
}
System.out.println(x);//读取x变量中的值,再打印
System.out.println(y);//读取y变量中的值失败,失败原因,找不到y变量,因为超出了y变量作用范围,所以不能使用y变量
}
09数据类型转换_自动转换
* A: 自动类型转换
* a:表示范围小的数据类型转换成范围大的数据类型,这种方式称为自动类型转换
自动类型转换格式:
范围大的数据类型 变量 = 范围小的数据类型值;
如:
double d = 1000;
或
int i = 100;
double d2 = i;
10数据类型转换_强制转换
* A: 强制类型转换
*a: 表示范围大的数据类型转换成范围小的数据类型,这种方式称为强制类型转换
*b: 强制类型转换格式:
范围小的数据类型 变量 = (范围小的数据类型) 范围大的数据类型值;
如:
int i = (int)6.718; //i的值为6
或
double d = 3.14;
int i2 = (int)d; //i2的值为3
11算数运算符_1
* A: 常见操作
运算符 运算规则 范例 结果
+ 正号 +3 3
+ 加 2+3 5
+ 连接字符串 “中”+“国” “中国”
- 负号 int a=3;-a -3
- 减 3-1 2
* 乘 2*3 6
/ 除 5/2 2
% 取模 5/2 1
++ 自增 int a=1;a++/++a 2
-- 自减 int b=3;a--/--a 2
* B: 注意事项
*a:加法运算符在连接字符串时要注意,只有直接与字符串相加才会转成字符串。
*b:除法“/”当两边为整数时,取整数部分,舍余数。当其中一边为浮点型时,按正常规则相除。
*c:“%”为整除取余符号,小数取余没有意义。结果符号与被取余符号相同。
*d:整数做被除数,0不能做除数,否则报错。
*e:小数做被除数,整除0结果为Infinity,对0取模结果为NaN
* C:代码演示
public class OperatorDemo1 {
public static void main(String[] args) {
/*
* 常量使用算数运算符
*/
System.out.println(10+20);
/*
* 变量使用算数运算符
*/
int x = 10;
int y = 20;
//"+"作为加法运算使用
int z = x + y;
//"+"作为连接字符串使用
System.out.println("x="+x);
System.out.println("y="+y);
System.out.println("z="+z);
}
}
12算数运算符_2
* A:算数运算符++、--的使用
* a: ++运算符,会在原有值的基础上自增1
* b: --运算符,会在原有值的基础上自减1。
* B:++ -- 位置的使用
* a:++,--运算符后置时,先使用变量a原有值参与运算操作,运算操作完成后,变量a的值自增1或者自减1;
* b:++,--运算符前置时,先将变量a的值自增1或者自减1,然后使用更新后的新值参与运算操作。
13赋值运算符
* A: 赋值运算符的使用
运算符 运算规则 范例 结果
= 赋值 int a=2 2
+= 加后赋值 int a=2,a+=2 4
-= 减后赋值 int a=2,a-=2 0
*= 乘后赋值 int a=2,a*=2 4
/= 整除后赋值 int a=2,a/=2 1
%= 取模后赋值 int a=2,a%=2 0
* B:案例演示
* 赋值运算符
* +=, -=, *=, /=, %= :
* 上面的运算符作用:将等号左右两边计算,会将结果自动强转成等号左边的数据类型,再赋值给等号左边的
* 注意:赋值运算符左边必须是变量
public class OperatorDemo2 {
public static void main(String[] args) {
byte x = 10;
x += 20;// 相当于 x = (byte)(x+20);
System.out.println(x);
}
}
14比较运算符
* A:比较运算符的使用
运算符 运算规则 范例 结果
== 相等于 4==3 False
!= 不等于 4!=3 True
< 小于 4<3 False
> 大于 4>3 True
<= 小于等于 4<=3 False
>= 大于等于 4>=3 True
15逻辑运算符
* A: 逻辑运算符的使用
运算符 运算规则 范例 结果
& 与 false&true False
| 或 false|true True
^ 异或 true^flase True
! 非 !true Flase
&& 短路与 false&&true False
|| 短路或 false||true True
规律小结:
短路与&&:参与运算的两边数据,有false,则运算结果为false;
短路或||:参与运算的两边数据,有true,则运算结果为true;
逻辑非! : 参与运算的数据,原先是true则变成false,原先是false则变成true。
16三元运算符
* A: 格式:
(条件表达式)?表达式1:表达式2;
* B: 代码案例
方式一:
System.out.println( 3>2 ? “正确” : “错误” );
// 三元运算符运算后的结果为true,运算结果为表达式1的值“正确”,然后将结果“正确”,在控制台输出打印
方式二:
int a = 3;
int b = 4;
String result = (a==b) ? “相等” : “不相等”;
//三元运算符运算后的结果为false,运算结果为表达式2的值“不相等”,然后将结果赋值给了变量result
方式三:
int n = (3>2 && 4>6) ? 100 : 200;
//三元运算符运算后的结果为false,运算结果为表达式2的值200,然后将结果200赋值给了变量n
17运算符优先级
优先级 描述 运算符
1 括号 ()、[]
2 正负号 +、-
3 自增自减,非 ++、--、!
4 乘除,取余 *、/、%
5 加减 +、-
6 移位运算 <<、>>、>>>
7 大小关系 >、>=、<、<=
8 相等关系 ==、!=
9 按位与 &
10 按位异或 ^
11 按位或 |
12 逻辑与 &&
13 逻辑或 ||
14 条件运算 ?:
15 赋值运算 =、+=、-=、*=、/=、%=
16 位赋值运算 &=、|=、<<=、>>=、>>>=
18 商场库存清单案例
A: 案例分析.
* a:观察清单后,可将清单分解为三个部分(清单顶部、清单中部、清单底部)
* b:清单顶部为固定的数据,直接打印即可
* c:清单中部为商品,为变化的数据,需要记录商品信息后,打印
经过观察,我们确定一项商品应该有如下几个属性:
品牌型号: 即商品名称,String型
尺寸:物品大小,double型
价格:物品单价,double型
配置:这一项为每种商品的配置信息,String型
库存数:这一项为每种商品的库存个数,int型
* d:清单底部包含了统计操作,需经过计算后,打印
我们发现两个单独的可变化量
总库存数:所有商品总个数,int型
库存商品总金额:所有商品金额,double型
B: 案例代码实现
//步骤一: 创建Demo01库存清单.java文件,编写main主方法
public class Demo01库存清单 {
public static void main(String[] args) {
}
}
//步骤二: 记录每种库存商品信息
//苹果笔记本电脑
String macBrand = "MacBookAir";
double macSize = 13.3;
double macPrice = 6988.88;
int macCount = 5;
//联想Thinkpad笔记本电脑
String thinkpadBrand = "ThinkpadT450";
double thinkpadSize = 14.0;
double thinkpadPrice = 5999.99;
int thinkpadCount = 10;
//华硕ASUS笔记本电脑
String ASUSBrand = "ASUS-FL5800";
double ASUSSize = 15.6;
double ASUSPrice = 4999.50;
int ASUSCount = 18;
//步骤三: 统计库存总个数、库存总金额
int totalCount = macCount + thinkpadCount + ASUSCount;
double totalMoney = (macCount * macPrice) + (thinkpadCount * thinkpadPrice) + (ASUSCount * ASUSPrice);
//步骤四: 列表顶部
System.out.println("------------------------------商城库存清单-----------------------------");
System.out.println("品牌型号 尺寸 价格 库存数");
步骤四:打印库存清单中部信息
//列表中部
System.out.println(macBrand+" "+macSize+" "+macPrice+" "+macCount);
System.out.println(thinkpadBrand+" "+thinkpadSize+" "+thinkpadPrice+" "+thinkpadCount);
System.out.println(ASUSBrand+" "+ASUSSize+" "+ASUSPrice+" "ASUSCount);
打印库存清单底部信息
//列表底部
System.out.println("-----------------------------------------------------------------------");
System.out.println("总库存数:"+totalCount);
System.out.println("库存商品总金额:"+totalMoney);
01创建引用类型变量公式
* A: 创建引用类型变量公式
* a: 我们要学的Scanner类是属于引用数据类型,我们先了解下引用数据类型。
* b: 引用数据类型的定义格式
* 与定义基本数据类型变量不同,引用数据类型的变量定义及赋值有一个相对固定的步骤或格式。
* 数据类型 变量名 = new 数据类型();
* c: 引用数据类型的使用
* 每种引用数据类型都有其功能,我们可以调用该类型实例的功能。
* 变量名.方法名();
02Scanner类的使用
* A: Scanner类的使用
* a: 导包import java.util.Scanner;
* b:创建键盘录入对象 Scanner sc = new Scanner(System.in);
* c: 读取键盘录入的一个整数
* int enterNumber = sc.nextInt();
* d: 读取键盘录入的字符串
* String enterString = sc.next();
* B: 案例代码
import java.util.Scanner;
public class Demo05Scanner{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
int enterNumber = sc.nextInt();
System.out.println("用户输入的整数为"+enterNumber);
String enterString = sc.next();
System.out.println("用户输入的字符串为"+enterString);
}
}
03Random随机数类的使用_1
* A: Random随机数类的使用_1
* a: 功能
* 生成随机数需要使用到引用类型随机数Random类
* b: 使用方式
* import导包:所属包java.util. Random
* 创建实例格式:Random random = new Random ();
* 调用方法
* nextInt(int maxValue) 产生[0,maxValue)范围的随机数,包含0不包含maxValue
* nextDouble() 产生[0,1)范围的随机数
如:
Random random = new Random ();
int myNumber = random.nextInt(100);//结果为0-99的一个数
* B: 案例代码
import java.util.Random;
public class RandomDemo{
public static void main(String[] args){
Random ran = new Random();
// Random类中的,产生随机数的功能
int i = ran.nextInt(100);
System.out.println(i);
//问题? 产生随机数,范围 1-100之间
// nextInt(100) 0-99 + 1
}
}
04Random随机数类的使用_2
* A: Random随机数类的使用_2
* a: 调用方法
* nextDouble() 产生[0,1)范围的随机数
如:
Random random = new Random ();
int myNumber = random.nextDouble();//结果为0.0-1.0之间的数(包括0.0不包括1.0)
05if语句格式第一种
* A: if语句格式第一种
* a: 书写格式
if(比较表达式) {
语句体;
}
* b:执行流程:
* 先计算比较表达式的值,看其返回值是true还是false。
* 如果是true,就执行语句体;
* 如果是false,就不执行语句体;
* B: 案例代码
public class IfDemo{
public static void main(String[] args){
int i = 5 ;
//对变量i进行if判断
if(i > 5){
System.out.println("if中的条件是true");
i++;
}
System.out.println(i);
}
}
06if语句格式第二种
* A: if语句格式第二种
* a: 书写格式
if(比较表达式) {
语句体1;
}else {
语句体2;
}
* b:执行流程:
* 首先计算比较表达式的值,看其返回值是true还是false。
* 如果是true,就执行语句体1;
* 如果是false,就执行语句体2;
* B: 案例代码
public class IfElseDemo{
public static void main(String[] args){
int i = 16 ;
//判断变量,是奇偶数, 除以2,看余数是0还是1
if( i % 2 == 0 ){
System.out.println(i+" 是偶数");
}else{
System.out.println(i+" 是奇数");
}
}
}
07if语句格式第三种
* A: if语句格式第三种
* a: 书写格式
if(比较表达式1) {
语句体1;
}else if(比较表达式2) {
语句体2;
}else if(比较表达式3) {
语句体3;
}
...
else {
语句体n+1;
}
* b:执行流程:
* 首先计算比较表达式1看其返回值是true还是false,
* 如果是true,就执行语句体1,if语句结束。
* 如果是false,接着计算比较表达式2看其返回值是true还是false,
* 如果是true,就执行语句体2,if语句结束。
* 如果是false,接着计算比较表达式3看其返回值是true还是false,
* 如果都是false,就执行语句体n+1。
* B: 案例代码
public class IfElseIfDemo{
public static void main(String[] args){
//成绩判断要求 ,成绩>80 成绩>70 成绩>60 不及格
//定义变量,保存成绩
int grade = 75;
//使用if else if 语句对成绩判断
if( grade > 80 ){
System.out.println(grade+" 成绩是优");
}else if ( grade > 70){
System.out.println(grade+" 成绩是良");
}else if ( grade > 60){
System.out.println(grade+" 成绩是中");
}else{
System.out.println(grade+" 成绩是差");
}
}
}
08if语句和三元运算符的互换
* A: 三元运算符
* a: 概念
* 用来完成简单的选择逻辑,即根据条件判断,从两个选择中选择一种执行
* b: 使用格式
* (条件表达式)?表达式1:表达式2;
* c: 运算规则
* 1: 判断条件表达式,结果为一个布尔值
* 2: true,运算结果为表达式1
* 3: false,运算结果为表达式2
* B: 案例代码
public class IfElseDemo_1{
public static void main(String[] args){
int j = 6;
int i = 15;
//使用if语句,判断出最大值
if(i>j){
int j = 6;
System.out.println(i+" 是最大值");
}else{
System.out.println(j+" 是最大值");
}
//使用三元运算实现
int k = i>j ? i : j;
System.out.println(k+" 是最大值");
}
}
* C: 使用if语句还是三元表达式
* 判断条件多,使用if
* 三元,必须有结果的, if 可以没有结果的
09while循环
* A: while循环结构
* a: 使用格式
初始化表达式;
while(条件){
循环体
}
* b: 执行顺序
当条件是true,就执行循环体,执行完循环体后
程序再次执行while中的条件,如果条件还是true,继续执行循环体
直到条件是false的时候,循环就结束
* B: 案例代码
public class WhileDemo{
public static void main(String[] args){
//输出 1-4之间的整数
//定义变量,整数类型, 循环的条件
int i = 1;
while( i < 5 ){
System.out.println(i);
i++;
}
}
}
10for循环_1
* A: for循环_1
* a: 使用格式
for(初始化变量 ; 条件 ; 增量){
循环体;
}
* b: 各模块解释
初始化变量: 定义变量,作用是用来控制循环的次数
条件: 当条件是true,执行循环体,条件是false,结束循环
增量: 变量自增情况
* B: 案例代码
public class ForDemo{
public static void main(String[] args){
//for循环,输出0-10
for(int i = 0 ; i < 11 ; i++){
System.out.println(i);
}
}
}
11for循环_2
* A: for循环的执行流程
for(① ; ② ; ③){
④
}
第一步,执行①
第二步,执行②,如果判断结果为true,执行第三步,如果判断结果为false,执行第五步
第三步,执行④
第四步,执行③,然后重复执行第二步
第五步,退出循环
12for循环_3
* A: 案例
* a: 利用for循环,计算1+4的结果
* B: 案例代码
public class ForDemo_1{
public static void main(String[] args){
// 定义变量,记录求和后的数据
int sum = 0;
// 利用循环,将变量从1变化到4
for(int i = 1 ; i <= 4 ; i++){
//对变量进行求和
sum = sum + i;
}
System.out.println(sum);
}
}
13do_while循环
* A: do_while循环
* a: 使用格式
do{
循环体;
}while(条件);
* b: 执行顺序
先执行一次循环体,然后再判断条件,如果条件为true,继续执行循环体,
如果条件为false,循环结束。
* c: 特点
* 无条件先执行一次
* B: 案例代码
public class DoWhileDemo{
public static void main(String[] args){
int i = 0;
do{
System.out.println(i);
i++;
}while( i < 5);
}
}
14死循环
* A: 死循环概述
* 无限循环存在的原因是并不知道循环多少次,而是根据某些条件,来控制循环
* B: 死循环格式
* while(true){}
* for(;;){}
15嵌套for循环_1
* A: 嵌套循环的概述
* 嵌套循环是指在一个循环语句的循环体中再定义一个循环语句的语法结构。while、do…while、for循环语句都可以进行嵌套,并且它们之间也可以互相嵌套,如最常见的在for循环中嵌套for循环。
* B: 嵌套循环的格式
for(初始化表达式; 循环条件; 操作表达式) {
………
for(初始化表达式; 循环条件; 操作表达式) {
执行语句
………
}
………
}
* C: 各模块解释
* 总的循环次数 = 内循环次数 * 外循环的次数
* 内循环,是外循环的循环体
* 外循环,控制的是行数
* 内循环,控制的是每行的个数
16嵌套for循环_2
* A: 案例
* a: 打印正三角形
* B: 案例代码
public class ForForDemo{
public static void main(String[] args){
for(int i = 0 ; i < 9 ; i++){
for(int j = 0; j < i+1 ;j++){
System.out.print("* ");
}
System.out.println();
}
}
}
17break语句
* A: break语句
* a: 作用
* 跳出所在的循环体
* b: 书写位置
* 必须出现在循环或选择结构内
* c: 举例
for(int i=0; i<10; i++) {
if(i>5) {
break;
}
System.out.println(“我爱Java”+i);
}
//会从0-5输出6次“我爱Java”
* B: break详细解释
* a: 作用
* 在loop/switch选择或者循环过程中,我们总是满足布尔表达条件才能执行对应的代码,然而在这些逻辑过程中,
可以使用一些关键字直接跳出正在执行的代码,去执行后边或者指定位置的代码,
这些关键字一旦出现就可以跳转语句执行顺序。
* b: 使用方式
* 无法单独使用,必须将break关键字置于switch或循环语句中
* c: 运行规律
* 不需要判断任何条件,只要遇到break变直接跳出执行后续代码。会完全跳出选择或者循环结构
* 只能跳出最近的代码块,不能跨越多级代码块
* C:循环标号
* a: 为什么使用循环标号
* 当在双层循环或者循环内有switch选择语句时,我们发现,使用break或者continue所作用的对象均是内层语句,无法直接跳出外层循环,这时就需要使用标号语句跳转了.
* b: 使用方式
* 在外层循环外的某行前边,使用后边跟有冒号”:”的标识符,即定义完毕。
使用时当在内层循环使用break或continue时后边紧跟之前定义的标号即可
* c: 运行规律
* 当外层循环外定义了标号
* 内层使用break,终止内外双层循环。
* 内层使用continue,终止内层循环,继续外层循环。
18continue语句
* A: continue语句
* a: 作用
* 提前结束本次循环,继续进行下次循环
* b: 使用方式
* 无法单独使用,必须将continue关键字置于循环语句中
* c:运行规律
* 不需要判断任何条件,只要遇到continue变直接跳出本轮循环进行下次循环
* d:案例代码
public class ContinueDemo{
public static void main(String[] args){
for(int i = 0 ; i < 10 ; i++){
if(i%2==0){
continue;
}
System.out.println(i);
}
}
}
//会把0-9之间所有的奇数打印到控制台上
19猜数字小游戏
* A: 猜数字小游戏
* a: 分析
* 用户给的数可能大于、小于、或等于被猜的数,这样就会出现三种情况,用前面讲的三元运算符可以实现,
但是得用三元运算符的嵌套,比较麻烦!可以用更简单的方式if条件判断,可以有三个以上的条件
* b: 需求分析
* 后台预先生成一个随机数1-100,用户键盘录入猜数字
* 如果猜对了,打印“恭喜您,答对了”
* 如果猜错了
* 猜大了:打印“sorry,您猜大了!”
* 猜小了:打印“sorry,您猜小了!”
直到数字猜到为止
最多只能猜5次,否则提示“sorry,您没有机会了!”
* B: 案例代码
/*
猜数字小游戏
完成猜数字小游戏:
1、产生随机数
后台预先生成一个随机数1-100,用户键盘录入猜数字
2、通过if语句对用户猜的数与随机数进行比较
如果猜对了,打印“恭喜您,答对了”
如果猜错了
猜大了:打印“sorry,您猜大了!”
猜小了:打印“sorry,您猜小了!”
3、通过for循环完成用户猜数的循环
直到数字猜到为止
最多只能猜5次,否则提示“sorry,您没有机会了!”
*/
import java.util.Random;
import java.util.Scanner;
//通过*的方式可以一次导入该包下所有的类,但是不建议使用。建议使用哪个导哪个。
//import java.util.*;
public class GuessNumber{
public static void main(String[] args) {
//1、产生随机数
//后台预先生成一个随机数1-100,用户键盘录入猜数字
//创建随机数对象
Random random = new Random();
//产生一个1-100的随机数
int randomNumber = random.nextInt(100)+1;
//System.out.println("我产生的随机数是:"+randomNumber+"你猜猜是多少?"); 作弊专用
//产生控制台录入的Scanner对象
Scanner sc = new Scanner(System.in);
//3、通过for循环完成用户猜数的循环
//通过for循环完成猜数字逻辑
for(int i=1; i<=5; i++){
//提示用户输入要猜的数,用变量接收
System.out.println();
System.out.println("请您输入一个1-100的数:");
int guessNumber = sc.nextInt();
//2、通过if语句对用户猜的数与随机数进行比较
//如果猜对了
if(guessNumber==randomNumber) {
//打印猜对后的提示
System.out.println("恭喜您,猜对了!");
//跳出循环,不用再猜了
break;
}else {//如果猜错了
//如果猜大了
if(guessNumber>randomNumber) {
System.out.println("sorry,您猜大了!");
}else {//如果猜小了
System.out.println("sorry,您猜小了!");
}
}
//如果猜到了最后的第5次仍然没有猜对就跳出循环
if(i==5) {
System.out.println("对不起,点太背,下次再来吧!");
break;
}
//每次猜错后,都提示还有多少次机会
System.out.println("请注意,您还有"+(5-i)+"次机会,请慎重作答!");
}
}
}
01switch语句解构
* A:switch语句解构
* a:switch只能针对某个表达式的值作出判断,从而决定程序执行哪一段代码。
* b:格式如下:
swtich(表达式){
case 常量1 :
要执行的语句;
break;
case 常量2 :
要执行的语句;
break;
case 常量3 :
要执行的语句;
break;
default:
要执行的语句;
break;
}
* c: 执行流程: 表达式,和case后面的常量进行比较和哪个case后的常量相同,就执行哪个case后面的程序,遇到break,就全结束
* d: 关键字: switch case default break
* e:举例
如果等于1,则输出星期一
如果等于2,则输出星期二
如果等于3,则输出星期三
如果等于4,则输出星期四
如果等于5,则输出星期五
如果等于6,则输出星期六
如果等于7,则输出星期天
02switch语句的星期判断
* A: switch语句的星期判断
* a: 明确需求
需求:初始化int类型变量(1-7)代表星期几,使用switch语句进行判断,并打印出该整数对应的星期.
* b: 代码实现
public class SwitchDemo01 {
public static void main(String[] args) {
int week = 5;
switch (week) {
case 1:
System.out.println("星期一");
break;
case 2:
System.out.println("星期二");
break;
case 3:
System.out.println("星期三");
break;
case 4:
System.out.println("星期四");
break;
case 5:
System.out.println("星期五");
break;
case 6:
System.out.println("星期六");
break;
case 7:
System.out.println("星期天");
break;
default:
System.out.println("输入的数字不正确...");
break;
}
}
}
03switch语句接受的数据类型
* A: switch语句接受的数据类型
* a:注意事项
switch语句中的表达式的数据类型,是有要求的
JDK1.0 - 1.4 数据类型接受 byte short int char
JDK1.5 数据类型接受 byte short int char enum(枚举)
JDK1.7 数据类型接受 byte short int char enum(枚举), String
04case穿透
* A:case穿透
* a: 在使用switch语句的过程中,如果多个case条件后面的执行语句是一样的,则该执行语句只需书写一次即可,这是一种简写的方式。
* b: 例如,要判断一周中的某一天是否为工作日,同样使用数字1~7来表示星期一到星期天,当输入的数字为1、2、3、4、5时就视为工作日,否则就视为休息日。
05数组的概述
* A: 数组的概述
* a:数组的需求
现在需要统计某公司员工的工资情况,例如计算平均工资、最高工资等。假设该公司有50名员工,用前面所学的知识完成,
那么程序首先需要声明50个变量来分别记住每位员工的工资,这样做会显得很麻烦.
* b:数组的概述
数组是指一组数据的集合,数组中的每个数据被称作元素。在数组中可以存放任意类型的元素,但同一个数组里存放的元素类型必须一致。
06数组的定义
* A:数组的定义
* b:格式:
数据类型[] 数组名 = new 数据类型[元素个数或数组长度];
* c:举例:
int[] x = new int[100];
* c:要点说明
1)数据类型: 数组中存储元素的数据类型
2) [] 表示数组的意思
3) 变量名 自定义标识符
4) new 创建容器关键字
5)数据类型: 数组中存储元素的数据类型
6)[] 表示数组的意思
7)元素个数,就是数组中,可以存储多少个数据 (恒定, 定长)
数组是一个容器: 存储到数组中的每个元素,都有自己的自动编号
自动编号,最小值是0, 最大值,长度-1
自动编号专业名次, 索引(index), 下标, 角标
访问数组存储的元素,必须依赖于索引, 公式 数组名[索引]
Java提供一个属性,操作索引的
数组的一个属性,就是数组的长度, 属性的名字 length
使用属性: 数组名.length 数据类型 int
数组的最小索引是0, 最大索引数组.length-1
07JVM内存划分
* A:内存划分
* JVM对自己的内存划分为5个区域
* a: 寄存器:内存和CUP之间
* b: 本地方法栈: JVM调用了系统中的功能
* c: 方法和数据共享: 运行时期class文件进入的地方
* d: 方法栈:所有的方法运行的时候进入内存
* e: 堆:存储的是容器和对象
08数组的内存
* A: 数组的内存
* int[] x; // 声明一个int[]类型的变量
* x = new int[100]; // 创建一个长度为100的数组
* 接下来,通过两张内存图来详细地说明数组在创建过程中内存的分配情况。
* 第一行代码 int[] x; 声明了一个变量x,该变量的类型为int[],即一个int类型的数组。变量x会占用一块内存单元,它没有被分配初始值
* 第二行代码 x = new int[100]; 创建了一个数组,将数组的地址赋值给变量x。在程序运行期间可以使用变量x来引用数组,这时内存中的状态会发生变化
09使用索引访问数组的元素
* A: 使用索引访问数组的元素
* 组中有100个元素,初始值都为0。数组中的每个元素都有一个索引(也可称为角标),要想访问数组中的元素可以通过“x[0]、x[1]、……、x[98]、x[99]”的形式。
* 需要注意的是,数组中最小的索引是0,最大的索引是“数组的长度-1”
10数组的length属性
* A: lenth属性
* a 在Java中,为了方便我们获得数组的长度,提供了一个length属性,在程序中可以通过“数组名.length”的方式来获得数组的长度,即元素的个数。
* b 求数组的长度
public class ArrayDemo01 {
public static void main(String[] args) {
int[] arr; // 声明变量
arr = new int[3]; // 创建数组对象
System.out.println("arr[0]=" + arr[0]); // 访问数组中的第一个元素
System.out.println("arr[1]=" + arr[1]); // 访问数组中的第二个元素
System.out.println("arr[2]=" + arr[2]); // 访问数组中的第三个元素
System.out.println("数组的长度是:" + arr.length); // 打印数组长度
}
}
11为数组的元素赋值
* A: 为数组的元素赋值
* a: 如果在使用数组时,不想使用这些默认初始值,也可以显式地为这些元素赋值。
* 赋值过的元素已经变为新的数值,没有赋值的元素默认初始化的数值
* b: 案例
public class ArrayDemo02 {
public static void main(String[] args) {
int[] arr = new int[4]; // 定义可以存储4个整数的数组
arr[0] = 1; // 为第1个元素赋值1
arr[1] = 2; // 为第2个元素赋值2
// 下面的代码是打印数组中每个元素的值
System.out.println("arr[0]=" + arr[0]);
System.out.println("arr[1]=" + arr[1]);
System.out.println("arr[2]=" + arr[2]);
System.out.println("arr[3]=" + arr[3]);
}
}
12数组的定义_2
* A: 定义数组格式2
* a: 数组初始化
动态初始化 : 在定义数组时只指定数组的长度,由系统自动为元素赋初值的方式称作动态初始化。
1、类型[] 数组名 = new 类型[长度];
int[] arr = new int[4];
静态初始化: 在初始化数组时还有一种方式叫做静态初始化,就是在定义数组的同时就为数组的每个元素赋值。
2、类型[] 数组名 = new 类型[]{元素,元素,……};
int[] arr = new int[]{1,2,3,4};
3、类型[] 数组名 = {元素,元素,元素,……};
int[] arr = { 1, 2, 3, 4 };
13遍历数组
* A:遍历数组
* 在操作数组时,经常需要依次访问数组中的每个元素,这种操作称作数组的遍历
* B:练习
public class ArrayDemo04 {
public static void main(String[] args) {
int[] arr = { 1, 2, 3, 4, 5 }; // 定义数组
// 使用for循环遍历数组的元素
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]); // 通过索引访问元素
}
}
}
上述代码中,定义一个长度为5的数组arr,数组的角标为0~4。由于for循环中定义的变量i的值在循环过程中为0~4,因此可以作为索引,依次去访问数组中的元素,并将元素的值打印出来
14数组中常见的异常
* A: 数组操作中,常见的两个异常
数组的索引越界异常
空指针异常
* B: 练习
public class ArrayDemo_4{
public static void main(String[] args){
//数组的索引越界异常
//int[] arr = {5,2,1};
//数组中3个元素,索引 0,1,2
//System.out.println(arr[3]);//java.lang.ArrayIndexOutOfBoundsException: 3
//空指针异常
int[] arr2 = {1,5,8};
System.out.println(arr2[2]);
arr2 = null; // arr2 不在保存数组的地址了
System.out.println(arr2[2]);//java.lang.NullPointerException
}
}
15数组最值
* A: 数组获取最值的原理思想
* 定义数组的第一个元素arr[0]为最大值;循环arr数组,判断如果有比arr[0] 大的就交换,直到arr数组遍历完毕,那么arr[0]中就保存了最大的元素
16数组获取最值代码实现
* A: 代码实现
public class ArrayDemo05 {
public static void main(String[] args) {
int[] arr = { 4, 1, 6, 3, 9, 8 }; // 定义一个数组
int max = arr[0]; // 定义变量max用于记住最大数,首先假设第一个元素为最大值
// 下面通过一个for循环遍历数组中的元素
for (int x = 1; x < arr.length; x++) {
if (arr[x] > max) { // 比较 arr[x]的值是否大于max
max = arr[x]; // 条件成立,将arr[x]的值赋给max
}
}
System.out.println("max=" + max); // 打印最大值
}
}
17二维数组的定义
* A 二维数组的作用
* 要统计一个学校各个班级学生的考试成绩,又该如何实现呢?
* 这时就需要用到多维数组,多维数组可以简单地理解为在数组中嵌套数组。
* B 定义格式
* a 第一种定义格式:
* int[][] arr = new int[3][4];
* 上面的代码相当于定义了一个3*4的二维数组,即二维数组的长度为3,二维数组中的每个元素又是一个长度为4的数组
* b 第二种定义格式
* int[][] arr = new int[3][];
* 第二种方式和第一种类似,只是数组中每个元素的长度不确定
* c 第三种定义格式
* int[][] arr = {{1,2},{3,4,5,6},{7,8,9}};
* 二维数组中定义了三个元素,这三个元素都是数组,分别为{1,2}、{3,4,5,6}、{7,8,9}
18二维数组元素的访问
* A: 二维数组的访问
* 案例:
class ArrayDemo08 {
public static void main(String[] args){
//定义二维数组的方式
int[][] arr = new int[3][4];
System.out.println( arr );
System.out.println("二维数组的长度: " + arr.length);
//获取二维数组的3个元素
System.out.println( arr[0] );
System.out.println( arr[1] );
System.out.println( arr[2] );
System.out.println("打印第一个一维数组的元素值");
System.out.println( arr[0][0] );
System.out.println( arr[0][1] );//访问的为二维数组中第1个一维数组的第2个元素
System.out.println( arr[0][2] );
System.out.println( arr[0][3] );
System.out.println("打印第二个一维数组的元素值");
System.out.println( arr[1][0] );
System.out.println( arr[1][1] );
System.out.println( arr[1][2] );
System.out.println( arr[1][3] );
System.out.println("打印第三个一维数组的元素值");
System.out.println( arr[2][0] );
System.out.println( arr[2][1] );
System.out.println( arr[2][2] );
System.out.println( arr[2][3] );
}
}
19二维数组内存图
* A: 二维数组内存图
* 举例:int[][] arr = new int[3][2];
* 外层数组长在内存开辟连续的3个大的内存空间,每一个内存空间都对应的有地址值
* 每一个大内存空间里又开辟连续的两个小的内存空间.
20二维数组的定义和访问
* A: 二维数组的定义和访问
* 格式1:
* int[][] arr = new int[3][]; 不推荐
* 格式2
* int[][] arr = {{1,2,4},{4,7},{0,9,3}};
*
* B: 二维数组的访问
举例:int[][] arr = {{1,2,4},{5,8,7},{0,9,3}};
想要打印数组中7这个元素需要先找到大的元素索引{5,7} 索引为2 ,在找7在{5,7}中的索引2
那么结果为 arr[2][2] 第一个[2]代表大数组中{5,8,7}这个元素索引
第二个[2]代表{5,8,7}中7元素的索引
22二维数组的遍历
* A:二维数组遍历
int[][] arr = {{1,2,4},{4,7},{0,9,3}};
先使用for循环遍历arr这个二维数组,得到每一个元素为arr[i]为一维数组
再外层for循环中嵌套一个for循环遍历每一个一维数组arr[i],得到每一元素
* B:举例:遍历二维数组
public class ArrayArrayDemo_2{
public static void main(String[] args){
int[][] arr = { {1,2,3},{4,5},{6,7,8,9},{0} };
//外循环,遍历二维数组
for(int i = 0 ; i < arr.length ;i++){
//内循环,遍历每个一维数组 arr[0] arr[1] arr[i]
for(int j = 0 ; j < arr[i].length; j++){
System.out.print(arr[i][j]);
}
System.out.println();
}
}
* C:二维数组累加求和
class ArrayDemo09 {
public static void main(String[] args){
int[][] arr2 = { {1,2},{3,4,5},{6,7,8,9,10} };
int sum2 = 0;
for (int i=0; i<arr2.length; i++) {
for (int j=0; j<arr2[i].length; j++) {
//System.out.println(arr2[i][j])
sum2 += arr2[i][j];
}
}
System.out.println("sum2= "+ sum2);
}
}
23二维数组的求和练习
* A 例如要统计一个公司三个销售小组中每个小组的总销售额以及整个公司的销售额。如下所示
* 第一小组销售额为{11, 12}万元
* 第二小组销售额为{21, 22, 23}万元
* 第三小组销售额为{31, 32, 33, 34}万元。
* B 代码实现
public class ArrayDemo10 {
public static void main(String[] args) {
int[][] arr = new int[3][]; // 定义一个长度为3的二维数组
arr[0] = new int[] { 11, 12 }; // 为数组的元素赋值
arr[1] = new int[] { 21, 22, 23 };
arr[2] = new int[] { 31, 32, 33, 34 };
int sum = 0; // 定义变量记录总销售额
for (int i = 0; i < arr.length; i++) { // 遍历数组元素
int groupSum = 0; // 定义变量记录小组销售总额
for (int j = 0; j < arr[i].length; j++) { // 遍历小组内每个人的销售额
groupSum = groupSum + arr[i][j];
}
sum = sum + groupSum; // 累加小组销售额
System.out.println("第" + (i + 1) + "小组销售额为:" + groupSum + " 万元");
}
System.out.println("总销售额为: " + sum + " 万元");
}
}
24随机点名器案例分析
* A 随机点名器案例分析
* B: 需求
* 随机点名器,即在全班同学中随机的打印出一名同学名字。
* C:分析:
* 1)定义数组存数全班同学
* 2)生成随机数范围0 到 数组长度-1
* 3)根据这个索引找到数组中的同学名称
25随机点名器代码实现
* A: 分析
随机点名器:
1 存储姓名
2. 预览所有人的姓名
3. 随机出一个人的姓名
* B 代码实现
import java.util.Random;
public class CallName{
public static void main(String[] args){
//存储姓名,姓名存储到数组中
//数组存储姓名,姓名的数据类型,String
String[] names = {"张三","李四","王五","李蕾","韩梅梅","小名","老王","小华","约翰逊","爱丽丝"};
//预览: 遍历数组,打印所有姓名
for(int i = 0 ; i < names.length ; i++){
System.out.println(names[i]);
}
System.out.println("=============");
//随机出一个人的名
//利用随机数,生成一个整数,作为索引,到数组中找到对应的元素
Random ran = new Random();
//随机数,范围必须是0-数组的最大索引
int index = ran.nextInt(names.length);//index 就是随机数,作为索引
System.out.println(names[index]);
}
}
25随机点名器代码实现_2
* A 代码优化:
import java.util.Random;
public class CallName{
public static void main(String[] args){
String[] names = {"张三","李四","王五","李蕾","韩梅梅","小名","老王","小华","约翰逊","爱丽丝"};
System.out.println(names[new Random().nextInt(names.length)]);
}
}
01引用数据类型_类
* A: 数据类型
* a: java中的数据类型分为:基本类型和引用类型
* B: 引用类型的分类
* a: Java为我们提供好的类,比如说:Scanner,Random等。
* b: 我们自己创建的类,按照类的定义标准,可以在类中包含多个方法与属性,来供我们使用。
02自定义类的概述
* A: 自定义类的概述
* java代码映射成现实事物的过程就是定义类的过程。
* 举例:
我们就拿一部手机进行分析,它能用来做什么呢?它可以打电话,上网,聊微信等,这些就是手机所提供的功能,也就是方法;手机也有它的特征,如颜色、尺寸大小、品牌型号等,这些就是手机的特征,也就是属性
* 目前,我们只关注类中的属性,类中的方法在面向对象部分再进行学习。
03自定义类的格式
* A: 自定义类的格式
* a: 使用类的形式,对现实中的事物进行描述。
* b: 事物由方法和属性两部分组成。
* 方法: 这个事物具备的功能。
* 属性: 这个事物具备的特征。
* c: 格式
public class 类名{
属性定义
修饰符 数据类型 变量名 = 值
方法定义
修饰符 返回值类型 方法名(参数列表){
}
}
04自定义的手机类
* A: 自定义的手机类
* a: 案例代码
public class Phone{
/*
定义手机的属性
*/
String color ;
String brand ;
double size ;
}
05测试手机类
* A: 调用方法执行流程
* a: 实现引用类型的步骤
* 1: 导入包 , 类都是在同一个文件夹,不需要导入包
* 2: 创建引用类型的变量
* 3: 变量.类型中的功能
* b: 案例代码
public class TestPhone{
public static void main(String[] args){
// 2: 创建引用类型的变量
Phone p = new Phone();
//System.out.println(p); //输出内存的地址
//3: 变量.类型中的功能
//变量 p.的方式,调用类中的属性
//属性就是变量 , 赋值和获取值
p.color = "土豪金";
p.brand = "爱立信";
p.size = 5.0;
//获取属性值
System.out.println(p.color+" "+p.brand+" "+p.size);
}
}
06自定义类的内存图_1
* A: 自定义类的内存图_1
07自定义类的内存图_2
* A: 自定义类的内存图_1
08两个引用类型变量内存图
* A: 自定义类的内存图_1
09自定义类的练习
* A: 实体类的代码
/*
电饭锅,包含属性(品牌、容量大小、颜色等)
定义类,描述事物,电饭锅
属性: 品牌,大小 ,颜色
定义类,类名字,电饭锅
类的范围,定义三个属性
*/
public class DianFanGuo{
//定义三个属性
String brand ;
double size ;
String color ;
}
/*
汽车,包含属性(品牌、排量、类型等)
定义类,类名 Car
属性 品牌 排量 类型
*/
public class Car{
//定义汽车三个属性
String brand ;
double paiLiang ;
String type;
}
/*
学生,包含属性(姓名,年龄,性别等)
定义类,类名Student
三个属性: 姓名,年龄,性别 (char)
*/
public class Student{
String name;
int age ;
char sex ;
}
* B: 测试类的代码
/*
定义的测试类
同时测试,电饭锅,汽车,学生
*/
public class Test{
public static void main(String[] args){
//创建电饭锅引用类型
DianFanGuo dfg = new DianFanGuo();
dfg.brand = "特斯拉";
dfg.color = "红色";
dfg.size = 30;
System.out.println(dfg.brand+" "+dfg.color+" "+dfg.size);
//创建汽车引用类型
Car c = new Car();
c.brand = "巨力";
c.type = "拖拉机";
c.paiLiang = 0.5;
System.out.println(c.brand+" "+c.type+" "+c.paiLiang);
//创建学生引用类型
Student stu = new Student();
stu.name = "张三";
stu.age = 20;
stu.sex = '男';
System.out.println(stu.name+" "+stu.age+" "+stu.sex);
}
}
10ArrayList创建变量的步骤
* A: ArrayList创建变量的步骤
* a: 导入包 java.util包中
* b: 创建引用类型的变量
数据类型< 集合存储的数据类型> 变量名 = new 数据类型<集合存储的数据类型>();
集合存储的数据类型: 要将数据存储到集合的容器中
创建集合引用变量的时候,必须要指定好,存储的类型是什么
* c: 变量名.方法
注意: 集合存储的数据,8个基本类型对应8个引用类型
存储引用类型,不存储基本类型
11ArrayList创建变量举例
* A: ArrayList创建变量的示例代码
import java.util.ArrayList;
public class ArrayListDemo{
public static void main(String[] args){
//创建集合容器,指定存储的数据类型
//存储字符串
ArrayList array = new ArrayList();
//创建集合容器,存储整数
ArrayList array2 = new ArrayList();
//创建集合容器,存储手机类型
ArrayList array3 = new ArrayList();
}
}
12ArrayList的常见方法
* A: ArrayList的常见方法
* a: add(参数) 向集合中添加元素
* b: get(int index) 取出集合中的元素,get方法的参数,写入索引
* c: size() 返回集合的长度, 集合存储元素的个数
* B: 案例代码
import java.util.ArrayList;
public class ArrayListDemo_1{
public static void main(String[] args){
//定义集合,存储字符串元素
ArrayList array = new ArrayList();
//调用集合方法add存储元素
array.add("abc");
array.add("itcast");
array.add("love");
array.add("java");
//输出集合的长度,调用集合方法size, size方法的返回值类型 int
int size = array.size();
System.out.println(size);
//获取出集合中的一个元素,获取1索引的元素
//集合的方法get, 获取元素后结果数据类型
String s = array.get(1);
System.out.println(s);
System.out.println(array.get(0));
System.out.println(array.get(1));
System.out.println(array.get(2));
System.out.println(array.get(3));
}
}
13ArrayList集合的遍历
* A: 案例代码
/*
集合的遍历
实现思想也是索引思想
集合的索引从0开始,到 size()-1
方法get(int index)
*/
import java.util.ArrayList;
public class ArrayListDemo_2{
public static void main(String[] args){
ArrayList array = new ArrayList();
array.add(121);
array.add(125);
array.add(123);
array.add(120);
array.add(128);
//对集合进行遍历
//使用方法 size+get组合进行遍历
for(int i = 0 ; i < array.size(); i++){
System.out.println( array.get(i) );
}
}
}
14ArrayList补充方法
* A: ArrayList补充方法
* a: add(int 索引,存储的元素) 将元素添加到指定的索引上
* b: set(int 索引,修改后的元素) 将指定索引的元素,进行修改
* c: remove(int 索引) 删除指定索引上的元素
* d: clear() 清空集合中的所有元素
* B: 案例代码
import java.util.ArrayList;
public class ArrayListDemo_3{
public static void main(String[] args){
ArrayList array = new ArrayList();
array.add(1);
array.add(2);
array.add(3);
array.add(4);
//在索引2上,添加元素7
array.add(2,7);
//将0索引上的元素,修改成10
array.set(0,10);
//将4索引上的元素,删除
array.remove(4);
array.clear();
//使用方法 size+get组合进行遍历
for(int i = 0 ; i < array.size(); i++){
System.out.println( array.get(i) );
}
}
}
15随机点名器案例分析
* A: 随机点名器案例分析
全班同学中随机的找出一名同学,打印这名同学的个人信息。
我们对本案例进行分析,得出如下分析结果:
1.存储全班同学信息(姓名、年龄)
将容器换成集合,集合中存的是Student类型
2.打印全班同学每一个人的信息(姓名、年龄)
遍历集合
3.在班级总人数范围内,随机产生一个随机数,查找该随机数所对应的同学信息(姓名、年龄)
随机点名器明确地分为了三个功能。如果将多个独立功能的代码写到一起,则代码相对冗长,我们可以针对不同的功能可以将其封装到一个方法中,将完整独立的功能分离出来。
而在存储同学姓名时,如果对每一个同学都定义一个变量进行姓名存储,则会出现过多孤立的变量,很难一次性将全部数据持有。此时,我们采用ArrayList集合来解决多个学生信息的存储问题
16随机点名器代码实现
* A: 随机点名器案例代码
/*
随机点名器,集合改进 (学生的姓名和年龄)
现实中有学生这个事物,使用定义类的形式,描述学生事物
属性: 姓名,年龄
姓名存储了数组, 将容器换成是集合
String[] s = {"",""};
集合中,存储的是学生的姓名吗? 应该存储Student类型
存储学生:
学生类型,存储到集合中
总览: 遍历集合
随机: 随机数,作为索引,到集合中找到元素
三个功能,共享的数据,集合容器,
定义三个方法,必须参数传递集合
*/
import java.util.ArrayList;
import java.util.Random;
public class CallName{
public static void main(String[] args){
//定义集合,存储的是StudentName类型变量
ArrayList array = new ArrayList();
//调用添加方法
add (array);
//调用遍历集合
printArrayList(array);
randomStudentName(array);
}
/*
随机数,当作集合的索引,到集合中找到元素
*/
public static void randomStudentName(ArrayList array ){
Random r = new Random();
int number = r.nextInt( array.size());
//随机数,索引,到集合中get
StudentName s = array.get(number);
System.out.println( s.name +" "+s.age);
}
/*
总览学生的信息,遍历集合
*/
public static void printArrayList(ArrayList array){
for(int i = 0 ; i < array.size();i++){
//存储集合的时候, 集合.add(sn1) sn1 是StudentName类型变量
//获取的时候,集合.get方法,获取出来的是什么, 还是StudentName类型变量
StudentName s = array.get(i);
System.out.println(s.name+" "+s.age);
}
}
/*
定义方法,实现存储学生的姓名和年龄
创建StudentName类型变量,存储到集合中
*/
public static void add (ArrayList array){
//创建StudentName类型变量
StudentName sn1 = new StudentName();
StudentName sn2 = new StudentName();
StudentName sn3 = new StudentName();
StudentName sn4 = new StudentName();
StudentName sn5 = new StudentName();
sn1.name = "张三1";
sn1.age = 201;
sn2.name = "张三2";
sn2.age = 202;
sn3.name = "张三3";
sn3.age = 203;
sn4.name = "张三4";
sn4.age = 204;
sn5.name = "张三5";
sn5.age = 205;
//将StudentName变量,存储到集合中
array.add(sn1);
array.add(sn2);
array.add(sn3);
array.add(sn4);
array.add(sn5);
}
}
17库存案例分析加入集合
* A: 库存案例分析加入集合
18库存案例添加商品信息
* A: 案例代码
/*
定义,.描述商品的类
商品 4个属性
商品名字 大小 价格 库存
String double double int
定义类,类名Goods
这个类型的变量,存储到集合中
*/
public class Goods{
//定义商品名字
String brand ;
//大小属性
double size ;
// 价格属性
double price ;
//库存属性
int count ;
}
/*
实现库存管理案例:
1.存储商品信息
存储商品类型变量
将商品类型的变量,存储到集合中
*/
//import java.util.ArrayList;
import java.util.*;
public class Shopp{
public static void main(String[] args){
//创建ArrayList集合,存储Goods类型
ArrayList array = new ArrayList();
//调用添加商品信息的方法
addGoods(array);
}
/*
定义方法,将商品的信息存储到集合中
集合是所有方法的共享数据,参数传递
*/
public static void addGoods (ArrayList array){
//创建商品类型变量 Goods类型的变量
Goods g1 = new Goods();
Goods g2 = new Goods();
g1.brand = "MacBook";
g1.size = 13.3;
g1.price = 9999.99;
g1.count = 3;
g2.brand = "Thinkpad";
g2.size = 15.6;
g2.price = 7999.99;
g2.count = 1;
//Goods类型的变量,存储到集合中
array.add(g1);
array.add(g2);
}
}
19库存案例查看库存清单
* A: 案例代码
/*
实现库存管理案例:
1.存储商品信息
存储商品类型变量
将商品类型的变量,存储到集合中
2.查看库存清单
将集合进行遍历, 获取出集合中存储的Goods类型变量
输出每一个Goods类型的属性
计算求和: 总库存,总金额
*/
//import java.util.ArrayList;
import java.util.*;
public class Shopp{
public static void main(String[] args){
//创建ArrayList集合,存储Goods类型
ArrayList array = new ArrayList();
//调用添加商品信息的方法
addGoods(array);
}
/*
定义方法,查看库存清单,遍历集合
*/
public static void printStore(ArrayList array){
//输出表头
System.out.println("----------商场库存清单----------");
System.out.println("品牌型号 尺寸 价格 库存数");
//定义变量,保存总库存数,和总金额
int totalCount = 0 ;
double totalMoney = 0;
//遍历集合
for(int i = 0 ; i < array.size(); i++){
//get(索引)获取出集合中的元素,存储的是Goods类,获取的也是Goods类型
//使用Goods类型变量,接受get方法结果
Goods g = array.get(i);
System.out.println(g.brand+" "+g.size+" "+g.price+" "+g.count);
totalCount = totalCount+g.count;
totalMoney = totalMoney + g.count*g.price;
}
System.out.println("总库存数: "+totalCount);
System.out.println("商品库存总金额: "+totalMoney);
}
/*
定义方法,将商品的信息存储到集合中
集合是所有方法的共享数据,参数传递
*/
public static void addGoods (ArrayList array){
//创建商品类型变量 Goods类型的变量
Goods g1 = new Goods();
Goods g2 = new Goods();
g1.brand = "MacBook";
g1.size = 13.3;
g1.price = 9999.99;
g1.count = 3;
g2.brand = "Thinkpad";
g2.size = 15.6;
g2.price = 7999.99;
g2.count = 1;
//Goods类型的变量,存储到集合中
array.add(g1);
array.add(g2);
}
}
20库存案例修改库存清单及测试代码的实现
* A: 案例代码
/*
实现库存管理案例:
1.存储商品信息
存储商品类型变量
将商品类型的变量,存储到集合中
2.查看库存清单
将集合进行遍历, 获取出集合中存储的Goods类型变量
输出每一个Goods类型的属性
计算求和: 总库存,总金额
3.修改商品的库存
集合遍历 ,获取出集合中存储的Goods类型变量
变量调用Goods类的属性count,值进行修改 (键盘输入)
*/
//import java.util.ArrayList;
import java.util.*;
public class Shopp{
public static void main(String[] args){
//创建ArrayList集合,存储Goods类型
ArrayList array = new ArrayList();
//调用添加商品信息的方法
addGoods(array);
//进入死循环中
while(true){
//调用选择功能的方法,获取到用户输入的功能序号
int number = chooseFunction();
//对序号判断,如果=1 进入查看库存功能 = 2 进入修改库存功能 =3 结束
switch(number){
case 1:
//进入查看库存,调用查看库存的方法,传递存储商品信息的集合
printStore(array);
break;
case 2:
//进入修改库存功能,调用修改库存的方法,传递集合
update(array);
break;
case 3:
return ;
default:
System.out.println("无此功能");
break;
}
}
}
/*
方法定义,修改库存
键盘的输入,将Goods中的属性值,修改
*/
public static void update(ArrayList array){
Scanner sc = new Scanner(System.in);
//遍历集合,获取集合中的每个元素
for(int i = 0 ; i < array.size(); i++){
//集合方法get获取的是集合的元素,元素类型Goods
Goods g = array.get(i);
System.out.println("请输入"+g.brand+"的库存数");
//Goods属性,count进行修改
g.count = sc.nextInt();
}
}
/*
定义方法,实现选择菜单,用户根据功能选择菜单
*/
public static int chooseFunction(){
System.out.println("-------------库存管理------------");
System.out.println("1.查看库存清单");
System.out.println("2.修改商品库存数量");
System.out.println("3.退出");
System.out.println("请输入要执行的操作序号:");
Scanner sc = new Scanner(System.in);
int number = sc.nextInt();
return number;
}
/*
定义方法,查看库存清单,遍历集合
*/
public static void printStore(ArrayList array){
//输出表头
System.out.println("----------商场库存清单----------");
System.out.println("品牌型号 尺寸 价格 库存数");
//定义变量,保存总库存数,和总金额
int totalCount = 0 ;
double totalMoney = 0;
//遍历集合
for(int i = 0 ; i < array.size(); i++){
//get(索引)获取出集合中的元素,存储的是Goods类,获取的也是Goods类型
//使用Goods类型变量,接受get方法结果
Goods g = array.get(i);
System.out.println(g.brand+" "+g.size+" "+g.price+" "+g.count);
totalCount = totalCount+g.count;
totalMoney = totalMoney + g.count*g.price;
}
System.out.println("总库存数: "+totalCount);
System.out.println("商品库存总金额: "+totalMoney);
}
/*
定义方法,将商品的信息存储到集合中
集合是所有方法的共享数据,参数传递
*/
public static void addGoods (ArrayList array){
//创建商品类型变量 Goods类型的变量
Goods g1 = new Goods();
Goods g2 = new Goods();
g1.brand = "MacBook";
g1.size = 13.3;
g1.price = 9999.99;
g1.count = 3;
g2.brand = "Thinkpad";
g2.size = 15.6;
g2.price = 7999.99;
g2.count = 1;
//Goods类型的变量,存储到集合中
array.add(g1);
array.add(g2);
}
}
01奇数求和练习
* A: 奇数求和练习
* a: 题目分析
* 为了记录累加和的值,我们需要定义一个存储累加和的变量
* 我们要获取到1-100范围内的数
* 判断当前数是否为奇数,是奇数,完成累加和操作
* 累加完毕后,最终显示下累加和的值
* b: 解题步骤
* 定义一个用来记录累加和的变量
* 使用for循环语句,完成1-100之间每个数的获取
* 使用if条件语句,判断当前数是否是奇数,是奇数,进行累加和操作
* 使用输出语句,打印累加和变量的值
* c: 案例代码
public class Test01 {
public static void main(String[] args) {
int sum = 0;
for (int i = 0; i < 100; i++) {
if (i%2==1) {
sum += i;
}
}
System.out.println("累加和的值 " + sum);
}
}
02水仙花练习功能实现
* A: 水仙花练习功能实现
* a: 题目分析
* 明确什么样的数就是水仙花数。水仙花数是指一个3位数(100-999之间),其每位数字立方之和等于该3位数本身。
如153 = 1*1*1 + 3*3*3 + 5*5*5,即 3位数本身 = 百位数立方 + 十位数立方 + 个位数立方;
* 获取水仙花范围内的所有3位数(100-999之间的每个3位数)
* 判断该3位数是否满足水仙花数,满足,打印该3位数
* b: 解题步骤
* 使用for循环,得到100-999之间的每个3位数
* 获取3位数中百位数字、十位数字、个位数字
* 使用if条件语句,判断该3位数是否满足水仙花数,满足,使用输出语句,打印该3位数
* c: 案例代码
public class Test02 {
public static void main(String[] args) {
for (int i = 100; i < 1000; i++) {
int bai = i/100%10;
int shi = i/10%10;
int ge = i%10;
if (i == bai*bai*bai + shi*shi*shi + ge*ge*ge) {
System.out.println(i);
}
}
}
}
03ASCII编码表
* A: ASCII编码表
* a: 英文全称
* American Standard Code for Information Interchange,美国标准信息交换代码
* b: ASCII编码表由来
* 计算机中,所有的数据在存储和运算时都要使用二进制数表示
* a、b、c、d这样的52个字母(包括大写)、以及0、1等数字还有一些常用的符号, 在计算机中存储时也要使用二进制数来表示
* 具体用哪些二进制数字表示哪个符号,当然每个人都可以约定自己的一套(这就叫编码)
* 大家如果要想互相通信而不造成混乱,那么大家就必须使用相同的编码规则,于是美国有关的标准化组织就出台了ASCII编码,
统一规定了上述常用符号用哪些二进制数来表示。
* c: 中文编码表
* GB2312
* UNICODE
* d: 字符中重要的ASCII码对应关系
* a : 97
* A : 65
* 0 : 48
04char类型的存储
* A: char类型的存储
* a: 取值范围
* short:占两个字节,是有符号数据,取值范围-32768-32767
* char: 占两个字节,是无符号数据,取值范围0-65536
* b: 类型转换
* char类型的数据参加运算时要线程程int数据类型
* c: 案例代码
/*
ASCII编码表演示
字符Java 数据类型,char
整数Java 数据类型,int
int 类型和 char 数据类型转换
char 两个字节, int 四个字节
char转成int类型的时候,类型自动提示,char数据类型,会查询编码表,得到整数
int转成char类型的时候,强制转换,会查询编码表
char存储汉字,查询Unicode编码表
char可以和int计算,提示为int类型, 内存中两个字节
char取值范围是0-65535, 无符号的数据类型
*/
public class ASCIIDemo{
public static void main(String[] args){
char c = 'a';
int i = c + 1;
System.out.println(i);
int j = 90;
char h = (char)j;
System.out.println(h);
System.out.println( (char)6 );
char k = '你';
System.out.println(k);
char m = -1;
}
}
05输出所有英文字母
* A: 输出所有英文字母
* a: 题目分析
* 一共26个大小写字母,那么,可以考虑循环26次。在每次循环中,完成指定字母的大小写打印
* 找出ABCDEFG…XYZ这些字母之间的变化规律
通过ASCII表发现,后面的字母比它前面的字母,ASCII值大1
下一个字母 = 上一个字母 + 1
如: A B C D
65 66 67 68
* 在每次循环中打印上一个字母大小写,并指定下一个字母
* b: 解题步骤
* 定义初始化大写变量,值为’A’; 初始化小写变量,值为’a’
* 使用for循环,进行26次循环
* 在每次循环中,打印大写字母、小写字母。
每次打印完成后,更新大写字母值、小写字母值
* c: 案例代码
public class Test04 {
public static void main(String[] args) {
char da = 'A';
char xiao = 'a';
for (int i = 0; i < 26; i++) {
System.out.println("大写字母 "+da+" ,小写字母 "+xiao);
da++; //更新大写字母值
xiao++; //更新小写字母值
}
}
}
0699乘法表的分析
* A: 99乘法表的分析
* a: 打印格式
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
* b: 题目分析
通过观察发现,如果把1*1=1这样的内容 看做一颗*的话,那么打印结果就成了如下效果:
*
**
***
****
…
这样,就是打印9行星,每行打印星的个数与当前行数相等。
再观察“1*3=3 2*3=6 3*3=9”得出它们如下的变化规律:
每行第n次 +"*"+ 行号 +"="+ 每行第n次 * 行号
如: 1 +"*"+ 2 +"="+ 1*2; // 相当于1*2=2
2 +"*"+ 2 +"="+ 2*2; // 相当于2*2=4
* c: 解题步骤
* 定义一个外层for循环,初始值从1开始,循环9次。用来控制打印的行数
* 在外层for循环内部,定义一个for循环,初始值从1开始,循环次数与当前行数相等。用来完成每行打印指定次数的乘法公式 如1*1=1
* 在内层for循环中,完成每行指定次数的乘法公式打印 如1*1=1
System.out.print(k +"*"+ j +"="+ j*k +"\t");
// 变量k代表:每行中的第n次
// 变量j代表:行号
* 在外循环中,当每行指定次数的乘法公式打印完毕后,通过System.out.println()切换到下一行。
这样,再次打印乘法公式时,就在下一行输出打印了
0799乘法表的功能实现
* A: 99乘法表的功能实现
* a: 案例代码
/*
利用嵌套for循环,实现99乘法表示
实现步骤:
1. 定义外循环控制行数
2. 内循环控制个数,个数,每次都在递增
3. 循环中输出,乘法表的格式 1*3=3
*/
public class Test05 {
public static void main(String[] args) {
for (int j = 1; j < 10; j++) {
for (int k = 1; k <= j; k++) {
System.out.print(k +"*"+ j +"="+ j*k +"\t");
}
System.out.println();
}
}
}
08实现数组的遍历
* A: 实现数组的遍历
* a: 题目分析
* 通过循环,我们可以完成数组中元素的获取,数组名[索引]
* 观察发现,每个数组元素之间加入了一个逗号”,”进行分隔;并且,整个数组的前后有一对中括号”[]”包裹数组所有元素。
* b: 解题步骤
* 使用输出语句完成打印 左边的中括号”[”
* 使用循环,输出数组元素值。输出元素值分为两种情况,如下:
* 最后一个数组元素,加上一个右边的中括号”]”
* 非最后一个数组元素,加上一个逗号”,”
* c: 案例代码
/*
定义方法,实现数组的遍历
遍历中,输出结果 [11,33,565,66,78,89]
int[] arr = {3,4,45,7};
结果包含字符串, [ ] ,
实现步骤:
1. 定义方法实现数组的遍历
2. 先打印[ 中括号
3. 遍历数组
输出数组的元素和逗号
判断是否遍历到了数组的最后一个元素,如果是最后一个元素,输出]中括号
*/
public class ArrayMethodTest{
public static void main(String[] args){
int[] arr = {11,44,55,33,66};
printArray(arr);
int[] arr2 = {22,88,99,33,66};
printArray(arr2);
}
/*
定义方法,实现功能
返回值: void
方法参数: 数组
*/
public static void printArray(int[] arr){
//输出一半中括号,不要换行打印
System.out.print("[");
//数组进行遍历
for(int i = 0 ; i < arr.length ; i++){
//判断遍历到的元素,是不是数组的最后一个元素
//如何判断 循环变量 到达 length-1
if( i == arr.length-1 ){
//输出数组的元素和]
System.out.print(arr[i]+"]");
}else{
//不是数组的最后一个元素,输出数组元素和逗号
System.out.print(arr[i]+",");
}
}
System.out.println();
}
}
09数组逆序原理
* A: 数组逆序原理
* a: 题目分析(图解见day07_source/数组的逆序原理.JPG)
* 通过观察发现,本题目要实现原数组元素倒序存放操作。即原数组存储元素为{11,22,33,44},
逆序后为原数组存储元素变为{44,33,22,11}。
* 通过图解发现,想完成数组元素逆序,其实就是把数组中索引为start与end的元素进行互换。
* 每次互换后,start索引位置后移,end索引位置前移,再进行互换
* 直到start位置超越了end位置,互换结束,此时,数组元素逆序完成。
* b: 解题步骤
* 定义两个索引变量start值为0,变量end值为数组长度减去1(即数组最后一个元素索引)
* 使用循环,完成数组索引start位置元素与end位置元素值互换。
* 在循环换过程中,每次互换结束后,start位置后移1,end位置前移1
* 在循环换过程中,最先判断start位置是否超越了end位置,若已超越,则跳出循环
10数组逆序功能实现
* A:案例代码
/*
数组的逆序:
数组中的元素,进行位置上的交换
逆序 不等于 反向遍历
就是数组中最远的两个索引,进行位置交换,实现数组的逆序
使用的是数组的指针思想,就是变量,思想,可以随时变换索引
反转 reverse
实现步骤:
1. 定义方法,实现数组的逆序
2. 遍历数组
实现数组的最远索引换位置
使用临时的第三方变量
*/
public class ArrayMethodTest_1{
public static void main(String[] args){
int[] arr = {3,5,7,1,0,9,-2};
//调用数组的逆序方法
reverse(arr);
//看到数组的元素,遍历
printArray(arr);
}
/*
定义方法,实现数组的逆序
返回值: 没有返回值
参数: 数组就是参数
*/
public static void reverse(int[] arr){
//利用循环,实现数组遍历,遍历过程中,最远端换位
//for的第一项,定义2个变量, 最后,两个变量++ --
for( int min = 0 , max = arr.length-1 ; min < max ; min++,max--){
//对数组中的元素,进行位置交换
//min索引和max索引的元素交换
//定义变量,保存min索引
int temp = arr[min];
//max索引上的元素,赋值给min索引
arr[min] = arr[max];
//临时变量,保存的数据,赋值到max索引上
arr[max] = temp;
}
}
}
11选择排序原理
* A: 选择排序原理
* a: 题目分析(图解见day07_source/选择排序原理.JPG)
* 通过观察发现,本题目要实现把数组元素{13,46,22,65,3}进行排序
* 提到数组排序,就要进行元素值大小的比较,通过上图发现,我们想完成排序要经过若干次的比较才能够完成。
* 上图中用每圈要比较的第一个元素与该元素后面的数组元素依次比较到数组的最后一个元素,把小的值放在第一个数组元素中,数组循环一圈后,则把最小元素值互换到了第一个元素中。
* 数组再循环一圈后,把第二小的元素值互换到了第二个元素中。按照这种方式,数组循环多圈以后,就完成了数组元素的排序。这种排序方式我们称为选择排序。
* b: 解题步骤
* 使用for循环(外层循环),指定数组要循环的圈数(通过图解可知,数组循环的圈数为数组长度 - 1)
* 在每一圈中,通过for循环(内层循环)完成数组要比较的第一个元素与该元素后面的数组元素依次比较到数组的最后一个元素,把小的值放在第一个数组元素中
* 在每一圈中,要参与比较的第一个元素由第几圈循环来决定。如上图所示
* 进行第一圈元素比较时,要比较的第一个元素为数组第一个元素,即索引为0的元素
* 进行第二圈元素比较时,要比较的第一个元素为数组第二个元素,即索引为1的元素
* 依次类推,得出结论:进行第n圈元素比较时,要比较的第一个元素为数组第n个元素,即数组索引为n-1的元素
12选择排序功能实现
* A: 案例代码
/*
数组的排序: 一般都是升序排列,元素,小到大的排列
两种排序的方式
选择排序: 数组的每个元素都进行比较
冒泡排序: 数组中相邻元素进行比较
规则: 比较大小,位置交换
*/
public class ArrayMethodTest_2{
public static void main(String[] args){
int[] arr = {3,1,4,2,56,7,0};
//调用选择排序方法
//selectSort(arr);
printArray(arr);
}
/*
定义方法,实现数组的选择排序
返回值: 没有
参数: 数组
实现步骤:
1.嵌套循环实现排序
外循环,控制的是一共比较了多少次
内循环,控制的是每次比较了多少个元素
2. 判断元素的大小值
小值,存储到小的索引
*/
public static void selectSort(int[] arr){
for(int i = 0 ; i < arr.length - 1; i++){
//内循环,是每次都在减少,修改变量的定义
for(int j = i+1 ; j < arr.length ; j++){
//数组的元素进行判断
if(arr[i] > arr[j]){
//数组的换位
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
}
/*
定义方法,实现功能
返回值: void
方法参数: 数组
*/
public static void printArray(int[] arr){
//输出一半中括号,不要换行打印
System.out.print("[");
//数组进行遍历
for(int i = 0 ; i < arr.length ; i++){
//判断遍历到的元素,是不是数组的最后一个元素
//如何判断 循环变量 到达 length-1
if( i == arr.length-1 ){
//输出数组的元素和]
System.out.print(arr[i]+"]");
}else{
//不是数组的最后一个元素,输出数组元素和逗号
System.out.print(arr[i]+",");
}
}
System.out.println();
}
}
13冒泡排序功能实现
* A: 冒泡排序功能实现
* a: 题目分析
* 通过观察发现,本题目要实现把数组元素{13,46,22,65,3}进行排序
* 提到数组排序,就要进行元素值大小的比较,通过上图发现,我们想完成排序要经过若干次的比较才能够完成。
* 上图中相邻的元素值依次比较,把大的值放后面的元素中,数组循环一圈后,则把最大元素值互换到了最后一个元素中。
数组再循环一圈后,把第二大的元素值互换到了倒数第二个元素中。按照这种方式,数组循环多圈以后,
就完成了数组元素的排序。这种排序方式我们称为冒泡排序。
* b: 解题步骤
* 使用for循环(外层循环),指定数组要循环的圈数(通过图解可知,数组循环的圈数为数组长度 - 1)
* 在每一圈中,通过for循环(内层循环)完成相邻的元素值依次比较,把大的值放后面的元素中
* 每圈内层循环的次数,由第几圈循环来决定。如上图所示
* 进行第一圈元素比较时,内层循环次数为数组长度 - 1
* 进行第二圈元素比较时,内层循环次数为数组长度 - 2
* 依次类推,得出结论:进行第n圈元素比较时,内层循环次数为数组长度 - n
* c: 案例代码
/*
数组的排序: 一般都是升序排列,元素,小到大的排列
两种排序的方式
选择排序: 数组的每个元素都进行比较
冒泡排序: 数组中相邻元素进行比较
规则: 比较大小,位置交换
*/
public class ArrayMethodTest_2{
public static void main(String[] args){
int[] arr = {3,1,4,2,56,7,0};
//调用选择排序方法
//selectSort(arr);
//调用冒泡排序方法
bubbleSort(arr);
printArray(arr);
}
/*
定义方法,实现数组的冒泡排序
返回值: 没有
参数: 数组
*/
public static void bubbleSort(int[] arr){
for(int i = 0 ; i < arr.length - 1; i++){
//每次内循环的比较,从0索引开始, 每次都在递减
for(int j = 0 ; j < arr.length-i-1; j++){
//比较的索引,是j和j+1
if(arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
/*
定义方法,实现功能
返回值: void
方法参数: 数组
*/
public static void printArray(int[] arr){
//输出一半中括号,不要换行打印
System.out.print("[");
//数组进行遍历
for(int i = 0 ; i < arr.length ; i++){
//判断遍历到的元素,是不是数组的最后一个元素
//如何判断 循环变量 到达 length-1
if( i == arr.length-1 ){
//输出数组的元素和]
System.out.print(arr[i]+"]");
}else{
//不是数组的最后一个元素,输出数组元素和逗号
System.out.print(arr[i]+",");
}
}
System.out.println();
}
}
14数组的折半查找原理
* A: 数组的折半查找原理(图解见day07_source/折半查找原理.JPG)
* a: 题目分析
* 通过观察发现,本题目要实现查找指定数值在元素有序的数组中存储的位置(索引),返回该位置(索引)。
* 我们使用数组最中间位置的元素值与要查找的指定数值进行比较,若相等,返回中间元素值的索引
* 最中间位置的元素值与要查找的指定数值进行比较,若不相等,则根据比较的结果,缩小查询范围为上次数组查询范围的一半;
再根据新的查询范围,更新最中间元素位置,然后使用中间元素值与要查找的指定数值进行比较
比较结果相等,返回中间元素值的索引
比较结果不相等,继续缩小查询范围为上次数组查询范围的一半,更新最中间元素位置,继续比较,依次类推。
* 当查询范围缩小到小于0个元素时,则指定数值没有查询到,返回索引值-1。
* b: 解题步骤
* 定义3个用来记录索引值的变量,变量min记录当前范围最小索引值,初始值为0;变量max记录当前范围最大索引值,初始值为数组长度-1;变量mid记录当前当前范围最中间元素的索引值,初始值为(min+max) / 2
* 使用循环,判断当前范围下,最中间元素值与指定查找的数值是否相等
若相等,结束循环,返回当前范围最中间元素的索引值mid
若不相等,根据比较结果,缩小查询范围为上一次查询范围的一般
中间元素值 比 要查询的数值大,说明要查询的数值在当前范围的最小索引位置与中间索引位置之间,此时,更新查询范围为:
范围最大索引值 = 上一次中间索引位置 -1;
中间元素值 比 要查询的数值小,说明要查询的数值在当前范围的最大索引位置与中间索引位置之间,此时,更新查询范围为:
范围最小索引值 = 上一次中间索引位置 +1;
在新的查询范围中,更新中间元素值的位置,再次使用最中间元素值与指定查找的数值是否相等。
中间索引值 = (范围最小索引值 +范围最大索引值) / 2;
* 每次查询范围缩小一半后,使用if语句判断,查询范围是否小于0个元素,若小于0个元素,则说明指定数值没有查询到,返回索引值-1。
15数组的折半查找代码实现
* A: 案例代码
/*
数组的查找功能
在一个数组中,找一个元素,是否存在于数组中,如果存在,就返回索引
普通查询:
找到元素在数组中出现的索引,如果没有这个 元素,结果就是负数
*/
public class ArrayMethodTest_3{
public static void main(String[] args){
int[] arr = {1,3,5,7,9,11,15};
int index = binarySearch(arr,10);
System.out.println(index);
}
/*
定义方法,实现,折半查找
返回值: 索引
参数: 数组,被找的元素
实现步骤:
1. 需要的变量定义
三个,三个指针
2. 进行循环折半
可以折半的条件 min <= max
3. 让被找元素,和中间索引元素进行比较
元素 > 中间索引 小指针= 中间+1
元素 < 中间索引 大指针= 中间-1
元素 == 中间索引 找到了,结束了,返回中间索引
4. 循环结束,无法折半
元素没有找到 ,返回-1
*/
public static int binarySearch(int[] arr, int key){
//定义三个指针变量
int min = 0 ;
int max = arr.length -1 ;
int mid = 0;
//循环折半,条件 min<=max
while( min <= max){
//公式,计算中间索引
mid = (min+max)/2;
//让被找元素,和中间索引元素进行比较
if(key > arr[mid]){
min = mid + 1;
}else if (key < arr[mid]){
max = mid - 1;
}else{
//找到元素,返回元素索引
return mid;
}
}
return -1;
}
/*
定义方法,实现数组的普通查询
返回值: 索引
参数: 数组, 被找的元素
实现步骤:
1. 遍历数组
2. 遍历过程中,使用元素和数组中的元素进行比较
如果相同,返回元素在数组中的索引
如果不同,返回负数
*/
public static int search(int[] arr, int key){
//遍历数组
for(int i = 0 ; i < arr.length ; i++){
//数组元素,被查找的元素比较
if(arr[i] == key){
//返回索引
return i;
}
}
return -1;
}
}
01Eclipse的下载安装
* A: Eclipse的下载安装
* B: Eclipse的特点
* a: 免费
* b: 纯Java语言编写
* c: 免安装
* d: 扩展性强
02Eclipse的工作空间和新建工程
* A: Eclipse的工作空间和新建工程
* a: 工作空间
* 其实就是我们写的源代码所在的目录
* b: 创建工程(项目)
* 右键/Package Explore 空白区/new /Java Project/输入项目名称如day08/
* c: 创建包(后面讲包的概念)
* 打开上面建立的day08项目/右键/new/package/在弹出的对话框的name中输入报名如"com.itheima.tests"/finish
* d: 创建类
* 创建一个java类:右击包名/new/class/在对话框的name中输入类名/finish
* B: 编译与执行
* a: 编译
* 自动编译,当java代码保存的时候,自动 编译class文件
* b: 运行
* 方式1:点击菜单工具栏中的 绿色带有三角形的 run按钮 运行
* 方式2:点击菜单栏中Run, 点击Run 运行 快捷键是 ctrl+F11
* 方式3:选中要运行的java文件,或者在编写代码的空白区域,右键选择 Run As --> 运行java程序
03Eclipse的HelloWorld编写
* A:HelloWorld编写
* a: 编写过程(参照上个知识点)
* 建立day08项目
* 建立包结构(包的概念还没有学到,不建立包的话,使用默认包结构default)
* 创建HelloWorld类(自动生成main方法)
* b: 案例代码
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
04Eclipse的字体设置
* A: Eclipse的字体设置
* a: 修改编译环境和运行环境
* 编译环境:Window -- Preferences – Java - Compiler
* 运行环境:Window -- Preferences – Java - Installed JREs
* b: 显示行号与隐藏行号
* 显示:在代码区域的左边空白区域,右键 -- Show Line Numbers
* 隐藏:将上面的操作再做一遍
* c: 更改字体大小与颜色
* Java代码区域的字体大小和颜色:
* window -- Preferences -- General -- Appearance -- Colors And Fonts --Java修改 -- Java Edit Text Font--edit进行修改
* 控制台
* window -- Preferences -- General -- Appearance -- Colors And Fonts -- Debug -- Console font
* 其他文件
* window -- Preferences -- General -- Appearance -- Colors And Fonts -- Basic -- Text Font
05Eclipse的窗口设置
* A: 窗口设置
* a: 显示的窗口乱了,还原默认显示模式
* Window – Perspective -- Reset Prespective
* b: 显示控制台
* Window--Show View—Console
06Eclipse的去掉多余的注释
* A: Eclipse的去掉多余的注释
* a:如何去掉默认注释
* Window -- Preferences -- Java -- Code Style -- Code Templates -- Comments – Methods,点击Edit ,将注释部分删除 (不建议删除)
* Window -- Preferences -- Java -- Code Style -- Code Templates -- Code -- Method body,点击Edit ,将注释部分删除
* b: 切换工作空间
* File – Switch Workspace – 指定工作空间 – ok
07Eclipse的快捷键
* A: Eclipse的快捷键
* a: 内容辅助键 Alt+/
* 自动补齐main方法 main 然后 Alt+/
* 自动补齐输出语句 syso 然后 Alt+/
* b: 格式化代码
* Ctrl+Shift+f
* 代码区域右键 -- Source – Format
* c: 自动导包
* Ctrl+Shift+o
* 如果当前类在多个包中都存在,这时候,使用Ctrl+shift+o,进行选择一个包导入即可。
* d: 注释
* 单行注释
* 加注释: 先选中需要注释的内容,然后 Ctrl+/
* 取消注释:先选中需要取消注释的内容, 然后 Ctrl+/
* 多行注释
* 加注释: 先选中需要注释的内容,然后 Ctrl+Shift+/
* 取消注释:先选中需要取消注释的内容, 然后 Ctrl+Shift+\
* e: 补充
* 代码上下移动
* 选中代码alt+上/下箭头
* 查看源码
* 选中类名(F3或者Ctrl+鼠标点击)
* 查找具体的类
* ctrl + shift + t,输入要查找的类的名称-->确定
* 查找具体类的具体方法
* ctrl + o
* 给建议
* ctrl+1,根据右边生成左边的数据类型,生成方法
* 删除代码
* ctrl + d
* 抽取方法
* alt + shift + m
* 改名
* alt + shift + r(类名,方法名,变量名)
08Eclipse的断点调试
* A:断点调试(又称为Debug调试)的作用
* 调试程序
* 查看程序执行流程
* B:如何查看程序执行流程
* 什么是断点:
* 就是一个标记,从哪里开始。
* 如何设置断点:
* 你想看哪里的程序,你就在那个有效程序的左边双击即可。
* 在哪里设置断点:
* 哪里不会点哪里。
* 目前:我们就在每个方法的第一条有效语句上都加。
* 如何运行设置断点后的程序:
* 右键 -- Debug as -- Java Application
* 看哪些地方:
* Debug:断点测试的地方
* 在这个地方,记住F6,或者点击也可以。一次看一行的执行过程。
* Variables:查看程序的变量变化
* ForDemo:被查看的源文件
* Console:控制台
* 如何去断点:
* a:再次双击即可
* b:找到Debug视图,Variables界面,找到Breakpoints,并点击,然后看到所有的断点,最后点击那个双叉
09Eclipse的工程删除和导入
* A:删除项目
* 选中项目 – 右键 – 删除
* 从项目区域中删除
* 从硬盘上删除
* B:导入项目
* 在项目区域右键找到import
* 找到General,展开,并找到
* Existing Projects into Workspace
* 点击next,然后选择你要导入的项目
* 注意:这里选择的是项目名称
10超市管理系统功能介绍
* A:超市管理系统功能介绍
* a: 显示主菜单
============欢迎光临ItCast超市============
1: 货物 清单 2: 添加货物 3: 删除货物 4: 修改货物 5: 退出
请您输入要操作的功能序号
* b: 货物清单
输入1:货物清单
================商品库存清单================
商品编号 商品名称 商品单价
9527 少林寺酥饼核桃 12.7
9008 尚康杂粮牡丹饼 5.6
9879 新疆原产哈密瓜 599.6
* c: 添加新货物
输入2:添加新货物
请输入新商品的编号:9523
请输入新商品的名字:斯柯达苹果醋
请输入新商品的单价:19.9
商品添加成功
* d: 删除货物
输入3:删除货物
选择的是删除功能
请输入商品的编号:9523
货物信息删除完毕
* e: 修改货物
输入4:修改货物
选择的是修改功能
请输入您要修改的商品的编号:9527
输入新的商品编号:100
输入新的商品名字:味道好凤梨干
输入新的商品价格:6.5
商品修改成功
* f: 输入5:退出系统
11超市管理系统案例分析
* A: 超市管理系统案例分析
* 完成超市商品初始化。创建商品,将商品添加到集合
* 显示来到超市能做的操作,也就是显示主菜单
* 根据接收到的功能选项,执行对应的功能
* 库存货物查询
* 添加新货物
* 删除货物
* 修改货物
* 退出系统,结束main方法的运行
* 循环,回到 2.显示主菜单
12自定义商品类
* A: 自定义商品类
* a: 目的
* 每种库存商品都拥有多项商品信息,为了方便管理每种商品的信息,我们对商品信息进行封装,编写FruitItem.java文件
* b:案例代码
public class FruitItem {
int ID; //商品编号
String name; //商品名称
double price; //商品单价
double number; //商品数量
double money; //商品金额
}
* 补充
* 上述代码中,对商品信息(编号、名称、单价、数量、金额)进行了封装。这样做的好处在于以后只要找到这个商品,就能够知道该商品的每项信息了。
13初始化商品属性
* A: 初始化商品属性
* a: 案例代码
import java.util.ArrayList;
import java.util.Scanner;
/*
* 超市管理系统主
* 实现:
* 1. 商品数据的初始化
* 2. 用户的菜单选择
* 3. 根据选择执行不同的功能
* 3.1 Read 查看商品
* 3.2 Create 添加商品
* 3.3 Delete 删除商品
* 3.4 Update 修改商品
*
*
* 所有功能 ,必须定义方法实现
* 主方法main 调用作用
*/
public class Shopp {
public static void main(String[] args) {
//创建ArrayList集合,存储商品类型,存储数据类型FruitItem类型
ArrayList array = new ArrayList();
//调用商品初始化方法,传递集合
init(array);
}
}
/*
* 定义方法,实现商品数据的初始化
* 先将一部分数据,存储集合中
* 返回值: 无
* 参数 : 集合
* 方法名: init
*/
public static void init(ArrayList array){
//创建出多个FruitItem类型,并且属性赋值
FruitItem f1 = new FruitItem();
f1.ID = 9527;
f1.name = "少林寺酥饼核桃";
f1.price = 12.7;
FruitItem f2 = new FruitItem();
f2.ID = 9008;
f2.name = "尚康杂粮牡丹饼";
f2.price = 5.6;
FruitItem f3 = new FruitItem();
f3.ID = 9879;
f3.name = "新疆原产哈密瓜";
f3.price = 599.6;
//创建的3个FruitItem类型变量,存储到集合中
array.add(f1);
array.add(f2);
array.add(f3);
}
}
14主菜单功能
* A: 主菜单功能
* a: 案例代码
import java.util.ArrayList;
import java.util.Scanner;
/*
* 超市管理系统主
* 实现:
* 1. 商品数据的初始化
* 2. 用户的菜单选择
* 3. 根据选择执行不同的功能
* 3.1 Read 查看商品
* 3.2 Create 添加商品
* 3.3 Delete 删除商品
* 3.4 Update 修改商品
*
*
* 所有功能 ,必须定义方法实现
* 主方法main 调用作用
*/
public class Shopp {
public static void main(String[] args) {
//创建ArrayList集合,存储商品类型,存储数据类型FruitItem类型
ArrayList array = new ArrayList();
//调用商品初始化方法,传递集合
init(array);
while(true){
//调用菜单方法
mainMenu();
}
}
/*
* 定义方法,实现主菜单
* 提示用户哪些选择 让选择序号
* 返回值: 无
* 参数: 无
*/
public static void mainMenu(){
System.out.println();
System.out.println("============欢迎光临ItCast超市============");
System.out.println("1: 货物 清单 2: 添加货物 3: 删除货物 4: 修改货物 5: 退出");
System.out.println("请您输入要操作的功能序号");
}
/*
* 定义方法,实现商品数据的初始化
* 先将一部分数据,存储集合中
* 返回值: 无
* 参数 : 集合
* 方法名: init
*/
public static void init(ArrayList array){
//创建出多个FruitItem类型,并且属性赋值
FruitItem f1 = new FruitItem();
f1.ID = 9527;
f1.name = "少林寺酥饼核桃";
f1.price = 12.7;
FruitItem f2 = new FruitItem();
f2.ID = 9008;
f2.name = "尚康杂粮牡丹饼";
f2.price = 5.6;
FruitItem f3 = new FruitItem();
f3.ID = 9879;
f3.name = "新疆原产哈密瓜";
f3.price = 599.6;
//创建的3个FruitItem类型变量,存储到集合中
array.add(f1);
array.add(f2);
array.add(f3);
}
}
15用户选择功能
* A: 用户选择功能
* a: 案例代码
import java.util.ArrayList;
import java.util.Scanner;
/*
* 超市管理系统主
* 实现:
* 1. 商品数据的初始化
* 2. 用户的菜单选择
* 3. 根据选择执行不同的功能
* 3.1 Read 查看商品
* 3.2 Create 添加商品
* 3.3 Delete 删除商品
* 3.4 Update 修改商品
*
*
* 所有功能 ,必须定义方法实现
* 主方法main 调用作用
*/
public class Shopp {
public static void main(String[] args) {
//创建ArrayList集合,存储商品类型,存储数据类型FruitItem类型
ArrayList array = new ArrayList();
//调用商品初始化方法,传递集合
init(array);
while(true){
//调用菜单方法
mainMenu();
//调用用户选择序号方法
int choose = chooseFunction();
switch (choose) {
case 1:
//调用1: 货物 清单
showFruitList(array);
break;
case 2:
//2: 添加货物
addFruit(array);
break;
case 3:
//3: 删除货物
deleteFruit(array);
break;
case 4:
//4: 修改货物
updateFruit(array);
break;
case 5:
return ;
default:
System.out.println("输入的序号没有");
break;
}
}
}
/*
* 定义方法,实现接受用户的键盘输入
* 返回编号
*/
public static int chooseFunction(){
Scanner sc = new Scanner(System.in);
return sc.nextInt();
}
/*
* 定义方法,实现主菜单
* 提示用户哪些选择 让选择序号
* 返回值: 无
* 参数: 无
*/
public static void mainMenu(){
System.out.println();
System.out.println("============欢迎光临ItCast超市============");
System.out.println("1: 货物 清单 2: 添加货物 3: 删除货物 4: 修改货物 5: 退出");
System.out.println("请您输入要操作的功能序号");
}
/*
* 定义方法,实现商品数据的初始化
* 先将一部分数据,存储集合中
* 返回值: 无
* 参数 : 集合
* 方法名: init
*/
public static void init(ArrayList array){
//创建出多个FruitItem类型,并且属性赋值
FruitItem f1 = new FruitItem();
f1.ID = 9527;
f1.name = "少林寺酥饼核桃";
f1.price = 12.7;
FruitItem f2 = new FruitItem();
f2.ID = 9008;
f2.name = "尚康杂粮牡丹饼";
f2.price = 5.6;
FruitItem f3 = new FruitItem();
f3.ID = 9879;
f3.name = "新疆原产哈密瓜";
f3.price = 599.6;
//创建的3个FruitItem类型变量,存储到集合中
array.add(f1);
array.add(f2);
array.add(f3);
}
}
16商品的清单功能
* A: 商品的清单功能
* a: 案例代码(显示商品清单的showFruitList(ArrayList)方法的代码如下)
/*
* 定义方法,实现显示货物清单功能
* 返回值: 无
* 参数: 集合
* 遍历集合,获取集合中的每个FruitItem变量,变量,调用属性
*/
public static void showFruitList(ArrayList array){
System.out.println();
System.out.println("================商品库存清单================");
System.out.println("商品编号 商品名称 商品单价");
//遍历集合
for(int i = 0 ; i < array.size(); i++){
//集合get方法,获取出每个FruitItem变量,可以使用FruitItem接受get结果
FruitItem item = array.get(i);
//变量item调用类中属性
System.out.println(item.ID+" "+item.name+" "+item.price);
}
}
17商品的添加功能
* A: 商品的添加功能
* a: 案例代码(商品添加功能的addFruit(ArrayList)方法的代码如下)
/*
* 定义方法,实现商品的添加功能
* 返回值:无
* 参数: 集合
* 提示用户选择的是添加商品的功能
*
* 提示用户输入的是什么
*
* 创建FruitItem变量,变量调用的属性
* 将输入的每个商品属性进行赋值
*/
public static void addFruit(ArrayList array){
System.out.println("选择的是添加商品功能");
//创建Scanner变量
Scanner sc = new Scanner(System.in);
System.out.print("请输入新商品的编号:");
//输入商品的编号
int ID = sc.nextInt();
//输入商品的名字
System.out.print("请输入新商品的名字:");
String name = sc.next();
//输入商品的单价
System.out.print("请输入新商品的单价:");
double price = sc.nextDouble();
//创建FruitItem变量
FruitItem item = new FruitItem();
//item.属性赋值
item.ID = ID;
item.name = name;
item.price = price;
array.add(item);
System.out.println("商品添加成功");
}
18商品的删除功能
* A: 商品的删除功能(删除商品deleteFruit(ArrayList)方法的代码如下)
* a: 案例代码
/*
* 定义方法,实现商品的删除功能
* 返回值: 无
* 参数: 集合
*
* 删除依靠的是商品的编号
* 提示用户选择的是删除功能
* 键盘输入商品的编号
* 遍历集合,获取集合中的每个FruitItem变量
* 变量调用属性 ID, 和用户的输入的编号,对比,相同就删除
*/
public static void deleteFruit(ArrayList array){
System.out.println("选择的是删除功能");
System.out.print("请输入商品的编号:");
Scanner sc = new Scanner(System.in);
int ID = sc.nextInt();
//遍历集合
for(int i = 0 ; i < array.size(); i++){
//获取到每个FruitItem变量
FruitItem item = array.get(i);
//变量,调用属性ID,和用户输入的编号比较
if( item.ID == ID){
//移除集合中的元素
//集合的方法remove实现
array.remove(i);
System.out.println("删除成功");
return;
}
}
System.out.println("你输入的编号不存在");
}
19商品的修改功能
* A: 商品的修改功能
* a: 案例代码(修改商品updateFruit(ArrayList)方法的代码如下)
/*
* 定义方法,实现商品的修改功能
* 返回值: 无
* 参数: 集合
*
* 提示用户选择的是修改功能
* 提示用户输入需要修改的商品编号
* 遍历集合,获取每个FruitItem变量
* 变量调用ID属性,属性和用户输入的编号比较
* 如果相同:
* 修改调FruitItem中的属性值
* 键盘输入
*/
public static void updateFruit(ArrayList array){
System.out.println("选择的是修改功能");
System.out.print("请输入您要修改的商品的编号:");
Scanner sc = new Scanner(System.in);
int ID = sc.nextInt();
//遍历集合,获取每个FruitItem变量
for(int i = 0 ; i < array.size(); i++){
FruitItem item = array.get(i);
//获取FruitItem的属性ID,和用户输入的ID比较
if(item.ID == ID){
System.out.print("输入新的商品编号:");
item.ID = sc.nextInt();
System.out.print("输入新的商品名字:");
item.name = sc.next();
System.out.print("输入新的商品价格:");
item.price = sc.nextDouble();
System.out.println("商品修改成功");
return ;
}
}
System.out.println("输入的编号不存在");
}
01面向对象和面向过程的思想
* A: 面向过程与面向对象都是我们编程中,编写程序的一种思维方式
* a: 面向过程的程序设计方式,是遇到一件事时,思考“我该怎么做”,然后一步步实现的过程。
* b: 面向对象的程序设计方式,是遇到一件事时,思考“我该让谁来做”,然后那个“谁”就是对象,他要怎么做这件事是他自己的事,反正最后一群对象合力能把事就好就行了。
02面向对象的思想的生活案例
* A: 买电脑(组装机)
* a: 面向过程:自己该怎么做
* b: 面向对象:找人帮我们做
03面向对象好处
* A: 面向对象好处
* a: 面向对象思维方式是一种更符合人们思考习惯的思想
* b: 面向过程思维方式中更多的体现的是执行者(自己做事情),面向对象中更多的体现是指挥者(指挥对象做事情)。
* c: 面向对象思维方式将复杂的问题简单化。
04大象装进冰箱的代码案例
* A: 需求:把大象装冰箱里
* a: 面向过程
* 自己打开冰箱门
* 自己将大象装进去
* 自己关闭冰箱门
* b: 面向对象
* 分析发现打开、装、关闭都是冰箱的功能。即冰箱对象具 备如下功能
* 冰箱打开
* 冰箱存储
* 冰箱关闭
* B: 通过伪代码描述大象和冰箱
* 描述大象:
class 大象
{
}
* 描述冰箱
class冰箱
{
void 打开(){}
void 存储(大象){}
void 关闭(){}
}
* C: 使用对象:
* 1、创建冰箱的对象
* 冰箱 bx = new 冰箱();
* 2、调用冰箱的功能
* 对象.功能();
* bx.打开();
* bx.存储(new 大象());
* bx.关闭();
* D:总结:
* 1、先按照名词提炼问题领域中的对象
* 2、对对象进行描述,其实就是在明确对象中应该具备的属性和功能
* 3、通过new的方式就可以创建该事物的具体对象
* 4、通过该对象调用它以后的功能。
05定义小汽车类
* A: 分析小汽车的属性和功能
* 属性
* 颜色
* 轮胎个数
* 功能
* 运行
* B: 通过伪代码描述小汽车
* 小汽车{
* 颜色
* 轮胎个数
* 运行(){}
* }
* C:通过JAVA代码描述小汽车
public class Car {
String color;
int number;
void run() {
System.out.println(color + ":" + number);
}
}
01测试汽车类
* A: 创见对象的格式
* a: 类名 变量名 = new 类名();
* B: 测试汽车类
public class CarDemo {
public static void main(String[] args) {
/*
测试:Car类中的run方法。
*/
// 1,创建Car的对象。给对象起个名字。
Car c = new Car();// c是类类型的变量。c指向了一个具体的Car类型的对象。
// 2,通过已有的对象调用该对象的功能。格式:对象.对象成员;
// 3,可以该对象的属性赋值。
c.color = "red";
c.number = 4;
c.run();
}
}
02对象的内存图
03类和对象的关系
* A: 类和对象的关系
* 类是对某一类事物的抽象描述,而对象用于表示现实中该类事物的个体
* B: 举例
* 可以将玩具模型看作是一个类,将一个个玩具看作对象,从玩具模型和玩具之间的关系便可以看出类与对象之间的关系
04成员变量和局部变量的区别
* 区别一:定义的位置不同
* 定义在类中的变量是成员变量
* 定义在方法中或者{}语句里面的变量是局部变量
* 区别二:在内存中的位置不同
* 成员变量存储在对内存的对象中
* 局部变量存储在栈内存的方法中
* 区别三:声明周期不同
* 成员变量随着对象的出现而出现在堆中,随着对象的消失而从堆中消失
* 局部变量随着方法的运行而出现在栈中,随着方法的弹栈而消失
* 区别四:初始化不同
* 成员变量因为在堆内存中,所有默认的初始化值
* 局部变量没有默认的初始化值,必须手动的给其赋值才可以使用。
01方法参数是基本数据类型和引用数据类型
* A.基本类型
class Demo
{
public static void main(String[] args)
{
int x = 4;
show(x);
System.out.println("x="+x);
}
public static void show(int x)
{
x = 5;
}
}
基本类型作为参数传递时,其实就是将基本类型变量x空间中的值复制了一份传递给调用的方法show(),当在show()方法中x接受到了复制的值,再在show()方法中对x变量进行操作,这时只会影响到show中的x。当show方法执行完成,弹栈后,程序又回到main方法执行,main方法中的x值还是原来的值。
* B.引用类型
class Demo
{
int x ;
public static void main(String[] args)
{
Demo d = new Demo();
d.x = 5;
show(d);
System.out.println("x="+d.x);
}
public static void show(Demo d)
{
d.x = 6;
}
}
当引用变量作为参数传递时,这时其实是将引用变量空间中的内存地址(引用)复制了一份传递给了show方法的d引用变量。这时会有两个引用同时指向堆中的同一个对象。当执行show方法中的d.x=6时,会根据d所持有的引用找到堆中的对象,并将其x属性的值改为6.show方法弹栈。
由于是两个引用指向同一个对象,不管是哪一个引用改变了引用的所指向的对象的中的值,其他引用再次使用都是改变后的值。
* C.结论
* 对于基本类型形式参数改变不会影响到实际参数
* 对于引用类型形式参数改变会影响到实际参数
02封装的概述
* A.面向对象三大特征
* 封装、继承、多态
* B.封装表现
* 1、方法就是一个最基本封装体
* 2、类其实也是一个封装体
* C.封装的好处
* 1、提高了代码的复用性
* 2、隐藏了实现细节,还要对外提供可以访问的方式。便于调用者的使用。这是核心之一,也可以理解为就是封装的概念
* 3、提高了安全性
03封装的生活中的举例
* A.封装的生活中的举例
机箱:
一台电脑,它是由CPU、主板、显卡、内存、硬盘、电源等部件组长,其实我们将这些部件组装在一起就可以使用电脑了,但是发现这些部件都散落在外面,很容造成不安全因素,于是,使用机箱壳子,把这些部件都装在里面,并在机箱壳上留下一些插口等,若不留插口,大家想想会是什么情况。
总结:机箱其实就是隐藏了办卡设备的细节,对外提供了插口以及开关等访问内部细节的方式。
* B.总结
* 机箱其实就是隐藏了办卡设备的细节,对外提供了插口以及开关等访问内部细节的方式
04private关键字
* A.private概述
* private可以修饰成员内容包括成员方法和成员变量
* 被private修饰的内容不能在其他类访问
* B.使用步骤
* 1、通过private修饰属性
* C.完整代码
class Person {
private int age;
private String name;
public void show() {
System.out.println("age=" + age + ",name" + name);
}
}
01get和set方法
* A.get和set方法
* 年龄已被私有,错误的值无法赋值,可是正确的值也赋值不了,这样还是不行,那肿么办呢?按照之前所学习的封装的原理,隐藏后,还需要提供访问方式。只要对外提供可以访问的方法,让其他程序访问这些方法。同时在方法中可以对数据进行验证。
* 一般对成员属性的访问动作:赋值(设置 set),取值(获取 get),因此对私有的变量访问的方式可以提供对应的 setXxx或者getXxx的方法。
class Person {
// 私有成员变量
private int age;
private String name;
// 对外提供设置成员变量的方法
public void setAge(int a) {
// 由于是设置成员变量的值,这里可以加入数据的验证
if (a < 0 || a > 130) {
System.out.println(a + "不符合年龄的数据范围");
return;
}
age = a;
}
// 对外提供访问成员变量的方法
public void getAge() {
return age;
}
}
* 总结
* 类中不需要对外提供的内容都私有化,包括属性和方法。
* 以后再描述事物,属性都私有化,并提供setXxx getXxx方法对其进行访问
* 注意
* 私有仅仅是封装的体现形式而已
02私有化Person类带get,set
* 标准代码
package cn.itcast.demo05;
/*
* 类描述人:
* 属性: 姓名和年龄
* 方法: 说话
*
* 私有化所有的属性 (成员变量) ,必须写对应的get/set方法
* 凡是自定义的类,自定义成员变量,应该私有化,提供get/set
*
* this关键字:
* 区分成员变量和局部变量同名情况
* 方法中,方位成员变量,写this.
*/
public class Person {
private String name;
private int age;
// set方法,变量name,age赋值
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
// get方法,变量name,age获取值
public int getAge() {
return age;
}
public String getName() {
return name;
}
public void speak() {
String name = "哈哈";
int age = 16;
System.out.println("人在说话 " + this.name + "..." + this.age);
}
}
* 标准测试代码
package cn.itcast.demo05;
public class PersonTest {
public static void main(String[] args) {
Person p = new Person();
//调用set方法,对成员变量赋值
p.setAge(18);
p.setName("旺财");
p.speak();
//调用get方法,获取成员变量的值
// System.out.println(p.getName());
// System.out.println(p.getAge());
}
}
03this关键字_区分成员变量和局部变量的同名
* A.什么时候用
* 当类中存在成员变量和局部变量同名的时候为了区分,就需要使用this关键字
* B.代码
class Person {
private int age;
private String name;
public void speak() {
this.name = "小强";
this.age = 18;
System.out.println("name=" + this.name + ",age=" + this.age);
}
}
class PersonDemo {
public static void main(String[] args) {
Person p = new Person();
p.speak();
}
}
04this内存图
* A.this内存图
01this的年龄比较
* A.需求:在Person类中定义功能,判断两个人是否是同龄人
* B.代码
class Person {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void speak() {
System.out.println("name=" + this.name + ",age=" + this.age);
}
// 判断是否为同龄人
public boolean equalsAge(Person p) {
// 使用当前调用该equalsAge方法对象的age和传递进来p的age进行比较
// 由于无法确定具体是哪一个对象调用equalsAge方法,这里就可以使用this来代替
/*
* if(this.age == p.age) { return true; } return false;
*/
return this.age == p.age;
}
}
02随机点名器案例重构
* A.需求:随机点名器,即在全班同学中随机的找出一名同学,打印这名同学的个人信息
它具备以下3个内容:
存储所有同学姓名
总览全班同学姓名
随机点名其中一人,打印到控制台
* B.代码
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
/**
* 思路:
* 第一步:存储全班同学信息
* 第二步:打印全班同学每一个人的信息
* 第三部:随机对学生点名,打印学生信息
*/
public class Test {
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList<Student>(); //1.1创建一个可以存储多个同学名字的容器
//1.存储全班同学信息
addStudent(list);
//2.打印全班同学每一个人的信息(姓名、年龄)
printStudent(list);
//3.随机对学生点名,打印学生信息
randomStudent(list);
}
public static void addStudent(ArrayList<Student> list) {
//键盘输入多个同学名字存储到容器中
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
//创建学生
Student s = new Student();
System.out.println("存储第"+i+"个学生姓名:");
String name = sc.next();
s.setName(name);
System.out.println("存储第"+i+"个学生年龄:");
int age = sc.nextInt();
s.setAge(age);
//添加学生到集合
list.add(s);
}
}
/**
2.打印全班同学每一个人的信息(姓名、年龄)
*/
public static void printStudent (ArrayList<Student> list) {
for (int i = 0; i < list.size(); i++) {
Student s = list.get(i);
System.out.println("姓名:"+s.getName() +",年龄:"+s.getAge());
}
}
/**
3.随机对学生点名,打印学生信息
*/
public static void randomStudent (ArrayList<Student> list) {
//在班级总人数范围内,随机产生一个随机数
int index = new Random().nextInt(list.size());
//在容器(ArrayList集合)中,查找该随机数所对应的同学信息(姓名、年龄)
Student s = list.get(index);
System.out.println("被随机点名的同学:"+s.getName() + ",年龄:" + s.getAge());
}
}
/**
* 学生信息类
*/
public class Student {
private String name; // 姓名
private int 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;
}
}
01继承的概述
*A:继承的概念
*a:继承描述的是事物之间的所属关系,通过继承可以使多种事物之间形成一种关系体系
*b:在Java中,类的继承是指在一个现有类的基础上去构建一个新的类,
构建出来的新类被称作子类,现有类被称作父类
*B:继承关系的子类特点
*a:子类会自动拥有父类所有非private修饰的属性和方法
02继承的定义格式和使用
*A:继承的格式
class 子类 extends 父类 {}
*B:雇员(Employee)与研发部员工(Developer)案例:
*cn.itcast.demo01包下:
*Employee.java:
/*
* 定义员工类Employee
*/
class Employee {
String name; // 定义name属性
public void work() {// 定义员工的工作方法
System.out.println("尽心尽力地工作");
}
}
*Developer.java:
/*
* 定义研发部员工类Developer 继承 员工类Employee
* 继承了父类中所有非private修饰的成员变量
*/
class Developer extends Employee {
// 定义一个打印name的方法
public void printName() {
System.out.println("name=" + name);
}
}
*测试员工类与研发部员工类:
/*
* 定义测试类
*/
public class Example01 {
public static void main(String[] args) {
Developer d = new Developer(); // 创建一个研发部员工类对象
d.name = "小明"; // 为该员工类的name属性进行赋值
d.printName(); // 调用该员工的printName()方法
d.work(); // 调用Developer类继承来的work()方法
}
}
*通过子类对象既可以调用自身的非private修饰的成员,也可以调用父类的非private修饰的成员
03继承的好处
*A:继承的好处:
*1、继承的出现提高了代码的复用性,提高软件开发效率。
*2、继承的出现让类与类之间产生了关系,提供了多态的前提。
04继承的注意事项
*A:继承的注意事项
*a:在Java中,类只支持单继承,不允许多继承,也就是说一个类只能有一个直接父类,例如下面这种情况是不合法的。
class A{}
class B{}
class C extends A,B{} // C类不可以同时继承A类和B类
假如支持多继承例如:
class A{
int a=3;
public void method(){
}
}
class B{
int a=5;
public void method(){
}
}
class C extends A,B{
}
class Demo{
public static void main(String[] args){
C c=new C();
System.out.println(c.a);//到底是调用A的还是B的成员变量??无法确定
c.method();//到底是调用A的还是B的成员方法??无法确定
}
}
*b:多个类可以继承一个父类,例如下面这种情况是允许的(就像你爹可以多个儿子,但是这些儿子都只有一个爹)
class A{}
class B extends A{}
class C extends A{} // 类B和类C都可以继承类A
*c:在Java中,多层继承是可以的,
即一个类的父类可以再去继承另外的父类,
例如C类继承自B类,而B类又可以去继承A类,这时,C类也可称作A类的子类。下面这种情况是允许的。
class A{}
class B extends A{} // 类B继承类A,类B是类A的子类
class C extends B{} // 类C继承类B,类C是类B的子类,同时也是类A的子类
*d:在Java中,子类和父类是一种相对概念,
也就是说一个类是某个类父类的同时,也可以是另一个类的子类。
例如上面的这种情况中,B类是A类的子类,同时又是C类的父类。
05继承的体系
*A:继承的体系:
动物(吃)
|
-------------------------
| |
猫科动物(吃,胎生) 爬行动物(吃,卵生)
| |
------------------------------- -----------------
| | | |
猫(吃,抓老鼠,胎生) 虎(吃,领地,胎生) 蛇(吃,冬眠,卵生) 鳄鱼(吃,潜水,卵生)
*a:动物体系是对每个具体事物共性的抽取,子类的共性抽取形成父类
*b:父类:具有所有子类的共性内容
子类:不但有共性还有自身特有的内容
*c:整个继承体系,越向上越抽象,越向下越具体
06继承后子类父类成员变量的特点
A:继承后子类父类成员变量的特点
a:子类的对象调用成员变量的时候,子类自己有,使用子类,子类自己没有调用的父类
class Fu{
//Fu中的成员变量。
int num = 5;
}
class Zi extends Fu{
//Zi中的成员变量
int num2 = 6;
//Zi中的成员方法
public void show()
{
//访问父类中的num
System.out.println("Fu num="+num);
//访问子类中的num2
System.out.println("Zi num2="+num2);
}
}
class Demo{
public static void main(String[] args)
{
Zi z = new Zi(); //创建子类对象
z.show(); //调用子类中的show方法
}
}
b:当子父类中出现了同名成员变量
class Fu{
//Fu中的成员变量。
int num = 5;
}
class Zi extends Fu{
//Zi中的成员变量
int num = 6;
void show(){
//子类的局部变量
int num=7
//直接访问,遵循就近查找原则
System.out.println(num);//7
//子父类中出现了同名的成员变量时
//在子类中需要访问父类中非私有成员变量时,需要使用super关键字
//访问父类中的num
System.out.println("Fu num="+super.num);//5
//访问子类中的num2
System.out.println("Zi num2="+this.num);//6
}
}
class Demo5 {
public static void main(String[] args)
{
Zi z = new Zi(); //创建子类对象
z.show(); //调用子类中的show方法
}
}
07继承后子类父类成员方法的特性_子类重写父类方法
A:继承后子类父类成员方法的特性
a:子类的对象调用方法的时候,子类自己有,使用子类,子类自己没有调用的父类
class Fu{
public void show(){
System.out.println("Fu类中的show方法执行");
}
}
class Zi extends Fu{
public void show2(){
System.out.println("Zi类中的show2方法执行");
}
}
public class Test{
public static void main(String[] args) {
Zi z = new Zi();
z.show(); //子类中没有show方法,但是可以找到父类方法去执行
z.show2();
}
}
b:为什么要有重写?
class Fu{
public void method(){
//上千行代码
//Fu类中的方法最先存在,那么如果项目需求变了,该方法
//功能不能够满足我们的需求,此时我们也不会去改这个方法
//因为项目中可能有大量的功能已经使用到该方法,如果随意修改可能使调用该方法的功能出现问题
//所以使用重写方式基于原有功能提供更强的功能
}
}
class Zi extends Fu{
}
c:子类中出现与父类一模一样的方法时,会出现覆盖操作,也称为override重写、复写或者覆盖
class Fu{
public void show(){
System.out.println("Fu show");
}
}
class Zi extends Fu{
//子类复写了父类的show方法
public void show(){
System.out.println("Zi show");
}
}
public class Test{
public static void main(String[] args) {
Zi z = new Zi();
z.show(); //Zi show 子类有直接使用子类
}
}
08方法覆盖的需求
A:方法覆盖的需求
a:案例:比如手机,当描述一个手机时,它具有发短信,打电话,显示来电号码功能,
后期由于手机需要在来电显示功能中增加显示姓名和头像,
这时可以重新定义一个类描述智能手机,并继承原有描述手机的类。
并在新定义的类中覆盖来电显示功能,在其中增加显示姓名和头像功能
b:分析:我们不改装(破坏)原来的手机,而是再买一个新的智能手机,不但有原有的功能,而且还有特有功能
例:厂商发布新手机都是基于原有手机的升级,不会拿着原有的手机在卖,新产一款
1:分析类的构建:
手机类
属性(成员变量):无
行为(成员方法):
发短信
打电话
来电显示:显示来电号码
智能手机类:
属性(成员变量):无
行为(成员方法):
发短信
打电话
来电显示:显示来电号码,显示姓名和头像
手机类和智能手机类有共性内容:
发短信
打电话
显示来电号码
2:继承关系分析:
对于发短信和打电话功能,让智能手机直接沿用(继承)手机的就可以
但是在智能手机中的来电显示不但实现号码,还显示姓名和头像,同样的都是来电显示功能,智能手机的来电显示比手机的功能更加强大,我们考虑使用重写
09方法覆盖的手机案例实现
//手机类
class Phone{
public void sendMessage(){
System.out.println("发短信");
}
public void call(){
System.out.println("打电话");
}
public void showNum(){
System.out.println("来电显示号码");
}
}
//智能手机类
class NewPhone extends Phone{
//覆盖父类的来电显示号码功能,并增加自己的显示姓名和图片功能
//从现实生活角度考虑沿用原有的showNum方法名便于用户更快熟悉和接受,而不是再起个新的名字
//用户还需要花费大量时间慢慢接受
public void showNum(){
//调用父类已经存在的功能使用super
//如果不加super这是调用子类自身的showNum(),自己调用自己,递归
//方法不断入栈导致内存溢出
super.showNum();
//增加自己特有显示姓名和图片功能
System.out.println("显示来电姓名");
System.out.println("显示头像");
}
}
public class Test {
public static void main(String[] args) {
new NewPhone().showNum();//来电显示 显示来电姓名 显示头像
}
}
10方法覆盖的注意事项
A:方法覆盖的注意事项
a:权限:子类方法覆盖父类方法,必须要保证权限大于等于父类权限。
四大权限:public>默认=protected>private
class Fu{
void show(){
}
public void method(){
}
}
class Zi() extends Fu{
public void show(){//编译运行没问题
}
void method(){//编译错误
}
}
b:方法定义:子类方法和要重写的父类的方法:方法的方法名和参数列表都要一样。
关于方法的返回值:
如果是基本数据类型,子类的方法和重写的父类的方法返回值类型必须相同
如果是引用数据类型,子类的方法和重写的父类的方法返回值类型可以相同或者子类方法的返回值类型是父类方法返回值类型的子类
class Fu{
int show(){
}
public Fu method(){
}
public Fu method2(){
}
}
class Zi() extends Fu{
public int show(){//返回值为基本类型的重写
}
public Fu method(){//子类的方法和重写的父类的方法返回值类型可以相同
}
public Zi method2(){//子类方法的返回值类型是父类方法返回值类型的子类
}
}
c:重载与重写对比:
重载:
权限修饰符(public private 默认):无关
方法名:重载的两个方法的方法名必须相同
形参列表:
形参类型的顺序不同
形参的个数不同
形参的类型不同
三者至少满足一个
返回值类型:
重载与返回值类型无关
重写:
权限修饰符(public private 默认):
子类方法的权限>=父类的方法的权限
方法名:
子类方法和父类方法必须相同
形参列表:
子类方法和父类方法的形参列表必须相同
返回值类型:
基本类数据类型:
必须相同
引用数据类型:
子类方法的返回值类型和父类方法的返回值类型相同
或者
子类方法的返回值类型是父类方法的返回值类型的 子类
11抽象类的产生
A:抽象类的产生
a:分析事物时,发现了共性内容,就出现向上抽取。会有这样一种特殊情况,就是方法功能声明相同,但方法功能主体不同。那么这时也可以抽取,但只抽取方法声明,不抽取方法主体。那么此方法就是一个抽象方法。
12抽象类的定义格式
A:抽象方法定义的格式:
a:public abstract 返回值类型 方法名(参数);
抽象类定义的格式:
abstract class 类名 {
}
b:抽象类示例代码:
/*
* 定义类开发工程师类
* EE开发工程师 : 工作
* Android开发工程师 : 工作
*
* 根据共性进行抽取,然后形成一个父类Develop
* 定义方法,工作: 怎么工作,具体干什么呀
*
* 抽象类,不能实例化对象, 不能new的
* 不能创建对象的原因: 如果真的让你new了, 对象.调用抽象方法,抽象方法没有主体,根本就不能运行
* 抽象类使用: 定义类继承抽象类,将抽象方法进行重写,创建子类的对象
*/
public abstract class Develop {
//定义方法工作方法,但是怎么工作,说不清楚了,讲不明白
//就不说, 方法没有主体的方法,必须使用关键字abstract修饰
//抽象的方法,必须存在于抽象的类中,类也必须用abstract修饰
public abstract void work();
}
13抽象类的使用方式
A:抽象类的使用方式
/*
* 定义类,JavaEE的开发人员
* 继承抽象类Develop,重写抽象的方法
*/
public class JavaEE extends Develop{
//重写父类的抽象方法
//去掉abstract修饰符,加上方法主体
public void work(){
System.out.println("JavaEE工程师在开发B/S 软件");
}
}
/*
* 定义Android类,继承开发人员类
* 重写抽象方法
*/
public class Android extends Develop{
public void work(){
System.out.println("Android工程师开发手机软件");
}
}
/*
* 测试抽象类
* 创建他的子类的对象,使用子类的对象调用方法
*/
public class Test {
public static void main(String[] args) {
JavaEE ee = new JavaEE();
ee.work();//"JavaEE工程师在开发B/S 软件"
Android and = new Android();
and.work();//"Android工程师开发手机软件"
}
}
14抽象类特点
A:抽象类的特点
a:抽象类和抽象方法都需要被abstract修饰。抽象方法一定要定义在抽象类中。
b:抽象类不可以直接创建对象,原因:调用抽象方法没有意义。
c:只有覆盖了抽象类中所有的抽象方法后,其子类才可以创建对象。否则该子类还是一个抽象类。之所以继承抽象类,更多的是在思想,是面对共性类型操作会更简单。
abstract class A{
public abstract void func();
public abstract void func2();
}
class A2 extends A{//A2把A中的两个抽象方法都重写掉了
//A2类不再是抽象类
public void func(){}
public void func2(){}
}
abstract class A3 extends A{//含有抽象方法的类一定是抽象类
public void func(){
}
//public abstract void func2();//func2相当于被继承下来
}
15抽象类的设计思想
A:抽象类的设计思想
a:抽象类的作用:继承的体系抽象类,强制子类重写抽象的方法
抽象员工:
规定一个方法,work工作
EE员工,Android员工
Develop类 抽象类
abstract work();
|
-------------
| |
EE Android //是我开发的一员必须工作
work(){} work(){}
16抽象类的细节
A:抽象类的细节
a:抽象类一定是个父类?
是的,因为不断抽取而来的。
b:抽象类中是否可以不定义抽象方法?
是可以的,那这个抽象类的存在到底有什么意义呢?不让该类创建对象,方法可以直接让子类去使用
(适配器设计模式)
/*
* 抽象类,可以没有抽象方法,可以定义带有方法体的方法
* 让子类继承后,可以直接使用
*/
public abstract class Animal {
public void sleep(){
System.out.println("动物睡觉");
}
}
public class Cat extends Animal{
}
public class Test {
public static void main(String[] args) {
//Cat c = new Cat();
new Cat().sleep();//不让该类创建对象,方法可以直接让子类去使用
}
}
c:抽象关键字abstract不可以和哪些关键字共存?
1:private:私有的方法子类是无法继承到的,也不存在覆盖,而abstract和private一起使用修饰方法,abstract既要子类去实现这个方法,而private修饰子类根本无法得到父类这个方法。互相矛盾。
/*
* 抽象类,可以没有抽象方法,可以定义带有方法体的方法
* 让子类继承后,可以直接使用
*/
public abstract class Animal {
// private abstract void show();
//抽象方法,需要子类重写, 如果父类方法是私有的,子类继承不了,也就没有了重写
}
17员工案例分析
A:员工案例分析:
a:需求描述:
某IT公司有多名员工,按照员工负责的工作不同,进行了部门的划分(研发部员工、维护部员工)。
研发部根据所需研发的内容不同,又分为JavaEE工程师、Android工程师;
维护部根据所需维护的内容不同,又分为网络维护工程师、硬件维护工程师。
公司的每名员工都有他们自己的员工编号、姓名,并要做它们所负责的工作。
工作内容
JavaEE工程师:员工号为xxx的 xxx员工,正在研发淘宝网站
Android工程师:员工号为xxx的 xxx员工,正在研发淘宝手机客户端软件
网络维护工程师:员工号为xxx的 xxx员工,正在检查网络是否畅通
硬件维护工程师:员工号为xxx的 xxx员工,正在修复打印机
b:继承体系:
员工
研发部员工 维护部员工
JavaEE工程师 Android工程师 网络维护工程师 硬件维护工程师
c:详细描述:
根据员工信息的描述,确定每个员工都有员工编号、姓名、要进行工作。
则,把这些共同的属性与功能抽取到父类中(员工类),
关于工作的内容由具体的工程师来进行指定。
工作内容
JavaEE工程师:员工号为xxx的 xxx员工,正在研发淘宝网站
Android工程师:员工号为xxx的 xxx员工,正在研发淘宝手机客户端软件
网络维护工程师:员工号为xxx的 xxx员工,正在检查网络是否畅通
硬件维护工程师:员工号为xxx的 xxx员工,正在修复打印机
创建JavaEE工程师对象,完成工作方法的调用
18员工案例Employee类的编写
A:员工案例Employee类的编写:按照分析的继承体系来逐个实现
/*
* 定义员工类
* 内容,都是所有子类的共性抽取
* 属性: 姓名,工号
* 方法: 工作
*/
public abstract class Employee {
private String id;// 员工编号
private String name; // 员工姓名
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//工作方法(抽象方法)
public abstract void work();
}
19员工案例的子类的编写
B:员工案例的子类的编写:
/*
* 定义研发员工类
* 属于员工中的一种, 继承员工类
* 抽象类Develop 给自己的员工定义自己有的属性
*/
public abstract class Develop extends Employee{
}
/*
* 描述JavaEE开发工程师类
* 工号,姓名 工作方法
* 其他的员工,也具备这些共性,抽取到父类中,自己就不需要定义了
* 是研发部员工的一种,继承研发部类
*/
public class JavaEE extends Develop{
//重写他父类的父类的抽象方法
public void work(){
//调用父类的get方法,获取name,id值
System.out.println("JavaEE的工程师开发淘宝"+ super.getName()+".."+super.getId());
}
}
/*
*定义Android工程师 继承 研发部员工类,重写工作方法
*/
public class Android extends Developer {
@Override
public void work() {
System.out.println("员工号为 " + getId() + " 的 " + getName() + " 员工,正在研发淘宝手机客户端软件");
}
}
/*
* 定义维护员工类,属于员工中的一种
* 继承员工类
* 抽象类Maintainer 给自己的员工定义自己有的属性
*/
public abstract class Maintainer extends Employee{
}
/*
* 描述的是网络维护工程师
* 属于维护部的员工,继承维护部类
*/
public class Network extends Maintainer{
public void work(){
System.out.println("网络工程师在检查网络是否畅通"+super.getName()+"..."+super.getId());
}
}
/*
*定义Hardware硬件维护工程师 继承 维护部员工类,重写工作方法
*/
public class Hardware extends Maintainer {
@Override
public void work() {
System.out.println("员工号为 " + getId() + " 的 " + getName() + " 员工,正在修复打印机");
}
}
01接口的概念
* A:接口的概念
接口是功能的集合,同样可看做是一种数据类型,是比抽象类更为抽象的”类”。
接口只描述所应该具备的方法,并没有具体实现,具体的实现由接口的实现类(相当于接口的子类)来完成。这样将功能的定义与实现分离,优化了程序设计。
请记住:一切事物均有功能,即一切事物均有接口。
02接口的定义
* A: 接口的定义
与定义类的class不同,接口定义时需要使用interface关键字。
定义接口所在的仍为.java文件,虽然声明时使用的为interface关键字的编译后仍然会产生.class文件。这点可以让我们将接口看做是一种只包含了功能声明的特殊类。
* B : 定义格式
public interface 接口名 {
抽象方法1;
抽象方法2;
抽象方法3;
}
* C: 定义步骤
使用interface代替了原来的class,其他步骤与定义类相同:
接口中的方法均为公共访问的抽象方法
接口中无法定义普通的成员变量
03接口的实现类
* A: 类与接口的关系
类与接口的关系为实现关系,即类实现接口。实现的动作类似继承,只是关键字不同,实现使用implements。
其他类(实现类)实现接口后,就相当于声明:”我应该具备这个接口中的功能”。实现类仍然需要重写方法以实现具体的功能。
* B: 类实现接口的格式
class 类 implements 接口 {
重写接口中方法
}
* C:注意事项
在类实现接口后,该类就会将接口中的抽象方法继承过来,此时该类需要重写该抽象方法,完成具体的逻辑。
接口中定义功能,当需要具有该功能时,可以让类实现该接口,只声明了应该具备该方法,是功能的声明。
在具体实现类中重写方法,实现功能,是方法的具体实现。
04接口中成员变量的特点
* A:成员变量特点
* a 接口中可以定义变量,但是变量必须有固定的修饰符修饰,public static final 所以接口中的变量也称之为常量,其值不能改变。后面我们会讲解static与final关键字
* B:案例
interface Demo { ///定义一个名称为Demo的接口。
public static final int NUM = 3;// NUM的值不能改变
}
05接口中成员方法的特点
* A: 成员方法特点
* a 接口中可以定义方法,方法也有固定的修饰符,public abstract
* b 子类必须覆盖掉接口中所有的抽象方法后,子类才可以实例化。否则子类是一个抽象类。
* B: 案例
interface Demo { ///定义一个名称为Demo的接口。
public abstract void show1();
public abstract void show2();
}
//定义子类去覆盖接口中的方法。类与接口之间的关系是 实现。通过 关键字 implements
class DemoImpl implements Demo { //子类实现Demo接口。
//重写接口中的方法。
public void show1(){}
public void show2(){}
}
06实现类还是一个抽象类
A: 接口的实现类
一个类如果实现类接口,有两种操作方法:
第一:实现类是非抽象类,就需要重写接口中所有的抽象方法.
第二:实现类也声明为抽象类,那么实现类可以不重写接口中的抽象方法。
07类和接口的多实现
* A:接口的多实现
了解了接口的特点后,那么想想为什么要定义接口,使用抽象类描述也没有问题,接口到底有啥用呢?
接口最重要的体现:解决多继承的弊端。将多继承这种机制在java中通过多实现完成了。
* B 多实现的优点
* 怎么解决多继承的弊端呢?
* 弊端:多继承时,当多个父类中有相同功能时,子类调用会产生不确定性。
* 其实核心原因就是在于多继承父类中功能有主体,而导致调用运行时,不确定运行哪个主体内容。
* 为什么多实现能解决了呢?
* 因为接口中的功能都没有方法体,由子类来明确。
* C :案例演示
interface Fu2{
void show2();
}
class Zi implements Fu1,Fu2 { // 多实现。同时实现多个接口。
public void show1(){}
public void show2(){}
}
08类在继承类的同时实现多接口
* A: 继承的同时实现接口
* 接口和类之间可以通过实现产生关系,同时也学习了类与类之间可以通过继承产生关系。当一个类已经继承了一个父类,它又需要扩展额外的功能,这时接口就派上用场了。
* 子类通过继承父类扩展功能,通过继承扩展的功能都是子类应该具备的基础功能。如果子类想要继续扩展其他类中的功能呢?这时通过实现接口来完成。
* 接口的出现避免了单继承的局限性。父类中定义的事物的基本功能。接口中定义的事物的扩展功能。
* B: 代码演示
class Fu {
public void show(){}
}
interface Inter {
pulbic abstract void show1();
}
class Zi extends Fu implements Inter {
public void show1() {
}
}
接口的出现避免了单继承的局限性。父类中定义的事物的基本功能。接口中定义的事物的扩展功能。
09接口的多继承
* A: 接口的多继承
* 学习类的时候,知道类与类之间可以通过继承产生关系,接口和类之间可以通过实现产生关系,那么接口与接口之间会有什么关系。
* 多个接口之间可以使用extends进行继承。
* B 代码演示
interface Fu1{
void show();
}
interface Fu2{
void show1();
}
interface Fu3{
void show2();
}
interface Zi extends Fu1,Fu2,Fu3{
void show3();
}
在开发中如果多个接口中存在相同方法,这时若有个类实现了这些接口,那么就要实现接口中的方法,由于接口中的方法是抽象方法,子类实现后也不会发生调用的不确定性。
10接口思想
* A:接口的思想
* 前面学习了接口的代码体现,现在来学习接口的思想,接下里从生活中的例子进行说明。
* 举例:我们都知道电脑上留有很多个插口,而这些插口可以插入相应的设备,这些设备为什么能插在上面呢?
* 主要原因是这些设备在生产的时候符合了这个插口的使用规则,否则将无法插入接口中,更无法使用。发现这个插口的出现让我们使用更多的设备。
* B: 接口的好处
* 总结:接口在开发中的它好处
* 1、接口的出现扩展了功能。
* 2、接口其实就是暴漏出来的规则。
* 3、接口的出现降低了耦合性,即设备与设备之间实现了解耦。
* 接口的出现方便后期使用和维护,一方是在使用接口(如电脑),一方在实现接口(插在插口上的设备)。例如:笔记本使用这个规则(接口),电脑外围设备实现这个规则(接口)。
11接口和抽象类的区别
* A: 明白了接口思想和接口的用法后,接口和抽象类的区别是什么呢?接口在生活体现也基本掌握,那在程序中接口是如何体现的呢?
通过实例进行分析和代码演示抽象类和接口的用法。
* B: 举例:
* 犬:
行为:
吼叫;
吃饭;
* 缉毒犬:
行为:
吼叫;
吃饭;
缉毒;
* C:思考:
* 由于犬分为很多种类,他们吼叫和吃饭的方式不一样,在描述的时候不能具体化,也就是吼叫和吃饭的行为不能明确。
* 当描述行为时,行为的具体动作不能明确,这时,可以将这个行为写为抽象行为,那么这个类也就是抽象类。
* 可是当缉毒犬有其他额外功能时,而这个功能并不在这个事物的体系中。这时可以让缉毒犬具备犬科自身特点的同时也有其他额外功能,可以将这个额外功能定义接口中。
* D: 代码演示
interface 缉毒{
public abstract void 缉毒();
}
//定义犬科的这个提醒的共性功能
abstract class 犬科{
public abstract void 吃饭();
public abstract void 吼叫();
}
// 缉毒犬属于犬科一种,让其继承犬科,获取的犬科的特性,
//由于缉毒犬具有缉毒功能,那么它只要实现缉毒接口即可,这样即保证缉毒犬具备犬科的特性,也拥有了缉毒的功能
class 缉毒犬 extends 犬科 implements 缉毒{
public void 缉毒() {
}
void 吃饭() {
}
void 吼叫() {
}
}
class 缉毒猪 implements 缉毒{
public void 缉毒() {
}
}
* E: 接口和抽象类区别总结
相同点:
都位于继承的顶端,用于被其他类实现或继承;
都不能直接实例化对象;
都包含抽象方法,其子类都必须覆写这些抽象方法;
区别:
抽象类为部分方法提供实现,避免子类重复实现这些方法,提高代码重用性;接口只能包含抽象方法;
一个类只能继承一个直接父类(可能是抽象类),却可以实现多个接口;(接口弥补了Java的单继承)
抽象类是这个事物中应该具备的你内容, 继承体系是一种 is..a关系
接口是这个事物中的额外内容,继承体系是一种 like..a关系
二者的选用:
优先选用接口,尽量少用抽象类;
需要定义子类的行为,又要为子类提供共性功能时才选用抽象类;
12多态概述
* A: 多态概述
多态是继封装、继承之后,面向对象的第三大特性。
现实事物经常会体现出多种形态,如学生,学生是人的一种,则一个具体的同学张三既是学生也是人,即出现两种形态。
Java作为面向对象的语言,同样可以描述一个事物的多种形态。如Student类继承了Person类,一个Student的对象便既是Student,又是Person。
Java中多态的代码体现在一个子类对象(实现类对象)既可以给这个子类(实现类对象)引用变量赋值,又可以给这个子类(实现类对象)的父类(接口)变量赋值。
如Student类可以为Person类的子类。那么一个Student对象既可以赋值给一个Student类型的引用,也可以赋值给一个Person类型的引用。
最终多态体现为父类引用变量可以指向子类对象。
多态的前提是必须有子父类关系或者类实现接口关系,否则无法完成多态。
在使用多态后的父类引用变量调用方法时,会调用子类重写后的方法。
13多态调用的三种格式
* A:多态的定义格式:
* 就是父类的引用变量指向子类对象
父类类型 变量名 = new 子类类型();
变量名.方法名();
* B: 普通类多态定义的格式
父类 变量名 = new 子类();
举例:
class Fu {}
class Zi extends Fu {}
//类的多态使用
Fu f = new Zi();
* C: 抽象类多态定义格式
抽象类 变量名 = new 抽象类子类();
举例:
abstract class Fu {
public abstract void method();
}
class Zi extends Fu {
public void method(){
System.out.println(“重写父类抽象方法”);
}
}
//类的多态使用
Fu fu= new Zi();
* D: 接口多态定义的格式
接口 变量名 = new 接口实现类();
如: interface Fu {
public abstract void method();
}
class Zi implements Fu {
public void method(){
System.out.println(“重写接口抽象方法”);
}
}
//接口的多态使用
Fu fu = new Zi();
* E: 注意事项
同一个父类的方法会被不同的子类重写。在调用方法时,调用的为各个子类重写后的方法。
如 Person p1 = new Student();
Person p2 = new Teacher();
p1.work(); //p1会调用Student类中重写的work方法
p2.work(); //p2会调用Teacher类中重写的work方法
当变量名指向不同的子类对象时,由于每个子类重写父类方法的内容不同,所以会调用不同的方法。
14多态成员方法的特点
* A: 掌握了多态的基本使用后,那么多态出现后类的成员有啥变化呢?前面学习继承时,我们知道子父类之间成员变量有了自己的特定变化,
* 那么当多态出现后,成员变量在使用上有没有变化呢?
* 多态出现后会导致子父类中的成员变量有微弱的变化
* B: 代码演示
class Fu {
int num = 4;
}
class Zi extends Fu {
int num = 5;
}
class Demo {
public static void main(String[] args) {
Fu f = new Zi();
System.out.println(f.num);
Zi z = new Zi();
System.out.println(z.num);
}
}
* C: 多态成员变量
当子父类中出现同名的成员变量时,多态调用该变量时:
编译时期:参考的是引用型变量所属的类中是否有被调用的成员变量。没有,编译失败。
运行时期:也是调用引用型变量所属的类中的成员变量。
简单记:编译和运行都参考等号的左边。编译运行看左边。
* D: 多态出现后会导致子父类中的成员方法有微弱的变化。看如下代码
class Fu {
int num = 4;
void show() {
System.out.println("Fu show num");
}
}
class Zi extends Fu {
int num = 5;
void show() {
System.out.println("Zi show num");
}
}
class Demo {
public static void main(String[] args) {
Fu f = new Zi();
f.show();
}
}
* E: 多态成员方法
编译时期:参考引用变量所属的类,如果没有类中没有调用的方法,编译失败。
运行时期:参考引用变量所指的对象所属的类,并运行对象所属类中的成员方法。
简而言之:编译看左边,运行看右边。
15instanceof关键字
* A: 作用
可以通过instanceof关键字来判断某个对象是否属于某种数据类型。如学生的对象属于学生类,学生的对象也属于人类
* 格式:
boolean b = 对象 instanceof 数据类型;
* 举例:
Person p1 = new Student(); // 前提条件,学生类已经继承了人类
boolean flag = p1 instanceof Student; //flag结果为true
boolean flag2 = p2 instanceof Teacher; //flag结果为false
16多态-向上转型
* A: 多态的转型分为向上转型与向下转型两种:
* B: 向上转型:当有子类对象赋值给一个父类引用时,便是向上转型,多态本身就是向上转型的过程。
使用格式:
父类类型 变量名 = new 子类类型();
如:Person p = new Student();
17多态-向下转型
* A: 向下转型:一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类引用转为子类引用,这个过程是向下转型。如果是直接创建父类对象,是无法向下转型的!
使用格式:
子类类型 变量名 = (子类类型) 父类类型的变量;
如:Student stu = (Student) p; //变量p 实际上指向Student对象
18多态的好处和弊端
* A: 多态的好处和弊端
* 当父类的引用指向子类对象时,就发生了向上转型,即把子类类型对象转成了父类类型。
向上转型的好处是隐藏了子类类型,提高了代码的扩展性。
* 但向上转型也有弊端,只能使用父类共性的内容,而无法使用子类特有功能,功能有限制。
* B: 看如下代码
//描述动物类,并抽取共性eat方法
abstract class Animal {
abstract void eat();
}
// 描述狗类,继承动物类,重写eat方法,增加lookHome方法
class Dog extends Animal {
void eat() {
System.out.println("啃骨头");
}
void lookHome() {
System.out.println("看家");
}
}
// 描述猫类,继承动物类,重写eat方法,增加catchMouse方法
class Cat extends Animal {
void eat() {
System.out.println("吃鱼");
}
void catchMouse() {
System.out.println("抓老鼠");
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Dog(); //多态形式,创建一个狗对象
a.eat(); // 调用对象中的方法,会执行狗类中的eat方法
// a.lookHome();//使用Dog类特有的方法,需要向下转型,不能直接使用
// 为了使用狗类的lookHome方法,需要向下转型
// 向下转型过程中,可能会发生类型转换的错误,即ClassCastException异常
// 那么,在转之前需要做健壮性判断
if( !a instanceof Dog){ // 判断当前对象是否是Dog类型
System.out.println("类型不匹配,不能转换");
return;
}
Dog d = (Dog) a; //向下转型
d.lookHome();//调用狗类的lookHome方法
}
}
* C 多态总结:
什么时候使用向上转型:
当不需要面对子类类型时,通过提高扩展性,或者使用父类的功能就能完成相应的操作,这时就可以使用向上转型。
如:Animal a = new Dog();
a.eat();
什么时候使用向下转型
当要使用子类特有功能时,就需要使用向下转型。
如:Dog d = (Dog) a; //向下转型
d.lookHome();//调用狗类的lookHome方法
向下转型的好处:可以使用子类特有功能。
弊端是:需要面对具体的子类对象;在向下转型时容易发生ClassCastException类型转换异常。在转换之前必须做类型判断。
如:if( !a instanceof Dog){…}
19多态举例
* A: 毕老师和毕姥爷的故事
* 案例:
/*
描述毕老师和毕姥爷,
毕老师拥有讲课和看电影功能
毕姥爷拥有讲课和钓鱼功能
*/
class 毕姥爷 {
void 讲课() {
System.out.println("政治");
}
void 钓鱼() {
System.out.println("钓鱼");
}
}
// 毕老师继承了毕姥爷,就有拥有了毕姥爷的讲课和钓鱼的功能,
// 但毕老师和毕姥爷的讲课内容不一样,因此毕老师要覆盖毕姥爷的讲课功能
class 毕老师 extends 毕姥爷 {
void 讲课() {
System.out.println("Java");
}
void 看电影() {
System.out.println("看电影");
}
}
public class Test {
public static void main(String[] args) {
// 多态形式
毕姥爷 a = new 毕老师(); // 向上转型
a.讲课(); // 这里表象是毕姥爷,其实真正讲课的仍然是毕老师,因此调用的也是毕老师的讲课功能
a.钓鱼(); // 这里表象是毕姥爷,但对象其实是毕老师,而毕老师继承了毕姥爷,即毕老师也具有钓鱼功能
// 当要调用毕老师特有的看电影功能时,就必须进行类型转换
毕老师 b = (毕老师) a; // 向下转型
b.看电影();
}
20笔记本电脑案例
* A:案例介绍
* 定义USB接口(具备开启功能、关闭功能),笔记本要使用USB设备,即笔记本在生产时需要预留可以插入USB设备的USB接口,即就是笔记本具备使用USB设备的功能,
* 但具体是什么USB设备,笔记本并不关心,只要符合USB规格的设备都可以。鼠标和键盘要想能在电脑上使用,那么鼠标和键盘也必须遵守USB规范,不然鼠标和键盘的生产出来无法使用
* 进行描述笔记本类,实现笔记本使用USB鼠标、USB键盘
USB接口,包含开启功能、关闭功能
笔记本类,包含运行功能、关机功能、使用USB设备功能
鼠标类,要符合USB接口
键盘类,要符合USB接口
* B: 案例分析
* 阶段一:
使用笔记本,笔记本有运行功能,需要笔记本对象来运行这个功能
* 阶段二:
想使用一个鼠标,又有一个功能使用鼠标,并多了一个鼠标对象。
* 阶段三:
还想使用一个键盘 ,又要多一个功能和一个对象
* 问题:每多一个功能就需要在笔记本对象中定义一个方法,不爽,程序扩展性极差。
降低鼠标、键盘等外围设备和笔记本电脑的耦合性。
21笔记本电脑案例代码实现
* A: 代码实现
定义鼠标、键盘,笔记本三者之间应该遵守的规则
interface USB {
void open();// 开启功能
void close();// 关闭功能
}
鼠标实现USB规则
class Mouse implements USB {
public void open() {
System.out.println("鼠标开启");
}
public void close() {
System.out.println("鼠标关闭");
}
}
键盘实现USB规则
class KeyBoard implements USB {
public void open() {
System.out.println("键盘开启");
}
public void close() {
System.out.println("键盘关闭");
}
}
定义笔记本
class NoteBook {
// 笔记本开启运行功能
public void run() {
System.out.println("笔记本运行");
}
// 笔记本使用usb设备,这时当笔记本对象调用这个功能时,必须给其传递一个符合USB规则的USB设备
public void useUSB(USB usb) {
// 判断是否有USB设备
if (usb != null) {
usb.open();
usb.close();
}
}
public void shutDown() {
System.out.println("笔记本关闭");
}
}
public class Test {
public static void main(String[] args) {
// 创建笔记本实体对象
NoteBook nb = new NoteBook();
// 笔记本开启
nb.run();
// 创建鼠标实体对象
Mouse m = new Mouse();
// 笔记本使用鼠标
nb.useUSB(m);
// 创建键盘实体对象
KeyBoard kb = new KeyBoard();
// 笔记本使用键盘
nb.useUSB(kb);
// 笔记本关闭
nb.shutDown();
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现