学习内容
static 关键字
final 关键字
枚举
1 static 关键字
static:表示静态,是Java的修饰符,用来修饰(成员变量/成员方法)
1.1 static关键字修饰成员变量

1.1.1 练习 --学生类的共享属性

staticvariabletest1.Student
java
package com.itstudy.staticvariabletest1;
public class Student {
//共享
String name;//姓名
int age;//年龄
//一个班级的学生共享同一个老师
static String teacherName;//老师姓名
}
staticvariabletest1.Test
java
package com.itstudy.staticvariabletest1;
public class Test {
public static void main(String[] args) {
/* 学生类的共享属性
学生有如下属性:姓名,年龄,老师
一个班级中,所有学生都是共享同一个老师
第一名学生:小诗诗,19 岁
第二名学生:小丹丹,20 岁
最初都是小雯老师上课,有一天小丹丹申请换老师,换成了阿玮老师
利用 static 模拟上述效果
关于static需要重点掌握的内容:
1. 静态变量,被当前类所有对象共享
共享:
赋值只要赋值一次
只要有一个对象修改了静态变量,其他对象再次访问的时候就是修改之后的结果了
2. 调用方式:
方式一:类名调用(推荐)
方式二:对象名调用
*/
//最初都是小雯老师上课
//student这个类所有对象的teacherName都是小雯老师
Student.teacherName = "小雯老师";
Student s1 = new Student();
s1.name = "小诗诗";
s1.age = 19;
Student s2 =new Student();
s2.name = "小丹丹";
s2.age = 20;
s2.teacherName = "阿玮老师";
System.out.println(s1.name +", " + s1.age+", " + s1.teacherName);
System.out.println(s2.name + ", " + s2.age+", " + s2.teacherName);
//用对象名访问静态属性
System.out.println(s1.teacherName);
//用类名访问静态属性
System.out.println(Student.teacherName);
}
}
1.1.2 练习 -- 判断是否可以用static修饰

答案:老师、饮水机可以用static修饰,因为是共享属性
1.1.3 static关键字的内存解析

输出:小诗诗 23 阿玮老师
null 0 阿玮老师
重点:静态变量是随着类的加载而加载的,优先于对象出现

注:方法执行完出栈,堆内存里对象没有调用时清空,而静态变量和方法区的字节码信息不清空,只有在虚拟机关闭后清空。
1.1.4 static静态变量小结

1.2 static关键字修饰成员方法

1.2.1 工具类
1.2.1 工具类书写方式

1.2.2 工具类练习

toolclasstest.ArrayUtil
java
package toolclasstest;
/*定义数组工具类
需求:
在实际开发中,经常会遇到一些数组使用的工具类。
请按照如下要求编写一个数组的工具类完成以下需求:
提供一个方法 printArr,用于遍历数组。
格式如下:[10, 20, 50, 34, 100](只考虑整数数组)
提供一个方法 getAverage,用于返回平均分。(只考虑整数数组)
*/
public class ArrayUtil {
//私有化构造方法,目的:不让外界创建对象
private ArrayUtil() {}
//定义方法(静态)
/*
提供一个方法 printArr,用于遍历数组。
格式如下:[10, 20, 50, 34, 100](只考虑整数数组)
*/
public static String printArr(int[] arr) {
//直接打印
/*System.out.print("[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
System.out.println(arr[i] + "]");
} else {
System.out.print(arr[i] + ", ");
}
}*/
//不直接打印,调用返回值打印
String result = "[";
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
result = result + arr[i] + "]";
} else {
result = result + arr[i] + ", ";
}
}
return result;
}
//提供一个方法 getAverage,用于返回平均分。(只考虑整数数组)
public static double getAverage(int[] arr) {
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
double avg = sum * 1.0 / arr.length; //只有乘1.0,才能得到浮点数结果,否则得到整数结果
return avg;
}
}
toolclasstest.Test
java
package toolclasstest;
public class Test {
public static void main(String[] args) {
/*定义数组工具类
需求:
在实际开发中,经常会遇到一些数组使用的工具类。
请按照如下要求编写一个数组的工具类完成以下需求:
提供一个方法 printArr,用于遍历数组。
格式如下:[10, 20, 50, 34, 100](只考虑整数数组)
提供一个方法 getAverage,用于返回平均分。(只考虑整数数组)
*/
//创建一个数组
int[] arr = {10, 50, 34, 100};
//调用数组工具类的方法遍历数组
// ArrayUtil.printArr(arr); //无返回值方法直接调用打印
String str = ArrayUtil.printArr(arr);//有返回值方法,需要接收返回值,才能打印
System.out.println(str);
int [] arr1={10,20,37,40,50};
//调用数组工具类的方法返回平均分
double average = ArrayUtil.getAverage(arr1);
System.out.println(average);
}
}
1.3 静态的注意事项
1.3.1 注意事项

