Java
目录
一、Java入门
1.常见的CMD命令
| 盘符名称+冒号 | 盘符切换 | dir | 查看当前路径下的内容(包括隐藏内容) |
|---|---|---|---|
| CD目录 | 进入目录 | CD.. | 退出当前目录 |
| cd\目录1\目录2... | 进入多级目录 | cd\ | 回退到盘符目录 |
| cls | 清屏 | exit | 退出命令提示窗口 |
2.Java三大平台
-
Java SE ——Java语言(标准版)。用于左面与应用开发,是其他两个版本的基础。
-
Java ME —— Java语言(小型版),用于嵌入式电子设备或小型移动设备。
-
Java EE ——Java语言(专业版),用于web方向的网站开发。
3.Java作用
-
桌面应用开发
-
企业级应用开发
-
移动应用开发
-
科学计算(matlab)
-
大数据开发
-
游戏开发
4.Java主要特征
-
面向对象
-
安全性
-
多线程
-
简单易用
-
开源
-
跨平台(window、mac、Linux)
-
跨平台原理
-
高级语言的编译方式:
-
编程:Java程序员写.java代码,c语言程序员写.c代码。
-
编译:机器只认识0011的机器语言,把.Java.c.py的代码转换成机器能认识的过程
-
编译型:C语言,全部翻译再运行,存在兼容性问题,非跨平台
-
解释型:py语言,按行翻译,再运行,
-
混合型:Java语言,混合翻译,在虚拟机内运行
-
-
运行:让机器执行编译后的指令
-
-
-
5.JDK和JRE
-
JDK是Java开发工具包
-
JVM虚拟机:Java运行的地方
-
核心类库:Java已经写好的东西,我们可以直接用
-
-
JRE是Java运行环境
-
包括JVM、核心类库、运行工具
-
-
JDK包含了JRE,JRE包含了JVM
二、Java基础语法
1.注释
-
单行 //
-
多行 /* */
-
文档 /** */
2.字面量
字面量告诉程序员的书写格式
分类:
| 字面量类型 | 说明 | 举例 |
|---|---|---|
| 整数类型 | 不带小数点的数字 | 888 |
| 小数类型 | 带小数的数字 | 13.12 |
| 字符串类型 | 双引号引起来的内容, | "HelloWorld","六神花露水" |
| 字符类型 | 用单括号引起来的内容,内容个数只能有一个 | 'A'、'0'、'我' |
| 布尔类型 | 布尔值,表示真假 | 只有两个值:true,false |
| 空类型 | 一个特殊的值,空值 | 值为:null |
特殊字面量:'\t' '\r' '\n'
-
'\t':制表符——缩进、对齐(字符串长度补齐到8位)、补空格
-
空类型:null
3.变量
数据类型:限定了变量能存储数据的类型
变量名:存储空间名字
作用:方便使用
idea变量批量修改:shift+f6
定义格式:数据类型 变量名 = 数据值;
输出打印、参与运算、修改记录的值
注意:
-
只能存一个值
-
变量名不允许重复定义
-
一条语句可以定义多个变量
-
变量在使用前一定要先进行赋值
-
变量的作用域范围
4.计算机的存储规则
在计算机中任意数据都是以二进制存储
存储数据:
-
Text文本
-
数字、字母、汉字
-
-
Image图片
-
黑白图、灰度图、彩色图
-
分辨率、像素、三原色(红绿蓝)
-
-
Sound声音
不同进制在代码中的表现形式
-
二进制:由0,1组成,ob开头
-
十进制:由0~9组成,无前缀
-
八进制:0~7组成,以0开头
-
十六进制:0~9和a~f组成,以0x开头
进制转换:
-
任意进制转换成十进制
-
公式:系数*基数的权次幂 相加
-
-
十进制转换成任意进制
-
除基取余法
-
5.数据类型
基本数据类型

