Java面向对象进阶5——包和final

  • 一、前言
  • 二、包
  • 1️⃣定义
  • 2️⃣命名
  • 3️⃣使用其他类
  • 🟡使用同一个包中的类时,不需要导包
  • 🟡使用java.lang包中类时,不需要导包
  • 🟡如果同时使用两个包中同类名,需要用全类名
  • 三、final关键字
  • 1️⃣定义
  • 2️⃣final修饰类
  • 🟡代码测试
  • 🟡源码阅读
  • 3️⃣final修饰方法
  • 🟡代码测试
  • 🟡源码阅读
  • 4️⃣final修饰基本数据类型
  • 🟡代码实现
  • 🟡源码阅读
  • 🟡常量
  • 5️⃣ final修饰引用数据类型
  • 🟡代码实现
  • 🟡源码阅读
  • 四、结语


一、前言

从本文开始,将会讲述Java面向对象中的一些小知识点,本文主要是讲述有关包和final的知识

二、包

1️⃣定义

包在操作系统中其实就是一个文件夹。包是用来分门别类的管理技术,不同的技术类放在不同的包下,方便管理和维护

2️⃣命名

  • 包名一般是公司域名倒写 + 包的作用
  • 全部英语小写
  • 路径名.路径名.xxx.xxx
  • 包名要用 “.” 连接
  • 包名的每个路径名必须是一个合法的标识符,而且不能是Java的关键字

3️⃣使用其他类

🟡使用同一个包中的类时,不需要导包

java从入门到精通第五版代码 java从入门到精通 第五版_类名


由于Test类和Teacher类同在一个polymorphism包中,使用在调用Teacher类时并不会报错,也不需要导包

🟡使用java.lang包中类时,不需要导包

java从入门到精通第五版代码 java从入门到精通 第五版_开发语言_02

当我们选中String后再使用 Ctrl+B 跟进,查看源码,发现String类是在 java.lang 包下

java从入门到精通第五版代码 java从入门到精通 第五版_类名_03

🟡如果同时使用两个包中同类名,需要用全类名

当不同的包中有相同的类名时,我们需要看清楚要调用的类名是在哪个包中的,并且在导入别的包中的类名时,需要用全类名

java从入门到精通第五版代码 java从入门到精通 第五版_jvm_04

java从入门到精通第五版代码 java从入门到精通 第五版_java从入门到精通第五版代码_05

三、final关键字

1️⃣定义

不可改变,最终的含义,可以用于修饰类、方法和变量。
类:被修饰的类,不能被继承
方法:被修饰的方法,不能被重写
变量:被修饰的变量,有且仅能被赋值一次(常量)

2️⃣final修饰类

被修饰的方法,不能被继承

🟡代码测试

final class  Fu{
        public  void  show(){
            System.out.println("这是父类");
        }
    }

    class Zi extends Fu {
        @Override
        public void show(){
            System.out.println("这是子类");
        }
    }

上述代码在IDEA中会爆红

java从入门到精通第五版代码 java从入门到精通 第五版_类名_06

🟡源码阅读

选中String类后使用 Ctrl+B 跟进,查看源码

java从入门到精通第五版代码 java从入门到精通 第五版_jvm_07


此处的String类是被final修饰的,即不可被继承,所以String类不能被任何一个类当作是父类

3️⃣final修饰方法

被修饰的方法,不能被重写

🟡代码测试

class  Fu{
        public final void  show(){
            System.out.println("这是父类");
        }
    }

    class Zi extends Fu {
        @Override
        public void show(){
            System.out.println("这是子类");
        }
    }

上述代码在IDEA中会爆红,所以在编写代码时一定要注意该问题

java从入门到精通第五版代码 java从入门到精通 第五版_java从入门到精通第五版代码_08

🟡源码阅读

Ctrl+N 查看类,搜索object类,并选择Java.lang

java从入门到精通第五版代码 java从入门到精通 第五版_java从入门到精通第五版代码_09

java从入门到精通第五版代码 java从入门到精通 第五版_java从入门到精通第五版代码_10


native

这个方法体是调用本地其他语言(C语言、汇编语言等)来写的,在这里是看不到它的方法体

get class()
获取编译以后的字节码文件

方法的作用
获取到字节码文件的对象,并与本地的操作系统产生交互

可以看到这个类是被final类修饰的,即该方法不可改变
如果再往下阅读源码,会发现还有public final native void notify()public final native void notifyAll()public final native void wait(long timeout) throws InterruptedException 三个被final修饰的方法,同样是不想让方法被改变

4️⃣final修饰基本数据类型

被修饰的变量,有且仅能被赋值一次(变为常量)

🟡代码实现

public static void main(String[] args) {
        final int a = 20;
        a = 30;
        System.out.println(a);
    }

此时代码会爆红

java从入门到精通第五版代码 java从入门到精通 第五版_jvm_11

🟡源码阅读

Ctrl+N 查看类,搜索Math

java从入门到精通第五版代码 java从入门到精通 第五版_类名_12


java从入门到精通第五版代码 java从入门到精通 第五版_jvm_13

可以看到,在Math类里面定义了两个常量 PIE

🟡常量

在实际开发中,常量一般作为系统的配置信息,方便维护,提高可读性

命名规范
单个单词:全部大写
多个单词:全部大写,单词间用下划线展开

5️⃣ final修饰引用数据类型

变量存储地址值不变,对象内部属性值可改变

🟡代码实现

public static void main(String[] args) {
        final int[] arr = {1,2,3,4,5};
        arr[0] = 0;
        arr[1] = 10;
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }

输出结果:0 10 3 4 5

java从入门到精通第五版代码 java从入门到精通 第五版_jvm_14

上述代码改变的就是对象内部属性值,所以是可行的,但是如果我们改变一下存储地址值(类型改变)的话会怎么样

public static void main(String[] args) {
        final int[] arr = {1,2,3,4,5};
        arr = new int[20];
        arr[0] = 0;
        arr[1] = 10;
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }

java从入门到精通第五版代码 java从入门到精通 第五版_java_15

代码报错,原因是这样会改变其地址值

🟡源码阅读

Ctrl+N 查看类,搜索String类,并选择 Java.long

java从入门到精通第五版代码 java从入门到精通 第五版_java_16


java从入门到精通第五版代码 java从入门到精通 第五版_java从入门到精通第五版代码_17


可以看到底层是有一个数组来存储字符串的内容,因为是用final来修饰的数组,所以其地址值不能改变

byte

存储数据类型

value[]

用来存储字符串的数组

private

私有,即外界无法获取到 value 记录的地址值

我们可以在这个源码中通过 Ctrl+F12 来搜索一下,发现没有value的get和set方法,使得我们没办法从外界获取其记录的地址值

java从入门到精通第五版代码 java从入门到精通 第五版_jvm_18


总结一下,上面这些都是字符串无法改变的原因

四、结语

通过阅读源码,我们可以更加深刻的了解到其原理所在,在之后的文章中,我也会多加分析源码,尽可能的将原理讲清楚,如果有任何疑问以及不足之处,欢迎指正