初识Java
Java程序结构
- 类名与文件名完全一样
- main()方法是Java程序的入口点
- main()方法的四要素
- public
- static
- void
- String[ ] args
- “{”和“}”一一对应,缺一不可
Java程序开发步骤
- 编写源程序
- 编译源程序
- 运行
使用记事本开发Java程序的步骤
- 编辑源程序,以.java为后缀名保存
- javac命令编译.java文件生成.class
- java命令运行.class文件
使用Eclipse开发Java程序的步骤
- 创建一个Java项目
- 手动创建Java源程序
- 编译Java源程序
- 运行Java程序
jdk安装及配置环境变量
安装jdk
打开jdk安装文件,可以全部选择安装在默认路径
配置环境变量(win10)
右键此电脑,选择属性
选择高级系统设置
选择环境变量
-
在系统变量点击点击新建,变量名:JAVA_HOME
变量值为:C:\ProgramFiles\Java\jdk1.8.0_131(jdk安装的路径)
在系统变量找到Path双击打开插入一行:%JAVA_HOME%\bin
验证是否成功
在cmd里,输入java,如果识别这个命令就安装成功了
数据类型与运算符
基本数据类型
-
数值型
- 整数类型
- byte :1字节
- short :2字节
- int :4字节
- long :8字节
- 浮点类型
- float :4字节
- double :8字节
- 整数类型
-
字符型
- char :2字节
-
布尔型
- boolean :1字节
引用数据类型
Java中的引用数据类型主要包含类型,接口,数组等。
String类型不是基本数据类型,而是引用数据类型,它给java提供了一个类
数据类型转换
(1)算术运算时
存储位数越多,级别越高。
(2)赋值运算时
自动转换:将级别低的类型赋值给级别高的类型
强制转换 将高级别的类型赋值给低级别类型是,必须进行强制转换。
int a=1;
byte b=(byte)a;
变量
声明变量
第一步:声明变量,即“根据数据类型在内存申请空间”
int money; //变量类型 变量名;
第二步:赋值,即“将数据存储至对应的内存空间”
money=1000; //变量名=数值;
第一步和第二步可以合并
int money=1000; //数据类型 变量名=数值;
变量命名
- 标识符命名规则
- 标识符由字母、数字、下划线_或者美元符号$组成
- 标识符首字母以字母、下划线或者美元符号开头,不能以数字开头。
- 标识符的命名不能与关键字、布尔值(true、false)和null相同。
- 标识符区分大小写,没有长度限制,坚持见名知义原则。
常量
整形常量:123 超过int类型取值范围需要在后面加上小写l或大写L
浮点型常量: 12.3f 默认double,float需要在后面加小f或大F
-
字符常量: '以'
- '\n' 转义换行
- '\t' 转义tab键
- '\b' 转义空格
字符串穿常量:"课工场"
-
boolean: 布尔常量只能为true和false
- true 真
- false 假
null常量:null 可以赋值给任意引用类型变量
final: 符号常量
final double PI=3.123456;
优点:比较安全,不能改变 常量通常大写 不同字符之间要用_分割
运算符
常用运算符
- 赋值运算符 =
- 算符运算符 +、-、++
- 关系运算符 ==、!=、>=
- 逻辑运算符
- & 逻辑与 两个操作数都是true,结果才为true,不论左边结果,两边都会运算
- | 逻辑或 两个操作数一个是true,结果才为true,不论左边结果,两边都会运算
- ^逻辑异或 两个操作数相投,结果为true,不同为false
- !逻辑非 操作数为true结果为false,操作数为false结果为true
- && 短路与 如果左边为false右边将不会运算
- || 短路或 如果左边为true右边将不会运算
- 位运算符 &、|、^
- 条件运算符 又称三元运算符 格式:条件?表达式1:表达式2; 如果结果为true返回1的值,flase返回2的值
boolean t=money<100;
String tc=t==true?"低于100":"不低于100";
运算符优先级
- 最高的优先级:小括号,即( ) //小括号对i++没用
- 最低的优先级:赋值运算符,即=
- 优先级顺序:算术运算符>关系运算符>逻辑运算符
获得键盘输入的数据
格式
导入Scanner类
import java.util.* //ctrl+shift+o
创建Scanner对象
Scanner input = new Scanner(System.in);
-
获取键盘输入的数据
int num = input.nextInt();
String next()
Int nextInt();
double nextDouble();
boolean hasNext 判断是否有数据输入
判断输入数是否为整形
if (input.hasNextInt()) {
int one = input.nextInt();
}
生一个0-9的随机数:
int random = (int) (Math.random() * 10);
选择结构与循环结构
选择结构
if控制语句
- if语句基本格式
if(表达式 必须是布尔值)
{
语句
}
- if-else语句基本格式
if(表达式 必须是布尔值){
语句1
}else{
语句2
}
- 多重if基本格式
if(表达式 必须是布尔值){
语句1
}else if{
语句2
}else{
语句3
}
- 嵌套if基本格式
If(表达式){
If(表达式){
}else{
语句1
}
}else{
语句2
}
equals用法
断字符串和变量的值是否相等
if(常量.equals(变量))
switch语句
- switch语句格式
switch (表达式) {
case 常量 1:
语句;
break;
case 常量 2:
语句;
break;
default:
语句;
break;
}
- switch后面的表达式只能是int、short、byte、char、枚举、String类型
- case常量 数据类型必须与switch数据类型相等
- default在最后找不到匹配值时运行
循环结构
while语句
- while语句格式
while(循环条件布尔类型值){
循环体
}
- do while语句格式
do{
循环体
}while(循环条件布尔类型);
while和do while的区别是while是判断在执行,do-while是先执行后判断
for语句循环与跳转
-
for循环语法和执行顺序:
for可以定义多个变量但只能是同一种类型 for(int i=0,j=6;i>j;i++,j--)
for(;;){}
表达式全省略,无条件判断,循环变量无改变,
应在循环体内设法结束循环;否则会造成死循环
-
跳转
break常用于switch结构和循环结构中
continue一般用于循环结构中
用(循环结构中):
break语句终止某个循环,程序跳转到循环块外的下一条语句(break在循环嵌套中只能跳出一个循环)
continue跳出本次循环,进入下一次循环
return结束当前方法执行并退出返回到调用该方法的语句处
二重循环
for(循环条件1) {
//循环操作1
for(循环条件2) {
//循环操作2
}
}
所有循环都可以相互嵌套
冒泡排序
将升序数组排序
for (int i = 0; i < scores.length - 1; i++) {
for (int j = 0; j < scores.length - 1 - i; j++) {
if (scores[j] > scores[j + 1]) {
int temp = 0;
temp = scores[j];
scores[j] = scores[j + 1];
scores[j + 1] = temp;
}
}
}
数组
- 数组的下标从0开始
- 数组大小必须指定
- 在向数组中添加获取元素时, 必须在范围之内, 不能超过长度,否则程序异常
- 添加数据,如果对象的空间没有存储信息, 对应空间内是存在默认值.比如int[]数组,默认值为0
- 数组.length属性返回是数组的实际长度(大小)
声明数组
- 声明数组
int[]=a;
//声明数组时不规定数组长度 - 分配空间
a=new int[5];
- 赋值
a[0]=8;
- 处理数据
a[0]=a[0]*10;
声明数组并分配空间:数据类型[ ] 数组名 = new 数据类型[大小] ;
边声明并赋值:
int[ ] score = {89, 79, 76};
int[ ] score = new int[ ]{89, 79, 76};
二维数组声明方法
int [][]socres;
scores=new int[5][50];
//或者
int [][]socres=new int[5][50];
二维数组声明并复制方法
int [][]socres=new int[][]{{90,80,70},{60,50},{40}};
//或者
int [][]socres={{90,80,70},{60,50},{40}};
动态地从键盘录入信息并赋值:
一维数组
Scanner input = new Scanner(System.in);
for(int i = 0; i < 30; i ++){
score[i] = input.nextInt();
}
二维数组
for(int i=0;i<arrys.length;i++){
for(int j=0;j<arrys[i].length;j++){
arrys[i][j] = input.nextInt();
}
}
使用java.util.Arrays类
int[] arrs = { 10, 52, 3, 62, 1, 20 }; //声明数组
int[] newArrs = Arrays.copyOf(arrs, 2); //使用 Arrays.copyOf(arrs, 2)方法复制arrs的前两个数到newArrs里
System.out.println(Arrays.toString(arrs)); //使用toString(arrs)方法把arrs转换成字符串打印出来
System.out.println(Arrays.toString(newArrs));
Arrays.sort(arrs); //使用Arrays.sort(arrs)方法,将数组内的值进行升序排序
int index = Arrays.binarySearch(arrs, 1); //使用Arrays.binarySearch(arrs, 1)方法找到值为1的数组下标,使用这个方法之前必须将数组排序
System.out.println(index);
综合实战 订餐系统
package java09;
import java.util.Scanner;
public class OderingMgr {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// 菜品初始化
String[] dishNames = new String[3];
double[] prices = new double[3];
int[] zans = new int[3];
// 订单初始化
String[] names = new String[4];
String[] dishInfo = new String[4];
int[] times = new int[4];
String[] addresses = new String[4];
int[] statuses = new int[4];
double[] sum = new double[4];
// 菜品赋值
dishNames[0] = "红烧带鱼";
dishNames[1] = "鱼香肉丝";
dishNames[2] = "时令蔬菜";
prices[0] = 38.0;
prices[1] = 20.0;
prices[2] = 10.0;
// 订单赋值
names[0] = "张请";
names[1] = "张请";
dishInfo[0] = "鱼香肉丝 2份";
dishInfo[1] = "红烧带鱼 2份";
times[0] = 12;
times[1] = 18;
addresses[0] = "天成路207号";
addresses[1] = "天成路207号";
statuses[0] = 1;
statuses[1] = 0;
sum[0] = 76.0;
sum[1] = 45.0;
while (true) {
System.out.println("欢迎使用“吃货联盟订餐系统”");
System.out.println("**********************************”");
System.out.println("1、我要订餐");
System.out.println("2、查看餐袋");
System.out.println("3、签收订单");
System.out.println("4、删除订单");
System.out.println("5、我要点赞");
System.out.println("6、退出系统");
System.out.println("**********************************”");
// 输入选择
System.out.print("请选择:");
int num = input.nextInt();
// 系统判断
switch (num) {
case 1:
for (int j = 0; j < names.length; j++) {
// 判断订单数组是否超出最大长度
if (names[j] == null) {
System.out.println("***我要订餐***");
// 输入姓名
System.out.println("请输入姓名:");
String inName = input.next();
// 遍历数组,打印输出菜单
System.out.println("序号\t菜名\t单价\t点赞数");
for (int i = 0; i < names.length; i++) {
if (names[i] != null) {
System.out.println((i + 1) + "\t" + dishNames[i] + "\t" + prices[i] + "\t" + zans[i]);
}
}
// 输入菜品编号
System.out.print("输入菜品序号:");
int choose = input.nextInt();
// 输入份数
System.out.print("请输入份数:");
int dishNum = input.nextInt();
// 输入送餐时间 10-20之间 否则重新输入
System.out.print("请输入送餐时间(10-20):");
int time = input.nextInt();
while (!(time >= 10 && time <= 20)) {
System.out.print("请重新输入送餐时间(10-20):");
time = input.nextInt();
}
// 输入地址
System.out.print("请输入地址:");
String inAddr = input.next();
// 订餐成功输出
System.out.println("订餐成功!");
System.out.println("您订的是:" + dishNum + "份" + dishNames[choose - 1]);
System.out.println("送餐时间:" + time + "点");
double dishSum = dishNum * prices[choose - 1];
int peiSong = 6;
if (dishSum >= 50) {
peiSong = 0;
}
System.out.println("餐费:" + dishSum + ",送餐费:" + peiSong + ",共计:" + (peiSong + dishSum));
// 遍历数组,去数组查询null的索引下标,储存目前数据
// statuses默认为0,不用储存
for (int i = 0; i < names.length; i++) {
if (names[i] == null) {
names[i] = inName;
dishInfo[i] = dishNames[choose - 1] + " " + dishNum + "份";
times[i] = time;
addresses[i] = inAddr;
sum[i] = peiSong + dishSum;
j += names.length;
break;
}
}
// 如果j==数组的最后一个下标,则组数即将超出长度
} else if (j == names.length - 1) {
System.out.println("无法订餐,餐单已满,请清理餐单!");
}
}
break;
case 2:
System.out.println("***查看餐袋***");
System.out.println("序号\t订餐人\t餐品信息\t\t送餐时间\t送餐地址\t\t总金额\t订单状态");
// 输出订单信息
for (int i = 0; i < names.length; i++) {
// 验证数组中字符串元素是否为null,在不为null的情况下输出结果
if (names[i] != null) {
String status = statuses[i] == 0 ? "已预定" : "已完成";
System.out.println((i + 1) + "\t" + names[i] + "\t" + dishInfo[i] + "\t" + times[i] + "\t"
+ addresses[i] + "\t" + sum[i] + "\t" + status);
}
}
break;
case 3:
System.out.println("***签收订单***");
// 接收订单号
System.out.println("请选择签收订单的订单号:");
int choose = input.nextInt();
boolean status = false; // 设置没有找到订单
// 遍历数组
for (int i = 0; i < names.length; i++) {
// 找到顶符合条件的订单 0已预定 1已完成
// 修改符合条件订单的statuses
if (names[i] != null && statuses[i] == 0 && i == choose - 1) {
statuses[i] = 1;
System.out.println("订单已签收!");
status = true; // 设为找到订单
} else if (names[i] != null && statuses[i] == 1 && i == choose - 1) {
System.out.println("订单已经完成,无法再次签收!");
status = true; // 设为找到订单
}
}
if (!status) {
System.out.println("您选择的订单不存在!");
}
break;
case 4:
System.out.println("***删除订单***");
// 接收要删除的订单号
System.out.println("请输入要删除的订单号:");
int delNum = input.nextInt();
int delStatus = 0;
// 遍历组数
for (int i = 0; i < names.length; i++) {
// 查询删除下标是否有值
if (names[i] != null && i == delNum - 1) {
// 查询statuses并记录删除下标的状态 1.已完成 2.已预约 3.没有找到
if (statuses[i] == 1) {
delStatus = 1;
} else if (statuses[i] == 0) {
delStatus = 2;
}
}
}
// 验证三种情况
if (delStatus == 1) {
// 移位
for (int i = delNum - 1; i < names.length - 1; i++) {
names[i] = names[i + 1];
dishInfo[i] = dishInfo[i + 1];
times[i] = times[i + 1];
addresses[i] = addresses[i + 1];
statuses[i] = statuses[i + 1];
sum[i] = sum[i + 1];
}
// 初始化数组最后一个值
names[names.length - 1] = null;
dishInfo[dishInfo.length - 1] = null;
times[times.length - 1] = 0;
addresses[addresses.length - 1] = null;
statuses[statuses.length - 1] = 0;
sum[sum.length - 1] = 0;
System.out.println("成功删除!");
} else if (delStatus == 2) {
System.out.println("订单没有完成,无法删除!");
} else {
System.out.println("没有找到订单!");
}
break;
case 5:
System.out.println("***我要点赞***");
// 接受餐品编号
System.out.println("请输入要点赞菜品的编号:");
choose = input.nextInt();
boolean zan = false; // 没有找到订单
// 循环遍历
for (int i = 0; i < zans.length; i++) {
// 判断要点赞的内容是否有值
if (dishNames[i] != null && i == choose - 1) {
zans[i]++;
zan = true; // 设为找到订单
}
}
// 判断没有找到订单
if (!zan) {
System.out.println("您选择的订单不存在!");
}
// 符合条件zans+1 else没有找到
break;
//
case 6:
System.out.println("结束退出");
System.exit(0);
default:
System.out.println("序号不存在请重新输入");
continue;
}
// 结束程序
System.out.print("输入0返回,任意键退出:");
num = input.nextInt();
if (num != 0) {
System.out.println("结束退出");
break;
}
}
}
}
面向对象程序设计
类和对象的关系
- 类是抽象的概念,仅仅是模板
- 对象是一个你能看得到、摸得着的具体实体
定义类
-
定义类
/* [访问修饰符] class 类名{ //省略类的内部具体代码 } */ public class Person{ //省略类的内部具体代码 }
- 访问修饰符如public、private等是可选的
- class是声明类的关键字
- 按照命名规范,类名首字母大写
-
属性
Java中类的内部主要包含属性和方法。对象所拥有的特征在类中表示时称为类的属性。
/* [访问修饰符] 数据类型 属性名; */ public class Person{ public String name; public String gender; public int age; }
-
方法
3.1 创建一个方法
/* [访问修饰符]返回类型 方法名称(参数类型 参数名1,) */ public class Person{ public String name; public String gender; public int age; //工作的行为 public void work(){ System.out.println(this.name+"的工作理念:干活挣钱有饭吃"); } }
3.2 方法重载
//无参的工作方法 public void work(){ System.out.println(this.name+"的工作理念:干活挣钱有饭吃"); } //有参的工作方法 public void work(String contect){ System.out.println(this.name+"的工作理念:"+contect); }
- 在同一个类中
- 方法名相同
- 参数的个数或类型不同
- 方法的返回值不能作为判断方法之间是否构成重载的依据。
-
构造方法
4.1 构造方法的定义
[访问修饰符]方法名([参数列表]){ //....省略方法代码 } public class Person{ public string name; public Person(){ this.name="张三"; } }
4.2 构造方法重载
public class Person{ public string name; //无参构造方法 public Person(){ this.name="张三"; } } //带参构造方法 public Person(String name){ this.name = name; }
定义对象
-
创建一个对象
类名 对象名 = new 类名();
- new是关键字
- 左边的类名对象的数据类型
- 右边的类名()称为类的构造方法
-
使用对象
对象名.属性 //引用对象的属性 对象名.方法名() //引用对象的方法
-
对象数组
public class Person{ public int age; public String name; public Person(String name.int age){ this.age = age; this.name = name; } } Person [] person = new Person[30]; //创建一个对象数组 Person[] person ={new Person(22,"张三"),new Person(23,"李四")}; //创建数组对象并赋值
封装的步骤
- 修改属性的可见性
- 将类中属性由public修改为private即可。
- 设置setter/getter()方法
- 快捷键 shift+atl+s,选择Generate Getters and Setters
- 可以在setter方法里设置限制
访问修饰符
static关键字
- 用static关键字修饰属性:用static修饰的属性称为静态变量或者类变量,没有使用static修饰的属性称为实例变量。
- 用static关键字修饰方法:用static修饰的方法称为静态方法或者类方法,不用static关键字修饰的方法称为实力方法。
- static方法不能操作实例变量。
静态变量和方法属于类管理,实例属于对象管理
继承和多态
- 继承符合is-a关系 例 Dog is a Pet
- 使用关键字extends复用
使用继承
//编写父类
class Pet{
//公共的属性和方法
}
//编写子类,继承父类
class Dog extends Pet{
//子类特有的属性和方法
}
class Penguin extends Pet{
}
不能被父类继承的成员有:
- private成员
- 子类与父类不在同包 使用默认访问权限的成员
- 构造方法
子类访问父类
- super关键字来访问父类的成员
- super只能出现在子类的方法和构造方法中
- super调用构造方法时,只能是第一句
- super不能访问父类的private成员
-
访问父类构造方法
super(); super(name);
- 在子类中没有显示调用父类的构造函数, 子类默认调用父类的无参数构造
- 如果父类没有提供无参数构造,并且提供了有参数构造,
- 子类必须手动调用父类的有参数构造
-
访问父类属性
super.name;
-
访问父类方法
super.print();
多重继承关系的初始化顺序
方法重写
构造方法不能重写,因为构造方法不能被继承
方法重载与方法重写
抽象类和抽象方法
关键字 abstract
抽象类不能被实例化
抽象类可以有0~多个抽象方法
抽象方法没有方法体
抽象方法必须在抽象类里
-
抽象方法必须在子类中被实现,除非子类是抽象类
//抽象类 public abstract class Pet{ //抽象方法 public abstract void print(); }
final用法
使用final类
-
Dog类不希望被继承
public final class Penguin extends Pet { //… }
-
方法不希望被重新
public final void print () { //… }
-
属性值不希望被修改
public class Penguin { final String home ="南极";// 居住地 public void setHome(String name){ this.home=home; //错误,不可再赋值 } }
多态
实现多态的三个要素
- 编写具有继承关系的父类和子类
- 子类重写父类方法
- 使用父类的引用指向子类的对象
- Pet pet =new Dog();//向上转型,自动类型转换
实现多态的两种形式
-
使用父类作为方法形参
//主人类 public class Master { public void feed( Pet pet ) { pet.eat(); } } //测试方法 Pet pet = new Dog(); Master master = new Master(); master.feed( pet );
-
使用父类作为返回值类型
public class Master { public Pet getPet(String typeId ){ … … } }
instanceof运算符
对类的类型进行判断
语法
- 对象 instanceof 类或接口
父类到子类的转换
instanceof通常和强制类型转换结合使用
public class Master {
public void play(Pet pet){
if (pet instanceof Dog) { //如果传入的是狗狗
Dog dog = (Dog) pet;
dog.catchingFlyDisc();
}else if (pet instanceof Penguin) { //如果传入的是企鹅
Penguin pgn = (Penguin) pet;
pgn.swimming();
}
}
}