• 常用类(总结)


    包装类

    包装类基本知识

    Java中八种基本数据类型并不是对象,是为了将基本数据类型和对象之间实现互相转化,Java为每一个基本数据类型提供了相应的包装类。

    JAVA是面向对象的语言,但是并不是“纯面向对象”的,因为经常用到的基本数据类型就不是对象,在实际的操作中需要将基本数据类型转化成为对象,以便于操作。

    Java在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数据类型对应的类统称为包装类。

    在八个基本数据类型中,除了Integer和Character,其它六个的类名和基本数据类型一致,首字母大写

    在这里插入图片描述

    Number类是抽象类,因此它的抽象方法,所有子类都需要提供实现。Number类提供了抽象方法,如图。表明了所有的“数字型”包装类都可以相互转型。
    image.png

    包装类的用途:
    1、作为和基本数据类型对应的类型存在,方便涉及到对象的操作,如Object[],集合等等
    2、包含每种基本数据类型的相关属性如最大值,最小值等。

    自动装箱和拆箱

    自动装箱(autoboxing)和拆箱(unboxing),将基本数据类型和包装类自动转换。

    自动装箱

    基本类型的数据处于需要对象的环境中时,会自动转为“对象”。
    如Integer i = 10;编译器会自动的转成Integer i = Integer.valueOf(10),这就是JAVA的自动装箱。

    自动拆箱

    需要一个值的时候,对象会自动的转成基本数据类型,没有必要再去显式调用intValue()、doubleValue()等转型方法。
    Integer i = Integer.valueOf(10); int j = i;编译器会自动转成:int j = i.intValue();这个过程就是自动拆箱。

    包装类的缓存问题

    整型和char类型对应的包装类,在自动装箱时,对于-128~127之间的值会进行缓存处理,目的是为了提高效率。

    缓存的原理:如果数据在-128~127这个区间,类在加载的时候就已经为该区间的每个数值创建了对象,并将这256个对象存放到一个名为cache的数组中,每当自动装箱过程发生时(或者手动valueOf())时,就会先判断是否在该区间,如果在则直接获取数组中对应的包装对象的引用,如果不在该区间,则会通过new调用包装类的构造方法来创建对象。

    //Integer源码片段
    public static Integer valueOf(int i){
        if (i >= IntegerCache.low && i <= IntegerCache.high){
            return IntegerCache.cache[i + (-IntegerCache.low)];
        } 
        return new Integer(i);
    }
    /**
    1. IntegerCache类为Integer类的一个静态内部类,仅供Integer类使用。由下面的源码我们可以看到,静态代码块的目的就是初始化数组cache的,这个过程
    会在类加载时完成
    2. 一般情况下 IntegerCache.low为-128,IntegerCache.high为127,
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    private static class IntegerCache {
            static final int low = -128;
            static final int high;
            static final Integer cache[];
    
            static {
                // high value may be configured by property
                int h = 127;
                String integerCacheHighPropValue =
                    sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
                if (integerCacheHighPropValue != null) {
                    try {
                        int i = parseInt(integerCacheHighPropValue);
                        i = Math.max(i, 127);
                        // Maximum array size is Integer.MAX_VALUE
                        h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                    } catch( NumberFormatException nfe) {
                        // If the property cannot be parsed into an int, ignore it.
                    }
                }
                high = h;
    
                cache = new Integer[(high - low) + 1];
                int j = low;
                for(int k = 0; k < cache.length; k++)
                    cache[k] = new Integer(j++);
    
                // range [-128, 127] must be interned (JLS7 5.1.7)
                assert IntegerCache.high >= 127;
            }
    
            private IntegerCache() {}
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    包装类总结

    • 自动装箱调用的是valueOf()方法,而不是new Integer()方法。
    • 自动拆箱调用的是xxxValueOf()方法。
    • 包装类在自动装箱时为了提高效率,对于-128~127之间的值会进行缓存处理,超过范围后,对象之间不能再使用==进行数值比较,应该使用equals方法。

    字符串类

    String类代表不可变的字符序列(final),StringBuilder和StringBuffer类代表可变字符序列。

    String类对象是不可变的Unicode字符序列,不可变对象指的是,对象内部的成员变量的值无法再修改。

    public final class String
        implements java.io.Serializable, Comparable<String>, CharSequence {
        
        /** The value is used for character storage. */
        private final char value[];
        /**
        字符串内容全部存储到 value[ ]数组中,而变量 value 是 final 类型的,也就
        是常量(即只能被赋值一次)。 这就是“不可变对象”的典型定义方式
        */
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    String 类的简单使用

    /**
    substring()是对字符串的截取操作,
    但本质是读取原字符串内容生成了新的字符串
    */
    public static void main(String[ ] args) {
            String s1 = new String("abcdef");
            String s2 = s1.substring(2, 4);
            // 打印:ab199863
            System.out.println(Integer.toHexString(s1.hashCode()));
            // 打印:c61, 显然 s1 和 s2 不是同一个对象
            System.out.println(Integer.toHexString(s2.hashCode()));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    /**
    在遇到字符串常量之间的拼接时,编译器会做出优化,即在编译期间就会完成字符串的
    拼接。
    */
     public static void main(String[ ] args) {
            //编译器做了优化,直接在编译的时候将字符串进行拼接
            String str1 = "hello" + " java";//相当于 str1 = "hello java";
            String str2 = "hello java";
            System.out.println(str1 == str2);//true
            String str3 = "hello";
            String str4 = " java";
            //编译的时候不知道变量中存储的是什么,所以没办法在编译的时候优化
            String str5 = str3 + str4;
            System.out.println(str2 == str5);//false
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    StringBuffer和StringBuilder

    StringBuffer和StringBuilder都是可变的

    • StringBuffer 线程安全,做线程同步检查,效率较低
    • StringBuilder 线程不安全,不做线程同步检查,效率较高。推荐使用

    常用的方法

    重载的 **public **StringBuilder append(…)方法
    可以为该 StringBuilder 对象添加字符序列,仍然返回自身对象。
    方法 **public **StringBuilder delete(**int **start,**int **end)
    可以删除从 start 开始到 end-1 为止的一段字符序列,仍然返回自身对象。
    方法 **public **StringBuilder deleteCharAt(**int **index)
    移除此序列指定位置上的 char,仍然返回自身对象。
    重载的 **public **StringBuilder insert(…)方法
    可以为该 StringBuilder 对象在指定位置插入字符序列,仍然返回自身对象。
    方法 **public **StringBuilder reverse()
    用于将字符序列逆序,仍然返回自身对象。
    方法 **public **String toString() 返回此序列中数据的字符串表示形式。
    和 String 类含义类似的方法

    public static void main(String[ ] args) {
    
            /**StringBuilder*/
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < 7; i++) {
                sb.append((char) ('a' + i));//追加单个字符
            }
            System.out.println(sb.toString());//转换成 String 输出
            sb.append(", I like learning");//追加字符串
            System.out.println(sb.toString());
            /**StringBuffer,下面的方法同样适用 StringBuilder*/
            StringBuffer sb2 = new StringBuffer("hello");
            sb2.insert(0, "好").insert(0, "你");//插入字符串
            System.out.println(sb2);
            sb2.delete(0, 2);//删除子字符串
            System.out.println(sb2);
            sb2.deleteCharAt(0).deleteCharAt(0);//删除某个字符
            System.out.println(sb2.charAt(0));//获取某个字符
            System.out.println(sb2.reverse());//字符串逆序
    
      
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述

    总结

    String经过初始化后,就不会改变其内容了,对String字符串的操作实际上是对其副本(原始拷贝)的操作,原来的字符串不会改变。如:String s = "a"; s = s + "b";实际上是原来的“a”字符串已经丢弃了,重新产生一个字符串s + “b”(“ab”)。如果多次执行这些改变,会导致大量副本字符串对象存留在内存中,降低效率,如果这种操作放在循环中,会极大的影响程序的时间和空间性能。甚至会造成服务器的浪费。而StringBuilder和StringBuffer类是对原始字符串本身操作的,可以对字符串进行修改而不产生副本或者减少生成副本。

    枚举

    JDK1.5引入了枚举类型,枚举类型的定义包括枚举声明和枚举体。
    所有的枚举类型隐性地继承自 java.lang.Enum。枚举实质上还是类!而每个被枚举的成员实质就是一个枚举类型的实例,他们默认都是 public static final 修饰的。可以直接通过枚举类型名使用它们

    public enum Season {
        SPRING,
        SUMMER,
        AUTUMN,
        WINTER
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    需要定义一组常量时,可以使用枚举类型。
    尽量不要使用枚举的高级特性,事实上高级特性都可以使用普通类来实现,没有必要引入枚举,增加程序的复杂性!

  • 相关阅读:
    Nvidia-Xavier-NX配置
    GraphQL 入门与实践
    数据分享|R语言武汉流动人口趋势预测:灰色模型GM(1,1)、ARIMA时间序列、logistic逻辑回归模型...
    面向对象设计模式之工厂方法模式
    03-Kafka之基本概念
    用ABAP语言写的扫雷游戏
    JavaScript使用对象
    牛客刷题——Python入门总结
    代码随想录训练营day58
    怎么截取视频做gif动图?手把手教你视频在线转gif制作
  • 原文地址:https://blog.csdn.net/qq_43545600/article/details/126102917