- 一、权限修饰符
- 二、final 关键字
- 2.1 final 作用
- 2.2 final 修饰变量举例
- 2.3 常量
- 三、枚举
- 3.1 枚举的格式
- 3.2 枚举的特征
- 3.3 枚举的应用
一、权限修饰符
权限修饰符 用于约束成员变量、构造器、方法等的访问范围。
权限修饰符: 有四种作用范围由小到大 (private -> 缺省 ->protected - > public)

注: 不同包下的子类指的是,不同包下的子类对象能访问,当前类创建父类对象访问不了。
// 模拟不同包下的子类
public class Zi extends Fu {
    public static void main(String[] args) {
        Fu fu = new Fu();
        // fu.privateMethod(); 访问不了
        // fu.method(); 访问不了
        // fu.protectedMethod(); 访问不了
        fu.publicMethod();
        Zi zi = new Zi();
        zi.protectedMethod(); // 可以访问 protected
    }
}
定义成员变量、构造器、方法等一般需满足如下要求:
① 成员变量一般私有。
② 方法一般公开。
③ 如果该成员只希望本类访问,使用 private 修饰。
④ 如果该成员只希望本类,同一个包下的其他类和子类访问,使用 protected 修饰。
二、final 关键字
2.1 final 作用
final 关键字是最终的意思,可以修饰类、方法与变量。
- 修饰类: 类不能被继承。工具类可以用 final 修饰。
- 修饰方法: 方法不能被重写。 模板方法可以用 final。
- 修饰变量: 有且仅能被赋值一次。
2.2 final 修饰变量举例
final 修饰 基本数据类型 的变量,其存储的数据不能改变。
 final 修饰 引用类型 的变量,其存储的地址不能改变,但是指向的对象内容可以改变。
举例:final 修饰变量
public class Test {
    // 修饰静态成员变量( public static final 修饰的也称为常量,必须一次赋完值 )
    public static final String name = "idea"; // 引用类型
    // 修饰实例成员变量( 必须一次赋完值,几乎不用 )
    public final String novelName = "孙悟空";
    public static void main(String[] args) {
        // final 修饰变量,总规则:变量有且仅能赋值一次
        // 变量有两种:局部变量;成员变量(实例成员变量、静态成员变量)
        // 局部变量
        final double rate = 3.14; // 基本数据类型
        // rate = 4.23; 报错,第二次赋值
        // 成员变量
        // name = "dev"; // 报错,第二次赋值
        // new Test().novelName = "唐僧"; // 报错,第二次赋值
    }
}

new Test().novelName = “唐僧”; 报错是由于引用地址发生了变化,内存原理是在堆内存的常量池中存储了一个“唐僧”的变量,并将引用地址赋给 novelName。
参考:Java 基础入门篇(六)—— String 类详解
举例:final 修饰引用类型的变量
class Teacher{
    private String hobby;
    public Teacher(String s) {
        hobby = s;
    }
    public String getHobby() {
        return hobby;
    }
    public void setHobby(String hobby) {
        this.hobby = hobby;
    }
}
public class Test {
    public static void main(String[] args) {
        // 注意: final修饰引用类型的变量,其地址值不能改变,但是指向的对象的内容可以改变的。
        final Teacher teacher = new Teacher("学习,授课");
        teacher.setHobby("打篮球");
        System.out.println(teacher.getHobby()); // 打篮球
    }
}
没有报错的原因:虽然 teacher 对象内部的引用数据的地址发生了变化,但是 teacher 对象的引用地址没有发生变化。
2.3 常量
常量是 public static final 修饰的成员变量,有且仅能赋值一次。
作用:做系统的配置信息,方便程序维护,提高可读性。
 规范:名称全部大写,多个单词用下划线连接
 常量会出现宏替换:所以常量名的地方在编译后都是变成真实的数据。
接口中的常量,默认加上 public static final 修饰,不写也有。如我们一般在项目中定义的常量接口:

三、枚举
枚举是一种特殊类型,其用来做信息的标志和信息的分类。
3.1 枚举的格式

3.2 枚举的特征
反编译后观察枚举的特征:
使用 javap 命令反编译 class 文件得到如下结果:
特征如下:
① 枚举类都是继承了枚举类型 java.lang.Enum。
② 枚举都是最终类,不可以被继承。
③ 构造器的构造器都是私有的,枚举对外不能创建对象。(看不到)
④ 枚举类的第一行默认都是罗列枚举对象的名称的。
⑤ 枚举类相当于是多例模式,如上文只有四个对象。
3.3 枚举的应用
应用 1:业务枚举类与业务结果包装类
/**
 * 业务消息枚举
 */
public enum CodeMsg {
    SUCCESS(200, "操作成功"),
    ERROR(110, "程序员送外卖去了"),
    
    USERNAME_PASSWORD_ERROR(4001001, "用户名或者密码错误!"),
    USER_LOGIN_NAME_EXIST_ERROR(4001002, "用户登陆名已经存在!"),
    USER_PHONE_EXIST_ERROR(4001003, "用户手机号已被使用!");
    public Integer code; // 业务码
    public String msg; // 业务消息
    CodeMsg(Integer code, String msg){
        this.code = code;
        this.msg = msg;
    }
}
/**
 * 业务结果包装类
 * 前端需要: code msg data 这样的数据格式
 * 因此后端对数据进行包装
 */
@Data
public class Result {
    private Integer code; //业务码
    private String msg; // 业务消息
    private Object data; // 业务数据
     /*
    所有的业务分为两种情况:
        1. 成功:
            1. 成功了没数据  如:删除
            2. 成功了有返回数据  如:查询
        2. 失败:
            失败时没有数据,返回失败原因
     */
    /**
     * 成功没有数据
     */
    public Result(){
        this.code = CodeMsg.SUCCESS.code;
        this.msg = CodeMsg.SUCCESS.msg;
    }
    /**
     * 成功有数据
     */
    public Result(Object data){
        this();
        this.data = data;
    }
    /**
     * 失败时没有数据,返回失败原因
     */
    public Result(CodeMsg codeMsg){
        this.code = codeMsg.code;
        this.msg = codeMsg.msg;
    }
    /**
     * 兼容异常信息
     *      因为异常中 code 和 msg
     * @param businessException
     */
    public Result(BusinessException businessException){
        this.code = businessException.getCode();
        this.msg = businessException.getMessage();
    }
}
应用 2:switch 兼容枚举类
public void showSeason(Season s){
	switch (s){
	    case SPRING: // 不用写成 s.SPRING, switch 兼容枚举
	        break;
	    case SUMMER:
	        break;
	    case AUTUMN:
	        break;
	    case WINTER:
	        break;
	    default:
	        break;
	}
}



















