• Java_包装类


    包装类

    在实际应用中, 经常需要把基本数据类型转化为对象以便操作. 因此, Java在设计类时, 为每个基本数据类型设计了一个对应的类进行包装,
    这样八个和基本数据类型对应的类统称为包装类(Wrapper Class).
    包装类---------> java.lang包中

    |:-----:|:-----:| | 基本数据类型 | 包装类 | | byte | Byte | | boolean | Boolean | | short | Short | | char | Character | | int | Int | | long | Long | | float | Float | | double | Double |

    除Character和Boolean类外, 其他的都是"数字型", "数字型"都是java.lang.Number的子类. Number类是抽象类, 因此它的抽象方法都需要在其子类当中实现. Number类提供了抽象方法:intValue(), langValue(), floatValue(), doubleValue(), 意味着所有的"数字型"包装类里都可以互相转型

    包装类主要用途:

    1.作为和基本数据类型对应的数据类型存在, 方便设计到对象的操作, 如Object[], 集合等操作
    2.包含每种基本数据类型的相关属性, 如最大值, 最小值, 以及相关的操作方法(这些操作方法的作用是在基本数据类型, 包装类对象, 字符串三者之间提供相互之间的转化方法)

    /*********************其他包装类用法类似*****************************/
    public class WrapperClass {
    	void testInteger() {
    		// 基本类型转化成Integer对象
    		Integer int_1 = new Integer(10);		// JDK9之后好像过时了
    		Integer int_2 = Integer.valueOf(20);	// 官方推荐写法 
    		
    		// 包装对象之间的转化
    		Short int1 = int_1.shortValue();
    		Double int2 = int_1.doubleValue();
    		
    		// Integer对象转化为int
    		int a = int_1.intValue();
    		
    		// 字符串转化成Integer对象
    		Integer int_3 = Integer.parseInt("3334");
    		Integer int_4 = new Integer("99");
    		
    		// Integer对象转化成字符串
    		String str_1 = int_3.toString();
    		
    		// 一些常见int类型相关的常量
    		System.out.println("int能表示的最大整数: " + Integer.MAX_VALUE);
    		System.out.println("int能表示的最小整数: " + Integer.MIN_VALUE);
    
    		System.out.print("int_3: ");
    		System.out.println(int_3);
    		System.out.print("int_4: ");
    		System.out.println(int_4);
    	}
    	
    	public static void main(String[] srgs) {		
    		WrapperClass test = new WrapperClass();
    		test.testInteger();
    	}
    }
    
    /*
    int能表示的最大整数: 2147483647
    int能表示的最小整数: -2147483648
    int_3: 3334
    int_4: 99
    */
    

    自动装/拆箱

    自动装箱和拆箱就是将基本数据类型和包装类之间进行自动的互换
    JDK1.5之后, Java引入自动装/拆箱

    自动装箱

    基本类型的数据处于需要对象的环境中时, 会自动转换为对象
    Integer i = 4在JDK1.5之前是非法的, 必须使用Integer i = new Integer(4)来实现基本数据类型转换为包装对象(new方法好像过时了)
    JDK1.5之后Integer i = 4是正确的, 自动执行Integer i = Integer.valueof(5)

    自动拆箱

    每当需要一个值是, 对象会自动转换成基本类型, 没必要再显式调用intValue(), doubleValue()等转型方法

    Integer i = 4;	// 自动装箱
    int j = i;		// 自动拆箱
    

    总结

    Integer i = 13;		// 自动装箱
    // 相当于编译器自动执行下面语句
    Integer i = Integer.valueOf(13);	// 调用的是valueOf(13), 而不是new Integer(13)
    
    int j = i;	// 自动拆箱
    // 相当于编译器自动执行下面语句
    int j = i.intValue();
    
    1. 自动装箱通过调用包装类的xxxx.ValueOf()方法实现(xxxx代表Integer, Short等)
    2. 自动拆箱通过调用包装类的VarName.xxxxValue()方法实现(xxxx代表int, short等)

    自动装/拆箱的功能实际上是通过编译器来帮忙实现的, 编译器在编译时所依据的语法, 决定是否装箱

    自动装/拆箱功能就是所谓的"编译器蜜糖", 虽然使用这个功能很方便, 但在程序运行过程中需了解Java语义, 注意包装类空指针异常

    /***************包装类空指针异常****************/
    public static void main(String[] srgs) {		
    	Integer i = null; 	// 空指针
    	int j = i;			
    }
    
    /********************报错***********************
    Exception in thread "main" java.lang.NullPointerException
    	at zyb.cn.WrapperClass.main(WrapperClass.java:37)
    */
    

    包装类的缓存

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

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

    /********************Integer相关源码************************/
    @HotSpotIntrinsicCandidate
    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类使用
    *	2.一般情况下IntegerCache.low为-128, IntegerCache.high为127, IntegerCache.cache为内部类的一个静态属性, 相关源码如下
    */
    
    /********************IntegerCache相关源码************************/
    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 =
                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() {}
    }
    

    由上面的源码可以看出, 静态代码块的目的就是初始化数组cache, 这个过程会在类加载时完成

    /***************************测试例子****************************/
    public static void main(String[] args) {
    /* 
     * 缓存[-128, 127]之间的数字, 实际是系统初始的时候, 创建了[-128, 127]之间的一个缓存数组
     * 当调用valueOf()时, 首先检查是否在[-128, 127]之间, 如果在这个范围则直接从缓存数组中拿出已经建好的对象
     *如果不在这个范围, 则创建新的Integer()对象 
     */
    	Integer in1 = -128;
    	Integer in2 = Integer.valueOf(-128);
    	System.out.println(in1 == in2);	// true, 因为128在缓存内
    	System.out.println(in1.equals(in2));
    	
    	System.out.println("############分隔符#############");
    	
    	Integer in3 = 1280;
    	Integer in4 = 1280;
    
    	System.out.println(in3 == in4);	// false, 因为1280不在缓存内
    	System.out.println(in3.equals(in4));
    }
    
    /*
    true
    true
    ############分隔符#############
    false
    true
    */
    
  • 相关阅读:
    wmi
    Python中基本同步原语的使用
    Python多线程的几种实现方式
    TCP/IP详解 卷1 第一章 概述
    对利用sqlmap获取os-shell过程的一次抓包分析
    12.19 Aggregate (GROUP BY) Functions
    13.2.9 SELECT 语法
    GitHack 源码分析
    CTF遇到的问题-长期更新
    在Windows server2008中搭建sqli-lab实验环境
  • 原文地址:https://www.cnblogs.com/hesper/p/9734148.html
Copyright © 2020-2023  润新知