zoukankan      html  css  js  c++  java
  • String为什么要设置成Final类型

    ---今天面试碰到个这样的问题:String在设计的时候为什么要设计成final的  当时回答的是String功能已经很丰富了,不需要对其进行扩展,所有巴拉巴拉。

    现在来正确看看为什么定义成final的吧

    首先,Final来修饰一个类,只有一个作用,就是不让此类被继承。

    好,那么String为什么不让其他类继承呢,网上看来看去,最靠谱的说法就是保证安全性,(其实也就是因为String的不可变性。)

    先看String内部结构:

    public final class String
        implements java.io.Serializable, Comparable<String>, CharSequence
    {
        /** The value is used for character storage. */
    private final char value[];
    
        /** The offset is the first index of the storage that is used. */
    private final int offset;
    
        /** The count is the number of characters in the String. */
    private final int count;
    
        /** Cache the hash code for the string */
    private int hash; // Default to 0
    
        /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = -6849794470754667710L;
        
        。。。。。。。。。。。。。。。。。。

    String里有个成员变量value字符型数组。修饰是private ,final

    private保证变量不会被外部和子类直接访问。

    final保证变量的值不会变化。

    但是这样是没办法保证value不可变,因为value是指向数组的地址,我们可以通过修改数组内容从而达到修改value的目的。

    也就是这个原因,String内的value就成了一个不可变的值,所以String不可变的原因就在这里。假如String去掉Final,会导致value变化吗,这问题 ,事实证明,父类的value是不会变化的,那假如子类有个名称一样的成员变量会如何呢?代码如下

    package com.zxy.test;
    
    import java.awt.*;
    
    /**
     * Created by Roderick on 2017/5/12.
     */
    public class Test2 {
    
        /**
         * 父类要设计成安全的模式
    */
    static class Base{
            private final char[] value = {'a'};
            public String getString(){
                return this.toString();
            }
            public void setString(String str){
                System.out.println("数组不能被修改");
            }
    
            public String toString(){
                StringBuilder tmp = new StringBuilder();
                for(char c: this.value){
                    tmp.append(c);
                }
                return tmp.toString();
            }
        }
    
        static class Child extends Base{
            public char[] value;
            @Override
            public String getString(){
                return this.toString();
            }
            @Override
            public void setString(String str){
                this.value = str.toCharArray();
            }
            @Override
            public String toString(){
                StringBuilder tmp = new StringBuilder();
                for(char c: this.value){
                    tmp.append(c);
                }
                return tmp.toString();
            }
        }
    
        public static void main(String[] arge){
            Base base = new Base();
            base.setString("aaaa");
            System.out.println(base.getString());
    
            Child child = new Child();
            child.setString("aaaa");
            System.out.println(child.getString());
        }
    }
    

    上面的代码,已经回答了这个答案,假如子类有个成员变量的名称和value一致,那么value从效果上看,就是被修改了。所以这就导致了子类可变。违背了String的规则,导致了此类不安全。

  • 相关阅读:
    python14 1.带参装饰器 | wrapper 了了解 # 2.迭代器 ***** # 可迭代对象 # 迭代器对象 # for迭代器 # 枚举对象
    python13 1.函数的嵌套定义 2.global、nonlocal关键字 3.闭包及闭包的运用场景 4.装饰器
    python12--字符串的比较 函数的默认值的细节 三元表达式 函数对象 名称空间 作用域 列表与字典的推导式 四则运算 函数的嵌套
    python11 函数的定义,调用,分类
    python10--函数的来源,优点,定义,组成,使用(定义,调用)函数的分类,函数的返回值
    python1--计算机原理 操作系统 进制 内存分布
    python2 配置环境变量
    python3 数据类型
    Java创建线程的三种方式
    webhooks动态更新配置
  • 原文地址:https://www.cnblogs.com/csong7876/p/9125173.html
Copyright © 2011-2022 走看看