侧边栏壁纸
博主头像
青菜-halo2 博主等级

行动起来,活在当下

  • 累计撰写 74 篇文章
  • 累计创建 6 个标签
  • 累计收到 7 条评论

目 录CONTENT

文章目录

14-面向对象进阶_03(包、final、权限修饰符、代码块)

Administrator
2025-11-12 / 0 评论 / 5 点赞 / 32 阅读 / 0 字

1 包、final

1.1 包

在Java中相当于文件系统中的文件夹,用来管理各种不同功能的java类,方便后期代码维护

包名命名规范

  • 公司域名反写 + 包的作用

  • 全部使用英文小写,做到见名知意

    例如:com.yq.domain

全类名(全限定名):包名 + 类名,如 com.yq.domain.Student

使用其他包中的类时,需要遵循以下规则:

使用其他类的规则:
    使用其他类时,需要使用全类名
        格式:import 关键字导包
    - 使用同一个包中的类时,不需要导包
        Student s = new Student();
    - 使用java.lang包中的类时,不需要导包
        String str = "Hello World";
    - 其他情况都需要导包
        import com.yq.a06domain1.Teacher;
    - 如果同时使用两个包中的同类名,需要用全类名
        com.yq.a06domain1.Teacher t1 = new com.yq.a06domain1.Teacher();
        com.yq.a06domain2.Teacher t2 = new com.yq.a06domain2.Teacher();

练习:

# 文件结构
a05test
  - Student.java
  - Test.java
a06domain1
  - Teacher.java
a06domain2
  - Teacher.java

//Student.java
package com.yq.a05test;
​
public class Student {
    private String name;
    private int age;
​
    // 构造方法
    public Student() {
    }
​
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
​
    // getter和setter方法
    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;
    }
}
​
//Teacher.java
package com.yq.a06domain1;
​
public class Teacher {
    private String name;
    private int age;
​
    //构造方法
    public Teacher() {
    }
​
    public Teacher(String name, int age) {
        this.name = name;
        this.age = age;
    }
​
    //getter和setter方法
    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;
    }
}
​
​
//Test.java - 演示不同情况下的包使用
package com.yq.a05test;
​
import com.yq.a06domain1.Teacher;
​
public class Test {
    public static void main(String[] args) {
        // 情况1:使用同包类,无需导包
        Student s = new Student();
        s.setName("张三");
        s.setAge(23);
        System.out.println(s.getName() + ", " + s.getAge());
​
        // 情况2:使用java.lang包,无需导包
        String str = "abc";
        System.out.println(str);
​
        // 情况3:使用其他包类,需要导包
        // Teacher t = new Teacher(); // 已通过import导包
​
        // 情况4:同名类冲突,使用全类名
        com.yq.a06domain1.Teacher t1 = new com.yq.a06domain1.Teacher("zhangsan", 23);
        com.yq.a06domain2.Teacher t2 = new com.yq.a06domain2.Teacher("lisi", 24);
        System.out.println(t1.getName() + ", " + t1.getAge());
        System.out.println(t2.getName() + ", " + t2.getAge());
    }
}

1.2 final

final关键字用于表示"不可改变的",可以修饰类、方法和变量:

  • final修饰方法:该方法成为最终方法,不能被重写

  • final修饰类:该类成为最终类,不能被继承

  • final修饰变量:该变量成为常量,只能被赋值一次

package com.yq.a07final01;
​
public class Test {
    public static void main(String[] args) {
        //final修饰变量:
        //  叫做常量,只能被赋值一次
        final int a = 10;
        System.out.println(a);
        //a = 20;  //final修饰变量 叫做常量,只能被赋值一次, 不能被修改
    }
}
​
//final class Fu {  //使用final 表明该类是最终类,不能被继承
class Fu {
    //public final void show() {  //使用final 表明该方法时最终方法,不能被重写
    public void show(){
        System.out.println("父类的show方法");
    }
}
​
class Zi extends Fu {
    @Override
    public void show() {
        System.out.println("子类的show方法");
    }
}

注意事项

常量:
    实际开发中,常量一般作为系统的配置信息,方便维护,提高可读性
    常量的命名规范:
        - 单个单词: 全部大写
        - 多个单词: 全部大写,单词之间用下划线隔开
细节:
    final修饰的变量是基本变量时,那么变量存储的数据值不能发生改变
    final修饰的变量是引用类型时,那么变量存储的地址值不能发生改变, 对象内部可以改变
    
