zoukankan      html  css  js  c++  java
  • Java数据类型转换

    基本类型转换

    byte a = 127,b=1;
    //byte c = a + b; // 编译无法识别变量的数据类型 Required type:byte; Provided:int
    System.out.println(a + b);//128 整数的数据类型默认为byte
    byte d = (byte)(a + b);  //强制类型转换 位数多 -> 位数少
    System.out.println(d); // -128
    

    # 基本数据类型和包装数据类型 > 对原文章的逻辑做了重新梳理 > [cloud.tencent.com/developer/article](https://cloud.tencent.com/developer/article/1512392)

    基本数据类->包装数据类型 叫装箱.反过来叫拆箱.
    Java 5引入自动拆箱和装箱. 发生在编译器,错误提示在编译器.
    image.png

    自动装箱
    Integer value=10; //int直接赋值Integer合法,由编译器实现
    自动拆箱
    int value=new Integer(10);  //int value=0; new Integer(10); value指向new Integer(10)
    
    自动拆箱和装箱的时机
    int a1 = 1;
    Integer a2 = 1;
    System.out.println(a2.equals(a1)); // equals(Object obj)  Object是对象 a1自动装箱
    a1=a1+a2;  or  a2=a1+a2; // 算术运算自动拆箱
    
    //自动装箱和拆箱的实现 jdk1.8 Integer 数据类型转换valueOf(),xxValue()
    public final class Integer extends Number implements Comparable<Integer> {
        private final int value; //final 表示Integer对象一经构造完成,它代表的值不再变
        
        //构造函数
        public Integer(int value) {
            this.value = value;
        }
        
        //重写equals方法,比较两个Integer对象的value,来判断是否相等
        public boolean equals(Object obj) { 
            if (obj instanceof Integer) {
                return value == ((Integer)obj).intValue();
            }
            return false;
        }
    
         /**
         * 内部静态类,缓存数据,保存Integer数组
         * low  缓存数据最小值 固定为-128
         * high 缓存数据最大值 默认为127.[127,Integer.MAX_VALUE - (-low) -1]
         * high >最大值,则cache.length>Integer.MAXVALUE,则溢出
         * cache[]保存[low,high]所对应的Integer对象,长度是high-low+1(因为有元素0,所以要加1)
         */
        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() {}
        }
        
        /**
         * 基本数据类型->包装数据类型
         * 先判断i是否在[low,high]之间
         * Y,则复用Integer.cache[i-low].如果Integer.valueOf(3),直接返回Integer.cache[131]
         * N, 调用构造方法,构造出一个新的Integer对象
         */
        public static Integer valueOf(int i) {
            if (i >= IntegerCache.low && i <= IntegerCache.high)
                return IntegerCache.cache[i + (-IntegerCache.low)];
            return new Integer(i);
        }
        
        /**
         * 包装数据类型->基本数据类型
         * 先判断i是否在[low,high]之间
         * 直接返回值
         */
        public int intValue() {
            return value;
        }
    }
    
    基本数据类型和包装数据类型判等:
    Integer a1 = 1; 
    Integer a2 = 1; 
    Integer a3 = new Integer(1); 
    System.out.println(a1 == a2); //true,因为a1和a2是同一个对象,都是Integer.cache[129] 
    System.out.println(a1 == a3);//false,a3构造了一个新的对象,不同于a1,a2 
    System.out.println(a3.equals(a1));//true,比较值
    


    基本数据类型缓存(常量(对象)池)

    同类型比较,数据类型在缓存范围内才发生自动装箱和拆箱
    
    Integer a1 = 128,a2 = 128;
    System.out.println(a1 == a2); //false Integer 范围为[-128,127]
    Integer a3 = -128,a4 = -128;
    System.out.println(a3 == a4); //true  
    
    Byte b1 = 127,b2 = 127;
    System.out.println(b1 == b2); //true Byte 范围为[-128,127]
    Byte b3 = -128,b4 = -128;
    System.out.println(b3 == b4); //true 
    
    Long c1 = 128L,c2 = 128L;
    System.out.println(c1 == c2); //false Long 范围为[-128L,127L]
    Long c3 = -128L,c4 = -128L;
    System.out.println(c3 == c4);//true
    
    Character d1 = 128,d2 = 128;
    System.out.println(d1 == d2); // false Long 范围为[0,127]
    Character d3 = 127,d4 = 127;
    System.out.println(d3 == d4);// true
    System.out.println(d1); //€  打印的是字符,如图
    
    Double和Float是连续不可数的.就是比较值.
    
    Boolean没有自动装箱与拆箱.
    
    不同类型比较
    Integer i = 10;
    Byte b = 10;
    // System.out.println(i == b); //Byte和Integer.两个对象无法直接比较,报错
    System.out.println("i == b " + i.equals(b)); // false  包装类先比较是否是同一个类,不是的话直接返回false.
    int ii = 128;
    short ss = 128;
    long ll = 128;
    char cc = 128;
    System.out.println("ii == ss " + (ii == ss)); // true 基本数据类型直接比较值,值一样就可以
    System.out.println("ii == ll " + (ii == ll)); // true
    System.out.println("ii == cc " + (ii == cc)); // true
    

    image.png

    String

    参考https://blog.csdn.net/a724888/article

    1. 直接赋值- 产生一个实例化对象。一个匿名对象被引用。
     String s2="aaa";//直接赋值,匿名对象自动保存到字符串常量池中
     String s3="aaa";
     System.out.println(s2==s3);//true,两个对象指向同一个堆内存空间。 
    

    1. 构造方法赋值-产生两个实例化对象
    String s="aaa";//直接赋值
    String s1=new String("aaa");//构造方法实例化,匿名对象将成为垃圾空间
    System.out.println(s==s1);// false,比较地址。直接赋值自动入池。实例化new不会入池。
    System.out.println(s.equals(s1));//true,比较内容
    
    String s2=new String("aaa").intern();//实例化方法手工入池 public String intern(); s2指向池
    System.out.println(s==s2);//true 地址
    
    String s3=new String("aaa");
    s3.intern(); //s3指向new区,s3.intern()将new区的内容入池,但s3依旧指向new区
    System.out.println(s==s3);//false
    String s3=new String("aaa"); 
    s3.intern();    //false 地址
    


    由上,为避免产生垃圾,String实例化要直接赋值。

    匿名对象
    null.equals():运行时异常NullPointerException。可看出,匿名对象一定是开辟好堆内存空间的对象
    
    + 连接对象-- 同时可以得出,运算时,编译期可识别常量,不可识别变量。要知道
    要知道,避免使用魔法值,+做字符串连接,用StringBuilder
    String s="aaa";//直接赋值
    String s2="a"+"a"+"a";//表达式都为常量,编译期自动处理字符串连接,s2是整体存在,不会产生内存垃圾.
    System.out.println(s==s2);// True 地址判断,,数据加载时,值相同。
    
    静态常量池和运行时常量池
    String value="a"; String s3="a"+"a"+value; //表达式有变量,运行期计算,地址不一样。
    System.out.println(s==s3);//false 地址判断  s3在静态常量池,s4在运行时常量池。
    

    String不可变

    不可变的含义: 修改数据会指向新地址.



    不可变的优势 --String很常用
    cnblogs.com/cangwei22/p/10582600

    1. 避免一个变量改变池中的共享数据
    String a="abc"; 
    String b="abc";
    System.out.println(a==b); //true 共用池中数据,避免产生垃圾空间。
    
    b="a";
    System.out.println("a:"+a+"; b:"+b); //a:abc; b:a   b要改变值,不能直接改变池中数据,
    //需要定义String为 final ,避免池中数据改变,影响指向池中
    
    1. String作为HashMap的key, String的不可变保证了hash值的不可变。
    2. String作为网络连接的参数,String的不可变性提供安全性。
    3. String不可变,线程安全。

    不可变的实现
    Jdk1.8保存字符数组private final char[] value;jdk1.9保存字节数组private final byte[] value;

    final int[] value={1,2,3};
    int[] another={4,5,6};
    //value=another;    //编译报错,但真正不可变是 编译器不允许把value指向堆区另一个地址。
    value[2]=100;  
    System.out.println(Arrays.toString(value)); //[1, 2, 100] 
    
    1. 持有String对象的引用本身是可以改变的,比如可以指向其他的对象。
    2. final只能保证类不可被继承,类的对象在堆内存中的地址不会被改变。
    3. final修饰的char数组保证了char数组的引用不可变。但是可以通过char[0] = 'a'来修改值。不过String内部并不提供方法来完成这一操作,所以String的不可变是基于代码封装和访问控制的。


    StringBuffer和StringBuilder

    + 连接对象,有变量运算用StringBuilder。无变量运算用String
    String a = "a";
    a = a + a;//计算变量,运行时计算, 先把a封装成StringBuilder,调用append方法,返回toString。生成大量StringBuilder实例
    String a2 = "a"+"a";//计算无变量,编译期直接合成"aa",直接引用"aa",
    

    StringBuilder 和StringBuffer 继承自AbstractStringBuilder。AbstractStringBuilder定义为 char[] value,定义了字符串的基本操作:append,insert,indexof;
    安全性:String内容不可变,相当于常量,可看作线程安全。StringBuilder线程不安全,有10%-15%的性能提升。StringBuffer加同步锁,线程安全。
    多用StringBuilder。 StringBuilder常用方法

    Java9改进了字符串(包括String、StringBuffer、StringBuilder)的实现。在Java9以前字符串采用char[]数组来保存字符,因此字符串的每个字符占2字节;而Java9的字符串采用byte[]数组再加一个encoding-flag字段来保存字符,因此字符串的每个字符只占1字节。所以Java9的字符串更加节省空间,字符串的功能方法也没有受到影响。
    原文链接:https://blog.csdn.net/csxypr/article/details/92378336

  • 相关阅读:
    elasticsearch-搜索-定位搜索(十一)
    redis-缓存设计-自动延迟调度,最热商品缓存(二)
    20200925
    20175312 2018-2019-2 实验一《Java开发环境的熟悉》实验报告
    20175312 2018-2019-2 《Java程序设计》结对编程练习_四则运算(第一周:阶段性总结)
    20175312 2018-2019-2 《Java程序设计》第5周学习总结
    20175312陶光远 与 20175309刘雨恒 结对
    20175312 2018-2019-2 《Java程序设计》第4周学习总结
    20175312 2018-2019-2 《Java程序设计》第3周学习总结
    20175312 2018-2019-2 《Java程序设计》第2周学习总结
  • 原文地址:https://www.cnblogs.com/laidianjilu/p/13091016.html
Copyright © 2011-2022 走看看