Java面向对象进阶5——包和final(含源码阅读)

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面向对象进阶5——包和final(含源码阅读)_第1张图片
由于Test类和Teacher类同在一个polymorphism包中,使用在调用Teacher类时并不会报错,也不需要导包

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

Java面向对象进阶5——包和final(含源码阅读)_第2张图片

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

在这里插入图片描述

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

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

Java面向对象进阶5——包和final(含源码阅读)_第3张图片

Java面向对象进阶5——包和final(含源码阅读)_第4张图片

三、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面向对象进阶5——包和final(含源码阅读)_第5张图片

源码阅读

选中String类后使用 Ctrl+B 跟进,查看源码
Java面向对象进阶5——包和final(含源码阅读)_第6张图片
此处的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面向对象进阶5——包和final(含源码阅读)_第7张图片

源码阅读

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

Java面向对象进阶5——包和final(含源码阅读)_第8张图片

Java面向对象进阶5——包和final(含源码阅读)_第9张图片
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面向对象进阶5——包和final(含源码阅读)_第10张图片

源码阅读

Ctrl+N 查看类,搜索Math
Java面向对象进阶5——包和final(含源码阅读)_第11张图片
Java面向对象进阶5——包和final(含源码阅读)_第12张图片可以看到,在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

在这里插入图片描述

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

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面向对象进阶5——包和final(含源码阅读)_第13张图片

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

源码阅读

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

Java面向对象进阶5——包和final(含源码阅读)_第14张图片
Java面向对象进阶5——包和final(含源码阅读)_第15张图片
可以看到底层是有一个数组来存储字符串的内容,因为是用final来修饰的数组,所以其地址值不能改变
byte
存储数据类型
value[]
用来存储字符串的数组
private
私有,即外界无法获取到 value 记录的地址值
我们可以在这个源码中通过 Ctrl+F12 来搜索一下,发现没有value的get和set方法,使得我们没办法从外界获取其记录的地址值

Java面向对象进阶5——包和final(含源码阅读)_第16张图片
总结一下,上面这些都是字符串无法改变的原因

四、结语

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

你可能感兴趣的:(Java进阶学习篇,java,jvm,开发语言)