1.3.2 静态的内存图

name报错,因为静态方法中没有this来指向对象的内存地址,且没有创建对象来传递地址,导致无法正常访问,即静态方法无法访问非静态变量或者非静态方法

非静态可以调用所有
1.4 static关键字总结


1.5 重新认识main方法

JVM指虚拟机
2 final 关键字
2.1 final关键字介绍

finaltest.Student
java
package finaltest;
public class Student {
private String name;
private int age;
//无参构造方法
public Student() {
}
//有参构造方法
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//get/set方法
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;
}
}
finaltest.Student1
java
package finaltest;
public class Student1 {
private final String NAME="张三"; //定义为常量,无法修改属性值 且无法使用this关键词
final int AGE=18; //为了方便调用,去掉private修饰符
//无参构造方法
public Student1() {
}
//get/set方法
public String getName() {
return NAME;
}
public int getAge() {
return AGE;
}
}
finaltest.FinalTest
java
package finaltest;
public class FinalTest {
public static void main(String[] args) {
/*
* final 修饰变量,此时叫做常量
* 特点1:只能被赋值一次,一旦赋值,无法再次修改
* 特点2:常量名大写,多个单词之间用下划线隔开
*
* 细节:
* 基本数据类型:
* byte short int long float double char boolean
* 变量里面记录的是真实的数据
* final int a =10; 此时变量里面记录的数据无法发生改变
* 引用数据类型:
* 除了上面四类八种,其他所有的数据类型都是引用类型 例:int[]、 String[]、Student
*
* stu里面记录对象的内存地址,不可改变的是stu记录的内存地址
* 而对象里面的属性值,是可以发生改变的
* final Student stu = new Student();
* 综上所述:
* final修饰哪个变量,这个变量里面记录的内容就无法再次发生改变
* */
//1.定义一个常量
final int NUMBER = 100;
//2.使用常量
System.out.println(NUMBER + 200);
// 不可修改赋值(报错)
// NUMBER=200;
//定义一个引用数据类型的常量
final Student STU = new Student("张三", 18);
// STU=new Student();(报错) 无法修改对象的内存地址
// 可以修改对象里面的属性值
STU.setName("李四");
STU.setAge(20);
System.out.println(STU.getName());
System.out.println(STU.getAge());
//定义一个引用数据类型的常量
final Student1 STU1 = new Student1();
System.out.println(STU1.getName());
System.out.println(STU1.AGE);
}
}
2.2 final的内存图

2.3 练习 -- 常量的练习

finaltest.Circle
java
package finaltest;
public class Circle {
/*
定义一个 Javabean 类描述圆
属性:半径和圆周率
行为:计算圆的面积和周长
*/
// 定义属性
private double radius; // 半径
private final double PI = 3.141592653589793238462; // 圆周率
// 无参构造方法
public Circle() {
}
// 有参构造方法
public Circle(double radius) {
this.radius = radius;
}
//get/set方法
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
public double getPI() {
return PI;
}
// 定义行为
// 计算圆的面积
public double getArea() {
return radius * radius * PI;
}
// 计算圆的周长
public double getLength() {
return 2 * PI * radius;
}
}
finaltest.FinalTest2
java
package finaltest;
public class FinalTest2 {
public static void main(String[] args) {
/* 常量的练习
定义一个 Javabean 类描述圆
属性:半径和圆周率
行为:计算圆的面积和周长
*/
// 定义一个圆对象
Circle c1 = new Circle(5.0);
// 获取圆里面的属性
System.out.println(c1.getRadius());
System.out.println(c1.getPI());
// 获取圆的面积
System.out.println(c1.getArea());
// 获取圆的周长
System.out.println(c1.getLength());
}
}
3 枚举
3.1 什么是枚举