字符串是不可变的: 因为 final修饰了
//Test.java
package com.yq.a08final02;
​
public class Test {
    public static void main(String[] args) {
        /*
        final修饰的变量是基本变量时,那么变量存储的 数据值 不能发生改变
        final修饰的变量是引用类型时,那么变量存储的 地址值 不能发生改变, 对象内部可以改变
​
        核心:
            常量记录的数值是不能发生改变的
​
        字符串是不可变的: 因为 final修饰了
        */
​
        final double PI = 3.14;
        //PI = 123; //final修饰的变量是基本变量时,那么变量存储的数据值不能发生改变
​
        //创建对象
        final Student S = new Student("zhangsan", 23);
        S.setName("lisi");
        S.setAge(24);
        System.out.println(S.getName() + ", " + S.getAge());
        //S = new Student(); //final修饰的变量是引用类型时,那么变量存储的地址值不能发生改变, 对象内部可以改变
​
        //数组
        final int[] ARR = {1, 2, 3, 4};
        //ARR = new int[10]
        ARR[0] = 10;
        ARR[1] = 20;
​
        for (int i = 0; i < ARR.length; i++) {
            System.out.println(ARR[i]);
        }
    }
}
​
​
//Student.java
package com.yq.a08final02;
​
public class Student {
    private String name;
    private int age;
​
    public Student() {
    }
​
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
​
    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;
    }
}
​

常量练习:

将学生管理系统中用户的操作改为常量的形式

public class StudentSystem {
    // 使用常量代替魔法数字,提高可读性
    private static final String ADD_STUDENT = "1";
    private static final String DELETE_STUDENT = "2";
    private static final String UPDATE_STUDENT = "3";
    private static final String QUERY_STUDENT = "4";
    private static final String EXIT = "5";
​
    public static void startStudentSystem() {
        ArrayList<Student> list = new ArrayList<>();
        loop: while (true){
            System.out.println("----------欢迎来到学生管理系统----------");
            System.out.println("1.添加学生");
            System.out.println("2.删除学生");
            System.out.println("3.修改学生");
            System.out.println("4.查询学生");
            System.out.println("5.退出");
​
            Scanner sc = new Scanner(System.in);
            String choose = sc.next();
            switch (choose){
                case ADD_STUDENT -> addStudent(list);
                case DELETE_STUDENT -> deleteStudent(list);
                case UPDATE_STUDENT -> updateStudent(list);
                case QUERY_STUDENT -> queryStudent(list);
                case EXIT -> {
                    System.out.println("退出");
                    //break; //只能跳出单层循环 此处只能跳出switch
                    //break loop;  //方法1 用loop标记
                    System.exit(0);  //方法2 停止虚拟机运行
                }
                default -> System.out.println("没有这个选项");
            }
        }
    }
}

2 权限修饰符、代码块

2.1 权限修饰符

  • 权限修饰符:用来控制一个成员能够被访问的范围

  • 可以修饰成员变量、方法、构造方法、内部类

    // private即是权限修饰符
    public class Student {
        private String name;
        private int age;
    }

  • 权限修饰符的分类

    四种权限修饰符的作用范围(从小到大)(private < 空着不写 < protected < public ):

    修饰符

    同一个类中

    同一个包中其他类

    不同包下的子类

    不同包下的无关类

    private

    默认(不写)

    protected

    public

    记忆技巧

    • private:像私房钱,只能自己用

    • 默认:像家庭资产,全家可用

    • protected:像家族资产,家人和亲戚可用

    • public:像公共设施,所有人都可用

    // demo1/Animal.java - 基类
    package com.yq.a10demo1;
    
    public class Animal {
        public String name; // public修饰,所有地方都可访问
        
        public void show() {
            System.out.println(name);
        }
    }
    
    // demo1/Test.java - 同一个包中的测试类
    package com.yq.a10demo1;
    
    public class Test {
        public static void main(String[] args) {
            Animal a = new Animal();
            System.out.println(a.name); // 可以访问public成员
        }
    }
    
    // demo2/Dog.java - 不同包中的子类
    package com.yq.a11demo2;
    import com.yq.a10demo1.Animal;
    
    public class Dog extends Animal {
        public void show() {
            System.out.println(name); // 可以访问父类的public成员
        }
    }
    
    // demo2/Test.java
    package com.yq.a11demo2;
    
    import com.yq.a10demo1.Animal;
    
    public class Test {
        public static void main(String[] args){
            Animal a = new Animal();
            System.out.println(a.name);
        }
    }

权限修饰符的使用规则:

实际开发中,一般只用private或者public

  • 成员变量私有化:使用private修饰

  • 方法公开化:使用public修饰

