什么是类的模板,类的信息是如何在内存空间中进行存储的呢?
- 声明:声明一个对象,包括对象名称和对象类型。 (1:准备一个class)
- 实例化:使用关键字 new 来创建一个对象。(2: new 去标识出来创建对象)
- 初始化:使用 new 创建对象时,会调用构造方法初始化对象。(3:会调用构造函数去java堆中申请空间)
抽象类:其是比普通类多了一个抽象方法, 抽象方法它是子类的一种约束,告诉子类一定要覆盖和重写的方法
抽象类可以继承抽象类吗?
枚举
用法一:常量
在JDK1.5 之前,我们定义常量都是: public static final… 。现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法。
用法二:switch
enum Signal {
GREEN, YELLOW, RED
}
public class TrafficLight {
Signal color = Signal.RED;
public void change() {
switch (color) {
case RED:
color = Signal.GREEN;
break;
case YELLOW:
color = Signal.RED;
break;
case GREEN:
color = Signal.YELLOW;
break;
}
}
}
用法三:向枚举中添加新方法
public enum Color {
RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
// 成员变量
private String name;
private int index;
// 构造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
}
// 普通方法
public static String getName(int index) {
for (Color c : Color.values()) {
if (c.getIndex() == index) {
return c.name;
}
}
return null;
}
// get set 方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}
用法四:覆盖枚举的方法
public enum Color {
RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
// 成员变量
private String name;
private int index;
// 构造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
}
//覆盖方法
@Override
public String toString() {
return this.index+"_"+this.name;
}
}
用法五:实现接口
所有的枚举都继承自java.lang.Enum类。由于Java 不支持多继承,所以枚举对象不能再继承其他类。
public interface Behaviour {
void print();
String getInfo();
}
public enum Color implements Behaviour{
RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
// 成员变量
private String name;
private int index;
// 构造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
}
//接口方法
@Override
public String getInfo() {
return this.name;
}
//接口方法
@Override
public void print() {
System.out.println(this.index+":"+this.name);
}
}
用法六:使用接口组织枚举
@Test
void contextLoads() {
for (Food.DessertEnum dessertEnum : Food.DessertEnum.values()) {
System.out.print(dessertEnum + " ");
}
System.out.println();
//我这地方这么写,是因为我在自己测试的时候,把这个coffee单独到一个文件去实现那个food接口,而不是在那个接口的内部。
for (Food.CoffeeEnum coffee : Food.CoffeeEnum.values()) {
System.out.print(coffee + " ");
}
System.out.println();
//搞个实现接口,来组织枚举,简单讲,就是分类吧。如果大量使用枚举的话,这么干,在写代码的时候,就很方便调用啦。
//还有就是个“多态”的功能吧,
Food food = Food.DessertEnum.CAKE;
System.out.println(food);
food = Food.CoffeeEnum.BLACK_COFFEE;
System.out.println(food);
}
public interface Food {
enum CoffeeEnum implements Food{
BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO
}
enum DessertEnum implements Food{
FRUIT, CAKE, GELATO
}
}
用法七:关于枚举集合的使用
java.util.EnumSet和java.util.EnumMap是两个枚举集合。EnumSet保证集合中的元素不重复;EnumMap中的 key是enum类型,而value则可以是任意类型。关于这个两个集合的使用就不在这里赘述,可以参考JDK文档。
@SpringBootTest
public class AdminWebApplicationTests {
@Test
void contextLoads() {
for (SimpleEnum simpleEnum : SimpleEnum.values()) {
System.out.println(simpleEnum + " ordinal " + simpleEnum.ordinal());
}
System.out.println("------------------");
for (TYPE type : TYPE.values()) {
System.out.println("type = " + type + " type.name = " + type.name() + " typeName = " + type.getTypeName() + " ordinal = " + type.ordinal());
}
System.out.println("======================================");
String typeName = "f5";
TYPE type = TYPE.fromTypeName(typeName);
if (TYPE.BALANCE.equals(type)) {
System.out.println("根据字符串获得的枚举类型实例跟枚举常量一致");
} else {
System.out.println("大师兄代码错误");
}
}
/**
* 季节枚举(不带参数的枚举常量)这个是最简单的枚举使用实例
* Ordinal 属性,对应的就是排列顺序,从0开始。
*/
private enum SimpleEnum {
SPRING,
SUMMER,
AUTUMN,
WINTER
}
private enum TYPE {
FIREWALL("firewall"),
SECRET("secretMac"),
BALANCE("f5");
private String typeName;
TYPE(String typeName) {
this.typeName = typeName;
}
/**
* 根据类型的名称,返回类型的枚举实例。
*
* @param typeName 类型名称
*/
public static TYPE fromTypeName(String typeName) {
for (TYPE type : TYPE.values()) {
if (type.getTypeName().equals(typeName)) {
return type;
}
}
return null;
}
public String getTypeName() {
return this.typeName;
}
}
}
PRING ordinal 0
SUMMER ordinal 1
AUTUMN ordinal 2
WINTER ordinal 3
------------------
type = FIREWALL type.name = FIREWALL typeName = firewall ordinal = 0
type = SECRET type.name = SECRET typeName = secretMac ordinal = 1
type = BALANCE type.name = BALANCE typeName = f5 ordinal = 2
======================================
根据字符串获得的枚举类型实例跟枚举常量一致
总结
enum这个关键字,可以理解为跟class差不多,这也个单独的类。可以看到,上面的例子里面有属性,有构造方法,有getter,也可以有setter,但是一般都是构造传参数。还有其他自定义方法。
那么在这些东西前面的,以逗号隔开的,最后以分号结尾的,这部分叫做,这个枚举的实例。
也可以理解为,class new 出来的实例对象。这下就好理解了。
只是,class,new对象,可以自己随便new,想几个就几个,而这个enum关键字,他就不行,他的实例对象,只能在这个enum里面体现。
也就是说,他对应的实例是有限的。这也就是枚举的好处了,限制了某些东西的范围,举个栗子:一年四季,只能有春夏秋冬,你要是字符串表示的话,那就海了去了,但是,要用枚举类型的话,你在enum的大括号里面把所有的选项,全列出来,那么这个季节的属性,对应的值,只能在里面挑。不能有其他的。
枚举的实际应用场景
ublic interface IResultEnum {
// 项目服务名 系统编码
String A = "101"; // 前台系统
String B = "202"; // APP系统
// 成功状态常量
int SUCCESS = 200;
String SUCCESS_TEXT = "SUCCESS";
// 无法捕获的异常状态
int SERVER_ERROR = 500;
// 需要覆盖的方法 每个子类堆外暴露的方法
int status();
String message();
}
public enum ResultStatusEnumA implements IResultEnum{
USER_PWR_STATUS("601", "100", "用户密码有误"),
USER_USERNAME_STATUS("601", "100", "请输入用户名"),
USER_PWR_STATUS_INPUT("603", "100", "请输入密码"),
TOKEN_EMPTY("604", "100", "token is empty!!!"),
TOKEN_EMPTY_EXPIRED("604", "100", "token is expired!!!"),
TOKEN_USER_EMPTY("605", "100", "User is not exisit!!!"),
TOKEN_UN_VALID("606", "100", "token unvalid!!!"),
ORDER_ERROR_STATUS("602", "102", "订单有误");
public static final Integer A1 = 100; // 用户登录
public static final Integer A2 = 101; // 支付
public static final Integer A3 = 102; // 产品课程
ResultStatusEnumA(String status, String bcode, String message) {
this.status = Integer.parseInt(IResultEnum.A.concat(bcode).concat(status));
this.message = message;
}
private int status;
private String message;
@Override
public int status() {
return this.status;
}
@Override
public String message() {
return this.message;
}
}