3.2 枚举的定义格式

3.3 枚举定义练习 -- 订单状态

enumtest.OrderState
java
package enumtest;
/*电商项目中,订单的状态只有以下 6 种,请编写代码实现。
待支付、处理中、已发货、配送中、已送达、已取消。*/
public enum OrderState {
// 在枚举类的第一行,把所有的对象都罗列出来了
PAYMENT_PENDING("待支付"),//待支付
PROCESSING("处理中"),//处理中
SHIPPED("已发货"),//已发货
OUT_OF_FOR_DELIVERY("配送中"),//配送中
DELIVERED("已送达"),//已送达
CANCELLED("已取消");////已取消
// 有参构造方法
private String name;
// 枚举类的构造方法默认使用 private 修饰,就算不写,虚拟机也会加上 private
private OrderState(String name) {
//每一个枚举项,都是该枚举类的对象(每一个对象都是通过构造方法创建出来的)
System.out.println("看看我执行了吗?"+name); //验证构造方法是否执行了
this.name = name;
}
public String getName() {
return name;
}
}
enumtest.Test
java
package enumtest;
public class Test {
public static void main(String[] args) {
/* 订单的状态
电商项目中,订单的状态只有以下 6 种,请编写代码实现。
待支付、处理中、已发货、配送中、已送达、已取消。*/
OrderState o1 = OrderState.PAYMENT_PENDING;
System.out.println(o1);
//匹配
switch (o1) {
case PAYMENT_PENDING -> System.out.println("待支付状态");
case PROCESSING -> System.out.println("处理中");
case SHIPPED -> System.out.println("已发货");
case OUT_OF_FOR_DELIVERY -> System.out.println("配送中");
case DELIVERED -> System.out.println("已送达");
case CANCELLED -> System.out.println("已取消");
}
}
}
3.4 枚举的注意事项

enumtest.OrderState
java
package enumtest;
/*电商项目中,订单的状态只有以下 6 种,请编写代码实现。
待支付、处理中、已发货、配送中、已送达、已取消。*/
public enum OrderState {
// 在枚举类的第一行,把所有的对象都罗列出来了
PAYMENT_PENDING("待支付"),//待支付
PROCESSING("处理中"),//处理中
SHIPPED("已发货"),//已发货
OUT_OF_FOR_DELIVERY("配送中"),//配送中
DELIVERED("已送达"),//已送达
CANCELLED("已取消");////已取消
// 有参构造方法
private String name;
// 枚举类的构造方法默认使用 private 修饰,就算不写,虚拟机也会加上 private
private OrderState(String name) {
//每一个枚举项,都是该枚举类的对象(每一个对象都是通过构造方法创建出来的)
System.out.println("看看我执行了吗?"+name); //验证构造方法是否执行了
this.name = name;
}
public String getName() {
return name;
}
}
enumtest.Test2
java
package enumtest;
public class Test2 {
public static void main(String[] args) {
/*
枚举的注意事项
1.每一个枚举项,都是该枚举类的对象(每一个对象都是通过构造方法创建出来的)
2.枚举项在底层其实就是常量,默认用 public static final 修饰
(终端输入 Javap OrderState.class查看底层逻辑)
3.枚举类的第一行上必须是枚举项,枚举项之间用逗号隔开,以分号作为结尾
4.枚举类的构造方法必须是 private 修饰,不让外界创建本类的对象
5.编译器会给枚举类新增两个默认存在的方法:values (),valueOf ()
values():表示获取本类所有的枚举项
valueOf(): 表示获取一个指定的枚举项
*/
OrderState o1 = OrderState.CANCELLED;
System.out.println(o1.getName());
OrderState[] arr = OrderState.values();
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
OrderState o2 = OrderState.valueOf("SHIPPED");
System.out.println(o2.getName());
}
}