特例:如果方法中的代码是抽取其他方法中共性代码,这个方法一般也私有,使用 private(比如 ArrayList 中grow方法)

2.2 代码块

  • 局部代码块(写在方法中的代码块 ,为了节约内存)

    public class Test {
        public static void main(String[] args) {
            // 局部代码块
            {
                int a = 10; // a的作用域仅限于该代码块
                System.out.println(a);
            }
            // System.out.println(a); // 编译错误:a已超出作用域
        }
    }

  • 构造代码块

    可以将多个重复的代码,放入构造代码块中

    //Student.java
    package com.yq.a12codeblockdemo1;
    
    public class Student {
        private String name;
        private int age;
    
        //构造代码块
        //1.写在成员位置的代码块
        //2.作用:可以把多个构造方法中,重复的部分抽取出来
        //3.执行时机:在创建本类对象时,会先执行构造代码块,再执行构造方法
        //逐渐被淘汰,不够灵活(因为必定会执行)
    
        // 构造代码块
        {
            System.out.println("开始创建对象了"); // 所有构造方法都会执行
        }
        
        public Student() {
            System.out.println("空参构造");
        }
    
        public Student(String name, int age) {
            System.out.println("有参构造");
            this.name = name;
            this.age = age;
        }
    
        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;
        }
    }
    
    
    //CodeBlockDemo1.java
    package com.yq.a12codeblockdemo1;
    
    public class CodeBlockDemo1 {
        public static void main(String[] args) {
            /*{
                int a = 10;
            }*/ //代码块结束以后,变量a就从内存中消失了
            // System.out.println(a);
    
            //创建对象
            Student s = new Student();
            Student s2 = new Student("zhangsan", 23);
        }
    }

执行时机:在创建对象时,先执行构造代码块,再执行构造方法。

注意:构造代码块在实际开发中逐渐被淘汰,推荐使用this()调用或提取公共方法的方式。

  • 静态代码块

    格式static { }

    特点

    • 使用static关键字修饰

    • 随着类的加载而执行

    • 自动触发且只执行一次

    使用场景:在类加载时进行数据初始化。

    应用示例 - 学生管理系统初始化:

    注意:需要将static代码块部分与main方法独立,否则main方法在被调用时,初始化部分也可以被调用

    //App.java
    public class App {
        // 静态变量
        static ArrayList<User> list = new ArrayList<>();
        
        // 静态代码块 - 类加载时执行初始化
        static {
            //添加一些用户信息
            list.add(new User("zhangsan","123456","110101200001011234","12333211234"));
        }
        
        public static void main(String[] args) {
    
            Scanner sc = new Scanner(System.in);
            while (true) {
                System.out.println("欢迎来到学生管理系统");
                System.out.println("请选择操作: 1登录 2注册 3忘记密码 4退出");
                String choose = sc.next();
                switch (choose) {
                    case "1" -> {
                        login(list);
                        //System.out.println("登录");
                    }
                    case "2" -> register(list);
                    case "3" -> forGetPassword(list);
                    case "4" -> {
                        System.out.println("谢谢使用, 再见");
                        System.exit(0);
                    }
                    default -> System.out.println("没有这个选项, 请重新输入");
                }
            }
    
        }
    
    
    //StudentSystem.java
    public class StudentSystem {
        // 静态变量
        static ArrayList<Student> list = new ArrayList<>();
        
        // 静态代码块 - 类加载时执行初始化
        static {
            //添加一些用户信息
            list.add(new Student("001","zhangsan",23,"beijing"));
        }
        
        public static void startStudentSystem() {
    
            loop: while (true){
                System.out.println("----------欢迎来到学生管理系统----------");
                System.out.println("1.添加学生");
                System.out.println("2.删除学生");
                System.out.println("3.修改学生");
                System.out.println("4.查询学生");
                System.out.println("5.退出");
    
                Scanner sc = new Scanner(System.in);
                String choose = sc.next();
                switch (choose){
                    case ADD_STUDENT -> addStudent(list);
                    case DELETE_STUDENT -> deleteStudent(list);
                    case UPDATE_STUDENT -> updateStudent(list);
                    case QUERY_STUDENT -> queryStudent(list);
                    case EXIT -> {
                        System.out.println("退出");
                        //break; //只能跳出单层循环 此处只能跳出switch
                        //break loop;  //方法1 用loop标记
                        System.exit(0);  //方法2 停止虚拟机运行
                    }
                    default -> System.out.println("没有这个选项");
                }
            }
        }
    }

5

评论区