final修饰的类不可以有子类,例如:java.lang.Math类就是一个final类,它不可以有子类

子类继承父类,可以访问父类的内部数据,可以重写父类的方法来改变父类方法的实现细节,可能导致不安全因素:为了保证某个类不可被继承,则可以使用fianl修饰这个类,

代码示例:

public final class FinalClass{}

//下面的类定义将出现错误

class Sub extends FinalClass{}

FinalClass为final类,不能被继承,编译错误

=======================================================================================================================================

  final之不可变类

  不可变类(immutable)类的意思是创建该类的实例后,该实例的实例变量是不可改变的,java提供的8个包装类和java.lang.String类都是不可变类,当创建它们的实例后,其实例的实列变量都是不可改变的.

代码示例:

  Double d=new Double(8.56);  

  String str=new String("Hello");\

  创建的Double和`String实例,传入6.5和"Hello"字符串作为参数,Doule类和String类肯定都需要提供实例变量来保存这两个参数,但是程序无法修改这两个实例变量的值,Double和String类都没有提供修改它们的方法.

  如果需要创建自定义的不可变类,需要遵守如下规则

1.使用private和final修饰符来修饰类的成员变量

  2.提供带参数构造器,用于根据传入参数来初始化类里的成员变量.

  3.仅为该类的成员变量提供getter方法,不要为该类的成员提供setter()方法,因为普通方法无法修改final修饰的成员变量.

  4.如果有必要,重写Object类的hashCode()和equals()方法(详情讲义301),equals()方法根据关键成员变量来作为两个对象是否相等的标准,除此之外,还应该保证两个用equals()方法判断为相等的对象的hashcode()也相等.java.lang.String这个类做的很好,它就是根据String对象里的字符序列来作为相等的标准,其hashCode()方法也是根据字符序列计算得到的,

代码示例:

   package com.j1803.finalTest;
 
   public class ImmutableStringTest {

        public static void main(String[] args) {
        String str1=new String("hellow");
        String str2=new String("hellow");
        
        System.out.println(str1==str2);
        System.out.println(str1.equals(str2));
        
        //下面输出两次的hashCode相同
        System.out.println(str1.hashCode());
        System.out.println(str2.hashCode());

      }

  }

  answer:

  false
  true
  -1220935195
  -1220935195

  与不可变类对应的是可变类,可变类的含义是该类的实例变量是可变的,大部分时候所创建的类都是可变类,特别是JavaBean,因为总是为其实例变量提供了setter和getter方法.

  前面介绍了final修饰引用类型变量时,仅仅只是表示这个引用类型变量不可被重新赋值,但引用类型变量所指向的对象依然可以改变,这就产生了一个问题,当创建一个不可变类时,如果它包含成员变量的类型是可变的,那么其对象的成员变量的值依然是可改变的,这个不可变类其实是失败的.

代码示例:

package com.j1803.finalTest;

public class PersonTest {
    private final Name name;
    public PersonTest(Name name) {
        super();
        this.name = name;
    }
    public Name getName() {
        return name;
    }
    public static void main(String[] args) {
        
        Name n=new Name("悟空","孙");
        PersonTest p=new PersonTest(n);
        //PersonTest对象的name的firstName值为"悟空"
        System.out.println(p.getName().getFirstName());
        //改变PersonTest对象的name的firstName值
        n.setFirstName("八戒");
        //PersonTest对象的name的firstName值被改为"八戒"
        System.out.println(p.getName().getFirstName());
    }

}
class Name{
    private String firstName;
    private String lastName;
    public Name(String firstName, String lastName) {
        super();
        this.firstName = firstName;
        this.lastName = lastName;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    
}

answer:

悟空
八戒

代码修改:

public class PersonTest {
    private final Name name;
    public PersonTest(Name name) {
        super();
        //设置name实例变量为临时创建的Name对象,该对象的firstName和lastName;
        this.name=new Name(name.getFirstName(),name.getLastName());
    }
    public Name getName() {
        //返回一个匿名对象,该对象的firstName和lastName
        //与该对象里的name的firstName和lastName相同
        return new Name(name.getFirstName(),name.getLastName());
    }

answer:

悟空
悟空

  因此,如果设计一个不可变类,尤其要注意其引用类型的成员变量,如果引用类型的成员变量的类是可变的,就必须采取必要的措施来保护该成员变量所引用的对象不会被修改,这样才能创建真正的不可变类

final修饰符(6)-final类的更多相关文章

  1. final修饰符(5)-final方法

    final修饰的类的方法不能被重写,例如如果父类不希望子类重写某个方法,则可以使用final修饰符修饰该方法 在java的Object类里面有一个final方法:getClass(),因为Java不希 ...

  2. Java中的(构造方法、方法重载、final修饰符使用及继承和抽象)

    构造方法: 构造方法的名称和类名相同,没有返回类型,参数列表(类型.个数)不同 方法重载:成员方法和构造方法都可以进行重载 方法名相同但是参数列表(类型,个数)不同,成为方法的重载. 继承:直支持单继 ...

  3. 类成员(static)和final修饰符

    在Java类里只能包含成员变量.方法.构造器.初始化块.内部类(包括接口.枚举)5种成员,类成员是用static来修饰的,其属于整个类. 当使用实例来访问类成员时,实际上依然是委托给该类来访问类成员, ...

  4. 构造方法为private与类修饰符为final

    构造方法为private的:在这个类外1:不能继承这个类2:不能用new来产生这个类的实例 在这个类内:1:可以继承这个类2:可以用new来产生这个类的实例 类修饰符为final的:在这个类外1:不能 ...

  5. 0025 Java学习笔记-面向对象-final修饰符、不可变类

    final关键字可以用于何处 修饰类:该类不可被继承 修饰变量:该变量一经初始化就不能被重新赋值,即使该值跟初始化的值相同或者指向同一个对象,也不可以 类变量: 实例变量: 形参: 注意可以修饰形参 ...

  6. Java final 修饰符知识点总结

    final从字面上理解含义为“最后的,最终的”.在Java中也同样表示出此种含义. final可以用来修饰变量(包括类属性.对象属性.局部变量和形参).方法(包括类方法和对象方法)和类. 1. fin ...

  7. Java中的final修饰符

    1.什么时候可以选择final修饰符 如果想让一个类不被其他类继承,不允许在有子类,这时候就要考虑用到final来修饰. 2.用final修饰的类 首先大家要明白,用final修饰的类是不能被继承的, ...

  8. java修饰符public final static abstract transient

    JAVA 修饰符public final static abstract transient  关键字: public final static abstract ...  1.public prot ...

  9. private static final 修饰符

    java修饰符分类修饰符字段修饰符方法修饰符根据功能同主要分下几种 1.权限访问修饰符 public,protected,default,private,四种级别修饰符都用来修饰类.方法和字段 包外 ...

随机推荐

  1. Mysql索引创建及删除

    1.索引 MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度. 打个比方,如果合理的设计且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的My ...

  2. TVMNN编译Compiler栈

    TVMNN编译Compiler栈 内容纲要 前言 调研目标 TVM介绍 TVM源码架构 FrontEnd Relay BackEnd VTA实现原理及设计思想提炼 整体结构 VTA Hardware ...

  3. TVM部署预定义模型

    TVM部署预定义模型 本文通过深度学习框架量化的模型加载到TVM中.预量化的模型导入是在TVM中提供的量化支持之一. 本文演示如何加载和运行由PyTorch,MXNet和TFLite量化的模型.加载后 ...

  4. Paddle Lite端侧部署

    Paddle Lite端侧部署 端侧推理引擎的由来 随着深度学习的快速发展.特别是小型网络模型的不断成熟,原本应用到云端的深度学习推理,就可以放到终端上来做,比如手机.手表.摄像头.传感器.音响,也就 ...

  5. 解决:ImportError: DLL load failed while importing _sqlite3: 找不到指定的模块。

    Django框架学习第一步,创建一个Django工程. 本次采用的是创建虚拟环境来创建Django工程.本地解释器采用anaconda ,内置Python3.8 在pycharm中报错: 内容如下:I ...

  6. QT环境变量设置

    首先找到自己对应的目录 我的如图 还有一个路径 将这两个路径添加到系统变量的Path中

  7. 【Java编程实战】Metasploit_Java后门运行原理分析以及实现源码级免杀与JRE精简化

    QQ:3496925334 文章作者:MG1937 CNBLOG博客ID:ALDYS4 未经许可,禁止转载 某日午睡,迷迷糊糊梦到Metasploit里有个Java平台的远控载荷,梦醒后,打开虚拟机, ...

  8. Linux操作系统(一)

    计算机本身就是一堆硬件,这些硬件中最核心的就是CPU(运算器,控制器) 和存储器设备. 为了能够实现计算机获取数据,数据的输入输出等等需要输入设备和输出设备. 计算机体系内部:主要是通过桥接接入当前系 ...

  9. iOS-block本质是什么?

    一: block的原理是怎样的?本质是什么? block本质上也是一个OC对象,因为它的内部也有个isa指针 block是封装了函数调用以及函数调用环境的OC对象 接下来我们将通过底层源码来论证上诉两 ...

  10. Docker入门与进阶(上)

    Docker入门与进阶(上) 作者 刘畅 时间 2020-10-17 目录 1 Docker核心概述与安装 1 1.1 为什么要用容器 1 1.2 docker是什么 1 1.3 docker设计目标 ...