JavaSE
文章目录
基础知识
1.Java入门
1.IDEA常用快捷键
main函数:输入psvm后按Tab键
System.out.println():输入sout后按Tab键
Ctrl+Shift+N 查找文件
Ctrl+Alt+L 格式化代码
Ctrl+Alt+O 优化导入的类和包
Alt+/ 自动补全代码 注:默认与输入法有冲突,在setting->keymap->main menu->code->complete code->basic
Ctrl+P 方法参数提示
Ctrl+X 删除行
Ctrl+D 复制行 复制当前行到下一行
Ctrl+H 显示类结构图
Ctrl+Q 显示注释文档
[b]Alt+1 快速打开或隐藏工程面板[/b]
F2 或Shift+F2 高亮错误或警告快速定位
代码标签输入完成后,按Tab,生成代码。
选中文本,按Ctrl+Shift+F7 ,高亮显示所有该文本,按Esc高亮消失。
Ctrl+W 选中代码,连续按会有其他效果
选中文本,按Alt+F3 ,逐个往下查找相同文本,并高亮显示。
Ctrl+Up/Down 光标跳转到第一行或最后一行下
Ctrl+B 快速打开光标处的类或方法
2. 基本dos命令
打开cmd win+r cmd 在文件夹路径加cmd打开命令行
shift+右键 powershell
盘符切换 E:
查看当前目录下所有文件 dir
切换目录 cd /d实现跨盘符切换 cd…上一级
清空 cls clear screen
退出终端exit
查看ipconfig
打开应用 calc mspaint notepad
ping
创建文件夹 md test
创建文件 cd>a.txt
删除 del
移除 rd test
3. Java环境搭建
1.卸载
1.删除安装目录
2.环境变量JAVA_HOME
3.PATH中关于java的
4.使用cmd查看java -version
2.jdk8下载安装
1.搜索jdk8,下载,安装
2.配置环境变量 JAVA_HOME D:\Java\jdk1.8.0_261
3.配置path %JAVA_HOME%\bin %JAVA_HOME%\jre\bin
4.使用cmd查看java -version
5.在任意路径 javac 检验
4.第一个程序
1.新建一个空工程
2.新建一个模块Module
3.新建一个包Packag
4.新建一个Java类
代码
package demo01;
public class Test01 {
public static void main(String[] args) {
System.out.println("Hello,World!");
}
}
运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ptsUwzYN-1651821374335)(F:\image\图片\屏幕截图 2022-03-10 233745.png)]
2.Java基础
1.注释
1.单行注释
`//这是当行注释`
2.多行注释
`/*`
`这是多行注释`
`*/`
3.文档注释
/**`
`这是文档注释`
`*/
代码
package demo01;
public class Test01 {
public static void main(String[] args) {
System.out.println("Hello,World!");
//这是单行注释
/*
* _ooOoo_
* o8888888o
* 88" . "88
* (| -_- |)
* O\ = /O
* ____/`---'\____
* . ' \\| |// `.
* / \\||| : |||// \
* / _||||| -:- |||||- \
* | | \\\ - /// | |
* | \_| ''\---/'' | |
* \ .-\__ `-` ___/-. /
* ___`. .' /--.--\ `. . __
* ."" '< `.___\_<|>_/___.' >'"".
* | | : `- \`.;`\ _ /`;.`/ - ` : | |
* \ \ `-. \_ __\ /__ _/ .-` / /
* ======`-.____`-.___\_____/___.-`____.-'======
* `=---='
这是多行注释
*/
/**
这是文档注释
*/
}
}
2.关键字标识符
1.关键字:
- 被Java语言赋予了特殊含义,用做专门用途的字符串(单词),关键字中所有字母都为小写
2.标识符
1.概念:
- Java 对各种变量、方法和类等要素命名时使用的字符序列称为标识符
- 凡是自己可以起名字的地方都叫标识符。
2.定义标识符的合法规则
- 由26个英文字母大小写,0-9 ,_或 $ 组成。
- 数字不可以开头。
- 不可以使用关键字和保留字,但能包含关键字和保留字。
- Java中严格区分大小写,长度无限制。
3.Java中的一些命名规范
- 包名:多单词组成时所有字母都小写。
- 类名、接口名:多单词组成时,所有单词的首字母大写。
- 变量名、方法名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写:
- 常量名:所有字母都大写。多单词时每个单词用下划线连接:PRIVATE_CONSTANT
- 例如public static final double PI=3.14; //使用final关键字修饰一个常量。
3.变量
1.变量的分类
1.按数据类型分
2.按声明位置分
- 在方法体外,类体内声明的变量称为成员变量(全局变量)。
- 在方法体外,类体内声明的变量称为局部变量。
- 注意:二者在初始化值方面的异同:
相同点:都有生命周期
不同点:局部变量(包括main函数里面的)除形参外,需显式初始化(赋初值)。
2.整数类型
- byte、short、int、long
- Java各整数类型有固定的表数范围和字段长度(任何平台都统一)。
- java的整型常量默认为 int 型,声明long型常量须后加‘l’或‘L’。
记忆规则,从小到大,分别占用的存储空间是1 2 4 8字节。
3.浮点类型
- Java 的浮点型常量默认为double型,声明float型常量,须后加‘f’或‘F’。
- 浮点型常量有两种表示形式:
- 十进制数形式:如:5.12 512.0f .512 (必须有小数点)
- 科学计数法形式:如:5.12e2 512E2 100E-2
4.字符类型 char
- char (占2字节)
- char类型是可以进行运算的。因为它都对应有Unicode码。
- 在用于计算的时候会自动转化为int类型。
- Java中还允许使用转义字符‘\’来将其后的字符转变为特殊字符型常量。例如:char c3 = ‘\n’; // '\n’表示换行符
5.布尔类型 boolean
-
boolean类型数据只允许取值true和false,无null。默认初值是false
不可以0或非 0 的整数替代false和true,这点和C语言不同。
代码
package demo01;
public class Test02 {
public static void main(String[] args) {
//八大基本数据类型
//整形
byte num1 = 10; //8bit
short num2 = 20; //16bit
int num3 = 30; //32bit
long num4 = 40L; //要在数字后面加L 64bit
System.out.println(num1);
System.out.println(num2);
System.out.println(num3);
System.out.println(num4);
System.out.println("————————————————————————————————————————————————————————-");
System.out.println("————————————————————————————————————————————————————————-");
//jdk7新特性,数字时间可以用下划线分割
int money = 10_0000_0000;
System.out.println(money);
System.out.println("————————————————————————————————————————————————————————-");
System.out.println("————————————————————————————————————————————————————————-");
//浮点型
float num5 = 0.5F; //要在数字后边加F 32bit
double num6 = 3.1415926; //64bit
System.out.println(num5);
System.out.println(num6);
System.out.println("————————————————————————————————————————————————————————-");
System.out.println("————————————————————————————————————————————————————————-");
//字符 16bit
char num7 = 'a';
char num8 = '中';
char num9 = '国';
System.out.println(num7);
System.out.println(num8);
System.out.println(num9);
System.out.println("————————————————————————————————————————————————————————-");
System.out.println("————————————————————————————————————————————————————————-");
//字符串 String 不是关键字,是类
String num10 = "你好";
String num11 = "中国";
System.out.println(num10);
System.out.println(num11);
System.out.println("————————————————————————————————————————————————————————-");
System.out.println("————————————————————————————————————————————————————————-");
//布尔类型 默认是false
boolean num12 = true;
boolean num13 = false;
System.out.println(num12);
System.out.println(num13);
System.out.println("————————————————————————————————————————————————————————-");
System.out.println("————————————————————————————————————————————————————————-");
// **整数扩展
System.out.println("整数扩展:");
int i1 = 0b10; //二进制
int i2 = 010; //八进制
int i3 = 10; //十进制
int i4 = 0x10; //十六进制
System.out.println("二进制10="+i1);
System.out.println("八进制10="+i2);
System.out.println("十进制10="+i3);
System.out.println("十六进制10="+i4);
System.out.println("————————————————————————————————————————————————————————-");
System.out.println("————————————————————————————————————————————————————————-");
// ***浮点数拓展
//float,double 有限,离散,舍入误差,大越接近但不等于
//面试题:银行业务 钱 不能用浮点数进行比较 用BigDecimal类
System.out.println("浮点数扩展:");
float f = 0.1F; //0.1
double d = 0.1; //0.1
double d1 = 1.0/10; //0.1
System.out.println(f);
System.out.println(d);
System.out.println("相比结果:");
System.out.println(f == d);
System.out.println();
System.out.println(f);
System.out.println(d1);
System.out.println("相比结果:");
System.out.println(f == d1);
float f1 = 123456789F;
float f2 = f1 +1;
System.out.println();
System.out.println(f1);
System.out.println("相比结果:");
System.out.println(f1 == f2 );
System.out.println("————————————————————————————————————————————————————————-");
System.out.println("————————————————————————————————————————————————————————-");
//转义字符
char c1 = 'a';
char c2 = 'A';
char c3 = '中';
char c4 = '\u0061';
System.out.println((int)c1);
System.out.println((int)c2);
System.out.println((int)c3);
System.out.println(c4);
System.out.println("————————————————————————————————————————————————————————-");
System.out.println("————————————————————————————————————————————————————————-");
//布尔类型
boolean flag = true;
if(flag == true){
System.out.println("我是新手!");
}
if(flag){
System.out.println("我是老手!");
}
}
}
运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q0EmOZXR-1651821374336)(F:\image\图片\屏幕截图 2022-03-10 234018.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lWZeKNjc-1651821374337)(F:\image\图片\屏幕截图 2022-03-10 234122.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b3dk1mbs-1651821374337)(F:\image\图片\屏幕截图 2022-03-10 234156.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IsYVbRzM-1651821374338)(F:\image\图片\屏幕截图 2022-03-10 234225.png)]
3.基本数据类型转换
- 自动类型转换:容量小的类型自动转换为容量大的数据类型。数据类型按容量大小排序为:
-
有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的那种数据类型,然后再进行计算。
-
byte,short,char之间不会相互转换,他们三者在计算时首先转换为int类型。
-
当把任何基本类型的值和字符串值进行连接运算时(+),基本类型的值将自动转化为字符串类型。byte和short涉及到赋值都会转换,但是特殊运送不会
1.String类
- 值null可以赋值给任何引用类型(类、接口、数组)的变量,用以表示这个引用类型变量中保存的地址为空。
- String类属于引用类型,可用null赋值。
- String对象创建出来就不可能被改变,每次复制都需要创建新的对象。
2.强制类型转换
-
自动类型转换的逆过程,将容量大的数据类型转换为容量小的数据类型。使用时要加上强制转换符,例如(int),但可能造成精度降低或溢出,格外要注意。
-
通常,字符串不能直接转换为基本类型,但通过基本类型对应的包装类则可以实现把字符串转换成基本类型。
如: String a = “43”; int i = Integer.parseInt(a);
-
boolean类型不可以转换为其它的基本数据类型。
代码
package demo01;
public class Test03 {
public static void main(String[] args) {
/*
类型转换
强制转换:(类型) 变量名 *注意内存溢出问题
低——————————>高 byte,short,int -> int -> long -> float -> double
注意:
不能对布尔类型进行转换
不能把对象类型转换为不相关的类型
高容量转低容量要 强制转换
转换的时候可能会 内存溢出 或者出现 精度问题
*/
int money = 10_0000_0000;
int num = 20;
int total = money * num;
System.out.println(total); //出现内存溢出问题 -1474836480
long total1 = money * num;
System.out.println(total1); //结果默认值是int,对溢出的值进行long转换还是 -1474836480
long total2 = money*((long)num);
System.out.println(total2); //对 num 进行强制转换为long类型,然后进行计算得到 20000000000
}
}
运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fxdaEejJ-1651821374338)(F:\image\图片\屏幕截图 2022-03-10 234307.png)]
4.变量
变量:可以变化的量
1.类变量(静态变量)
- 类变量也称为静态变量,在类中以 static 关键字声明,但必须在方法之外。
- 无论一个类创建了多少个对象,类只拥有类变量的一份拷贝。
- 静态变量除了被声明为常量外很少使用,静态变量是指声明为 public/private,final 和 static 类型的变量。静态变量初始化后不可改变。
- 静态变量储存在静态存储区。经常被声明为常量,很少单独使用 static 声明变量。
- 静态变量在第一次被访问时创建,在程序结束时销毁。
- 与实例变量具有相似的可见性。但为了对类的使用者可见,大多数静态变量声明为 public 类型。
- 默认值和实例变量相似。数值型变量默认值是 0,布尔型默认值是 false,引用类型默认值是 null。变量的值可以在声明的时候指定,也可以在构造方法中指定。此外,静态变量还可以在静态语句块中初始化。
- 静态变量可以通过:ClassName.VariableName的方式访问。
- 类变量被声明为 public static final 类型时,类变量名称一般建议使用大写字母。如果静态变量不是 public 和 final 类型,其命名方式与实例变量以及局部变量的命名方式一致。
2.局部变量
- 局部变量声明在方法、构造方法或者语句块中;
- 局部变量在方法、构造方法、或者语句块被执行的时候创建,当它们执行完成后,变量将会被销毁;
- 访问修饰符不能用于局部变量;
- 局部变量只在声明它的方法、构造方法或者语句块中可见;
- 局部变量是在栈上分配的。
- 局部变量没有默认值,所以局部变量被声明后,必须经过初始化,才可以使用。
3.实例变量
- 实例变量声明在一个类中,但在方法、构造方法和语句块之外;
- 当一个对象被实例化之后,每个实例变量的值就跟着确定;
- 实例变量在对象创建的时候创建,在对象被销毁的时候销毁;
- 实例变量的值应该至少被一个方法、构造方法或者语句块引用,使得外部能够通过这些方式获取实例变量信息;
- 实例变量可以声明在使用前或者使用后;
- 访问修饰符可以修饰实例变量;
- 实例变量对于类中的方法、构造方法或者语句块是可见的。一般情况下应该把实例变量设为私有。通过使用访问修饰符可以使实例变量对子类可见;
- 实例变量具有默认值。数值型变量的默认值是0,布尔型变量的默认值是false,引用类型变量的默认值是null。变量的值可以在声明时指定,也可以在构造方法中指定;
- 实例变量可以直接通过变量名访问。但在静态方法以及其他类中,就应该使用完全限定名:ObejectReference.VariableName。
package day02;
public class Demo01 {
//类变量
//static关键字 数据类型 变量名 = 值;
static int a = 10;
//实例变量:从属于对象;如果不自行初始化,这个类型的默认值 0.0
//布尔值:默认是false
//除了基本类型,其余的默认值都是null;
byte b;
short c;
int d;
boolean f;
String e;
//常量:
//关键字 final 变量类型 变量名 = 值;
//变量名一般用大写字母
private static final double PI = 3.14;
public static final double PII = 3.14;
static final double PI1 = 3.14;
final static double PI2 = 3.14;//修饰符static不存在先后顺序
public static void main(String[] args) {
//局部变量必须声明和初始化值
int i = 10;
System.out.println(i);
//类变量 static
System.out.println(a);
//实例变量
//变量类型 变量名字 = new Demo01(); Demo01是类名
Demo01 demo01 = new Demo01();
System.out.println(demo01.b);
System.out.println(demo01.c);
System.out.println(demo01.d);
System.out.println(demo01.f);
System.out.println(demo01.e);
System.out.println(PI);
System.out.println(PII);
System.out.println(PI1);
System.out.println(PI2);
}
//其他方法
public void add(){
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kjAWVWpc-1651821374339)(F:\image\截屏\Snipaste_2022-03-13_13-58-54.png)]
5.常量
常量:(Constant):初始化(initialize)后不能再改变值!不会变动的值。所谓常量可以理解成一种特殊的变量,它的值被设定后,在程序运行过程中不允许被改变.
package day02;
public class Demo01 {
//常量:
//关键字 final 变量类型 变量名 = 值;
//变量名一般用大写字母
private static final double PI = 3.14;
public static final double PII = 3.14;
static final double PI1 = 3.14;
final static double PI2 = 3.14;//修饰符static不存在先后顺序
public static void main(String[] args) {
System.out.println(PI);
System.out.println(PII);
System.out.println(PI1);
System.out.println(PI2);
}
}
6.变量的命名规范
- 所有变量、方法、类名:见名知义 类成员变量:首字母小写和驼峰原则: monthSalary 局部变量:首字母小写和驼峰原则 常量:大写字母和下划线: MAX_ VALUE 类名:首字母大写和驼峰原则: Man, GoodMan 方法名:首字母小写和驼峰原则: run(), runRun()
- 类成员变量:首字母小写和驼峰原则: monthSalary
- 局部变量:首字母小写和驼峰原则
- 常量:大写字母和下划线: MAX_ VALUE
- 类名:首字母大写和驼峰原则: Man, GoodMan
- 方法名:首字母小写和驼峰原则: run(), runRun()
7.运算符
运算符:是一种特殊的符号,用以表示数据的运算、赋值和比较等,共以下八种。
- 位运算符
- 算术运算符
- 赋值运算符
- 比较运算符(关系运算符)
- 逻辑运算符
- 三元运算符
1.位运算符
2.算术运算符
1.“+” 是从左到右的,例如下:
- 当左右两边都是数值类型时,做加法运算
- 当左右两边有一方为字符串,则做拼接运算
- 运算顺序是从左都右
package day02;
public class Demo02 {
public static void main(String[] args) {
System.out.println("5+5="+5+5);//输出 5+5=55 字符串在加号左边,从左到右做拼接运算
System.out.println("5="+5+5); //输出 5=55 字符串在加号左边,从左到右做拼接运算
System.out.println("5+5="+5); //输出 5+5=5 字符串在加号左边,从左到右做拼接运算
System.out.println(5); //输出 5
System.out.println(5+5+"=10");//输出10=10字符串在加号右边,从左到右先做加法运算,在做拼接运算
System.out.println(5+"=10"); //输出5=10 字符串在加号右边,从左到右先做加法运算,在做拼接运算
System.out.println(5+5); //输出 10 两边都是数值类型,做加法运算
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O3Vf4ty4-1651821374339)(F:\image\截屏\Snipaste_2022-03-17_20-06-04.png)]
2.i++是先用后加,++i是先加后用i++的效率比i=i+1高
例题(非常重点):
package day02;
public class Demo03 {
public static void main(String[] args) {
int i = 0; // i=0
int i1 = i++; // i1=0,i=i+1=0+1=1
int i2 = ++i; // i2=i+1=1+1=2
System.out.println("i = " + i1);
System.out.println("i = " + i2);
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oVN63Jcv-1651821374339)(F:\image\截屏\Snipaste_2022-03-17_20-27-52.png)]
3.关于Java 中的 i += 1 和 i = i + 1 问题
public class test {
public static void main(String[] args) {
short s = 1;
s = s + 1; //编译错误
s += 1; //编译通过
}
}
错误是由于 s1+1 在运算时会自动提升表达式的类型至 int 型
再赋值给 short 类型的 s1 时将发生强制类型转换的错误
虽然 x+=y 和 x=x+y 两个表达式在一般情况下可以通用,但是在 Java 环境中运行时存在一些细微的差别。这差别在于, += 除了实现 + 功能外,还会根据接收变量的类型自动进行类型的强制转换。
提问:如果x是short类型变量,x++和++x是否会进行强制类型转换:不会。
3.赋值运算符
区分好==和=的区别。
== 是等于, = 是赋值符号
布尔类型不可以和其他类型进行转换
4.比较运算符
insanceof运算符:该运算符用于操作对象实例,检查该对象是否是一个特定类型(类类型或接口类型)。
instanceof运算符使用格式如下:
( Object reference variable ) instanceof (class/interface type)
如果运算符左侧变量所指的对象,是操作符右侧类或接口(class/interface)的一个对象,那么结果为真。
下面是一个例子:
String name = "James";
boolean result = name instanceof String; // 由于 name 是 String 类型,所以返回真
5.逻辑运算符
-
“&”和“&&”的区别:
单&时,左边无论真假,右边都进行运算;
双&时,如果左边为真,右边参与运算,如果左边为假,那么右边不参与运算。
-
短路与&&要关注一个问题
如果&&右边是i++之类的带有变量的值会改变的操作,那么最好用&,否则可能会因为&&左边的条件判断为假,i++就不执行了。 -
^是异或,相同为0,不同为1。
6.三元运算符
package day03;
public class Demo01 {
public static void main(String[] args) {
int grade1 = 71;
int grade2 = 60;
int grade3 = 59;
String type1 = grade1 >= 60 ? "及格" : "不及格" ;
String type2 = grade2 >= 60 ? "及格" : "不及格" ;
String type3 = grade3 >= 60 ? "及格" : "不及格" ;
System.out.println(type1); //及格
System.out.println(type2); //及格
System.out.println(type3); //不及格
}
}
7.运算符优先级
单目运算符(++、–)
8.包机制
- 为了更好地组织类,Java提供了包机制,由于区分类名的命名空间
- 包的语法格式:
package pkg1[.pkg2[.pkg3...]];
- 一般利用公司域名倒置作为包名;com.kuangstudy.www
- 为了能够使用一个包的成员,需要在Java程序中导入该包
import package1[.package2...].(className|*); //通配符* 导入包下所有的类
- 参考:阿里巴巴Java开发手册
9.JavaDoc
-
javadoc命令是用来生成自己API文档的
-
参数信息:
@author 作者名
@version 版本号
@since 指明最早用的jdk版本
@param 参数名
@return 返回值情况
@throws 异常抛出情况
API文档:https://docs.oracle.com/javase/8/docs/api/
package day02;
/**
* @author SuWeii
* @version 1.0
* @since 1.8
*/
public class Doc {
String name;
/**
* @author SuWei
* @param name
* @return
* @throws Exception
*/
public String test(String name) throws Exception{
return name;
}
}
生成步骤:
- 打开某个类所在文件夹下的cmd命令行
- 输入:javadoc -encoding UTF-8 -charset UTF-8 Doc(类名).java
- 会自动生成该类有关的API文档,查看文件夹发现多了一些文件
- 打开 index.html(首页)查看文档注释
3.Java流程控制
1.用户交互Scanner
- 之前我们学的基本语法并没有实现程序和人的交互,Java给我们提供了一个工具类,可以获取用户的输入java.util.Scanner是Java5的新特征,我们通过Scanner类来获取用户的输入。
- 基本语法
Scanner s = new Scanner(System.in);
- 通过Scanner类的 next()与 nextLine()方法获取用户的字符串,读取前一般用hasNext()与hasNextLine()判断是否还有输入的数据。
1.next()
- 一定要读取到有效字符才可以结束输入
- 对输入有效字符之前遇到的空白,next()方法会将其去掉
- 只有输入有效字符后才将其后面输入的空白作为结束符
- next()不能得到带有空格的字符串
package day03;
import java.util.Scanner;
public class Demo01 {
public static void main(String[] args) {
//创建一个扫描器对象
Scanner scanner = new Scanner(System.in);
System.out.println("使用next方法接收");
//判断用户有没有输入的字符串
if(scanner.hasNext()){
//使用next方法接收
String str = scanner.next();
System.out.println("输入的内容为:"+str);
}
//凡是属于IO流的类如果不关闭会一直占用资源
scanner.close();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NArtQYTW-1651821374340)(F:\image\截屏\Snipaste_2022-03-20_11-03-21.png)]
2.nextLine()
- 以Enter作为结束符,即返回输入回车之前所有的字符
- nextLine()可以获取空白
package day03;
import java.util.Scanner;
public class Demo02 {
public static void main(String[] args) {
//创建一个扫描器对象
Scanner scanner = new Scanner(System.in);
System.out.println("使用nextLine方法接收");
//判断用户有没有输入的字符串
if(scanner.hasNextLine()){
String str = scanner.nextLine();
System.out.println("输入的内容为:"+str);
}
scanner.close();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K6Ze2Fc8-1651821374341)(F:\image\截屏\Snipaste_2022-03-20_11-14-29.png)]
3.nextInt()
- 以空格为结束符,即返回空格之前的所有数字
- 返回值为数字
- 同理还有nextByte() 返回值为字节,nextShort() 返回值为short类型,nextLong() 返回值为long类型,nextFloat() 返回值为float类型,nextDouble() 返回值为double类型,nextBoolean() 返回值为Boolean类型
package day03;
import java.util.Scanner;
public class Demo03 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个整数:");
int i = scanner.nextInt();
System.out.println("你输入的整数是:"+i);
scanner.close();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kWvOGVGf-1651821374341)(F:\image\截屏\Snipaste_2022-03-20_11-27-21.png)]
4.next()、nextLine()和nextInt()的区别
通过上面的例子我们可以知道next(),nextInt(),nextLine()三者的读取与返回情况。
next()与nextInt()读取返回方式一致,但不同之处在于next()返回的值为字符串,但nextInt()的返回值为数值型,而nextLine()和next()返回值的类型一致,均为字符串型。
事实上,next()与nextInt()的结束标志有俩,space和enter,而nextLine()的结束标志只有enter一个。但不同的是,前两个并不会读取space和enter,无论标志在输入的句首或句末,而nextLine()则会读取enter,同样无论其位于句首或句末,然后扔掉enter并结束语句。
因此,为了避免输入的值影响后边的值,常将nextLine()写在前两者后面与前两者搭配使用。
5.输入多个数字,并求其总和和平均数,每输入一个数字用回车确认,并通过输入非数字来结束输入并输出执行结果
package day03;
import java.util.Scanner;
public class Demo05 {
public static void main(String[] args) {
//输入多个数字,并求其总和和平均数,每输入一个数字用回车确认,并通过输入非数字来结束输入并输出执行结果
Scanner scanner = new Scanner(System.in);
System.out.println("请输入数字:");
//记录和
double sum = 0;
//计算输入了多少个数字
int i = 0;
//通过循环判断是否还有输入,并在里面对每一次进行求和统计
while (scanner.hasNextDouble()){
double d = scanner.nextDouble();
i++;
sum = sum +d;
System.out.println("第"+ i +"次输入数据,和为:"+ sum);
}
System.out.println("总和为:"+sum);
System.out.println("平均数为:"+sum/i);
scanner.close();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WtLb7R1j-1651821374341)(F:\image\截屏\Snipaste_2022-03-21_21-01-32.png)]
2.顺序结构
- Java的基本结构就是顺序结构,除非特别指明,否则就按语句一条一条执行。
- 顺序结构是最简单的算法结构。
- 语句语句之间是按从上到下执行的,它是由若干个依次执行的处理步骤组成的,它是如何一种算法都离不开的一种基本算法结构。
3.选择结构
- if单选择结构 if( )
- if双选择结构 if( ){ }else{ }
- if多选择结构 if( ){ }else if{ }else{}
- 嵌套的if结构 if( ){ if( ) }
package day04;
import java.util.Scanner;
public class Demo01 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入分数:");
int i = scanner.nextInt();
if(i == 100){
System.out.println("恭喜你考了满分!");
}else if(i < 100 && i >= 90){
System.out.println("A级");
}else if(i < 90 && i >= 80){
System.out.println("B级");
}else if(i < 80 && i >= 70){
System.out.println("C级");
}else if(i < 70 && i >= 60){
System.out.println("D级");
}else if(i < 60 && i >= 0){
System.out.println("不及格");
}else{
System.out.println("输入的成绩不正确!");
}
}
}
switch多选择结构
package day04;
public class SwitchDemo02 {
public static void main(String[] args) {
char grade1 = 'C';
char grade2 = 'C';
switch (grade1){ //不加break;会有case穿透现象
case 'A':
System.out.println("优秀");
case 'B':
System.out.println("良好");
case 'C':
System.out.println("及格");
case 'D':
System.out.println("不及格");
default:
System.out.println("不及格");
}
System.out.println("===============================================");
switch (grade2){
case 'A':
System.out.println("优秀");
break;
case 'B':
System.out.println("良好");
break;
case 'C':
System.out.println("及格");
break;
case 'D':
System.out.println("不及格");
break;
default:
System.out.println("不及格");
break;
}
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DM4W0ysZ-1651821374342)(F:\image\截屏\Snipaste_2022-03-24_21-56-12.png)]
package day04;
import java.util.Scanner;
public class SwitchDemo03 {
public static void main(String[] args) {
String name = "苏伟";
switch (name){
case "张三":
System.out.println("张三");
break;
case "李四":
System.out.println("李四");
break;
case "苏伟":
System.out.println("苏伟");
break;
default:
System.out.println("错了!");
break;
}
}
}
IDEA反编译之后.class文件与源代码对比
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ibSJsqCC-1651821374342)(F:\image\截屏\Snipaste_2022-03-24_21-54-51.png)]
4.循环结构
1.while循环(先判断在再执行)
package day04;
public class WhileDemo01 {
public static void main(String[] args) {
//计算1+2+3+...+100
int i = 0;
int sum = 0;
while (i<=100){
sum = sum + i;
i++;
}
System.out.println("1~100的和为:"+sum); // 1~100的和为:5050
while (true){} // 这是个死循环
}
}
package day04;
public class WhileDemo02 {
public static void main(String[] args) {
//循环输出1~1000能被5整除的数,并且每行输出3个
int i = 1;
while (i <= 1000){
if(i % 5 == 0){
System.out.print("\t"+i);
if(i % 15 == 0){
System.out.print("\n");
// System.out.println();
}
}
i++;
}
}
}
2.do…while循环(先判断再执行)
package day04;
public class DoWhileDemo01 {
public static void main(String[] args) {
//计算 1~100 的和
int i = 0;
int sum = 0;
do{
sum = sum + i;
i++;
}while(i<=100);
System.out.println("1~100的和为:"+sum); // 1~100的和为:5050
}
}
3.for循环
package day04;
public class ForDemo01 {
public static void main(String[] args) {
//计算1~100的和
int sum = 0;
for (int i = 0; i <= 100; i++) {
sum = sum + i;
}
System.out.println("1~100的和为:"+sum); // "1~100的和为:5050
}
}
package day04;
public class ForDemo02 {
public static void main(String[] args) {
//计算0~100的奇数和偶数的和
int odd = 0;
int even = 0;
for (int i = 0; i <= 100; i++) {
if(i % 2 == 0){
even = even + i;
}else{
odd = odd + i;
}
}
System.out.println("1~100的奇数和为:"+odd);
System.out.println("1~100的偶数和为:"+even);
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-29J1Iu6r-1651821374343)(F:\image\截屏\Snipaste_2022-03-24_22-26-38.png)]
package day04;
public class ForDemo03 {
public static void main(String[] args) {
//循环输出1~1000能被5整除的数,并且每行输出3个
for (int i = 1; i <= 1000; i++) {
if(i % 5 == 0){
System.out.print("\t"+i);
if(i % 15 == 0){
System.out.println();
}
}
}
}
}
package day04;
public class ForDemo04 {
public static void main(String[] args) {
//打印九九乘法表
for (int i = 1; i <= 9; i++) {
for (int j = i; j <= 9; j++) {
System.out.print("\t"+i+"x"+j+"="+i*j);
if (j == 9){
System.out.println();
}
}
}
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aFejBLpl-1651821374344)(F:\image\截屏\Snipaste_2022-03-24_22-57-11.png)]
package day04;
public class ForDemo05 {
public static void main(String[] args) {
//打印九九乘法表
/*
1x1=1
2x1=2 2x2=4
3x1=3 3x2=6 3x3=9
4x1=4 4x2=8 4x3=12 4x4=16
5x1=5 5x2=10 5x3=15 5x4=20 5x5=25
6x1=6 6x2=12 6x3=18 6x4=24 6x5=30 6x6=36
7x1=7 7x2=14 7x3=21 7x4=28 7x5=35 7x6=42 7x7=49
8x1=8 8x2=16 8x3=24 8x4=32 8x5=40 8x6=48 8x7=56 8x8=64
9x1=9 9x2=18 9x3=27 9x4=36 9x5=45 9x6=54 9x7=63 9x8=72 9x9=81
*/
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
System.out.print("\t"+i+"x"+j+"="+i*j);
}
System.out.println();
}
}
}
4.增强for循环
package day04;
public class ForDemo07 {
public static void main(String[] args) {
int[] number = {10,20,30,40,50};
for(int x:number){
System.out.println(x);
}
System.out.println("=====================");
for(int i = 0; i < number.length; i++){
System.out.println(number[i]);
}
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ItlPJxdT-1651821374344)(F:\image\截屏\Snipaste_2022-03-25_12-08-52.png)]
5.break & continue
- break可用在任何循环的主体部分,由于强行退出循环,也可以用在switch语句,防止case穿透。
- continue用于循环语句中,终止某次循环过程,跳过剩余语句,之间进行下一次循环条件判断。
- 标签:后面跟一个冒号的标识符 label:
package day04;
public class WhileDemo03 {
public static void main(String[] args) {
//在1~100中输出1~15后再输出123
int i = 0;
while (i <= 100){
i++;
System.out.println(i);
if(i == 30){
break;
}
}
System.out.println(123);
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2ywr6jjX-1651821374344)(F:\image\截屏\Snipaste_2022-03-25_12-18-28.png)]
package day04;
public class WhileDemo04 {
public static void main(String[] args) {
//输出 1~100 遇到10的倍数不输出并换行
int i = 0;
while (i < 100){
i++;
if(i % 10 == 0){
System.out.println();
continue;
}
System.out.print("\t"+i);
}
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ayFJt0iH-1651821374345)(F:\image\截屏\Snipaste_2022-03-25_12-25-24.png)]
package day04;
public class LableDemo {
public static void main(String[] args) {
//打印101~150的质数
//质数:只能被1和它本身整除的数
int count = 0;
outer:for (int i = 101; i <= 150; i++) {
for(int j = 2; j < i/2; j++){
if(i % j == 0)
continue outer; //不建议使用标签
}
System.out.print(i+" "); // 101 103 107 109 113 127 131 137 139 149
}
}
}
6.流程控制练习
package day04;
import java.util.Scanner;
public class ForDemo06 {
public static void main(String[] args) {
//打印三角形
/* 输入为5时
* **** *
*** *** ** *
***** ** *** **
******* * **** ***
********* ***** ****
*/
Scanner scanner = new Scanner(System.in);
System.out.print("请输入三角形行数:");
int n = scanner.nextInt();
for(int i = 1; i <= n; i++){
for(int j = i; j < n; j++){
System.out.print(" ");
}
for(int j = 1 ;j <= i; j++){
System.out.print("*");
}
for (int j = 1; j < i; j++){
System.out.print("*");
}
System.out.println();
}
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1q51LuyI-1651821374345)(F:\image\截屏\Snipaste_2022-03-25_14-04-28.png)]
package day04;
import java.util.Scanner;
public class ForDemo08 {
public static void main(String[] args) {
//打印等腰空心三角形
/* 例如:输入为4时
*
* *
* *
* * * *
*/
Scanner scanner = new Scanner(System.in);
System.out.print("请输入三角形行数:");
int n = scanner.nextInt(); //n为三角形高
for(int i=1;i<=n;i++){
for(int j=1;j<=2*n-1;j++){
if(i!=n){ //若不为最后一行
if(i+j==n+1)
System.out.print("*"); //三角形左腰边
else if(i+j==n+2*i-1)
System.out.print("*"); //三角形右腰边
else System.out.print(" ");
}
else if(j%2!=0){ //最后一行,底边
System.out.print("*");
}else {
System.out.print(" ");
}
}
System.out.println(); //换行
}
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tTui0N7p-1651821374346)(F:\image\截屏\Snipaste_2022-03-25_14-07-49.png)]
5.Random类:生成随机数
package basics.method;
import java.util.Random;
public class Demo08 {
public static void main(String[] args) {
//生成随机数第一种方法
Random random = new Random();
int i = random.nextInt(10)+1; //生成[1,10]的整数
System.out.println(i);
//生成随机数第二种方法
int random1 = (int)(Math.random()*10);
//Math.random() 生成[0,1)之间的数
//Math.random()*10 生成[0,10)之间的数
//(int)(Math.random()*10) 强转成int 生成[0,10)之间的整数
System.out.println(random1);
}
}
4.Java方法
1.方法的定义
-
Java的方法类似与其他语言的函数,是一段用来完成特定功能的代码片段。
-
方法包含一个方法头和一个方法体。
-
修饰符:可选,定义了方法的访问类型,告诉编译器如何调用该方法。
-
返回值类型:方法可能会返回值。returnValueType是方法返回值的数 据类型。有些方法没有返回值 则returnValueType为关键字void。
-
方法名:是方法的实际名称,方法名与参数表共同构成方法签名。
-
参数类型:像一个占位符。方法被调用时,传递值给参数,该值称为实参或变量。参数列表是指方法的参数类型、顺序和参数个数。参数是可选的,方法可以不包含任何参数。
形式参数:在方法被调用时用于接收外界输入的数据。
实参:调用方法时实际传给方法的数据。
- 方法体:方法体包含具体的语句,定义该方法的功能。
修饰符 返回值类型 方法名(参数类型 参数名,...){ 方法体... return 返回值; }
-
//定义一个求和的方法
public static int add(int a,int b){
return a+b;
}
//定义一个打印三角形的方法
public static void test(){
Scanner scanner = new Scanner(System.in);
System.out.print("请输入三角形行数:");
int n = scanner.nextInt();
for(int i = 1; i <= n; i++){
for(int j = i; j < n; j++){
System.out.print(" ");
}
for(int j = 1 ;j <= i; j++){
System.out.print("*");
}
for (int j = 1; j < i; j++){
System.out.print("*");
}
System.out.println();
}
}
2.方法的调用
- 调用方法:对象名.方法名(实参列表)。
- Java支持两种调用方法的方式,根据方法是否返回值来选择。
- 当方法返回一个值的时候,方法调用通常被当成一个值。
int sum = add(10, 20);
- 如果方法返回值是void,方法调用一定是一条语句。
test();
- 扩展:值传递和引用传递 ( Java都是值传递)。
- 调用其他类的方法,除非是static静态方法,不然必须实例化这个类(new)
package method;
import java.util.Scanner;
public class Demo01 {
public static void main(String[] args) {
int sum = add(10, 20); //调用add方法
System.out.print("add方法:");
System.out.println(sum);
System.out.print("test方法:");
test(); //调用test方法
}
//定义一个求和的方法
// static静态方法,否则就要new实例化来调用
public static int add(int a,int b){
return a+b;
}
//定义一个打印三角形的方法
// static静态方法,否则就要new实例化来调用
public static void test(){
Scanner scanner = new Scanner(System.in);
System.out.print("请输入三角形行数:");
int n = scanner.nextInt();
for(int i = 1; i <= n; i++){
for(int j = i; j < n; j++){
System.out.print(" ");
}
for(int j = 1 ;j <= i; j++){
System.out.print("*");
}
for (int j = 1; j < i; j++){
System.out.print("*");
}
System.out.println();
}
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TWFOwtxa-1651821374346)(F:\image\截屏\Snipaste_2022-03-26_14-21-59.png)]
值传递 &引用传递
3.方法的重载
-
重载是在一个类中,有相同的方法名,参数列表不同的方法。
-
方法重载的规则:
- 方法名称必须相同
- 参数列表必须不同(参数个数、参数类型、或参数顺序不同)
- 参数的名称不同,不构成方法的重载
- 返回类型可以相同也可以不相同,与返回值类型无关
- 仅仅返回类型不同不足以成为方法的重载
-
实现理论:方法名称相同时,编译器会根据调用方法的参数个数、参数类型,参数顺序去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错。
重载第一种情况:参数的个数不同
package method; public class Demo02 { //重载第一种情况:参数的个数不同 public static int add(int a,int b){ return a + b; } public static double add(int a,int b,int c){ return a + b + c; } public static int add(int a,int b,int c,int d){ return a + b + c + d; } public static void main(String[] args) { int sum = add(1, 2, 3, 4); System.out.println(sum); // 输出:10 } }
重载第二种情况:参数的类型不同
package method; public class Demo03 { //重载第二种情况:参数的类型不同 public static double add(int a,int b){ return a + b; } public static double add(int a,double b){ return a - b; } public static void main(String[] args) { double num = add(2, 1.0); System.out.println(num); // 输出:1.0 } }
重载第三种情况:参数的顺序不同
package method;
public class Demo04 {
public static double add(double a,int b){
return a + b;
}
public static double add(int a,double b){
return a - b;
}
public static void main(String[] args) {
double sum = add(2, 1.0);
System.out.println(sum); // 输出:1.0
}
}
4.命令行传参
- 有时候你希望运行一个程序时候传递给它消息,这要靠传递命令行参数给main()函数实现。
package method;
public class Demo05 {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
System.out.println("args["+i+"]"+args[i]);
}
}
}
- 找到当前类的文件夹,打开cmd.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qWRvQ6yA-1651821374347)(F:\image\截屏\Snipaste_2022-03-26_15-36-18.jpg)]
5.可变参数
- Jdk1.5开始,Java支持传递同类型的可变参数给一个方法。
- 在方法声明中,在指定参数类型后加一个省略号 (…)。
- 一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。
package method;
public class Demo06 {
//定义一个求最大值的方法
public static void max(int ... num){
if(num.length == 0){
System.out.println("没有值传入");
}
int result = num[0];
for (int i = 0; i < num.length; i++) {
if(num[i] > result){
result = num[i];
}
}
System.out.println("最大的值是:"+result);
}
public static void main(String[] args) {
max(5,2,7,9,10,3); //最大的值是:10
max(new int[]{5,2,9,12,3}); //最大的值是:12
}
}
6.递归
-
递归就是:A方法调用A方法,自己调用自己!
-
递归策略只需少量的代码可描述解题过程中多次重复计算,大大减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。
-
递归结构:
-
递归头:什么时候不调用自身方法,没有头 将陷入死循环。
-
递归体:什么时候需要调用自身方法。
-
package method;
import java.util.Scanner;
public class Demo07 {
//求n!的方法 n!=n*(n-1)!
public static int f(int n){
if(n == 1){
return 1;
}else {
return n*f(n-1);
}
}
//求Sn的方法 Sn=n+(n-1)+(n-2)+...+3+2+1
public static int f1(int n){
if (n == 1){
return 1;
}else {
return n+f1(n-1);
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("你要求几的阶乘:");
int n = scanner.nextInt();
System.out.print(n+"的阶乘为:"+f(n));
//System.out.println(f(5));
//也可以写成下面这样:
//int f = f(5);
//System.out.println(f);
System.out.println();
System.out.print("你要求前多少项的和:");
int n1 = scanner.nextInt();
System.out.print("前"+n1+"项的和为:"+f1(n1));
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f8cq55A8-1651821374347)(F:\image\截屏\Snipaste_2022-03-27_10-51-54.png)]
Java方法的练习:简单计算器的实现
package method;
import java.util.Scanner;
public class Test {
//写一个计算器,实现加减乘除功能,并且能够循环接受新的数据,通过用户交互实现
//写四个方法:加减乘除
//利用循环+swtich进行用户交互
//传递需要操作的两个数
//输出结果
//加法计算器
public static double add(double a, double b) {
return a + b;
}
//减法计算器
public static double sub(double a, double b) {
return a - b;
}
//乘法计算器
public static double ride(double a, double b) {
return a * b;
}
//除法计算器
public static double div(double a, double b) {
return a / b;
}
public static void main(String[] args) {
for (int i = 1; ; i++) { // i 的范围表示总共进行几轮运算
if(i == 1){
Scanner scanner = new Scanner(System.in);
System.out.print("请输入第一个数:");
double a = scanner.nextDouble();
System.out.print("请输入第二个数:");
double b = scanner.nextDouble();
System.out.print("请选择一种计算方法(+,-,*,/):");
String s = scanner.next();
switch (s) {
case "+":
System.out.println(a +"+"+ b + "="+add(a,b));
break;
case "-":
System.out.println(a +"-"+ b + "="+sub(a,b));
break;
case "*":
System.out.println(a +"*"+ b + "="+ride(a,b));
break;
case "/":
System.out.println(a +"/"+ b + "="+div(a,b));
break;
default:
System.out.println("运算符号输入错误!");
break;
}
}else {
Scanner scanner = new Scanner(System.in);
System.out.println("继续运算请按 1,否则按其他数字键退出");
int i1 = scanner.nextInt();
if(i1 == 1){
Scanner scanner1 = new Scanner(System.in);
System.out.print("请输入第一个数:");
double a = scanner1.nextDouble();
System.out.print("请输入第二个数:");
double b = scanner1.nextDouble();
System.out.print("请选择一种计算方法(+,-,*,/):");
String s = scanner1.next();
switch (s) {
case "+":
System.out.println(a +"+"+ b + "="+add(a,b));
break;
case "-":
System.out.println(a +"-"+ b + "="+sub(a,b));
break;
case "*":
System.out.println(a +"*"+ b + "="+ride(a,b));
break;
case "/":
System.out.println(a +"/"+ b + "="+div(a,b));
break;
default:
System.out.println("输入错误!");
break;
}
}else {
break;
}
}
}
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mb8FHXFw-1651821374348)(F:\image\截屏\1.jpg)]
5.Java数组
1.数组的定义
- 数组是相同类型数据的有序集合
- 数组描述的是相同类型的若干数据,按照一定先后次序排序组合而成
- 其中,每一个数据称作一个数组元素,每个数组元素可以通过下标访问它们
2.数组的声明创建
- 首先必须声明数组变量,才能在程序中使用数组。
dataType[] arrayRefVar; //首选 int[] array;
dataType arrayRefVar[]; //效果相同,但不是首选 int array[]
- Java语言使用new操作符来创建数组,语法如下
dataType[] arrayRefVar = new dataType[arraySize];
//int[] nums=new int[10]
- 数组的元素是通过索引访问的,数组索引从0开始
- 获取数组长度:arrays.length
package array;
public class Demo01 {
public static void main(String[] args) {
int[] array; //1.声明一个数组
array = new int[3]; //2.创建一个数组
//3.给数组元素赋值
array[0] = 1;
array[1] = 2;
array[2] = 3;
for (int num : array) { //打印数组元素,用的增强for循环
System.out.println(num);
}
System.out.println("==============================");
for (int i = 0; i < array.length; i++) { //打印数组元素,用的普通for循环
System.out.println(array[i]);
}
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-koffsMrI-1651821374348)(F:\image\截屏\Snipaste_2022-03-27_15-17-39.png)]
3.内存分析
4.数组的三种初始化
- 静态初始化
//静态初始化:创建+赋值
int[] a = {1,2,3};
//Man[] man = {new Man(1,1),new Man(2,2)};
- 动态初始化
//动态初始化 包含默认初始化
int[] b = new int[3]; //默认值为0
b[0] = 1;
b[1] = 2;
b[2] = 3;
- 默认初始化
- 数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。
5.数组的基本特点
-
其长度是确定的,数组一旦被创建,它的大小就是不可改变的。
-
其元素必须是相同类型,不允许出现混合类型。
-
数组中的元素可以是任何数据类型,包括基本类型和引用类型。
-
数组变量属于引用类型,数组也可以看作对象,其中每个元素相当于该对象的成员变量。
数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组本身是在堆中的。
6.数组边界
7.数组的使用
- For-Each循环
package array;
public class Demo02 {
public static void main(String[] args) {
//静态初始化:创建+赋值
int[] a = {1,2,3};
//Man[] man = {new Man(1,1),new Man(2,2)};
//动态初始化 包含默认初始化
int[] b = new int[3]; //默认值为0
b[0] = 1;
b[1] = 2;
b[2] = 3;
for (int array : a) {
System.out.println(array);
}
System.out.println("=====");
for (int array1 : b) {
System.out.println(array1);
}
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-34w90Ckd-1651821374349)(F:\image\截屏\Snipaste_2022-03-27_15-38-54.png)]
- 数组作方法入参
package array;
public class Demo03 {
//数组作方法入参
//打印数组元素
public static void printArray(int[] a){
for (int i : a) {
System.out.println(i);
}
}
public static void main(String[] args) {
int[] a = {1,2,3,4,5};
printArray(a);
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zPanHxGP-1651821374349)(F:\image\截屏\Snipaste_2022-03-27_15-43-17.png)]
- 数组作返回值
package array;
public class Demo04 {
//数组作返回值
//数组的反转
public static int[] reverse(int[] a){
int[] result = new int[a.length];
//反转操作
for (int i = 0; i < a.length; i++) {
result[i] = a[a.length-i-1];
}
return result;
}
public static void main(String[] args) {
int[] a = {1,2,3,4,5};
for (int i : a) {
System.out.print(i+" ");
}
System.out.println();
System.out.println("数组反转:");
int[] b = reverse(a);
for (int i : b) {
System.out.print(i+" ");
}
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1nzd10IU-1651821374349)(F:\image\截屏\Snipaste_2022-03-27_15-57-23.png)]
8.多维数组
- 多维数组可以看成数组的数组,比如二维数组就是一个特殊的数组,其每一个元素都是一个一维数组。
int arr[][] = new int[3][2]; //二维数组,三行两列
package array;
public class Demo05 {
public static void main(String[] args) {
int[][] array = {{1,2},{2,3},{3,4}};
//打印二维数组所有元素
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
System.out.print(array[i][j]+" ");
}
}
}
}
9.Arrays类
- 数组的工具类java.util.Arrays
- 由于数组对象本身并没有什么方法可以供我们使用,但API提供了一个工具类Arrays供我们使用。
- Array类中的方法都是static修饰的静态方法,使用时直接使用类名进行调用,可以不用对象调用。
- 常用功能
- 给数组赋值:fill方法。
- 排序:sort方法,升序。
- 比较数组:equals方法比较数组中元素值是否相等。
- 查找数组元素:binarySearch对排序好的数组进行二分查找法操作。
package array;
import java.util.Arrays;
public class Demo06 {
public static void main(String[] args) {
int[] a = {1,5,55,62,12,41};
System.out.println(a);
//Arrays.toString 打印数组元素
System.out.println(Arrays.toString(a));
//Arrays.binarySearch 二分法查找某值 返回下标
System.out.println(Arrays.binarySearch(a,55));
//Arrays.fill 填充
Arrays.fill(a,2,4,0); //数组[a[2]~a[4])之间填充0
System.out.println(Arrays.toString(a));
//Arrays.sort 升序排序
Arrays.sort(a);
System.out.println(Arrays.toString(a));
}
}
10.冒泡排序 重点
- 冒泡排序是八大排序最出名的排序算法。
- 代码:两层循环,外层冒泡轮数,里层依次比较。
- 当我们看到嵌套循环,应该立马就可以得出这个算法的时间复杂度为O(n2)。
package array;
import java.util.Arrays;
public class Demo07 {
//冒泡排序
//1.比较数组中两个相邻的元素,如果第一个数大于第二个数,交换它们位置
//2.每一次比较,都会产生一个最大或最小的数字(升序为最大数)
//3.下一轮则可以少一次排序
//4.依次循环,直到结束
public static int[] sort(int[] array){
int temp = 0; // 定义的第三个变量,在交换两个数的位置时用
for (int i = 0; i < array.length-1; i++) { // 外层循环:控制轮数 循环array.length-1次,因为最后一轮不需要循环
for (int j = 0; j < array.length-1-i; j++) { // 内层循环:进行比较,比较相邻的两个数,如果第一个数比第二个数大,则交换它们位置 循环array.length-1-i次,因为最后一轮不需要循环,然后再减去循环过的i轮
if (array[j] > array[j+1]){
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
return array;
}
public static void main(String[] args) {
int[] a = {2,15,36,2,-5,69,82,0,23};
int[] sort = sort(a);
System.out.println(Arrays.toString(sort));
//Arrays类中的排序方法
Arrays.sort(a);
System.out.println(Arrays.toString(a));
}
}
package array;
import java.util.Arrays;
public class Demo07 {
//冒泡排序
//1.比较数组中两个相邻的元素,如果第一个数大于第二个数,交换它们位置
//2.每一次比较,都会产生一个最大或最小的数字(升序为最大数)
//3.下一轮则可以少一次排序
//4.依次循环,直到结束
public static int[] sort(int[] array){
int temp = 0; // 定义的第三个变量,在交换两个数的位置时用
for (int i = 0; i < array.length-1; i++) { // 外层循环:控制轮数 循环array.length-1次,因为最后一轮不需要循环
for (int j = 0; j < array.length-1-i; j++) { // 内层循环:进行比较,比较相邻的两个数,如果第一个数比第二个数大,则交换它们位置 循环array.length-1-i次,因为最后一轮不需要循环,然后再减去循环过的i轮
if (array[j] > array[j+1]){
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
return array;
}
public static void main(String[] args) {
int[] a = {2,15,36,2,-5,69,82,0,23};
int[] sort = sort(a);
System.out.println(Arrays.toString(sort));
//Arrays类中的排序方法
Arrays.sort(a);
System.out.println(Arrays.toString(a));
}
}
package array;
import java.util.Arrays;
public class Demo07 {
//冒泡排序
//1.比较数组中两个相邻的元素,如果第一个数大于第二个数,交换它们位置
//2.每一次比较,都会产生一个最大或最小的数字(升序为最大数)
//3.下一轮则可以少一次排序
//4.依次循环,直到结束
public static int[] sort(int[] array){
int temp = 0; // 定义的第三个变量,在交换两个数的位置时用
for (int i = 0; i < array.length-1; i++) { // 外层循环:控制轮数 循环array.length-1次,因为最后一轮不需要循环
for (int j = 0; j < array.length-1-i; j++) { // 内层循环:进行比较,比较相邻的两个数,如果第一个数比第二个数大,则交换它们位置 循环array.length-1-i次,因为最后一轮不需要循环,然后再减去循环过的i轮
if (array[j] > array[j+1]){
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
return array;
}
public static void main(String[] args) {
int[] a = {2,15,36,2,-5,69,82,0,23};
int[] sort = sort(a);
System.out.println(Arrays.toString(sort));
//Arrays类中的排序方法
Arrays.sort(a);
System.out.println(Arrays.toString(a));
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rtgmGUoN-1651821374350)(F:\image\截屏\Snipaste_2022-03-27_16-43-58.png)]
11.稀疏数组
package array;
public class Demo08 {
public static void main(String[] args) {
//创建一个二维数组 11*11 0:没有棋子,1:黑棋 2:白棋
int[][] array1 = new int[11][11];
array1[1][2] = 1;
array1[2][3] = 2;
//输出原始的数组
System.out.println("原始的数组:");
for (int[] array : array1) {
for (int i : array) {
System.out.print(i + "\t");
}
System.out.println();
}
//转换为稀疏数组保存
//1.有效值的个数
int sum = 0; //有效值总数
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if (array1[i][j] != 0) {
sum++;
}
}
}
//2.创建一个稀疏数组
int[][] array2 = new int[sum + 1][3];
array2[0][0] = 11;
array2[0][1] = 11;
array2[0][2] = sum;
//3.遍历二维数组,将有效值存放到稀疏数组
int count = 0;
for (int i = 0; i < array1.length; i++) {
for (int j = 0; j < array1[i].length; j++) {
if (array1[i][j] != 0) {
count++;
array2[count][0] = i;
array2[count][1] = j;
array2[count][2] = array1[i][j];
}
}
}
//4.输出稀疏数组
System.out.println("稀疏数组:");
for (int i = 0; i < array2.length; i++) {
for (int j = 0; j < array2[i].length; j++) {
System.out.print(array2[i][j] + "\t");
}
System.out.println();
}
/* 结果:
输出原始的数组
0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0
0 0 0 2 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
稀疏数组
11 11 2
1 2 1
2 3 2
*/
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2Z3BWkXr-1651821374350)(F:\image\截屏\Snipaste_2022-03-27_16-48-29.png)]
面向对象
1.初识面向对象
1.面向过程&面向对象
- 面向过程思想
- 步骤清晰简单,第一步做什么,第二部做什么…
- 面向过程适合处理一些较为简单的问题
- 面向对象思想
- 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。
- 面向对象适合处理复杂的问题,适合处理需要多人协作的问题!
- 对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。
package opp.demo01;
//Demo01类
public class Demo01 {
//main方法
public static void main(String[] args) {
}
// 修饰符 返回值类型 方法名(){
// 方法体
// return 返回值;
// }
//return结束方法,返回一个结果!
public String sayHello() {
return "Hello World!";
}
public void print() {
return;
}
public int max(int a, int b) {
return a > b ? a : b; //三元运算符
}
}
2.什么是面向对象
- 面向对象编程(Object-Oriented Programming, OOP)
- 本质:以类的方式组织代码,以对象的组织(封装)数据。
- 抽象
- 三大特性
- 封装
- 继承
- 多态
- 从认识论的角度考虑是先有对象后有类。对象是具体的事物,类是对象的抽象。
- 从代码运行角度考虑是先有类后有对象。类是对象的模板。
3.类与对象的关系
- 类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但并不能代表某一个具体的事物。一个类中只有属性和方法。
- 动物、植物、手机、电脑…
- Person类、Pet类、Cat类等,都是用来描述/定义某一具体的事物应该具备的特点和行为。
- 对象是抽象概念的具体实例,如张三是人的一个具体实例、张三家里的狗旺财就是狗的一个具体实例。
package opp.demo01;
public class Demo02 {
public static void main(String[] args) {
Student.say();
//调用非静态方法要实例化这个类 使用new关键字
//对象类型 对象名 = 值
Student student = new Student();
student.tall();
}
//两个静态方法可以互相调用,两个非静态方法也可以互相调用
public void a() {
b();
}
public void b() {
a();
}
//两个静态方法可以互相调用
public static void c() {
d();
}
public static void d() {
c();
}
/* public static void e(){
f(); //这里报错
}
public void f(){
e();
}
一个静态方法和一个非静态方法中,非静态方法中可以调用静态方法(因为静态方法和类一起加载,所以非静态方法可以调用静态方法)
但是静态方法调用非静态方法时会报错,因为非静态方法它不像静态方法一样和类一起加载,就如同一个存在的方法去调用一个不存在的方法是不行的
*/
}
package opp.demo01;
public class StudentDemo {
public static void main(String[] args) {
//调用 Student 类中的静态方法只需 类名.方法名
Student.say(); //学生说话了!
//调用 Student 类中的非静态方法要实例化(new)这个类,然后才能调用
Student student = new Student();
student.tall(); //学生讲话了!
}
}
/*
package opp.demo01;
//学生类
public class Student {
//静态方法
public static void say() {
System.out.println("学生说话了!");
}
//非静态方法
public void tall(){
System.out.println("学生讲话了!");
}
}
*/
2.创建与初始化对象
- 使用new来创建对象。
- 使用new关键字创建的时候,除了分配内存之外,还会给创建好的对象进行默认的初始化,以及对类中构造器的调用。
- 类中的构造器也被称为构造方法,创建对象时必须要调用。有以下特点:
- 必须和类的名字相同
- 没有返回类型,也不能写void
- 一个类即使什么都不写,也会存在一个默认的构造方法
package opp.demo02;
public class Application {
//一个项目中应该只存在一个main方法
public static void main(String[] args) {
//类:抽象的 需要实例化 new关键字
//类实例化后会返回一个自己的对象
// student对象就是Student类的一个实例
Student zhangsan = new Student();
Student lisi = new Student();
System.out.println(zhangsan.name); // 输出的默认值 null
System.out.println(zhangsan.age); // 输出的默认值 0
System.out.println(lisi.name); // 输出的默认值 null
System.out.println(lisi.age); // 输出的默认值 0
Student wangwu = new Student();
Student xiaoming = new Student();
wangwu.name = "王五";
wangwu.age = 18;
xiaoming.name = "小明";
xiaoming.age = 20;
System.out.println(wangwu.name);
System.out.println(wangwu.age);
System.out.println(xiaoming.name);
System.out.println(xiaoming.age);
}
}
/**
package opp.demo02;
//学生类
public class Student {
//一个类中只有属性和方法
//属性:字段
String name;
int age;
//方法
public void studey(){
System.out.println("在学习!");
}
}
*/
1.构造器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HUINRBHc-1651821374351)(F:\image\截屏\Snipaste_2022-03-30_21-53-38.png)]
package opp.demo02;
public class Person {
//一个类即使什么都不写,也会存在一个默认的无参构造方法
//显示地定义构造器
String name;
int age;
//作用:1. 使用new关键字,本质是在调用构造器
//2. 用来初始化对象的值
public Person() {
} //无参构造
// 3.一旦定义了有参构造,无参就必须显示定义
public Person(String name, int age) {
this.name = name;
this.age = age;
}
//有参构造
//Alt+insert 快捷键插入构造方法
}
/*
package opp.demo02;
public class Application {
//一个项目中应该只存在一个main方法
public static void main(String[] args) {
//对象类型 对象名 = 对象的值
Person person1 = new Person();
//这个new调用的是 无参构造
Person person = new Person("张三",18);
//这个new调用的是 有参构造
System.out.println(person.name);
System.out.println(person.age);
}
}
构造器:
1.和类名相同
2.没有返回值
作用:
1.new本质是在调用构造方法
2.初始化对象的值
注意点:
1.定义有参构造后,想使用无参构造,就得现实的定义一个无参构造
快捷键;alt+insert
*/
2.内存分析
package opp.demo02;
public class Pet {
String name;
int age;
public void shout(){
System.out.println("叫了一声!");
}
}
/*
package opp.demo02;
public class Application {
//一个项目中应该只存在一个main方法
public static void main(String[] args) {
Pet dog = new Pet();
Pet cat = new Pet();
dog.name = "旺财";
dog.age = 3;
cat.name = "咪咪";
cat.age = 3;
System.out.println(dog.name);
System.out.println(dog.age);
dog.shout();
}
}
*/
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WVIEiAJK-1651821374352)(F:\image\截屏\Snipaste_2022-03-30_22-27-42.png)]
注意点:
1.类和对象:类是一个模板:抽象,对象是一个具体的实例
2.方法:定义,调用
3.对象的引用:
- 引用类型,基本类型(8种)
- 对象是通过引用来操作的 栈---->队
4.属性:字段 (Field) 成员变量
- 默认初始化:
- 数字: 0 0.0
- char: u0000
- boolean: false
- String: null
- 引用: null
- 修饰符 属性类型 属性名 = 属性值
5.对象的创建和使用
- 必须使用new关键字来创建对象,构造器 Person person = new Person;
- 对象的属性: person.name
- 对象的方法: person.sleep
6.类:
- 静态的属性 属性
- 动态的方法 方法
3.封装(属性私有,get/set)
- 该露的露,该藏的藏
- 我们程序设计要追求“高内聚,低耦合”。高内聚就是类的内部数据细节由自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。
- 封装(数据的隐藏)
- 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,称为信息隐藏。
- 作用
- 提高程序的安全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 系统可维护性增加了
- 可以在类中对传给属性的数据进行验证合法性
4.继承
-
继承的本质是对某一批类的抽象,从而实现对世界更好地建模。
-
extends的意思是”扩展“。子类是父类的扩展,使用关键字extends来表示。
-
Java中类只有单继承,没有多继承!一个类只能继承一个父类。
-
继承是类与类之间的一种关系,此外还有依赖、组合、聚合等。
-
继承关系的两个类,一个为子类(派生类),一个为**父类(基类)**子类继承父类。
-
子类和父类之间,从意义上讲应该具有”is a“的关系。
package opp.demo03;
//Teacher 类 Teacher is a Person
public class Teacher extends Person{
}
- 子类继承了父类,就会拥有父类的全部方法,而private私有属性及方法无法继承。
- 在Java中,所有类,都默认直接或间接继承Object类 (Ctrl+H 可以查看类关系)
- 被final修饰的类,无法被继承(断子绝孙)。
package opp.demo03;
//Teacher 类 Teacher is a Person
public class Teacher extends Person{
}
/*
package opp.demo03;
//Person 类
public class Person { // Person extends Object Person类默认的直接或间接继承Object类
public String name;
private int age;
public void say(){
System.out.println("说了一句话");
}
}
*/
/*
package opp;
import opp.demo03.Teacher;
public class Application {
public static void main(String[] args) {
Teacher teacher = new Teacher();
teacher.say();
teacher.name = "张三";
//teacher.age age 属性是私有的,不能被继承,所以不能调用
}
}
*/
super & this
- super()调用父类的构造方法,必须在构造方法的第一个
- super必须只能出现在子类的方法或构造方法中
- **super()和this()**不能同时调用构造方法,因为this也必须写在第一行
- super与this的区别:super代表父类对象的引用,只能在继承条件下使用;this调用自身对象,没有继承也可以使用。
super(); //隐藏代码,默认调用了父类的无参构造,要写只能写第一行
package opp.demo04;
public class Student extends Person{
private String name = "学生类";
public Student() {
//在这里有一句隐藏代码,作用是调用父类的无参构造器
super(); //隐藏代码,调用父类的无参构造器,可以不写,默认是存在的,但是写的话只能写在第一行
System.out.println("Student无参执行了");
}
public void print(){
System.out.println("学生");
}
public void test2(){
print(); //学生
this.print(); //学生
super.print(); //人
}
public void test1(String name){
System.out.println(name); //学生类的形参
System.out.println(this.name); //学生类
System.out.println(super.name); //人类 (利用super关键字调用父类属性)
}
}
/*
package opp.demo04;
public class Person {
protected String name = "人类";
public Person() {
System.out.println("Person无参执行了");
}
//使用 private 修饰符修饰的方法是私有的,无法被继承
public void print(){
System.out.println("人");
}
}
*/
/*
package opp;
import opp.demo04.Student;
public class Application {
public static void main(String[] args) {
// 使用 new 关键字本身就是在调用构造器,这里没有参数传过去,所以调用了无参构造
Student student = new Student();
//打印
// Person无参执行了
// Student无参执行了
//看似调用的Student无参构造器,但是实际上也调用了其父类Person的无参构造器
//student.test1("学生类的形参");
//student.test2();
}
}
*/
super注意点:
- super调用父类的构造方法,必须在构造方法的第一个
- super必须只能出现在子类的方法或者构造方法中
- super 和 this 不能同时调用构造方法
和this关键字的不同点:
- 代表的对象不同:
- this : 本身调用着这个对象
- super : 代表父类对象的应用
- 前提:
- this : 没有继承也可以使用
- super : 只能在继承条件下才可以使用
- 构造方法:
- this : 调用本类的构造器
- super : 调用父类的构造器
方法的重写
- 重写:子类的方法必须与父类方法必须一致,方法体不同。
- 重写是方法的重写,与属性无关
- 重写方法只与非静态方法有关,与静态方法无关(静态方法不能被重写)
package opp.demo05;
public class Animal {
public String name;
public Animal(String name) {
this.name = name;
}
public void call(){
System.out.println(name+"在走路");
}
}
/*
package opp.demo05;
public class Dog extends Animal{
public Dog(String name) {
super(name);
}
@Override
public void call() {
System.out.println(name+"叫了一声");
}
}
*/
/*
package opp;
import opp.demo05.Animal;
import opp.demo05.Dog;
public class Application {
public static void main(String[] args) {
Animal dog = new Dog("旺财");
dog.call(); //调用父类的方法,执行的是子类的方法体(方法的重写) 旺财叫了一声
Animal animal = new Animal("旺财");
animal.call(); //调用父类方法,执行父类方法体 旺财在走路
}
}
*/
package opp.demo05;
public class Person {
public void test1(){
System.out.println("在外面");
}
public void test2(){
System.out.println("在玩");
}
}
/*
package opp.demo05;
public class Student extends Person {
public void test1(){
System.out.println("在学校");
}
@Override
public void test2() {
super.test2();
}
}
*/
/*
package opp;
import com.sun.jnlp.PersistenceServiceNSBImpl;
import opp.demo05.Person;
import opp.demo05.Student;
public class Application {
public static void main(String[] args) {
//Person类
Person person = new Person();
person.test1(); //调用父类Person中test1();方法 在外面
//Student类
Person student = new Student();
student.test1(); //调用子类Student中test1();方法 在学校
System.out.println("==========================");
person.test2(); //调用父类Person中test2();方法 在玩
student.test2(); //也调用的是父类Person中的test2();方法 在玩
}
}
*/
package opp.demo05;
public class B {
public static void test(){ //静态方法
System.out.println("B===>test");
}
public void tests(){ //非静态方法
System.out.println("调用父类方法");
}
}
/*
package opp.demo05;
public class A extends B{
public static void test(){ //静态方法
System.out.println("A===>test");
}
@Override //重写了B的方法
public void tests() { //非静态方法
System.out.println("调用子类方法");
}
}
*/
/*
package opp;
import opp.demo05.A;
import opp.demo05.B;
public class Application {
public static void main(String[] args) {
A a = new A(); //方法的调用之和左边定义的类型有关
a.test(); //打印 A==>test()
a.tests(); //打印 调用子类方法
//父类的引用指向了子类,但静态方法没有被重写
B b = new A();
b.test(); //打印 B==>test()
b.tests(); // //子类重写了父类的方法,执行子类的方法 打印 调用子类方法
/*
静态方法是类的方法,非静态方法是对象的方法
有static时,b调用了B类的方法,因为b是b类定义的
没有static时,b调用的是对象的方法,而b是A类new出来的对象,调用A的方法
}
}
*/
- 静态方法属于类,非静态方法属于对象
- 注意点:
- 方法名、参数列表必须相同
- 修饰符范围可以扩大,不能缩小(public>protect>private)
- 抛出的异常 范围可以被缩小,不能扩大
- 被**static(属于类,不属于实例),final(常量方法),private(私有)**修饰的方法不能重写
为什么要重写:父类的功能子类不一定满足,或者不一定需要
快捷键:alt+insert :override
多态
- 动态编译:类型
- 即同一方法可以根据发送对象的不同而采用不同的行为方式
- 一个对象的实际类型是确定的,但可以指向对象的引用可以有很多
- 多态存在条件
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类对象
- 注意点:
- 多态是方法的多态,没有属性的多态
- 父类和子类,有联系 类型转换异常: ClassCastException
- 存在条件:继承关系,方法需要重写,父类引用指向子类对象! Father f1() = new Son();
- static 修饰的方法,属于类,不属于实例
- final 修饰的方法是常量
- private 修饰的私有的方法
package opp.demo06;
public class Person {
public void run(){
System.out.println("run");
}
}
/*
package opp.demo06;
public class Student extends Person{
public void eat(){
System.out.println("eat");
}
@Override
public void run() {
System.out.println("son");
}
}
*/
/*
package opp;
import opp.demo06.Person;
import opp.demo06.Student;
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
//new Student();
//new Person();
//但是可以指向的引用类型就不确定了:父类的引用指向子类
//对象能执行哪些方法,主要看左边的类型,和右边关系不大,如果父类子类有相同的方法,子类就重写了父类的方法,此时执行的是子类重写后的方法,否则父类子类各自执行各自的方法
Student s1 = new Student(); //Student 能调用的方法都是自己的或者继承的父类的
s1.run();
s1.eat();
Person s2 = new Student(); //父类:可以指向子类,能调用的方法只有自己的,不能直接调用子类独有的方法(需强制转换)
s2.run();
((Student) s2).eat();
Object s3 = new Student(); //祖宗类,能调用的方法只有自己的
}
}
*/
instanceof和类型转换
- instanceof 引用类型比较,判断一个对象是什么类型
public static void main(String[] args) {
// Object > String
// Objest > Person > Student
// Objest > Person > Teacher
Object object = new Student();
// X instanceof Y,X引用指向的对象是不是Y的子类
System.out.println(object instanceof Student); //true
System.out.println(object instanceof Person); //true
System.out.println(object instanceof Teacher); //false
System.out.println(object instanceof Object); //true
System.out.println(object instanceof String); //false
//类型之间的转化:父-子(高-低),低可以转换为高
Person obj = new Syudent(); //只能用Person方法(重写了用子类重写过的方法)
(Student)obj.go(); //强转之后可以用Student方法(Student->go())
}
类型转换
- 父类引用指向子类的对象
- 把子类转换为父类,向上转型,会丢失自己原来的一些方法
- 把父类转换为子类,向下转型,强制转换,才调用子类方法
- 方便方法的调用(转型),减少重复的代码,简洁。
Static
- 静态变量可以直接用类名访问,也称类变量。
- 静态变量(或方法)对于类,所有对象(实例)所共享。
- 静态区代码 加载类时一起被初始化,最早执行且只执行一次(第一次new)。
- Math->随机数:
package opp.demo07;
public class Student {
private static int age = 18;//静态属性
private double score = 98;//非静态属性
public void run(){ //非静态方法
System.out.println("run");
}
public static void go(){ //静态方法
System.out.println("go");
}
public static void main(String[] args) {
System.out.println(Student.age);//调用静态属性可以直接类名.属性
//调用非静态属性则需要new 类.属性
System.out.println(new Student().age);
System.out.println(new Student().score);
//调用静态方法,可以类名.方法名 或者 直接使用方法名
Student.go();
go();
//调用非静态方法,则需要new 类.方法名
new Student().run();
}
}
package opp.demo07;
public class Person {
//第二个加载
{
System.out.println("匿名代码块");
}
//第一个加载,只执行一次
static {
System.out.println("静态代码块");
}
//第三个加载
public Person() {
System.out.println("无参构造方法");
}
public static void main(String[] args) {
Person person1 = new Person();
//静态代码块
//匿名代码块
//无参构造方法
System.out.println("===============");
Person person2 = new Person();
//匿名代码块
//无参构造方法
}
}
package opp.demo07;
//静态导入包
import static java.lang.Math.random;
import static java.lang.Math.PI;
public class Test {
public static void main(String[] args) {
//第一种方法不用导包
System.out.println(Math.random()); //0.9384625605154566
//第二章方法需要静态导入包
System.out.println(random()); //0.6167090889383677
System.out.println(PI); //3.141592653589793
}
}
抽象类(abstract)
- abstract修饰的类就是抽象类,修饰的方法就是抽象方法。
- 抽象类中可以没有抽象方法,但有抽象方法的类一定要声明为抽象类。
- 抽象类不能使用new来创建对象,它是用来让子类继承的。
- 抽象方法只有方法的声明,没有实现,让其子类实现。
- 子类继承抽象类,必须实现抽象类的所有方法,否则该子类也要声明为抽象类。
package opp.demo08;
//abstract 关键字修饰抽象类,类只能单继承,但是接口可以多继承。
public abstract class Action {
//只是一个约束,有人帮我们实现~
//抽象方法只有方法名,没有方法的实现
public abstract void doSomething();
//1.不能new抽象类,只能靠子类去实现它,仅作为一个约束
//2.抽象方法只能出现在抽象类中,抽象类可以有普通方法
//3.抽象类有构造器,可以派生子类
//4.抽象类的意义:约束,提高开发效率。但是类只能单继承,所以有局限 用的不多
}
/*
package opp.demo08;
//子类继承了抽象父类,则子类必须重写抽象父类中的抽象方法
public class A extends Action{
@Override
public void doSomething() {
}
}
*/
接口(interface)
-
普通类:只有具体实现
-
抽象类:具体实现和规范(抽象方法)都有
-
接口:只有规范,没有方法实现,专业的约束!约束与实现分离:面向接口编程~
-
接口就是规范,定义的是一组规则,"你是什么…必须做什么…"的思想。
-
接口的本质是约束,就像人间法律一样,制定好大家都遵守。
package opp.demo09;
//interface 接口,接口都要有继承类
//实现类(implements 可以继承多个接口)
//多继承,利用接口实现多继承
public interface UserService {
//定义的属性都是常量,默认修饰 public static final,可以不写
public static final int AGE = 18; //一般不用
//接口中的所有的定义的方法都是抽象的 默认public abstract,可以不写
public abstract void run();
void add();
void delete();
void update();
void select();
}
/*
package opp.demo09;
public interface TimerService {
void timer();
}
*/
/*
package opp.demo09;
public class UserServiceImpl implements UserService,TimerService {
@Override
public void run() {
}
@Override
public void add() {
}
@Override
public void delete() {
}
@Override
public void update() {
}
@Override
public void select() {
}
@Override
public void timer() {
}
}
*/
注意点:
- 接口没有构造方法,不能被实例化
- 实现类必须要重写接口中的方法
- 实现类(implements) 可以实现多个接口
内部类
- 内部类就是在一个类的内部再定义一个类,比如A类中定义了一个B类,那么B就是A的内部类,而A相对B来说就是外部类
- 成员内部类:可以操作外部类的私有属性及方法
- 静态内部类:static修饰,不能访问外部类私有属性
- 局部内部类:外部类的方法里定义的类
- 匿名内部类:没有名字初始化类
package opp.demo10;
public class Outer {
private int id = 18;
public void out(){
System.out.println("这是外部类的方法!");
}
public class Inner{
public void in(){
System.out.println("这是内部类的方法!");
}
//获取外部类的私有属性
public void getId(){
System.out.println(id);
}
/*
package opp;
import opp.demo10.Outer;
public class Application {
public static void main(String[] args) {
Outer outer = new Outer();
outer.out();
Outer.Inner inner = outer.new Inner();
inner.in();
inner.getId();
}
}
*/
}
}
package opp.demo10;
public class Test {
public static void main(String[] args) {
new A().eat();
}
}
class A{
public void eat(){
System.out.println("eat");
}
}
异常
-
软件程序在运行过程中,经常可能遇到异常问题,异常英文(Exception),意思是例外,这些例外情况需要我们写程序做出合理的处理,而不至于让程序崩溃。
-
异常指程序运行中出现的不期而至的各种状况:文件找不到,网络连接错误,非法参数等。
-
异常发生在程序运行期间,它影响了正常的执行流程。
简单分类
- 检查型异常:最具代表性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如用户要打开一个不存在的文件时引发的异常,这些异常在编译时不能被简单地忽略。
- 运行时异常:是可能被程序员避免的异常,与检查性异常相反,运行时异常可以在编译时忽略。
- 错误Error:错误不是异常,而是脱离程序员控制的问题。错误在代码经常被忽略。例如当栈溢出,一个异常就发生了,它们在编译也检查不到。
package exception.demo01;
public class Test1 {
public static void main(String[] args) {
int a = 1;
int b = 0;
System.out.println(a / b); //Exception in thread "main" java.lang.ArithmeticException
new Test1().a(); //Exception in thread "main" java.lang.StackOverflowError
}
public void a(){
a();
}
public void b(){
b();
}
}
异常处理机制
- 抛出异常
- 捕获异常
- 异常处理关键字:try、catch、finally、throw、throws
- 快捷键:Ctrl+alt+t
package exception.demo01;
public class Test2 {
public static void main(String[] args) {
int a = 1;
int b = 0;
//捕获多个异常时,错误需要从小到大进行捕获
try{ // try 代码块为监控区域
System.out.println(a / b);
}catch(ArithmeticException e){ // catch 捕获异常
System.out.println("ArithmeticException");
}catch (Exception e){
System.out.println("Exception");
}catch (Throwable t){
System.out.println("Throwable");
}finally { //处理善后工作,一定会执行,如关闭资源
System.out.println("finally");
}
}
}
package exception.demo01;
public class Test3 {
public static void main(String[] args) {
int a = 1;
int b = 0;
try {
if (b == 0){ //抛出异常一般在方法中使用
throw new ArithmeticException(); //主动抛出异常
}
System.out.println(a / b);
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("finally");
}
}
}
package exception.demo01;
public class Test4 {
public static void main(String[] args) {
//方法中或方法上抛出异常,这里就需要捕获异常
try {
new Test4().test(1,0);
} catch (ArithmeticException e) {
e.printStackTrace();
} finally {
System.out.println("处理善后工作");
}
}
public void test(int a,int b) throws ArithmeticException{
if (b == 0){
throw new ArithmeticException(); //主动抛出的异常,一般在方法中使用,假设方法中处理不掉,则需在继续方法上抛出异常
}
System.out.println(a/b);
}
}
自定义异常
package exception.demo01;
//自定义的异常类
public class MyException extends Exception{ //自定义的异常类需要继承Exception类
//传递的数字>10,抛出异常
private int detail;
public MyException(int a) {
this.detail = a;
}
public MyException() {
}
@Override
public String toString() {
return "MyException{" +
"detail=" + detail +
'}';
}
private void test(int a) throws MyException{
System.out.println("传递的参数为:"+a);
if (a > 10){
throw new MyException(a); //抛出异常
}
System.out.println("OK!");
}
public static void main(String[] args) throws MyException {
try {
new MyException().test(11);
} catch (MyException e) {
System.out.println("MyException->"+e);
} finally {
System.out.println("处理善后工作");
}
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GxAvXAZ4-1651821374352)(F:\image\截屏\watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZsbG93X3dpbmQ=,size_16,color_FFFFFF,t_70)]