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. 自动调度GPU的卷积层

    自动调度GPU的卷积层 这是有关如何对GPU使用自动调度程序的文档. 与依靠手动模板定义搜索空间的基于模板的autotvm不同,自动调度程序不需要任何模板.用户只需要编写计算声明,而无需任何调度命令或 ...

  2. TVM Reduction降低算力

    TVM Reduction降低算力 这是有关如何降低算力TVM的介绍材料.像sum / max / min这样的关联约简运算符是线性代数运算的典型构造块. 本文将演示如何降低TVM算力. from _ ...

  3. 『言善信』Fiddler工具 — 9、Fiddler自动响应器(AutoResponder)详解

    目录 1.AutoResponder介绍 2.AutoResponder界面说明 (1)选项: (2)按钮: (3)Rule Editor(规则编辑): (4)test(测试): (5)规则框: 1. ...

  4. servlet、过滤器、监听器、拦截器之间的关系和区别

    一.概念 1.什么是servlet servlet是一个接口.定义了一套处理网络请求的规范,所有实现servlet的类,都需要实现它那五个方法,其中最主要的是两个生命周期方法 init()和destr ...

  5. QT Dialog模态与非模态

    模态 // 创建对话框窗口 TestDialog* dlg = new TestDialog(this); // 阻塞程序的运行 dlg->exec(); 这样的话,当运行对话窗口的时候,会阻塞 ...

  6. Java IO学习笔记四:Socket基础

    作者:Grey 原文地址:Java IO学习笔记四:Socket基础 准备两个Linux实例(安装好jdk1.8),我准备的两个实例的ip地址分别为: io1实例:192.168.205.138 io ...

  7. 三、DNS子域授权

    前提:准备两台虚拟机:父域: www.tedu.cn(虚拟机A)子域:www.bj.tedu.cn(虚拟机B) 一.在两台虚拟机上安装域名解析软件 root@pc207 ~]# yum -y inst ...

  8. 解析 Nebula Graph 子图设计及实践

    本文首发于 Nebula Graph 公众号 NebulaGraphCommunity,Follow 看大厂图数据库技术实践. 前言 在先前的 Query Engine 源码解析中,我们介绍了 2.0 ...

  9. 一篇文章快速搞懂 Apache SkyWalking 的 OAL

    OAL简介 在流模式(Streaming mode)下,SkyWalking 提供了 观测分析语言(Observability Analysis Language,OAL) 来分析流入的数据. OAL ...

  10. Unity StateMachineBehaviour

    在unity animator中单个Animator Clip中点击Add Behaviour增加当执行该动画时的一些状态代码,请看如下 创建完之后基本代码结构如下:(如果想修改默认代码结构,请看示例 ...