一. 静态方法的定义有啥规律可循?总结几句话(除了静态方法、其他也总结下)。定义一个枚举,按照总结的要求来。
静态方法:
- 静态方法必须在枚举类的内部定义,不能在枚举的实例中定义。
- 静态方法使用关键字static来修饰,表明该方法属于类而不是实例,可以直接通过类名调用。
- 静态方法可以访问枚举类的静态成员(如其他静态方法、静态变量),但不能直接访问非静态成员(实例变量)。
- 静态方法在枚举类加载时被初始化,且只会初始化一次。
- 静态方法通常用于执行与枚举类整体相关的操作,而非特定枚举实例的操作。
与枚举类型的区别:
定义方式:
枚举:在Java中,枚举是一种特殊的数据类型,用于定义一组相关的命名常量。枚举类型在Java中是通过关键字enum
来声明的。
静态常量:静态常量是指在类级别声明的常量,使用关键字final
来修饰,并且必须在声明时进行初始化。
类型安全:
枚举:枚举提供了类型安全性,编译器会检查枚举类型的值是否在定义的范围内。
静态常量:静态常量没有类型安全性,它们只是普通的常量,并且可以在编译时和运行时修改。
实例化:
枚举:枚举类型的实例化是有限的,它们在声明时都被预先定义好,不允许在运行时动态添加新的实例。
静态常量:静态常量只是简单的值的定义,并不涉及实例化过程,可以根据需要动态添加。
可读性和可维护性:
枚举:枚举类型提供了更好的可读性,因为它们允许为每个常量赋予有意义的名称,并且IDE通常会提供自动补全功能来帮助选择合适的枚举常量。
静态常量:静态常量的可读性较差,因为它们通常只是简单的字面值,不具备语义信息。
使用场景:
枚举:适用于表示有限的、预定义的常量集合,如星期几、月份、状态等。
静态常量:适用于表示不可变的全局常量,如数学常数(π)、通用配置值等。
非静态方法:
7. 非静态方法必须在枚举的内部定义,作为枚举类的成员方法。
8. 非静态方法没有使用关键字static修饰,因此它是属于枚举类的实例的,需要通过枚举对象来调用。
9. 非静态方法可以访问枚举类的静态成员和非静态成员,包括其他方法、静态变量和实例变量。
10. 每个枚举实例都共享相同的非静态方法代码,但可以根据实例的状态(属性值)在方法内部执行不同的操作。
11. 非静态方法在每个枚举实例上都可以独立执行,因此可以在枚举实例级别上定义特定于实例的行为。
- 枚举
简单枚举:
enum Weekday {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
enum Season{
SPRING("WARM"), SUMMER("HOT"), AUTUMN("COOL"), WINTER("CLOD");
private final String temperature;
Season(String temperature) {
this.temperature = temperature;
}
public String getTemperature() {
return temperature;
}
}
public void test01(){
Weekday[] weekdays = Weekday.values();
for (Weekday days : weekdays) {
System.out.println(days);
}
System.out.println("---------------------------");
Season[] seasons = Season.values();
for (Season sa : seasons) {
System.out.println(sa);
System.out.println(sa.getTemperature());
}
}
仿照上课例子写的枚举:
public void test02(){
Season2 spring = Season2.SPRING;
System.out.println(spring.getOption());
System.out.println(spring.getTemperature());
}
enum Season2 {
SPRING(1, "warm"),
SUMMER(2, "hot"),
AUTUMN(3, "cool"),
WINTER(4, "cold");
private final int option;
private final String temperature;
Season2(int option, String temperature) {
this.option = option;
this.temperature = temperature;
}
public String getTemperature() {
return temperature;
}
public int getOption() {
return option;
}
}
二. 同样是定义常量,使用枚举和类的静态变量、接口的静态变量进行对比,有哪些差异?
- 类型安全性:枚举提供了类型安全的常量定义。它们在编译时就能够进行类型检查,可以避免使用错误的常量值。类的静态变量和接口的静态变量没有这种类型安全性保证,可以被赋予任何值。
- 命名空间:枚举常量是在枚举类型的命名空间中定义的,具有更高的封装性,所以不同的枚举类型可以使用相同的敞亮名称而不会产生冲突。而类的静态变量和接口是在他们所属的类或接口的命名空间中定义的,可能会冲突。
- 枚举类型使用类型所提供的内置遍历方法如values()方法来遍历枚举变量,可以用==来进行比较。对于类的静态变量和接口的静态变量,如果需要迭代或进行比较,就需要自己实现相应的逻辑。
- 添加行为:可以为枚举常量定义方法来执行相关的操作。而类的静态变量和接口的静态变量则无法直接附加方法或属性。
三. 使用 Lombok 注解重写 1. 定义的枚举;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;
/**
* test03 使用 Lombok 注解重写 1. 定义的枚举
*/
@Test
public void test03(){
Season3 spring = Season3.SPRING;
System.out.println(spring.getOption());
System.out.println(spring.getTemperature());
}
/**
* test03枚举类型练习
* @Getter`:自动生成属性的 getter 方法。
* @AllArgsConstructor`:生成一个包含所有参数的构造方法。
* @ToString`:自动生成 `toString()方法,用于将枚举实例转换为字符串表示。
*/
@Getter
@AllArgsConstructor
@ToString
enum Season3 {
SPRING(1, "warm"),
SUMMER(2, "hot"),
AUTUMN(3, "cool"),
WINTER(4, "cold");
private final int option;
private final String temperature;
}
四. 定义坐标点类
- 提供属性:横坐标、纵坐标
- 提供方法:
- 计算坐标点到原点的距离
- 计算当前坐标点到另外任意坐标点的距离
- 计算给定两个坐标点的距离
@Test
public void test05() {
PointAnnotation point0 = new PointAnnotation(0,0);
PointAnnotation point1 = new PointAnnotation(5, 12);
PointAnnotation point2 = new PointAnnotation(39, 23);
PointAnnotation point3 = new PointAnnotation(8, 15);
/**
* point1到原点的距离
*/
System.out.println(point1.distanceToOrigin());
/**
* point1到point2的距离
*/
System.out.println(point1.distanceToOtherPoint(point2));
/**
* point2和point3之间的距离
*/
System.out.println(point1.distanceBetweenPoints(point2,point3));
}
/**
* 输出:
* 13.0
* 35.73513677041127
* 32.01562118716424
*/
/**
* test05 使用注解
*定义坐标点类
* + 提供属性:横坐标、纵坐标
* + 提供方法:
* 1. 计算坐标点到原点的距离
* 2. 计算当前坐标点到另外任意坐标点的距离
* 3. 计算给定两个坐标点的距离
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
class PointAnnotation {
public int x;
public int y;
/**
* 给出任意两点坐标计算两点之间的距离
* @param Point1
* @param Point2
* @return
*/
public static double distanceBetweenPoints(PointAnnotation Point1, PointAnnotation Point2) {
int x1 = Point1.getX()-Point2.getX();
int y1 = Point1.getY()-Point2.getY();
return Math.sqrt(x1 * x1 + y1 * y1);
}
/**
* 坐标到原点的距离
* @return
*/
public double distanceToOrigin() {
return distanceBetweenPoints(this,new PointAnnotation(0,0));
}
public double distanceToOtherPoint(PointAnnotation otherPoint) {
return distanceBetweenPoints(this,otherPoint);
}
}
五. 验证下原因:对于使用了以上四个注解的 Query、PO、BO、VO 类,如果属性有默认值,那么需要在属性上增加注解 @Builder.Default
@Test
public void test06() {
/**
* 使用构造器设置默认值
*/
Test06 eg1 = Test06.builder().name("小马").build();
System.out.println("eg1: " + eg1);
/**
* 不使用构造器设置默认值
*/
Test06 eg2 = new Test06();
eg2.setName("老马");
System.out.println("eg2: " + eg2);
}
/**
* 输出:
* eg1: Test06(name=小马, ageWithoutDefault=0, ageWithDefault=18)
* eg2: Test06(name=老马, ageWithoutDefault=188, ageWithDefault=18)
*/
/**
* test06
* @Data
* @Builder
* @NoArgsConstructor
* @AllArgsConstructor
* 对于使用了以上四个注解的 Query、PO、BO、VO 类,如果属性有默认值,那么需要在属性上增加注解 @Builder.Default
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
class Test06 {
private String name;
/**
* 没有使用@Builder.Default注解,没有默认值
*/
private int ageWithoutDefault = 188;
/**
* 使用@Builder.Default注解,有默认值
*/
@Builder.Default
private int ageWithDefault = 18;
}