zoukankan      html  css  js  c++  java
  • Java基础-数据类型

    基本类型

    • byte/8
    • char/16
    • short/16
    • int/32
    • float/32
    • long/64
    • double/64
    • boolean/~

    boolean只有两个值:true、false,可以用1bit来存储,但是具体大小没有明确规定。JVM会在编译时期将boolean类型的数据转换为int,使用1来表示true,0表示false。JVM支持数组,但是是通过读写byte数组来实现的。

    包装类型

    基本类型都有对应的包装类型,基本类型与其对应的包装类型之间的赋值使用自动装箱与拆箱完成。

    将原始值(例如int)转换为相应包装类(Integer)的对象的过程称为自动装箱。 当原始值是:Java编译器将应用自动装箱:

    • 作为参数传递给需要相应包装类对象的方法。
    • 分配给相应包装器类的变量。
    //    自动装箱
        static void autoboxing(){
            List<Integer> li = new ArrayList<>();
            for (int i = 1; i < 50; i+=2){
                li.add(i);
            }
            System.out.println("自动装箱:"+li);
        }
        /**
         * 尽管您将int值作为原始类型(而不是Integer对象)添加到li,但代码将进行编译。因为li是一个整型对象的列表,而不是一个整型值的列表,
         * 所以您可能想知道为什么Java编译器没有发出编译时错误。编译器不会产生错误,因为它从i创建了一个Integer对象,并将该对象添加到li中。
         * 因此,编译器在运行时将前面的代码转换为下面的代码
         */
        static void autoboxing1(){
            List<Integer> li = new ArrayList<>();
            for (int i = 1; i < 50; i+=2){
                li.add(Integer.valueOf(i));
            }
            System.out.println("正常转换:"+li);
        }

    将包装器类型(Integer)的对象转换为其对应的原始(int)值称为拆箱。 当包装器类的对象为:

    • 作为参数传递给需要相应原始类型值的方法。
    • 分配给相应原始类型的变量。
    //   自动拆箱
        public static int sumEven(List<Integer> li) {
            int sum = 0;
            for (Integer i: li)
                if (i % 2 == 0)
                    sum += i;
            return sum;
        }
        /**
         * 由于余数(%)和一元加号(+ =)不适用于Integer对象,因此您可能想知道Java编译器为何在不发出任何错误的情况下编译该方法。
         * 编译器不会生成错误,因为它在运行时调用intValue方法将Integer转换为int:
         */
        public static int sumEven1(List<Integer> li) {
            int sum = 0;
            for (Integer i : li)
                if (i.intValue() % 2 == 0)
                    sum += i.intValue();
            return sum;
        }

    运行结果:

    public static void main(String[] args){
    //        自动拆箱
            autoboxing();
            autoboxing1();
    
            List<Integer> li = new ArrayList<>();
            for (int i = 0; i < 50; i+=2){
                li.add(i);  // 2,4,6,8...48
            }
    
    //        自动装箱
            System.out.println("自动拆箱:"+sumEven(li));
            System.out.println("正常转换:"+sumEven1(li));
    
        }

     自动装箱和拆箱使开发人员可以编写更简洁的代码,从而使其更易于阅读。 下表列出了原始类型及其对应的包装器类,Java编译器将其用于自动装箱和拆箱:

     缓存池

    new Integer(123) 与 Integer.valueOf(123) 的区别在于:

    • new Integer(123) 每次都会新建一个对象;
    • Integer.valueOf(123) 会使用缓存池中的对象,多次调用会取得同一个对象的引用。
    Integer x = new Integer(123);
    Integer y = new Integer(123);
    System.out.println(x == y);    // false
    Integer z = Integer.valueOf(123);
    Integer k = Integer.valueOf(123);
    System.out.println(z == k);   // true
                

    valueOf() 方法源码,其实现比较简单,就是先判断值是否在缓存池中,如果在的话就直接返回缓存池的内容。

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

    在 Java 8中,Integer 缓存池的大小默认为 -128~127。

     private static class IntegerCache {
            static final int low = -128;
            static final int high;
            static final Integer[] cache;
            static Integer[] archivedCache;
    
            static {
                // high value may be configured by property
                int h = 127;
                String integerCacheHighPropValue =
                    VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
                if (integerCacheHighPropValue != null) {
                    try {
                        h = Math.max(parseInt(integerCacheHighPropValue), 127);
                        // Maximum array size is Integer.MAX_VALUE
                        h = Math.min(h, Integer.MAX_VALUE - (-low) -1);
                    } catch( NumberFormatException nfe) {
                        // If the property cannot be parsed into an int, ignore it.
                    }
                }
                high = h;
    
                // Load IntegerCache.archivedCache from archive, if possible
                VM.initializeFromArchive(IntegerCache.class);
                int size = (high - low) + 1;
    
                // Use the archived cache if it exists and is large enough
                if (archivedCache == null || size > archivedCache.length) {
                    Integer[] c = new Integer[size];
                    int j = low;
                    for(int i = 0; i < c.length; i++) {
                        c[i] = new Integer(j++);
                    }
                    archivedCache = c;
                }
                cache = archivedCache;
                // range [-128, 127] must be interned (JLS7 5.1.7)
                assert IntegerCache.high >= 127;
            }
    
            private IntegerCache() {}
        }

    编译器会在自动装箱过程调用 valueOf() 方法,因此多个值相同且值在缓存池范围内的 Integer 实例使用自动装箱来创建,那么就会引用相同的对象;若该值不在缓存池内,则属于不同对象。

    // Integer 缓存池的大小默认为 -128~127
    //不在缓存池内
    Integer a = 200;
    Integer b = 200;
    System.out.println(a==b);   // false
    Integer c = -200;
    Integer d = -200;
    System.out.println(c==d);  // false
    // 在缓存池内
    Integer e = 10;
    Integer f = 10;
    System.out.println(e==f);   //true

    基本类型对应的缓冲池如下:

    • boolean values true and false
    • all byte values
    • short values between -128 and 127
    • int values between -128 and 127
    • char in the range u0000 to u007F

    在使用这些基本类型对应的包装类型时,如果该数值范围在缓冲池范围内,就可以直接使用缓冲池中的对象。

    在 jdk 1.8 所有的数值类缓冲池中,Integer 的缓冲池 IntegerCache 很特殊,这个缓冲池的下界是 - 128,上界默认是 127,但是这个上界是可调的,在启动 jvm 的时候,通过 -XX:AutoBoxCacheMax=<size> 来指定这个缓冲池的大小,该选项在 JVM 初始化的时候会设定一个名为 java.lang.IntegerCache.high 系统属性,然后 IntegerCache 初始化的时候就会读取该系统属性来决定上界。

    上面内容学习自:cs-notes

  • 相关阅读:
    关于mysql的wait_timeout参数 设置不生效的问题【转】
    mysql只读模式的设置方法与实验【转】
    ansible批量修改linux服务器密码的playbook
    Serv-U 的升级及数据备份和迁移【转】
    java系统的优化
    JBoss6.1.0修改启动jvm内存以及修改日志级别【转】
    JAVA_OPTS讲解【转】
    RabbitMQ集群、镜像部署配置
    LVS+MYCAT+读写分离+MYSQL主备同步部署手册
    常用数据库高可用和分区解决方案(2) — MongoDB篇
  • 原文地址:https://www.cnblogs.com/dong973711/p/14566345.html
Copyright © 2011-2022 走看看