整数和小数取值的大小范围关系:
double>float>long>int>short>byte
字符串String
6.标识符
标识符命名规则——硬性要求
-
必须由数字、字母、下划线(_)和美元符号($)组成
-
不能以数字开头
-
不能是关键字
-
区分大小写
标识符命名规则——软性要求
-
小驼峰命名法:方法、变量
-
标识符为一个单词时全是小写
-
标识符为多个单词组成时,第一个单词首字母小写,其他单词首字母大写
-
-
大驼峰命名法:类名
-
标识符是一个单词时首字母大写;
-
标识符为多个单词组成时每个单词首字母要大写
-
-
标识符见名知意
7.键盘录入
Java已有一个Scanner类,该类可以接收键盘输入的数字
-
导包——
import java.util.Scanner;
-
创建对象——
Scanner sc = new Scanner(System.in); //上面这个格式里面,只有sc是变量名,可以变,其他不能改变
-
接收数据——
int i = sc.nextInt(); //在这个格式里面只有i是变量名,可以变,其他不能变。
第一套体系
nextInt();接收整数,
nextDouble();接收小数和整数
next;接收字符串
遇到空格、制表符,就停止接收
第二套体系
next Line();按行接收,
可以接收空格、制表符,遇到回车停止接收
获取随机数
-
导包——
import java.util.Random;
-
创建对象——
Random sc = new Random(); //上面这个格式里面,只有sc是变量名,可以变,其他不能改变
-
接收数据——
int number = sc.nextInt(101); //在这个格式里面只有101是随机数的范围,左闭右开范围是0~100,默认从0开始, int number = sc.nextInt(50)+5; //这个随机数范围是5~54,这是改变随机数最小值的方法
8.运算符
(1).运算符和表达式
运算符:对字面量或者变量进行操作的符号
例如:+/-*
表达式:用运算符把字面量或变量连接起来,符合Java语法的式子
例如:a=b+c
-
算术运算符
| 符号 | 作用 |
|---|---|
| + | 加 |
| - | 减 |
| * | 乘 |
| / | 除 |
| % | 取余 |
取余 应用场景:
可以判断A是否被B整除
可以判断A是否是偶数。为零是偶数,为1是奇数
注意:
-
整数参与计算,结果只能得到整数。
-
小数参与运算结果可能不精确。
快速书写主函数:psvm + Tab/Enter
快速写输出函数:sout + Tab/Enter
练习:
输入任意数字,返回个位十位百位....
数值拆分:个位:数值%10;十位:数值/10%10;百位:数值/100%10....
数字相加,10+12.3
隐式转换:
1.将取值范围小的转换成取值范围大的
int a=10; double b=a;//b=10.02.byte short char 三种类型的数据在运算的时候,都会直接先转换成int,再计算。
byte a = 10; byte b = 20; //c=a+b;转换后再相加,则C为int类型3.取值范围:byte<short<int<long<float<double
4.什么时候转换:数据类型不一样,不能计算,需要转换成一样时
强制转换
格式
目标数据类型 变量名 = (目标数据类型) 被强转的数据;
byte a=10; int b = (int) a字符串的“+”操作
当“+”操作中出现字符串时,这个“+”是字符串的连接符,而不是算数运算符。
System.out.println(3.1+"abc");//"3.1abc" System.out.println("abc"+trun);//"abctrue" System.out.println('中'+"abc"+trun);//"中abctrue" System.out.println(1+2+"abc"+1+2);//"3abc12" System.out.println("a"+1);//"98"——字符加数字即字符对应的ASCII编码加数字
-
自增运算符
| 符号 | 作用 | 说明 |
|---|---|---|
| ++ | 加 | 变量加1 |
| -- | 减 | 变量减1 |
++和--无论是放在变量的前面还是变量的后面,单独写一行结果是一样的。
int a=10; a++; System.out.println(a);//11 ++a; System.out.println(a);//12 a--; System.out.println(a);//11 --a; System.out.println(a);//10++和--参与运算时,放在左边还是右边结果是不一样的
int a=10; int b=a++; //b=10————先用再加 int a=10; int b=++a; //b=11————先加再用 ************************************** int x=10; int y=x++; System.out.println(y);//10 int z=++x; System.out.println(z);//12 System.out.println(x);//12
-
赋值运算符
| 符号 | 作用 | 说明 |
|---|---|---|
| = | 赋值 | int a=10;将10赋值给变量a |
| += | 加后赋值 | |
| -= | 减后赋值 | |
| *= | 乘后赋值 | |
| /= | 除后赋值 | |
| %= | 取余后赋值 |
-
关系运算符
| 符号 | 说明 |
|---|---|
| == | 判断是否相等,等于返回true,不等返回false |
| != | 判断是否不等 |
| > | 判断是否大于 |
| >= | 判断是否大于等于 |
| < | 判断是否小于 |
| <= | 判断是否小于等于 |
注意关系运算符的结果都是Boolean类型,要么是true,要么是false
-
逻辑运算符
| 符号 | 作用 | 说明 |
|---|---|---|
| & | 与 | 并且,两边都为真才是真 |
| | | 或 | 或者,两边都是假才是假 |
| ^ | 异或 | 相同为假,不同为真 |
| ! | 非 | 取反 |
-
短路逻辑运算符
提升代码运算效率
| 符号 | 作用 | 说明 |
|---|---|---|
| && | 短路与 | 结果和&相同,但是有短路效果(前面不满足则不执行后面) |
| || | 短路或 | 结果和|相同,但是有短路效果(前面满足不执行后面) |
#####
-
三元运算符
格式:关系表达式?表达式1:表达式2;
int number1 = 10,number2 = 20;
int a = number1>number2 ? number1:number2;
System.out.println(a);
-
运算符的优先级
小括号优先于所有
(2).判断和循环
-
顺序结构
代码按顺序执行
-
分支结构
-
if语句
if(关系表达式1){ 语句体1; }ielse if(关系表达式2){ 语句体2; }else(关系表达式3){ 语句体3; } -
switch语句
switch(表达式){ case 值1: 语句体1; break; case 值2: 语句体2; break; ....... default: 语句体n; break; }注意:
-
表达式:(将要匹配的值)取值为byte、short、int、char。
-
case:后面跟的是要和表达式进行比较的值,(被匹配的值)。
-
break:跳出循环,不能缺省,否则会造成case穿透。
-
default:都不匹配时执行该处内容。
-
case后面的值只能是字面量,不能是变量。
-
case后面的值不能重复。
简化写法
switch(表达式){ case 值1 ->语句体1 case 值2 ->语句体2 ....... default ->语句体n } -
-
-
循环结构
-
for循环
for(初始化语句;条件判断语句;条件控制语句){
循环提语句;
}
-
自增变量后面不能使用
-
知道循环范围或次数时使用
-
-
while循环
while(条件判断语句){
循环体语句;
条件控制语句;
}
-
先判断后执行,自增变量后面还可以使用
-
不知道循环范围和次数时使用
-
-
do...while循环
do{
循环体语句;
条件控制语句;
}while(条件判断语句);
-
先执行后判断
-
-
循环高级综合练习
-
无限循环
循环条件判断为true。
-
跳转循环控制语句
-
continue:跳出本次循环,执行下次循环。
-
break:结束整个循环。
-
-
练习
1.求输入数字的平方根
Scanner sc = new Scanner(System.in); System.out.println("请输入要开方的数字"); int number = sc.nextInt(); for (int i = 1; i <= number; i++) { int temp = i * i; if (temp == number) { System.out.println(number + "的平方根是:" + i); break; } else if (temp < number) { continue; } else if (temp > number) { System.out.println(number + "的平方根整数是:" + (i - 1)); break; } }2.判断输入整数是否为质数
Scanner sc = new Scanner(System.in); System.out.println("请输入一个整数"); int number = sc.nextInt(); boolean temp = true; for (int i = 2; i < number; i++) { if(number%i==0){ temp=false; break; } } if(temp){ System.out.println(number+"是质数"); }else { System.out.println(number+"不是质数"); }3.猜数字小游戏
Random sc = new Random(); int number = sc.nextInt(101); Scanner s = new Scanner(System.in); while (true){ System.out.println("猜数字"); //将输入值放入循环内部,所猜的值就会一直变化 int gusset = s.nextInt(); if (number>gusset){ System.out.println("小了"); continue; } else if (number<gusset) { System.out.println("大了"); continue; }else { System.out.println("猜对了"); break; }
-
-
9.数组
1.数组介绍
数组是一种容器,可以用来存储同种数据类型的多个值
-
数组容器在存储数据时,需要结合隐式转换考虑
-
建议容器类型和存储的数据类型保持一致
2.数组定义和静态初始化
//定义
1.数据类型【】 数组名
int [] array;
2.数据类型 数组名【】
int array[];
数组的静态初始化
- 初始化:就是在内存中,为数据容器开辟空间,并将数据存入容器中的过程
- 简化格式:数据类型【】数组名={元素1,元素2,.....};
//字符串类型String
string[] array={"zhang","wang","li"};
string[] array=new string[]{"zhang","wang","li"};//完整格式
数组元素访问
3.数组的地址值表示数组在内存中的位置
int[] array = {1,2,3,4,5};
System.out.println(array);//结果是数组位置
4.数组遍历
int[] array = {1,2,3,4,5};
int len = array.length; //获取数组长度的函数length,获取字符串长度的函数size()
for (int i = 0; i < len; i++) {
System.out.println(array[i]);
}
5.数组动态初始化
初始化时只指定数组的长度,由系统为数组分配初始值。
数据类型 【】 数组名=new 数据类型【数组长度】;
int [] arr = new int[3];
arr[0]=1; arr[1]=2; arr[2]=3;
默认初始化类型规律
-
整数类型:默认初始化为0
-
小数:0.0
-
字符:'/u0000' 空格
-
布尔:false
-
引用数据类型:null
数组动态初始化和静态初始化的区别
-
动态初始化:手动指定数组长度,由系统给出默认初始化值
只明确数组长度,不知道具体数值
-
静态初始化:手动指定数组元素,系统会根据数组元素个数计算出数组长度
需求明确已经要求操作的具体数据
6.数组内存图
7.数组常见问题
-
索引越界异常
8.二维数组
1.二维数组的静态初始化
//格式 数据类型【】【】数组名=new 数据类型【】【】{{元素1,元素2},{元素1,元素2}}; int [][] arr=new int[][]{{1,2},{11,22}}; //简化格式 数据类型【】【】数组名={{元素1,元素2},{元素1,元素2}}; int [][] arr={{1,2},{11,22}};2.获取元素
arr[i][j] i:获取二维数组里面的一维数组 j:表示一维数组的索引,获取一维数组的元素3.二维数组的动态初始化
数据类型【】【】数组名=new 数据类型【n】【m】; n:表示这个二维数组可以存放多少个一维数组; m:表示每一个一维数组可以存放多少个元素;
9.数组常见操作
求最值
//已知数组元素为{33,5,22,44,55},求最大最小值 int [] arr = {33,5,22,44,55}; int max = arr[0], min=arr[0]; //初始化值是数组元素就行 for (int i = 1; i < arr.length; i++) { //循环开始条件为1,提高循环效率 max = arr[i]>=max? arr[i]:max; min = arr[i]<=min? arr[i]:min; } System.out.println(max); System.out.println(min);遍历数组求和
Random sc=new Random(); int [] arr =new int[10]; for (int i = 0; i < arr.length; i++) { arr[i] = sc.nextInt(100)+1; } int sum =0,avg=0,count=0; for (int i = 0; i < arr.length; i++) { sum += arr[i]; } System.out.println("和"+sum); avg=sum/10; System.out.println("平均"+avg); for (int i = 0; i < arr.length; i++) { if(arr[i]<avg){ count++; } } System.out.println(count);//小于平均数的个数交换数组首尾元素
int [] arr = {1,2,3,4,5}; for (int i = 0,j= arr.length-1; i < j ; i++,j--) { int temp = arr[i]; arr[i]=arr[j]; arr[j]=temp; }打乱数组中的数据
int [] arr = {1,2,3,4,5}; Random sc=new Random(); for (int i = 0; i < arr.length; i++) { int t=sc.nextInt(5); int temp=arr[0]; arr[0]=arr[t]; arr[t]=temp; }
10.java内存分配
| 栈 | 方法运行时使用的内存,比如main方法运行,进入方法栈中执行 |
|---|---|
| 堆 | 存储对象或数组,new来创建的,都存储在堆内存 |
| 方法区 | 存储可以运行的class文件 |
| 本地方法堆 | JVM在使用操作系统功能时使用,和我们开发无关 |
| 寄存器 | 给CPU使用,与我们无关 |
-
只要是new出来的一定是在堆里面开辟了一个小空间
-
如果new了多次,那么在堆里面有多个小空间,每个小空间中都有各自的数据
11.方法
方法:程序当中最小的执行单元
意义:重复代码,具有独立功能的代码抽取到方法中,可以提高代码复用性、和可维护性。
自动抽取方法:CTRL+alt+M
1.方法定义
把一些代码打包在一起,该过程就是方法定义。
//简单定义 public static void 方法名(){ 方法体(就是打包起来的代码); } //有参数的调用 public static void 方法名(形参1,形参2){ 方法体(就是打包起来的代码); } //有返回值的调用 public static 返回值类型 方法名(){ 方法体(就是打包起来的代码); return 返回值; }形参:全体形式参数,方法定义中的参数
2.方法调用
方法定义后并不是直接运行的,需要手动调用才能执行,该过程称为方法调用。
//简单调用 方法名(); //含参数调用 方法名(实参1,实参2); //赋值调用 整数类型 变量名 = 方法名(实参); //输出调用 System.out.print(方法名(实参));实参:全体实际参数,方法调用中的参数
注意:参数调用时,参数的数量必须与方法定义中小括号里面的变量一一对应,(类型和数量)
注意:
-
方法不调用就不会执行
-
方法之间是平级关系,不能相互嵌套
-
方法的执行顺序和编写顺序无关
-
方法的返回值类型为void时,表明没有返回值,
-
return 语句表示结束方法,无返回值时可以省略,下方不能编写代码
3.方法重载
1.在同一个类中,定义了很多同名的方法,这些方法都有相同的功能
2.每个方法具有不同的参数类型和参数个数,与返回值无关,这些同名的方法,就构成了重载的关系
3.参数不同:个数不同、类型不同、顺序不同。
基本数据类型:变量中存放的是真实的数据
int a=10; int b=a;//b=10引用数据类型:(基本数据类型以外的)变量中储存的是地址值,数据值存放在其他空间。引用:使用了其他空间中的数据
int [] arr1 = {1,2,3,4}; int [] arr2 = arr1;//arr2和arr1共用一个地址
4.方法传递基本数据类型的内存原理
1.传递基本数据类型时,传递的是真实的数据,形参的改变,不影响实际参数的值
2.传递应用数据类型时,传递的是地址值,形参的改变,影响实际参数的值
5.练习
1.卖机票
//旺季(5~10),头等舱折扣9折,经济舱8.5折,淡季(11~4),头等舱7折,经济舱6.5折 Scanner sc = new Scanner(System.in); System.out.println("请输入机票原价"); int ticke = sc.nextInt(); System.out.println("请输入月份"); int month = sc.nextInt(); System.out.println("请输入座位:头等舱0,经济舱1"); int seat = sc.nextInt(); if (month >= 5 && month <= 10) { int price = getPrice(ticke, seat, 0.9, 0.85); System.out.println(price); } else if ((month <= 4 && month >= 1) || (month <= 12 && month >= 11)) { int price = getPrice(ticke, seat, 0.7, 0.65); System.out.println(price); } else { System.out.println("月份不对"); } } public static int getPrice(int ticke, int seat, double v1, double v2) { if (seat == 0) { ticke = (int) (ticke * v1); } else { ticke = (int) (ticke * v2); } return ticke; }2,找质数
//判断101~200之间有多少个质数,并打印所有质数 int count = 0; for (int i = 101; i <= 200; i++) { boolean flag = true; for (int j = 2; j < i; j++) { if (i % j == 0) { flag = false; break; } } if (flag) { System.out.println("数字" + i + "是质数"); count++; } } System.out.println("一共有" + count + "个质数");3.开发验证码
//定义方法随机生成一个5位的验证码, // 前四位是大写或小写字母,最后一位是数字 //1.大写字母和小写字母放入一个数组中 char[] arr = new char[52]; for (int i = 0; i < arr.length; i++) { if (i < 26) { arr[i] = (char) (97 + i); } else { arr[i] = (char) (65 + i - 26); } } String result = " "; //2.随机抽取4次 Random ra = new Random(); for (int i = 0; i < 4; i++) { int randomIndex = ra.nextInt(52); result = result + arr[randomIndex]; } //3.随机抽取0~9数字 int number = ra.nextInt(10); result += number; System.out.println(result);4.数组元素的复制
//把一个数组的元素复制到另一个新数组中去 int [] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int len = arr.length; int [] copyArr = new int[len]; int index=0; for (int i = 0; i < arr.length; i++) { copyArr[index]=arr[i]; index++; } for (int i = 0; i < copyArr.length; i++) { System.out.print(copyArr[i]+" "); }5.评委打分
public static void main(String[] args) { //去掉最高分和最低分,求平均分 int[] arr = getArr(); int max = getMax(arr); int min = getMin(arr); int sum=getSum(arr); int result=(sum-max-min)/4; System.out.println("平均分是"+result); } public static int[] getArr() { Scanner sc = new Scanner(System.in); int[] arr = new int[6]; for (int i = 0; i < arr.length; ) { System.out.println("请输入分数:"); int number = sc.nextInt(); if (number >= 0 && number <= 100) { arr[i] = number; i++; } else { System.out.println("分数只能在0~100之间,此时数组下标为" + i); } } return arr; } public static int getMax(int[] arr) { int max = arr[0]; for (int i = 1; i < arr.length; i++) { if (max < arr[i]) { max = arr[i]; } } return max; } public static int getMin(int[] arr) { int min = arr[0]; for (int i = 1; i < arr.length; i++) { if (min > arr[i]) { min = arr[i]; } } return min; } public static int getSum(int [] arr){ int sum=0; for (int i = 0; i < arr.length; i++) { sum+=arr[i]; } return sum; }6.数字加密
//加密规则:每位数字先加5,再对10取余,最后所有数字进行翻转 int[] arr = {1, 9, 8, 3}; for (int i = 0; i < arr.length; i++) { arr[i] = arr[i] + 5; } for (int i = 0; i < arr.length; i++) { arr[i] = arr[i] % 10; } for (int i = 0, j = arr.length - 1; i < j; i++, j--) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } int number = 0; for (int i = 0; i < arr.length; i++) { number = number * 10 + arr[i]; } System.out.println(number);7.把整数上的每一位都添加到数组当中
//加密规则:每位数字先加5,再对10取余,最后所有数字进行翻转 int number = 12345; int temp = number; int count = 0; while (number > 0) { number = number / 10; count++; } int[] arr = new int[count]; int index = arr.length-1; while (temp != 0) { int ge = temp % 10; temp = temp / 10; arr[index] = ge; index--; } for (int j : arr) { System.out.print(j + " "); }8.将加密的数据解密出来
//按照加密规则进行解密,加密规则:每位数字先加5,再对10取余,最后所有数字进行翻转 //先反转,5~9不变0~4+10,减5 int [] arr ={8,3,4,6}; for (int i = 0,j=arr.length-1; i < j; i++,j--) { int temp=arr[i]; arr[i]=arr[j]; arr[j]=temp; } for (int i = 0; i < arr.length; i++) { if(arr[i]>=0&&arr[i]<=4){ arr[i]=arr[i]+10; } } for (int i = 0; i < arr.length; i++) { arr[i]=arr[i]-5; } int number=0; for (int i = 0; i < arr.length; i++) { number=number*10+arr[i]; } System.out.println(number);9.抢红包
public static void main(String[] args) { //5个奖项,被抽过的不能再抽 int [] arr={2,588,888,1000,10000}; int [] newArr=new int[arr.length]; Random r=new Random(); for (int i = 0; i < 5; i++) { int index= r.nextInt(arr.length); int price=arr[index]; if(!contains(newArr,price)){ newArr[i]=price; i++;ss } } for (int i = 0; i < newArr.length; i++) { System.out.print(newArr[i]+" "); } } public static boolean contains(int [] arr, int price){ for (int i = 0; i < arr.length; i++) { if(arr[i]==price){ return true; } } return false; } ////改进 int [] arr={2,588,888,1000,10000}; Random r=new Random(); for (int i = 0; i < arr.length; i++) { int randomIndex=r.nextInt(arr.length); int temp=arr[i]; arr[i]=arr[randomIndex]; arr[randomIndex]=temp; } for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); }
12.面向对象
1.类和对象
类:是对象共同特征的描述;
对象:是真实存在的事物;
//类定义
public class 类名(){
1.成员变量(代表属性,一般是名词)
2.成员方法(代表行为,一般是动词)
3.构造器
4.代码块
5.内部类
}
//得到类对象
类名 对象名=new 类名();
//使用对象
访问属性: 对象名.成员变量
访问行为: 对象名.访问方法(...)
2.javabean类
1.用来描述一类事物的类,专业叫javabean类,在javabean类中无main方法。
2.以前编写main方法的类,叫做测试类。可以在测试类中创建JavaBean类的对象并进行赋值调用。
3.类名首字母大写,见名知意,驼峰模式。
4.一个java中可以定义多个class类,且只能一个类是public修饰。public修饰的类名必须是Java代码的文件名。实际开发中,建议一个文件一个class类
5.成员变量的完整定义是:修饰符 数据类型 变量名 = 初始化值;一般无需初始化,存在默认值。
对象成员变量的默认值规则
基本类型
byte、short、int、long :0
floa、double :0.0
Boolean :false
引用数据类型:
类、接口、数组、String :null
3.封装
定义:对象代表什么,就得封装对应的数据,并提供数据对应的行为
1.private
private关键字是一个权限修饰符
可以修饰成员(成员变量和成员方法)
被private修饰的成员变量,如果需要被其他类使用,提供相应的操作
提供“setXxx(参数)”方法,用于给成员变量赋值,方法用public修饰。
提供“getXxx(参数)”方法,用于获取成员变量值,方法用public修饰。
4.this关键字
成员变量:定义在方法外的变量
局部变量:定义在方法内的变量
就近原则:当局部变量和成员变量一样时,谁近用谁
加上this关键字则使用成员变量
privat int age = 20; public void getAge(){ int age=10; System.out.println(age);//10 System.out.println(this.age);//20 } private String name; public void setName(String name){ //左边表示成员变量的位置 //右边局部变量表示测试类中调用方法传递过来的数据 this.name=name; }
5.构造方法
定义:构造方法也叫构造器、构造函数
作用:在创建对象的时候给成员函数变量进行赋值的,虚拟机自动调用,给成员变量进行初始化的。
public class Student{ 修饰符 类名(参数){ 方法体; }特点:
方法名与类名相同,大小写也要一致
没有返回值类型,连void也没有
没有具体的返回值(不能由return带回结果数据)
注意:
如果没有定义构造方法,系统将给出一个默认的无参构造方法
如果定义了构造方法,系统将不再提供默认的构造方法
重载:
带参构造方法,和无参构造方法两着方法名相同,但是参数不同,这叫做构造方法的重载
无论是否使用,都需要手写无参构造方法和有参构造方法
6.标准JavaBean
1.类名见名知意
2.成员变量用private修饰
3.提供至少两个构造方法,无参和带全部参数
4.成员方法
提供每一个成员变量对应的setXxx()/getXxx()
如果还有其他行为要写上
7.快捷键
快速生成构造函数、setXxx()/getXxx()、
alt+insert
alt+fn+insert
插件PTG 1秒生成标准JavaBean:ctrl+shift+逗号
8.Static静态
静态成员被所有类的对象共享,不属于对象属于类,优先于对象存在
静态方法只能访问静态,非静态方法可以访问静态,静态方法无this关键字
调用方法:类名调用,对象名调用
9.API
API:应用程序编程接口
简单理解:API就是别人已经写好的东西,我们不需要自己编写,直接使用
java API:是指JDK中提供的各种功能的java类
10.创建String对象的两种方式
1.直接赋值
String name = "黑马程序员";2.new
构造方法 说明 public String() 创建空白字符串,不含任何内容 public String(String original) 根据传入的字符串,创建字符串对象 public String(char[] chs) 根据字符数组,创建字符串对象 public String(byte[] chs) 根据字节数组,创建字符串对象 String s1=new String(); String s2=new String("店面"); byte[] bytes={97,98,99,100}; String s4=new String(bytes); char[] chars={'a','b','c'}; String s5= new String(chars);
11.字符串
1),字符串的比较
| Boolean equals 方法(要比较的字符串) | 完全一样结果才是true,否则为false |
|---|---|
| Boolean equalsgnoreCase(要比较的字符串) | 忽略大小写比较 |
2),string
概述:表示字符串的类,定义了许多操作字符串的方法
构造方法+成员方法
| 方法 | 说明 |
|---|---|
| String() | 初始化新创建的 String对象,使其表示空字符序列。 |
String(byte[] bytes) | 通过使用平台的默认字符集解码指定的字节数组来构造新的 String 。 |
String(byte[] bytes, Charset charset) | 构造一个新的String由指定用指定的字节的数组解码charset 。 |
String(byte[] bytes, int offset, int length) | 通过使用平台的默认字符集解码指定的字节子阵列来构造新的 String 。 |
//==号比较
基本数据类型:比的是数据值.
引用数据类型:比的是地址值
String s1=new String("abc");
String s2="abc";
String s3="Abc";
System.out.println(s1==s2);//false
boolean result=s1.equals(s2);
System.out.println(result);//true
boolean result1=s1.equals(s2);
System.out.println(result1);//true
boolean result2=s1.equals(s3);
System.out.println(result2);//false
boolean result3=s1.equalsIgnoreCase(s3);
System.out.println(result3);//true
//练习1,已有账号密码,登录
String name="admin";
String KeyWord="123456";
Scanner sc =new Scanner(System.in);
int count=3;
while(true){
System.out.println("请输入用户名");
String username=sc.next();
System.out.println("请输入密码");
String userkeyword=sc.next();
if(name.equals(username)&&KeyWord.equals(userkeyword)){
System.out.println("登陆成功");
break;
}else {
count--;
if(count==0){
System.out.println("账号被锁定,请联系管理员");
break;
}
System.out.println("登录失败,还剩"+count+"次机会");
}
}
//练习2,遍历字符串
public char charAt(int index):根据索引返回字符
public int length():返回此字符串的长度
数组长度:数组名.length
字符串长度:字符串对象.length()
Scanner sc=new Scanner(System.in); System.out.println("请输入一个字符串"); String str = sc.next(); for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); System.out.println(c); }
//统计字符个数
键盘录入一个字符串,统计该字符串中大写字母字符,小写字母字符,数字字符出现的个数(不考虑其他字符)
Scanner sc = new Scanner(System.in); System.out.println("请输入一个字符串"); String str = sc.next(); int bigcount=0,smallcount=0,numbercount=0; for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); if(c>='a'&&c<='z'){ smallcount++; } else if (c>='A'&&c<='Z') { bigcount++; } else if (c>='0'&&c<='9') { numbercount++; } } System.out.println("大写"+bigcount+"个,小写"+smallcount+"个,数字"+numbercount+"个");
//拼接字符串
把数组变成字符串再返回
public static void main(String[] args) {
int [] arr = {1,2,3};
String pin = pin(arr);
System.out.println(pin);
}
public static String pin(int[] arr){
if(arr==null){
return "";
}else if (arr.length==0){
return "[ ]";
}
String result="[";
for (int i = 0; i < arr.length; i++) {
result+=arr[i];
}
result+="]";
return result;
}
//字符串的反转
public static void main(String[] args) { Scanner sc=new Scanner(System.in); System.out.println("请输入字符串"); String next = sc.next(); String fan = fan(next); System.out.println(fan); } public static String fan(String str){ String temp=""; for (int i = str.length()-1; i >=0 ; i--) { temp+=str.charAt(i); } return temp; }
//金额转换
将阿拉伯数字转换成中文带单位
public static void main(String[] args) { Scanner sc=new Scanner(System.in); int money=0; while (true){ System.out.println("请输入数字"); money = sc.nextInt(); if(money>=0&&money<9999999){ break; }else { System.out.println("金额无效"); } } //转换成大写 String moneyStr=""; while (true){ int ge = money%10; String capitalNumber = getCapitalNumber(ge); moneyStr=capitalNumber+moneyStr; //让拼接顺序与数字原顺序一致 money=money/10; if(money==0){ break; } } //前面补零,补齐7位 int count =7-moneyStr.length(); for (int i = 0; i < count; i++) { moneyStr="0"+moneyStr; } //插入单位 //定义一个数组表示单位 String[] arr = {"佰","拾","万","仟","佰","拾","元",}; String result=""; for (int i = 0; i < moneyStr.length(); i++) { char c = moneyStr.charAt(i); result = result+c+arr[i]; } System.out.println(result); } public static String getCapitalNumber(int number){ String [] str={"零","壹","贰","叁","肆","伍","陆","柒","捌","玖",}; return str[number]; }
//手机号屏蔽
String str="12345678910"; String start = str.substring(0, 3); String end = str.substring(7); String result=start+"****"+end; System.out.println(result);
//身份证查看
根据身份证判断男女和出生年月日
String id = "479027201405102125"; String year = id.substring(6, 10); String month = id.substring(10, 12); String day = id.substring(12, 14); System.out.println("出生:"+year+"年"+month+"月"+day+"日"); char gender = id.charAt(16); int num = gender - 48; if(num%2==0){ System.out.println("女"); }else { System.out.println("男"); }
//敏感词替换
Scanner sc= new Scanner(System.in); System.out.println("你说"); String talk = sc.next(); //定义一个敏感词库 String [] arr = {"TMD","CNM","SB","NC"}; for (int i = 0; i < arr.length; i++) { talk = talk.replace(arr[i],"***"); } System.out.println(talk);
3),StringBuilder
概述:可以看成一个容器,创建之后内容可变
作用:提高字符串的操作效率
构造方法2+成员方法4:
方法名 说明 public StringBuilder() 创建一个空白可变的字符串对象,不包含有任何内容 public StringBuilder(string str) 根据字符串的内容,来创建可变字符串对象 public StringBuilder append ( 任意类型) 添加数据,并返回对象本身 public StringBuilder reverse () 反转容器中的内容 public int length() 返回字符串长度 public String toString() 通过toString可以把StringBuilder 转化成String 打印StringBuilder 是打印属性值,非地址值。
StringBuilder sb = new StringBuilder(); sb.append(1); //添加字符串内容 sb.append(2.3); sb.append("abc"); System.out.println(sb);//12.3abc sb.reverse(); System.out.println(sb);//cba3.21 System.out.println(sb.length()); String temp = sb.toString(); System.out.println(temp);public static void main(String[] args) { //链式编程,调用一个方法时,不用接收返回结果,可以继续调用其他方法 int temp = getString().replace("a","w").length(); System.out.println(temp); } public static String getString(){ Scanner sc = new Scanner(System.in); System.out.println("输入"); String t = sc.next(); return t; } //以上添加字符串内容可以用链式编程 sb.append(1).append(2.3).append("abc");
//对称字符串
//键盘接收字符串,判断是否是对称字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入");
String str = sc.next();
String result = new StringBuilder(str).reverse().toString();
if (str.equals(result)) {
System.out.println("对称");
}else {
System.out.println("不对称");
}
//定义方法,把int数组按照指定格式拼接成字符串
public static void main(String[] args) {
int [] str = {1,3,4,5};
String t = reverse(str);
System.out.println(t);
}
public static String reverse(int [] str){
StringBuilder sb=new StringBuilder();
sb.append('[');
for (int i = 0; i < str.length; i++) {
sb.append(str[i]);
}
sb.append(']');
return sb.toString();
}
4),StringJoiner
概述:跟StringBuilder一样可以看成容器,创建之后里面的内容是可变的。
作用:提高字符串的操作效率,而且代码编写特别简洁,但是目前市场上很少有人用
构造方法2+成员方法3:
| 方法名 | 说明 |
|---|---|
| public StringJoiner(间隔符号) | 创建一个StringJoiner对象,指定拼接时的间隔符号 |
| public StringJoiner(间隔符号,开始符号,结束符号) | 创建一个StringJoiner对象,指定拼接时的间隔符号,开始符号,结束符号 |
| public StringJoiner add(添加的内容) | 添加数据,并返回对象本身 |
| public int length() | 返回长度(字符出现的个数) |
| public String toString() | 返回字符串(该字符串就是拼接成的) |
StringJoiner sj = new StringJoiner(",","[","]");
sj.add("aaa").add("bbb").add("ccc");
System.out.println(sj); //[aaa,bbb,ccc]
System.out.println(sj.length()); //13
System.out.println(sj.toString()); //[aaa,bbb,ccc]
5),字符串原理
内存原理
直接赋值会复用字符串常量池中的·
new出来不会复用,而是开辟一个新的空间
==号比较什么
基本数据类型比较数据值
引用数据类型比较地址值
字符串拼接原理
拼接无变量 ,编译后就是拼接后的结果,会复用串池里的字符串
拼接有变量 , 每一行拼接的代码,都会在内存中创建心得字符串,浪费空间资源
StringBuilder提高效率原理
所有要拼接的内容都会放入StringBuilder中,不会创建很多无用的空间,节约成本,节约内存
6),综合练习
//1,录入字符串0~9,转成罗马数字
//I-1,II-2,III-3,IV-4,V-5,VI-6,VII-8,IX-9
import java.util.Scanner;
import java.util.StringJoiner;
public class StringDemo1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
StringBuilder sb = new StringBuilder();
String str = "";
while (true) {
System.out.println("请输入字符串");
str = sc.next();
boolean flag = checkStr(str);
if (!flag) {
System.out.println("该字符串不符合要求,请重新输入!");
continue;
} else {
break;
}
}
for (int i = 0; i < str.length(); i++) {
char a = str.charAt(i);
String s = result((a - 48));
sb.append(s);
}
StringJoiner sj = new StringJoiner(",","[","]");
sj.add(sb);
System.out.println(sj);
sb.toString();
System.out.println(sb);
}
public static boolean checkStr(String str) {
if (str.length() > 9) {
return false;
}
for (int i = 0; i < str.length(); i++) {
char a = str.charAt(i);
if (a < '0' || a > '9') {
return false;
}
}
return true;
}
public static String result(int number){
String[] str = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
return str[number];
}
}
//2.调整字符串
//给定两个字符串,A和B,将A最左边字符移到最右边,在若干操作后,A变成B返回true,否则返回false。
public class main {
public static void main(String[] args) {
String str1= "abcde";
String str2= "cdeab";
System.out.println(check(str1,str2));
}
/*//法1
public static String rotate(String str){
char a = str.charAt(0);
String b = str.substring(1);
return b+a;
}*/
//法2:
public static String rotate(String str){
char [] arr = str.toCharArray();
char a = arr[0];
for (int i = 1; i < arr.length; i++) {
arr[i-1] = arr[i];
}
arr[arr.length-1] = a;
String st = new String(arr);
return st;
}
public static boolean check(String str1,String str2){
for (int i = 0; i < str1.length(); i++) {
str1 = rotate(str1);
if(str1.equals(str2)){
return true;
}
}
return false;
}
}
修改字符串内容:
用subString进行截取,再进行修改
把字符串变成数组toCharArray(),再进行修改
//键盘输入任意字符串,打乱其中内容
Scanner sc = new Scanner(System.in);
System.out.println("请输入字符串:");
String str = sc.next();
Random rd = new Random();
char [] arr = str.toCharArray();
for (int i = 0; i < arr.length; i++) {
int j = rd.nextInt(arr.length);
char temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
String result = new String(arr);
System.out.println(result);
//生成验证码
//大小写字母、数字、长度5。4位字母,1位数字,数字位置任意。
char[] arr = new char[52];
for (int i = 0; i < arr.length; i++) {
if (i < 26) {
arr[i] = (char) (97 + i);
} else {
arr[i] = (char) (65 + i - 26);
}
}
String result = " ";
//2.随机抽取4次
Random ra = new Random();
for (int i = 0; i < 4; i++) {
int randomIndex = ra.nextInt(52);
result = result + arr[randomIndex];
}
//3.随机抽取0~9数字
int number = ra.nextInt(10);
result += number;
System.out.println(result);
//4.打乱
char[] charArray = result.toCharArray();
for (int i = 0; i < charArray.length; i++) {
int index = ra.nextInt(charArray.length);
char temp = charArray[i];
charArray[i] = charArray[index];
charArray[index] = temp;
}
String re = new String(charArray);
System.out.println(re);
//给出两个字符串非负整数num1和num2,得出它们的乘积也是字符串。
String num1 = "1234";
String num2 = "10000";
//字符串变成整数
int num11 = become(num1);
int num22 = become(num2);
//相乘
int result = num11*num22;
//整数变成字符串
String str = Integer.toString(result);
System.out.println(str);
}
public static int become(String str){
char [] ch = str.toCharArray();
int result = 0;
for (int i = 0; i < ch.length; i++) {
result = result*10+(ch[i]-48);
}
System.out.println(result);
return result;
}
//给出字符串S,由单词组成,单词前后用空格隔开。
//返回最后一个单词的长度。
Scanner sc = new Scanner(System.in);
System.out.println("请输入字符串,单词用空格隔开");
String s = sc.nextLine();
char [] ch = s.toCharArray();
int count = 0;
System.out.println(ch.length);
for (int i = ch.length-1; i >=0; i--) {
if(ch[i] == ' '){
break;
}
count++;
}
System.out.println(count);
13,集合
在Java中,集合(Collection)是一组对象的容器,用于存储、操作和传输数据。Java集合框架提供了一组类和接口,用于表示和操作不同类型的集合对象。集合框架主要包括以下接口和类:
Collection 接口:是所有集合类的根接口,定义了集合的基本操作,如添加、删除、遍历等。
List 接口:继承自 Collection 接口,表示有序的集合,允许重复元素,常见的实现类有 ArrayList、LinkedList。
Set 接口:继承自 Collection 接口,表示不允许重复元素的集合,常见的实现类有 HashSet、TreeSet。
Map 接口:不属于 Collection 接口的一部分,用于表示键值对的映射关系,常见的实现类有 HashMap、TreeMap。
集合存储数据类型的特点:
-
不能存储基本数据类型,需要变成包装类
-
可存储引用数据类型
集合和数组对比
-
长度
-
数组长度固定
-
集合长度可变
-
-
存储类型
-
数组可以存基本数据类型和引用数据类型
-
集合可存引用数据类型,和保证类
-
构造方法和成员方法
| 方法名 | 说明 |
|---|---|
| ArrayList<String> 集合名 =new ArrayList<>(); | 创建一个空集合 |
| boolean add(E e) | 添加元素,返回值表示是否添加成功 |
| boolean remove(E e) | 删除元素,返回值表示是否删除成功 |
| E remove(int index) | 删除指定索引的元素,返回被删除元素 |
| E set(int index,E e) | 修改指定索引的元素,返回原来的元素 |
| E get(int index) | 获取指定索引元素 |
| int size() | 集合的长度,也就是集合中元素的个数 |
ArrayList<String> list =new ArrayList<>();
boolean re = list.add("aaa");
list.add("bb");
list.add("ccc");
list.add("aaa");
System.out.println("添加"+re); //添加true
System.out.println("添加后"+list); //添加后[aaa, bb, ccc, aaa]
boolean aaaa = list.remove("aaa");
System.out.println("删除"+aaaa); //删除true
String remove = list.remove(1);
System.out.println("删除指定下标的元素,被删除元素:"+remove); //删除指定下标的元素,被删除元素:ccc
String set = list.set(1,"bbbb");
System.out.println("修改指定下标元素,被修改元素:"+set); //修改指定下标元素,被修改元素:aaa
String get = list.get(0);
System.out.println("获取指定下标元素:"+get); //获取指定下标元素:bb
int len = list.size();
System.out.println("集合长度"+len); //集合长度2
System.out.println(list); //[bb, bbbb]
//练习
1,集合的遍历方式
ArrayList<String> list = new ArrayList<>();
list.add("你吃了吗?");
list.add("你喝了吗?");
list.add("你睡了吗?");
list.add("你想我了吗?");
System.out.print("[");
for (int i = 0; i < list.size(); i++) {
if(i==list.size()-1){
System.out.print(list.get(i));
}else {
System.out.print(list.get(i)+",");
}
}
System.out.println("]");
2,添加数字并遍历
//不能添加基本数据类型,应该添加基本数据类型对应的包装类
ArrayList<Integer> list = new ArrayList<>();
list.add(123);
list.add(234);
list.add(345);
list.add(456);
//其他同上
| 基本数据类型 | 所对应的包装类 |
|---|---|
| byte | Byte |
| short | Short |
| char | Character |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
| boolean | Boolean |
3,添加学生对象并遍历
//先创建学生类
public class Student {
private String name;
private String xuehao;
private int age;
private String gender;
public Student() {
}
public Student(String name, String xuehao, int age, String gender) {
this.name = name;
this.xuehao = xuehao;
this.age = age;
this.gender = gender;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getXuehao() {
return xuehao;
}
public void setXuehao(String xuehao) {
this.xuehao = xuehao;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
//测试类
//创建集合
ArrayList<Student> list = new ArrayList<>();
//创建学生对象
Student s1 = new Student("zhangsan", "123", 20, "女");
Student s2 = new Student("lisi", "124", 20, "男");
Student s3 = new Student("wangpin", "125", 20, "女");
//添加元素
list.add(s1);
list.add(s2);
list.add(s3);
//遍历
for (int i = 0; i < list.size(); i++) {
Student stu = list.get(i);
System.out.println(stu.getName() + "," + stu.getXuehao() + "," + stu.getAge() + ","+stu.getGender());
}
//以上练习改进成键盘录入学生信息
//创建集合
ArrayList<Student> list = new ArrayList<>();
//键盘录入学生
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();
String xuehao = sc.next();
int age = sc.nextInt();
String gender = sc.next();
//添加到学生对象
s.setName(name);
s.setXuehao(xuehao);
s.setAge(age);
s.setGender(gender);
//学生对象添加到集合
list.add(s);
}
//遍历
for (int i = 0; i < list.size(); i++) {
Student stu = list.get(i);
System.out.println(stu.getName() + "," + stu.getXuehao() + "," + stu.getAge() + ","+stu.getGender());
}
4,添加学生对象并且判断用户是否存在
//创建集合
ArrayList<Student> list = new ArrayList<>();
//创建学生对象
Student s1 = new Student("zhangsan", "123", 20, "女");
Student s2 = new Student("lisi", "124", 20, "男");
Student s3 = new Student("wangpin", "125", 20, "女");
list.add(s1);
list.add(s2);
list.add(s3);
//键盘录入学生
Scanner sc = new Scanner(System.in);
while (true) {
Student s = new Student(); //创建学生对象
//输入信息
System.out.println("请输入学生的姓名,学号,年龄,性别(按顺序输入)!");
String name = sc.next();
String xuehao = sc.next();
int age = sc.nextInt();
String gender = sc.next();
//判断对象是否存在
boolean t = panduan(list,xuehao);//将学号的字符串类型改成整型
System.out.println(t);
break;
}
}
public static boolean panduan(ArrayList<Student> list,String xuehao){
Student stu = new Student();
for (int i = 0; i < list.size(); i++) {
stu = list.get(i);
if(stu.getXuehao().equals(xuehao)){
return true;
}
}
return false;
}
5,创建手机对象,定义一个方法返回小于3000的手机
public static void main(String[] args) {
ArrayList<Phone> list = new ArrayList<>();
//添加手机对象元素
Phone p1= new Phone("华为", 8999);
Phone p2= new Phone("荣耀", 2999);
Phone p3= new Phone("三星", 1999);
list.add(p1);
list.add(p2);
list.add(p3);
//调用方法
ArrayList<Phone> resultePhone = test(list);
for (int i = 0; i < resultePhone.size(); i++) {
Phone p = resultePhone.get(i);
System.out.println(p.getName()+p.getPrice());
}
}
public static ArrayList<Phone> test(ArrayList<Phone> list){
ArrayList<Phone> resultPhone = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
Phone phone = list.get(i);
if(phone.getPrice()<3000){
resultPhone.add(phone);
}
}
return resultPhone;
}
学生管理系统
需求:采取控制台的方式书写学生管理系统
分析:
初始菜单:
"__________学生管理系统__________" "1:添加学生" "2:删除学生" "3:修改学生" "4:查询学生" "5:退出" "请输入您的选择:"
学生类:属性:ID、姓名、年龄、家庭住址
添加功能:键盘录入每一个学生信息并添加,需要满足ID唯一
删除功能:id存在,删除,不存在提示不存在并返回初始菜单
修改功能:id存在,继续录入其他信息,不存在返回初始菜单
查询功能:打印所有学生信息,没有则提示
//学生类
public class Student {
private String name;
private String id;
private int age;
private String address;
public Student() {
}
public Student(String name, String id, int age, String address) {
this.name = name;
this.id = id;
this.age = age;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
import java.util.ArrayList;
import java.util.Scanner;
public class main {
public static void main(String[] args) {
Student s1 = new Student("张三", "a201201", 16, "四川成都");
Student s2 = new Student("李四", "a201202", 17, "四川绵阳");
Student s3 = new Student("王五", "a201203", 18, "四川乐山");
Student s4 = new Student("陈陆", "a201204", 19, "四川成都");
ArrayList<Student> list = new ArrayList<>();
list.add(s1);
list.add(s2);
list.add(s3);
list.add(s4);
loop:
while (true) {
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("请输入您的选择");
Scanner sc = new Scanner(System.in);
String choose = sc.next();
switch (choose) {
case "1" -> AddStudent(list);
case "2" -> deleteStudent(list);
case "3" -> updateStudent(list);
case "4" -> queryStudent(list);
case "5" -> {
System.out.println("退出!");
break loop;
}
default -> System.out.println("没有这个功能");
}
}
}
//添加功能
public static void AddStudent(ArrayList<Student> list) {
//利用空参创建学生对象
Student stu = new Student();
//添加信息
Scanner sc = new Scanner(System.in);
System.out.println("请输入要添加的学生姓名!");
String name = sc.next();
stu.setName(name);
while (true) {
System.out.println("请输入要添加的学生学号!");
String id = sc.next();
boolean flag = contains(list, id);
if (flag) {
stu.setId(id);
break;
} else {
System.out.println("学号不能重复,请重新录入!");
}
}
System.out.println("请输入要添加的学生年龄!");
int age = sc.nextInt();
stu.setAge(age);
System.out.println("请输入要添加的学生地址!");
String address = sc.next();
stu.setAddress(address);
//添加到集合中
list.add(stu);
//提示
System.out.println("学生信息添加成功");
}
//删除功能
public static void deleteStudent(ArrayList<Student> list) {
System.out.println("请输入要删除的学生学号:");
Scanner sc = new Scanner(System.in);
String Id = sc.next();
int index = getindex(list, Id);
if(index>=0){
list.remove(index);
}else {
System.out.println("ID不存在,删除失败!");
}
}
//修改功能
public static void updateStudent(ArrayList<Student> list) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入要修改的学生学号:");
String id = sc.next();
int index = getindex(list,id);
if(index>=0){
Student stu = new Student();
stu = list.get(index);
System.out.println("请输入要修改的学生姓名:");
String name = sc.next();
stu.setName(name);
System.out.println("请输入要修改的学生年龄:");
int age = sc.nextInt();
stu.setAge(age);
System.out.println("请输入要修改的学生地址:");
String address = sc.next();
stu.setAddress(address);
}else {
System.out.println("这个ID不存在,返回失败!");
}
}
//查询功能
public static void queryStudent(ArrayList<Student> list) {
if (list.size() == 0) {
System.out.println("当前无学生信息,请添加后再查找");
return; //结束方法
}
System.out.println("学号\t\t姓名\t年龄\t家庭地址");
for (int i = 0; i < list.size(); i++) {
Student stu = new Student();
stu = list.get(i);
System.out.println(stu.getId() + "\t\t" + stu.getName() + "\t" + stu.getAge() + "\t\t" + stu.getAddress());
}
}
//判断id是否存在
public static boolean contains(ArrayList<Student> list, String id) {
return getindex(list, id) < 0;
}
//通过id获取索引
public static int getindex(ArrayList<Student> list, String id) {
for (int i = 0; i < list.size(); i++) {
Student stu = list.get(i);
if (stu.getId().equals(id)) {
return i;
}
}
return -1;
}
}
学生管理系统升级版
需求
-
为学生管理系统写一个登录、注册、忘记密码的功能。
-
只有用户成功登陆后,才能进入到学生管理系统中
分析
登录:
System.out.println("欢迎来到学生管理系统!"); System.out.println("请选择操作:1登录2注册3忘记密码");初始菜单:
"欢迎来到学生管理系统" "请选择操作:1登录 2注册 3忘记密码"
学生类:用户名、密码、身份证号、手机号码
注册
用户名唯一、长度3~15、字母加数字组合
密码输入两次,两次一致才可注册
身份证长度18,不以0开头,前17位必须为数字,最后一位是数字或是大小写x。
手机号11位,不以0开头
登录
显示未注册,结束方法,提示用户名未注册请先注册
判断验证码是否正确,如果不正确重新输入
判断用户名和密码是否正确,3次机会
忘记密码
输入用户名,不存在提示用户不存在请先注册
键盘输入手机号和身份证号
判断当前用户手机号和身份证号是否一致
一致:提示输入密码,进行修改
不一致:提示账号信息不匹配,修改失败
//User
package StudentAPP;
public class User {
public String userName;
public String password;
public String userID;
public String phoneNumber;
public User() {
}
public User(String userName, String password, String userID, String phoneNumber) {
this.userName = userName;
this.password = password;
this.userID = userID;
this.phoneNumber = phoneNumber;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUserID() {
return userID;
}
public void setUserID(String userID) {
this.userID = userID;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
//student
package StudentAPP;
public class Student {
private String name;
private String id;
private int age;
private String address;
public Student() {
}
public Student(String name, String id, int age, String address) {
this.name = name;
this.id = id;
this.age = age;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
//studenSystem
package StudentAPP;
import java.util.ArrayList;
import java.util.Scanner;
public class studenSystem {
public static void startStudenSystem() {
Student s1 = new Student("张三", "a201201", 16, "四川成都");
Student s2 = new Student("李四", "a201202", 17, "四川绵阳");
Student s3 = new Student("王五", "a201203", 18, "四川乐山");
Student s4 = new Student("陈陆", "a201204", 19, "四川成都");
ArrayList<Student> list = new ArrayList<>();
list.add(s1);
list.add(s2);
list.add(s3);
list.add(s4);
loop:
while (true) {
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("请输入您的选择");
Scanner sc = new Scanner(System.in);
String choose = sc.next();
switch (choose) {
case "1" -> AddStudent(list);
case "2" -> deleteStudent(list);
case "3" -> updateStudent(list);
case "4" -> queryStudent(list);
case "5" -> {
System.out.println("退出!");
break loop;
}
default -> System.out.println("没有这个功能");
}
}
}
//添加功能
public static void AddStudent(ArrayList<Student> list) {
//利用空参创建学生对象
Student stu = new Student();
//添加信息
Scanner sc = new Scanner(System.in);
System.out.println("请输入要添加的学生姓名!");
String name = sc.next();
stu.setName(name);
while (true) {
System.out.println("请输入要添加的学生学号!");
String id = sc.next();
boolean flag = contains(list, id);
if (flag) {
stu.setId(id);
break;
} else {
System.out.println("学号不能重复,请重新录入!");
}
}
System.out.println("请输入要添加的学生年龄!");
int age = sc.nextInt();
stu.setAge(age);
System.out.println("请输入要添加的学生地址!");
String address = sc.next();
stu.setAddress(address);
//添加到集合中
list.add(stu);
//提示
System.out.println("学生信息添加成功");
}
//删除功能
public static void deleteStudent(ArrayList<Student> list) {
System.out.println("请输入要删除的学生学号:");
Scanner sc = new Scanner(System.in);
String Id = sc.next();
int index = getindex(list, Id);
if(index>=0){
list.remove(index);
}else {
System.out.println("ID不存在,删除失败!");
}
}
//修改功能
public static void updateStudent(ArrayList<Student> list) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入要修改的学生学号:");
String id = sc.next();
int index = getindex(list,id);
if(index>=0){
Student stu = new Student();
stu = list.get(index);
System.out.println("请输入要修改的学生姓名:");
String name = sc.next();
stu.setName(name);
System.out.println("请输入要修改的学生年龄:");
int age = sc.nextInt();
stu.setAge(age);
System.out.println("请输入要修改的学生地址:");
String address = sc.next();
stu.setAddress(address);
}else {
System.out.println("这个ID不存在,返回失败!");
}
}
//查询功能
public static void queryStudent(ArrayList<Student> list) {
if (list.size() == 0) {
System.out.println("当前无学生信息,请添加后再查找");
return; //结束方法
}
System.out.println("学号\t\t姓名\t年龄\t家庭地址");
for (int i = 0; i < list.size(); i++) {
Student stu = new Student();
stu = list.get(i);
System.out.println(stu.getId() + "\t\t" + stu.getName() + "\t" + stu.getAge() + "\t\t" + stu.getAddress());
}
}
//判断id是否存在
public static boolean contains(ArrayList<Student> list, String id) {
return getindex(list, id) < 0;
}
//通过id获取索引
public static int getindex(ArrayList<Student> list, String id) {
for (int i = 0; i < list.size(); i++) {
Student stu = list.get(i);
if (stu.getId().equals(id)) {
return i;
}
}
return -1;
}
}
//app
package StudentAPP;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
public class APP {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
ArrayList<User> list = new ArrayList<>();
System.out.println("欢迎来到学生管理系统!");
while (true) {
System.out.println("请选择操作:1登录 2注册 3忘记密码");
int order = sc.nextInt();
switch (order) {
case 1 -> land(list);
case 2 -> login(list);
case 3 -> forgetPassword(list);
default -> System.out.println("没有这个选项,请重新输入!");
}
}
}
private static void forgetPassword(ArrayList<User> list) {
Scanner sc = new Scanner(System.in);
String userName;
System.out.println("请输入用户名:");
userName = sc.next();
boolean flag = checkUserName(list, userName);
if (flag) {
System.out.println("用户未" + userName + "注册,请先注册!");
return;
}
System.out.println("请输入手机号码");
String phoneNumber = sc.next();
System.out.println("请输入身份证号码");
String personID = sc.next();
User u = new User();
for (int i = 0; i < list.size(); i++) {
u = list.get(i);
if (!(u.getPhoneNumber().equals(phoneNumber) && u.getUserID().equals(personID))) {
System.out.println("账号信息不匹配,修改失败!");
} else {
break;
}
}
System.out.println("请输入密码:");
String password = sc.next();
System.out.println("请再一次输入密码:");
String againPassWord = sc.next();
if (!password.equals(againPassWord)) {
System.out.println("两次密码输入不一致,请重新输入");
} else {
u.setPassword(password);
System.out.println("修改密码成功,请重新登录!");
getPrintList(list);
}
}
private static void login(ArrayList<User> list) {
Scanner sc = new Scanner(System.in);
User u1 = new User();
String userName;
while (true) {
System.out.println("请输入用户名:");
userName = sc.next();
boolean flag = checkUserName(list, userName);
if (!flag) {
System.out.println("用户名已存在,请重新输入");
continue;
}
boolean flag1 = CheckUserNameSuper(userName);
if (!flag1) {
System.out.println("用户名长度必须在3~15之间,字母加数字组合,请重新输入");
continue;
} else {
u1.setUserName(userName);
break;
}
}
String passWord;
while (true) {
System.out.println("请输入密码:");
passWord = sc.next();
System.out.println("请再一次输入密码:");
String againPassWord = sc.next();
boolean flag2 = isCheckPassWord(passWord, againPassWord);
if (!flag2) {
System.out.println("两次密码输入不一致,请重新输入!");
continue;
} else {
u1.setPassword(passWord);
break;
}
}
String userId;
while (true) {
System.out.println("请输入身份证号码:");
userId = sc.next();
boolean flag = checkUserId(userId);
if (flag) {
u1.setUserID(userId);
break;
} else {
System.out.println("身份证格式错误,请重新输入!");
continue;
}
}
String userPhoneNumber;
while (true) {
System.out.println("请输入手机号码:");
userPhoneNumber = sc.next();
boolean flag = checkUserPhoneNumber(userPhoneNumber);
if (!flag) {
System.out.println("手机号码格式错误,请重新输入!");
continue;
} else {
u1.setPhoneNumber(userPhoneNumber);
break;
}
}
u1.setUserName(userName);
list.add(u1);
System.out.println("注册成功!");
getPrintList(list);
}
private static void getPrintList(ArrayList<User> list) {
for (int i = 0; i < list.size(); i++) {
User u = list.get(i);
System.out.println(u.getUserName() + "," + u.getPassword() + ","
+ u.getUserID() + "," + u.getPhoneNumber());
}
}
private static boolean checkUserPhoneNumber(String userPhoneNumber) {
if (!(userPhoneNumber.length() == 11)) {
return false;
}
char[] c = userPhoneNumber.toCharArray();
if (c[0] == 0) {
return false;
}
return true;
}
private static boolean checkUserId(String userId) {
if (userId.length() != 18) {
return false;
}
if (userId.startsWith("0")) {
return false;
}
for (int i = 0; i < userId.length() - 1; i++) {
char c = userId.charAt(i);
if (!(c >= '0' && c <= '9')) {
return false;
}
}
char endID = userId.charAt(userId.length() - 1);
if ((endID >= '0' && endID <= '9') || (endID == 'x') || (endID == 'X')) {
return true;
} else {
return false;
}
}
private static boolean isCheckPassWord(String passWord, String againPassWord) {
if (passWord.equals(againPassWord)) {
return true;
}
return false;
}
private static boolean CheckUserNameSuper(String userName) {
int len = userName.length();
if (len < 3 || len > 15) {
return false;
}
for (int i = 0; i < len; i++) {
char c = userName.charAt(i);
if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'))) {
return false;
}
}
int count = 0;
for (int i = 0; i < len; i++) {
char c = userName.charAt(i);
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
count++;
}
}
return count > 0;
}
private static void land(ArrayList<User> list) {
Scanner sc = new Scanner(System.in);
String userName;
while (true) {
System.out.println("请输入用户名:");
userName = sc.next();
boolean flag = checkUserName(list, userName);
if (!flag) {
break;
} else {
System.out.println("用户未" + userName + "注册,请先注册!");
return;
}
}
//生成验证码
while (true) {
System.out.println("当前验证码为:");
String captcha = getCaptcha();
System.out.println(captcha);
System.out.println("请输入验证码");
String code = sc.next();
if (!(captcha.equalsIgnoreCase(code))) {
System.out.println("验证码输入错误,请重新输入!");
continue;
} else {
break;
}
}
//判断用户名和密码是否正确,3次机会。
for (int i = 0; i < 3; i++) {
boolean flag = checkUserNamePassword(list, userName);
if (flag) {
System.out.println("登录成功,欢迎使用学生管理系统!");
//创建对象调用方法,启用学生管理系统
studenSystem ss = new studenSystem();
ss.startStudenSystem();
break;
}
if (i == 2) {
System.out.println("账号被锁定,请联系管理员!");
} else {
System.out.println("账户" + userName + "还有" + (2 - i) + "次机会");
}
}
}
private static boolean checkUserNamePassword(ArrayList<User> list, String userName) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入密码:");
String passWord = sc.next();
for (int i = 0; i < list.size(); i++) {
User u = list.get(i);
if ((u.getUserName().equals(userName)) && (u.getPassword().equals(passWord))) {
return true;
}
}
return false;
}
private static String getCaptcha() {
ArrayList<Character> arr = new ArrayList<>();
for (int i = 0; i < 26; i++) {
arr.add((char) ('a' + i));
arr.add((char) ('A' + i));
}
StringBuilder sb = new StringBuilder();
Random rd = new Random();
for (int i = 0; i < 4; i++) {
int index = rd.nextInt(52);
char c = arr.get(index);
sb.append(c);
}
int c = rd.nextInt(10);
sb.append(c);
char[] list = sb.toString().toCharArray();
int maxIndex = rd.nextInt(list.length);
char temp = list[maxIndex];
list[maxIndex] = list[list.length - 1];
list[list.length - 1] = temp;
return new String(list);
}
private static boolean checkUserName(ArrayList<User> list, String userName) {
for (int i = 0; i < list.size(); i++) {
User u1 = list.get(i);
if (u1.getUserName().equals(userName)) {
return false;
}
}
return true;
}
}
13,static静态变量
(1)static
static表示静态,是java中的一个修饰符,可以修饰成员方法,成员变量
-
被static修饰的成员变量,成为静态变量
特点:该类被所有类共享、不属于对象,属于类、随着类的加载而加载,优于对象存在
调用方法:类名调用、对象名调用
-
被static修饰的成员方法,成为静态方法
特点:多用在测试类和工具类中、JavaBean类中很少用
调用方法:类名调用、对象名调用
JavaBean类:用来描述一些事物的类,比如Student、Teacher、Dog、Cat等
测试类:用来检查其他类是否书写正确,带有main方法的类,是程序的入口
工具类:帮助我们做一些事情,但是不描述任何事物的类
工具类:
见名知意、私有化的构造方法、方法定义为静态
public class ArrUtil { private ArrUtil(){} public static int getMax(){} public static int getMin(){} public static int getSun(){} public static int getAvg(){} }
练习
//定义数组工具类
//需求:1,prinArr方法返回整数数组内容.2,getAvg方法返回平均分。
package Test;
public class ArrUtil {
//私有化构造方法,为了不让外界创建它的对象
private ArrUtil(){}
public static int getSun(int [] arr){
int Sun = arr[0];
for (int i = 1; i < arr.length; i++) {
Sun +=arr[i];
}
return Sun;
}
public static int getAvg(int [] arr){
int sun = getSun(arr);
return sun/arr.length;
}
public static void printArr(int [] arr){
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
if(i==arr.length-1){
System.out.print(arr[i]);
}else {
System.out.print(arr[i]+",");
}
}
System.out.println("]");
}
}
//定义测试类调用该工具类的方法,并返回结果。
package Test;
public class test {
public static void main(String[] args) {
int [] arr = {3,4,5,6,9,12,33,18,8,4,7};
System.out.print("遍历数组:");
ArrUtil.printArr(arr);
int sun = ArrUtil.getSun(arr);
System.out.println("数组和:"+sun);
int avg = ArrUtil.getAvg(arr);
System.out.println("平均数:"+avg);
}
}
重新认识mian方法
-
public:被jvm(虚拟机)调用,访问权限足够大
-
static:被jvm调用,不用创建对象,直接类名访问
因为main方法是静态的,所以测试类中其他方法也需要是静态的
-
void:被jvm调用,不需要给jvm返回值
-
main:一个通用的名称,虽然不是关键字,但是被jvm识别
-
String[] args: 以前用于接收键盘录入数据的,现在没用
注意
-
静态方法只能访问静态变量和静态方法
-
非静态方法可以访问所有(静态\非静态的(成员)变量\方法)
-
静态方法是没有this关键字
总结:
-
静态方法中,只能访问静态
-
非静态方法可以访问所有
-
静态方法无this关键字
(2)继承
面向对象三大特性:封装、继承、多态。
-
封装:对象代表说明,就得封装对应的数据,并提供数据对应的行为
-
继承:java提供的一个关键字extends,可以让一个类和另一个类建立起继承关系。public class Student extends Person{}
-
子类可以在父类的基础上添加新功能,继承父类方法和变量
-
当类与类之间,存在相同(共性)的内容,并满足子类是父类中的一种,就可以考虑使用继承,来优化代码。子类只能访问父类中非私有的成员
继承的特点:java只支持单继承,不支持多继承,但支持多层继承
每一个类都直接或间接的继承于Object类。
练习:设计一个继承体系
布偶猫(吃饭喝水抓老鼠)、狸花猫(吃饭喝水抓老鼠)、哈士奇(吃饭喝水看家拆家)、泰迪(吃饭喝水看家蹭蹭) 画图法:画出父类子类之间的关系。共性内容网上抽取、子类是父类的一种。
动物(吃饭喝水)
猫(吃饭喝水抓老鼠)
布偶
狸花
狗(看家)
哈士奇(拆家)
泰迪(蹭蹭)
| 能否继承 | ||
|---|---|---|
| 成员变量 | 非私有 能 | private 能 |
| 成员方法 | 非私有 能 | private 不能 |
| 构造方法 | 非私有 不能 | private 不能 |
继承中:成员变量的访问特点:
-
就近原则(谁近用谁)
-
super调用,到父类查找
方法重写:当父类的方法不能满足子类现在的需求时,需要进行方法重写
书写格式:继承体系中子类和父类中一摸一样的方法声明,我们就称子类这个方法是重写的方法。
@Override重写注释:放在重写后的方法上,校验子类重写的语法是否正确。语法错误会出现红色波浪线。
如果子类的方法重回写,虚方法表会被覆盖。
继承中:成员方法的特点:
-
重写方法名称、行式与父类保持一致
-
访问权限子类大于等于父类
-
返回值类型小于等于父类
-
重写方法尽量与父类保持一致
-
只有被添加到虚方法表中的方法才能被重写。
继承中:构造方法的访问特点:
-
子类不能继承父类的构造方法,但是可以通过super调用
-
子类构造方法地第一行,有一个默认super()。
-
子类中所有的构造方法默认先访问父类的无参构造,再执行自己。
-
如果想要调用父类的有参构造,必须手动书写。
this、super方法:
-
this:理解为一个变量,表示当前方法调用者的地址值。
-
super:代表父类存储空间。
(3)多态
-
多态:同类型的对象,表现出不同形态。对象的多种形态。
-
表现行式:父类类型 对象名称 = 子类对象;
-
多态前提: Fu f = new Zi();
-
有继承关系
-
有父类引用指向子类
-
有方法重写
-
-
好处:使用父类型作为参数,可以接收所有子类对象。体现了多态的扩展性与遍历。
-
多态的应用场景
-
继承与派生、接口实现、泛型等。
-
//简单运用
//____________________Persion类_______________________
package Test1;
public class Person {
private String name;
private int age;
..........标准JavaBean
public void show(){
System.out.println(name+","+age);
}
}
//____________________Student类_______________________
package Test1;
public class Student extends Person{
@Override
public void show(){
System.out.println("学生的信息为"+getName()+","+getAge());
}
}
//____________________Teacher类_______________________
package Test1;
public class Teacher extends Person{
@Override
public void show(){
System.out.println("老师的信息为"+getName()+","+getAge());
}
}
//_________________Administrator类____________________
package Test1;
public class Administrator extends Person{
@Override
public void show(){
System.out.println("管理员的信息为"+getName()+","+getAge());
}
}
//_______________________测试类________________________
package Test1;
public class Test {
public static void main(String[] args) {
Student s = new Student();
s.setName("张三");
s.setAge(18);
Teacher t = new Teacher();
t.setName("王志成");
t.setAge(30);
Administrator a = new Administrator();
a.setName("陈建国");
a.setAge(45);
//调用rigister函数
rigister(s);
rigister(t);
rigister(a);
}
//这个方法能接收老师、学生、管理员信息
//可以把参数写成这三个类型的父类
public static void rigister(Person p){
p.show();
}
}
-
多态调用成员的特点
-
变量调用:编译看左边,运行也看左边。
-
javac编译代码时先看左边父类有没有这个变量,有则成功,无则失败。
-
java运行代码的时候,实际获取的时左边父类中成员变量的值。
-
-
方法调用:编译看左边,运行看右边。
-
javac编译代码时先看左边父类有没有这个方法,有则成功,无则失败。
-
java运行代码的时候,实际获取的时右边子类中的方法。
-
Animal a = new Dog(); //对象是Animal类型的,用a调用变量和方法时默认调用父类的方法和变量。
成员变量:在子类的对象中,会把父类的成员变量也继承下的。 成员方法:如果子类对方法进行了重写,那么在虚方法表中是会把父类的方法进行覆盖的。
简单举例
//____________________Animal类_______________________ public class Animal { String name = "花花"; int age = 5; .............标准JavaBean public void show(){ System.out.println("动物"); } } //____________________Dog类_______________________ public class Dog extends Animal{ String name = "朵朵"; int age = 2; @Override public void show(){ System.out.println("狗狗"); } } //____________________test类_______________________ public class test { public static void main(String[] args) { Animal a = new Dog(); System.out.println(a.getName()+","+ a.getAge()); a.show(); } } //____________________输出结果_______________________ 花花,5 狗狗 -
多态优势
-
方法中,使用父类作为参数,可以接收所有子类对象
-
在多态形势下,右边对象可以实现解耦合,便于扩展和维护。
-
定义方法的时候,使用父类型作为参数,可以接收所有的子类对象,体现多态的扩展性与遍历。
StringBuilder和集合类型的变量可以添加任意类型。
多态弊端
-
不能调用子类的特有功能。
-
解决方案:Dog d = (Dog)a; //变回子类类型
-
细节:转换时候不瞎转,先判断 a instanceof Dog(如果a是Dog类型返回true,否则返回false)
-
Java新特性:判断和强转结合 。 a instanceof Dog d (如果是则强转成Dog类型,转换之后变量为d,如果不是不强转,结果false)
-
//练习
package Test2;
public class test {
public static void main(String[] args) {
Person p1 = new Person("老王",30);
Dog d = new Dog("黑色",2);
Cat c = new Cat("橘黄色",3);
p1.keepPet(d,"狗粮");
Person p2 = new Person("老李",34);
p2.keepPet(c,"鱼");
}
}
class Animal{
private String color;
private int age;
public void eat(String somgthing){
System.out.println("吃"+somgthing);
}
public Animal() {
}
public Animal(String color, int age) {
this.color = color;
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class Dog extends Animal{
String color ;
int age ;
@Override
public void eat(String somgthing){
System.out.println(getAge()+"岁的"+getColor()+"的狗狗吃狗粮");
}
public void lookHome(){
System.out.println("看家");
}
public Dog(String color, int age) {
super(color,age);
this.color = color;
this.age = age;
}
@Override
public String getColor() {
return color;
}
@Override
public void setColor(String color) {
this.color = color;
}
@Override
public int getAge() {
return age;
}
@Override
public void setAge(int age) {
this.age = age;
}
}
class Cat extends Animal{
String color;
int age;
public Cat(String color, int age) {
super(color,age);
this.color = color;
this.age = age;
}
@Override
public String getColor() {
return color;
}
@Override
public void setColor(String color) {
this.color = color;
}
@Override
public int getAge() {
return age;
}
@Override
public void setAge(int age) {
this.age = age;
}
@Override
public void eat(String somgthing){
System.out.println(getAge()+"岁的"+getColor()+"的猫猫吃猫粮");
}
public void catchMouse(){
System.out.println("抓老鼠");
}
}
class Person {
String name;
int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void keepPet(Animal animal, String somgthing){
if(animal instanceof Dog d){
System.out.println("年龄为"+getAge()+"的"+getName()+"用"+somgthing+"喂养"+d.getAge()+"岁的"+d.getColor()+"的狗");
d.eat(somgthing);
}else if(animal instanceof Cat c){
System.out.println("年龄为"+getAge()+"的"+getName()+"用"+somgthing+"喂养"+c.getAge()+"岁的"+c.getColor()+"的狗");
c.eat(somgthing);
}
}
}
(4)包、final、权限修饰符、代码块
-
包 就是文件夹。用来管理各种不同功能的java类,方便代码后期维护。
-
包的命名规则:公司域名反写+包的作用,需要全部英文小写,见名知意。
-
使用其他类的规则:
-
使用同一个包中的类时,不需要导包。
-
使用java.lang包(Java的核心包)中的类时,不需要导包。
-
其他情况都需要导包。
-
如果同时使用两个包中的同名类,需要用全名类。
-
-
全类名:包名+类名
-
-
final 修饰方法、类、变量。被修饰后不能发生改变
-
方法不能重写
-
类不能被继承
-
表示常量,只能赋值一次
-
常量:实际开发当中,常量一般作为系统的配置信息,方便维护,提高可读性。命名规则:单个单词全大写;多个单词全大写,单词间用下划线隔开。
-
细节:修饰基本数据类型时,记录的值不能发生改变。修饰引用数据类型时,内部的属性值可以改变,地址值不能改变(不能new)。
-
核心:常量记录的数据不能变。
-
-
-
权限修饰符
-
用来控制一个成员能够被访问的范围。
-
可以修饰成员变量、方法、构造方法、内部类。
-
| 修饰符 | 同一个类中 | 同一个包其他类 | 不同包下的子类 | 不同包下的无关类 |
|---|---|---|---|---|
| private私有的 | 可访问 | |||
| 空着不写,只能本包使用 | 可 | 可 | ||
| protected受保护的 | 可 | 可 | 可 | |
| public公共的 | 可 | 可 | 可 | 可 |
权限修饰符的使用规则:
实际开发中,一般只用private和public。成员变量私有,方法公开。
如果方法中的代码时抽取其他方法中的共性代码,这个方阿飞一般也私有。
-
代码块
-
局部代码块:写在方法里面的代码块,目的节省空间,现已淘汰。
public class Test{ public static void main(String[] args){ { int a = 10; System.out.println(a); }//代码执行到这里,a消失。 } }-
构造代码块:写在成员位置的代码块,作用是把构造方法中重复代码抽取出来。优先于构造方法执行。不够灵活。
public class Student{ private String name; private int age; { System.out.println("开始创建对象了!"); } public Student(){} public Student(String name,int age){ this.name = name; this.age = age; } }-
静态代码块:就是在构造代码块前加上static关键字修饰。随着类的加载而加载,并且自动触发、只执行一次。
-
(5)抽象类和抽象方法
-
抽象方法:将共性行为(方法)抽取到父类之后。
由于每一个子类执行的内容是不一样的,所有在父类中不能确定具体的方法体。该方法就可以定义为抽象方法。
-
定义格式:
public abstract 返回值类型 方法名(参数列表);
-
-
抽象类:拥有抽象方法的类叫抽象类。
-
定义格式:
public abstract class类名{}
-
注意事项:
-
抽象类不能实例化,不能创建对象。
-
抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类。
-
可以有构造方法,当创建子类对象时,给属性进行赋值。
-
抽象类的子类
-
要么重写抽象类中所有的抽象方法,(鼠标点击红色波浪线Alt+enter,选择第一个....methods)
-
要么是抽象类。
-
//_________________Animal类____________________
public abstract class Animal {
private String name;
private int age;
public Animal() {
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public abstract void eat();
}
//_________________frog类____________________
package test;
public class Frog extends Animal{
public Frog() {
}
public Frog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("青蛙在吃虫子");
}
}
//_________________test类____________________
public static void main(String[] args) {
Frog f = new Frog("小鹿",2);
System.out.println(f.getName()+","+f.getAge());
f.eat();
}
(6)接口
将具体实现细节从类中抽取出来。
-
接口使用关键字interface来定义
public interface 接口名{} -
接口不能实例化
-
接口和类之间时实现关系,通过implements关键字表示
public class 类名 implements 接口名{} -
接口的子类(实现类)
-
要么重写接口中所有抽象方法
-
要么时抽象类
-
注意
-
接口和类的实现关系,可以单实现,也可以多实现。
public class 类名 implements接口名1,接口名2{} -
实现类还可以在继承一个类的同时实现多个接口。
public class 类名 extends 父类 implements接口名1,接口名2{}
练习
//Animal类同上
//Swin接口
package test;
public interface Swim {
public abstract void swim();
}
//_________________frog类____________________
package test;
public class Frog extends Animal implements Swim{
public Frog() {
}
public Frog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("青蛙在吃虫子");
}
@Override
public void swim() {
System.out.println("青蛙会游泳");
}
}
//_________________test类____________________
package test;
public class test {
public static void main(String[] args) {
Frog f = new Frog("小鹿",2);
System.out.println(f.getName()+","+f.getAge());
f.eat();
f.swim();
Rabbit r = new Rabbit();
r.eat();
}
}
接口中成员的特点
-
成员变量
-
只能时常量。默认修饰符:public static final
-
-
构造方法
-
没有
-
-
成员方法
-
只能时抽象方法。默认修饰符:public abstract
-
接口和类之间的关系
-
类和类
-
继承关系,只能单继承,但可以多层继承
-
-
类和接口
-
实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口。
-
-
接口和接口
-
继承关系,可以单继承,也可以多继承。如果实现类实现最下面的子接口,所有的抽象方法都要重写。
-
综合案例

package test1;
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package test1;
public abstract class Sporter extends Person{
public abstract void study();
public Sporter() {
}
public Sporter(String name, int age) {
super(name, age);
}
}
package test1;
public abstract class Coach extends Person{
public abstract void teach();
public Coach() {
}
public Coach(String name, int age) {
super(name, age);
}
}
package test1;
import javax.xml.transform.Source;
public class Basketball extends Sporter{
public Basketball() {
}
public Basketball(String name, int age) {
super(name, age);
}
@Override
public void study() {
System.out.println("篮球运动员在学篮球");
}
}
package test1;
public class Pingpong extends Sporter implements Speakenglish{
public Pingpong() {
}
public Pingpong(String name, int age) {
super(name, age);
}
@Override
public void study() {
System.out.println("乒乓球运动员在学乒乓球");
}
@Override
public void speak() {
System.out.println("乒乓球运动员在说英语");
}
}
package test1;
public class Bcoach extends Coach {
public Bcoach() {
}
public Bcoach(String name, int age) {
super(name, age);
}
@Override
public void teach() {
System.out.println("篮球教练在教篮球");
}
}
package test1;
public class Pcoach extends Coach implements Speakenglish{
@Override
public void teach() {
System.out.println("乒乓球教练在教乒乓球");
}
public Pcoach() {
}
public Pcoach(String name, int age) {
super(name, age);
}
@Override
public void speak() {
System.out.println("乒乓球教练在说英语");
}
}
package test1;
public interface Speakenglish {
public abstract void speak();
}
package test1;
public class test {
public static void main(String[] args) {
Pingpong p1 = new Pingpong("马冬梅",20);
System.out.println(p1.getName()+","+p1);
p1.speak();
p1.study();
}
}
JDK8以后接口中新增的方法
-
允许在接口中定义默认方法,需要使用关键字default修饰。
-
解决接口升级问题。
-
-
接口中默认方法的定义格式:
-
格式及范例
public default 返回值类型 方法名(参数表){} public default void show(){}
-
-
接口中默认方法的注意事项:
-
默认方法不是抽象方法,所以不强制被重写。但是如果被重写,重写时候去掉default关键字。
-
public可以省略·,default不能省略·
-
如果实现了多个接口,多个接口中存在相同名字的默认方法,子类就必须对该对方进行重写。
-
-
允许在接口中定义静态方法,需要用static修饰。
-
接口中静态方法的定义格式:
public static 返回值类型 方法名(参数列表){} public static void show(){} -
接口中静态方法的注意事项:
-
静态方法只能通过接口名调用,不能通过实现类名或对象名调用
-
public可以省略·,static不能省略
-
JDK8以后接口中新增的方法
private不想为给外界提供
-
接口中私有方法的定义格式:
-
//为默认方法服务 private 返回值类型 方法名(参数列表){} private void show(){} //给静态方法服务 private static 返回值类型 方法名(参数列表){} private static void show(){}
-
接口的应用
-
接口代表规则,时行为的抽象。想要让哪个类拥有一个行为,就让这个类实现对应的接口就可以了。
-
当一个方法的参数时接口实,可以传递接口所有实现类的对象,这个方式称之为接口多态。
适配器设计模式
设计模式就是解决各种问题的各种套路。
-
当一个接口中抽象方法过多,但只需要其中一小部分时,就可以用适配器。
-
实现步骤:
-
编写中间类XXXAdapter,实现对应的接口。
-
对接口中的抽象放大进行空实现。
-
让真正的实现类继承中间类,并重写需要用到的方法。
-
(7)内部类
写在一个类里面的类。
类的五大成员:属性、方法、构造方法、代码块、内部类
内部类
内部类表示的事物是外部类的一部分
内部类单独出现没有任何意义
特点:可以访问外部类的成员,包括私有。外部类要访问内部类的成员,必须创建对象。
package test3;
public class Car {
String carName;
String carColor;
int carAge;
class Engine{
String engineName;
int engineAge;
}
public void show(){
System.out.println(carName);
Engine a = new Engine();
System.out.println(a.engineName);
}
}
/////////////////////////////////////////////////
package test3;
public class test {
public static void main(String[] args) {
Car c = new Car();
c.carName = "小米";
c.carAge = 2;
c.carColor = "橘黄色";
Car.Engine e = new Car().new Engine();
e.engineName = "xiaomi";
e.engineAge = 2;
c.show();
}
}
-
成员内部类
-
写在成员位置的,属于外部类的成员。
-
成员内部类可以被一些修饰符所修饰,比如:private,默认,protected,public,static等。
-
如果内部类private修饰,测试类无法创建内部类对象
-
解决方案1:将private改成public
-
解决方案2:在外部类创建一个获取内部类对象的方法
public Inner getInstance(){ return new Inner(); } -
-
外部类成员变量和内部类成员变量重名时,在内部类访问:
System.out.println(Outer.this.变量名);
-
-
静态内部类
-
用static修饰的内部类。
-
静态内部类只能访问外部类中的静态变量和静态方法,如果想要访问非静态的需要创建对象。
-
直接创建静态内部类对象的方式
Outer.Inter oi = new Outer.Inner();
-
如何调用静态内部类中的方法
-
非静态方法:先创建对象,再用对象调用
-
静态方法:外部类名.内部类名.方法名();
-
-
-
局部内部类
-
定义在方法里面类叫局部类,类似于方法里面的局部变量。
-
外部无法直接使用,需要在方法内部创建对象并使用。
-
该类可以直接访问外部类的成员,也可以访问方法内的局部变量。
-
-
匿名内部类
-
隐藏了名字的内部类。可以写在成员位置,也可以写在局部位置。
-
new 类名或接口名(){ 重写方法 }; -
使用场景
-
当方法的参数时接口或者类时
-
以接口为例,可以传递这个接口的实现类对象,
-
如果实现类只使用一次,就可以用匿名内部类简化代码。
-
-
1304





