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. final 修饰符

    修饰属性,方法,类 1.修饰属性 属性只能被赋值一次 基本类型:值不能改变 引用类型:引用不可以被修改 2.修饰方法 表示方法不可以被重写,但可以被子类访问 3.修饰类 表示类不可以被继承 //fin ...

  2. Amazon SageMaker和NVIDIA NGC加速AI和ML工作流

    Amazon SageMaker和NVIDIA NGC加速AI和ML工作流 从自动驾驶汽车到药物发现,人工智能正成为主流,并迅速渗透到每个行业.但是,开发和部署AI应用程序是一项具有挑战性的工作.该过 ...

  3. NVIDIA Turing Architecture架构设计(下)

    NVIDIA Turing Architecture架构设计(下) GDDR6 内存子系统 随着显示分辨率不断提高,着色器功能和渲染技术变得更加复杂,内存带宽和大小在 GPU 性能中扮演着更大的角色. ...

  4. 英特尔® 至强® 平台集成 AI 加速构建数据中心智慧网络

    英特尔 至强 平台集成 AI 加速构建数据中心智慧网络 SNA 通过 AI 方法来实时感知网络状态,基于网络数据分析来实现自动化部署和风险预测,从而让企业网络能更智能.更高效地为最终用户业务提供支撑. ...

  5. IDEA骚技巧

    1. var 声明 2. null 判空 3. notnull 判非空 4. nn 判非空 5. for 遍历 6. fori 带索引的遍历 7. not 取反 8. if 条件判断 9. cast ...

  6. 在spring配置文件中引入外部properties配置文件 context:property-placeholder

    在spring的配置文件中,有时我们需要注入很多属性值,这些属性全都写在spring的配置文件中的话,后期管理起来会非常麻烦.所以我们可以把某一类的属性抽取到一个外部配置文件中,使用时通用spring ...

  7. CentOS:操作系统级监控及常用计数器解析---除CPU以外

    I/O I/O 其实是挺复杂的一个逻辑,但我们今天只说在做性能分析的时候,应该如何定位问题. 对性能优化比较有经验的人(或者说见过世面比较多的人)都会知道,当一个系统调到非常精致的程度时,基本上会卡在 ...

  8. Java接口以及匿名内部类,静态代码块

    接口 接口中只能定义public并且是final的公共静态常量,不允许定义变量. 抽象类可以定义抽象方法和非抽象方法,接口中只能定义公共的,抽象的实例方法. 接口只能由其他接口实现继承 子接口继承的目 ...

  9. JavaScript DOM编程艺术第四章 — JavaScript图片库案例研究

    这一章通过JavaScript图片库案例,学习了一些DOM属性. HTML代码 <!DOCTYPE html> <html> <head> <meta cha ...

  10. 【模拟8.01】big(trie树)

    一道trie树的好题 首先我们发现后手对x的操作就是将x左移一位,溢出位在末尾补全 那么我们也可以理解为现将初值进行该操作,再将前i个元素异或和进行操作,与上等同. 那么我们等于转化了问题:     ...