精华内容
下载资源
问答
  • 编程入门基础 原生类型与复合类型 主讲教师 耿宇航 Copyright2013, All Rights Reserved java数据类型 int byte short long double float 基本类型 char boolean 类型 类 复合类型 接口 数组 Copyright2013,, All ...
  • 其实在原生类型中也是有 Class 的,有时候我们需要判断某个 Class 是否是原生类型,这时候可以使用 java.lang.Class#isPrimitive 方法: package dongguabai.demo.testing.classloader; /** * @author Dongguabai ...

    我们都知道 Java 类主要分为两种:

    • 对象类型
    • 原生类型(byteshortcharintlongfloatdoubleboolean

    其实在原生类型中也是有 Class 的,有时候我们需要判断某个 Class 是否是原生类型,这时候可以使用 java.lang.Class#isPrimitive 方法:

    package dongguabai.demo.testing.classloader;
    
    /**
     * @author Dongguabai
     * @Description
     * @Date 创建于 2020-11-22 01:01
     */
    public class Main {
    
        public static void main(String[] args) {
            System.out.println(int.class.isPrimitive());  //true
            System.out.println(Void.class.isPrimitive());  //false
            System.out.println(Integer.class.isPrimitive());  //false
        }
    }
    
    展开全文
  • 在Kotlin中,所有东西都是对象,我们可以在任何变量(如基本类型:数字、字符、布尔、数组与字符串等)上调用成员函数和属性。一、数字1. 内置类型种类Kotlin提供了如下内置类型来表示数据(和Java很近); 类型 ...

    在Kotlin中,所有东西都是对象,我们可以在任何变量(如基本类型:数字、字符、布尔、数组与字符串等)上调用成员函数和属性。

    一、数字


    1. 内置类型种类

    Kotlin提供了如下内置类型来表示数据(和Java很近);

    类型比特宽度
    Double64
    Float32
    Long64
    Int32
    Short16
    Byte8

    Java对比:在Kotlin中,字符不是数字;

    2. 字面常量的表示

    整数字面值有如下几种:

    • 十进制:123,Long类型使用大写L标记:123L;
    • 十六进制:0x0F;
    • 二进制:0b00001011;

    注意:不支持八进制;

    浮点数常规表示如下:

    • 默认double:123.5、123.5e10;
    • Float用f或者F标记:123.5f;

    使用下划线使数字常量更易阅读

    //如果数字位数,信用号,进制数据分隔易于阅读
    val oneMillion = 1_000_000
    val creditCardNumber = 1234_5678_9012_3456L
    val hexBytes = 0xFF_EC_DE_5E
    val bytes = 0b11010010_01101001_10010100_10010010

    3. 可空引用或泛型才数字装箱

    Kotlin运行在Java平台,数字物理存储为JVM的原生类型, 除非需要可空的引用(如Int?)或泛型,才会把数字装箱
    数字装箱不保留同一性,它保留了相等性

    val a: Int = 10000
    //a分别装箱为boxedA何anotherBoxedA
    val boxedA: Int? = a
    val anotherBoxedA: Int? = a
    //输出false,boxedA和anotherBoxedA不是一个对象
    print(boxedA === anotherBoxedA)
    //输出trud,但是两个对象的值相等
    print(boxedA == anotherBoxedA)

    4. 不支持隐士转换只能显示转换

    由于不同的表示方式,较小的类型不是较大类型的子类型。因此较小的类型不能隐士转换成较大类型;
    可以显示转换来拓宽数字,每个数字类型都支持如下方法:

    toByte(): Byte
    toShort(): Short
    toInt(): Int
    toLong(): Long
    toFloat(): Float
    toDouble(): Double
    toChar(): Char

    缺乏隐式转换影响并不大,类型会从上下文推断算术运算会重载做适当转换;

    // 字面值是静态检测为Byte类型
    val b: Byte = 1
    // 错误,b为Byte类型,不能隐士转换层较大的Int类型 
    val i: Int = b 
    // 正确,通过toInt显式拓宽为Int;
    val i: Int = b.toInt() 
    // Long + Int 为 Long
    val l = 1L + 3 

    5. 运算定义成类成员

    Kotlin**支持数字运算标准集运算被定义成相应的类成员**;
    对于位运算,没有特殊字符表示,只可用中缀方式调用命名函数。完整位运算列表(只用于Int和Long)如下:

    shl(bits):有符号左移,如Java中<<
    shr(bits):有符号右移动,如Java中>>
    ushr(bits):无符号右移,如Java的>>>
    and(bits):位与
    or(bits):位或
    xor(bits):位异或
    inv():位非
    
    val x = (1 shl 2) and 0x000FF000

    二、字符


    1. 字符的表示

    字符使用Char表示,它们不能直接当作数字;

    fun check(c: Char) {
        //字符不能当做数字;
        if (c == 1) {
            // ……
        }
    }

    2. 字符的转义

    字符字面值用单引号括号起来:’1’;
    特殊字符使用反斜杠转义,如:\t、\b、\n、\r、\’、\”、\和$等;
    编码字符使用Unicode转义序列语法:’\uFF00’;

    3. 字符可显示转换

    可以显示把字符转换为Int数字

    fun decimalDigitValue(c: Char): Int {
        if (c !in '0'..'9')
            throw IllegalArgumentException("Out of range")
        // 显式转换为数字
        return c.toInt() - '0'.toInt() 
    }

    当需要可空引用时,像数字、字符会被装箱。装箱不会保留同一性

    三 、布尔值


    1. 布尔值用Boolean类型表示,它有两个值:true和false;
    2. 若需要可空引用布尔值会被装箱
    3. 内置布尔值运算有:||-短路逻辑或、&&-短路逻辑与和!-逻辑非;

    三、数组


    1. 数组的表示

    数组在Kotlin中使用Array类来表示

    2.数组的函数

    定义了get和set函数(按照运算符重载约定会转变为[])和size属性,以及一些其它有用成员函数;

    class Array<T> private constructor() {
        val size: Int
        operator fun get(index: Int): T
        operator fun set(index: Int, value: T): Unit
    
        operator fun iterator(): Iterator<T>
        // ……
    }

    3. 数组的创建

    数组使用库函数arrayOf()来创建数组,并传递元素值给它;
    或者使用arrayOfNulls()可以创建指定大小,元素都为空的数组
    用接受数组大小和一个函数参数的工厂函数用作参数,函数返回给定索引的每个元素初始化值

    var array= arrayOf(1, 2, 3)
    var nullArray = arrayOfNulls<Int>(5)
    //创建一个 Array<String> 初始化为 ["0", "1", "4", "9", "16"]
    val asc = Array(5, { i -> (i * *).toString() })

    Java对比: Kotlin中数组是不型变的,意味着Kotlin不让我们把Array赋值给Array,防止可能运行时失败;

    4. 原生类型数组

    Kotlin有无装箱开销的专门类来表示原生类型数组:ByteArray、ShortArray、IntArray等;
    它们和Array没有继承关系,有同样的方法属性集,有相应的工厂方法;

    val x: IntArray = intArrayOf(1, 2, 3)
    x[0] = x[1] + x[2]

    四、字符串


    1. 字符串的表示

    字符串用String类型表示,是不可变的
    字符串的元素—字符可以使用索引运算符访问:s[i],可以用for循环迭代字符串;

    for (c in str) {
        println(c)
    }

    原生字符串使用三个引号(”“”)分界符号括起来,内部没有转义并且可以包含换行和任何其他字符

    val text = """
        //内部不需要使用转义字符\"
        for (c in "foo")
            print(c)
    """

    2. 字符串字面值

    Kotlin有两种类型字符串字面值:转义字符串可以有转义字符原生字符串可以包含换行和任意文本

    val s = "Hello, world!\n"

    3. 字符串模板

    字符串可以包含模板表达式,即一小段代码,会求值并把结果合并到字符串中;
    模板表达式以美元符号($)开头,由一个简单的名字构成

    val i = 10
    // 求值结果为 "i = 10"
    val s = "i = $i"

    或者使用花括号括起来任意表达式;

    val s = "abc"
    // 求值结果为 "abc.length is 3"
    val str = "$s.length is ${s.length}"

    原生字符串和转义字符串内部都支持模板,如果你需要在原生字符串中标识字面值$字符(它不支持反斜杠),可用如下语法:

    val price = """
    ${'$'}9.99
    """

    1.新技术,新未来!尽在1024工场。时刻关注最前沿技术资讯,发布最棒技术博文!(甭客气!尽情的扫描或者长按!)
    1024工场服务号
    2.加入“Kotlin开发”QQ讨论群,一起学习一起Hi。(甭客气!尽情的扫描或者长按!)
    Kotlin开发群

    展开全文
  • Java 原生类型与包装器类型深度剖析

    千次阅读 多人点赞 2016-09-24 16:05:33
    本文对 Java 原生类型与包装器类型进行深度剖析,主要涉及以下四个方面:原生类型与包装器类型基础、字面值概念和种类、 基本类型的自动转型与强制转型 和自动装箱与拆箱机制。

    摘要:

      本文对 Java 原生类型与包装器类型进行深度剖析,主要涉及以下四个方面:原生类型与包装器类型基础、字面值概念和种类、 基本类型的自动转型与强制转型和自动装箱与拆箱机制。


    要点:

    • 原生类型与包装器类型

    • 字面值概念和种类

    • 基本类型、自动转型与强制转型

    • 自动装箱与拆箱机制(Autoboxing and Unboxing)


    一. 原生类型与包装器类型

    在Java中有八种基本数据类型:

              基本类型.png-111.6kB

    特别需要注意以下几点:

    • 未带有字符后缀标识的整数默认为 int 类型未带有字符后缀标识的浮点数默认为 double 类型

    • 只有 byte,char,short,int 四种基本类型及其包装类(需要Java5.0/1.5以上版本支持)可以用于 switch 语句(只有 enum 类型 和 int类型可以应用到 swith),其它类型编译会报错;

    • char(两个字节)可以用单引号表示单个字符(可以是汉字),如:‘良’,’A’;

    • 整数可以由二进制(以0B/0b开头)、八进制(以0开头的整数)、十进制、十六进制(以0x或0X开头的整数)表示;


    二. 字面值

      在Java源代码中,字面值用于表示固定的值(fixed value)。数值型的字面值是最常见的,字符串字面值也很常见可以算是一种,当然也可以把特殊的null当做字面值。字面值大体上可以分为 整型字面值(int型字面值 、 long型字面值 和 字符字面值)整型字面值、浮点型字面值(double型字面值 和 float型字面值)字符串字面值特殊字面值 四种。


    (1) 整型字面值

      从形式上看是整数的值归类为整型字面值。例如: 10, 100000L, ‘B’‘B’、0XFF 这些都可以称为整型字面值。在使用时,需要注意以下几点:

    • 整型字面值可以用 十进制十六进制(以0X/0x开头)、八进制(以0开头) 和 二进制(以0B/0b开头) 来表示。当然,基数不能超出进制的范围,比如09是不合法的,八进制的基数只能到 7。

    • 一般情况下,字面值创建的是int类型,但是int字面值可以赋值给 byte、short、char、long 和 int。当然,前提是字面值在目标范围以内(Java会自动完成转换);如果试图将超出范围的字面值赋给某一类型(比如把128赋给byte类型),编译通不过,需要强制类型转换

    byte b0 = 128;       // Type mismatch: cannot convert from int to byte
    byte b1 = 12;       // OK
    byte b2 = (byte)300// OK 需要强制转换,但表示的数字是截取后的数字(300二进制为100101100,截取后为00101100,即44)
    
    char c0 = 5;       // OK
    char c1 = char(-3);       // 编译通过,但打印值为 ?(char 为无符号的)
    System.out.println(c1);   // ?
    • 如果想创建一个 int 类型无法表示的 long 类型,则需要在字面值最后面加上L或者l(通常建议使用容易区分的L)。所以,整型字面值包括int字面值和long字面值两种。

    • Java中,字符字面值用单引号括起来(也属于整型字面值),如‘@’,‘1’。所有的UTF-16字符集都包含在字符字面值中。不能直接输入的字符,可以使用转义字符,如‘\n’为换行字符。也可以使用八进制或者十六进制表示字符,八进制使用反斜杠加3位数字表示,例如’\141’表示字母a。十六进制使用\u加上4为十六进制的数表示,如’\u0061’表示字符a。也就是说,通过使用转义字符,可以表示键盘上的有的或者没有的所有字符。常见的转义字符序列有:
      \ddd(八进制) 、 \uxxxx(十六进制Unicode字符)、\’(单引号)、\”(双引号)、\ (反斜杠)\r(回车符) \n(换行符) \f(换页符) \t(制表符) \b(回格符)


    (2) 浮点字面值

      浮点字面值简单的理解可以理解为小数,分为float字面值double字面值。如果在小数后面加上F或者f,则表示这是个float字面值,如11.8F。如果小数后面不加F/f(如10.4),或者小数后面加上D/d,则表示这是个double字面值。

    double d1 = 10// OK,自动类型转换
    double d2 = 11.4;    // OK
    double d3 = 1.23E3;    // OK  
    double d4 = 10D;    // OK  
    double d5 = 0.4D;     // OK 
    float f1 = 10;      // OK,自动类型转换
    float f2 = 11.1F;      // OK
    float f3 = 11.1;      // Type mismatch: cannot convert from double to float

    (3) 字符及字符串字面值

      Java中字符字面值用单引号括起来,如‘@’,‘1’。所有的UTF-16字符集都包含在字符字面值中。不能直接输入的字符,可以使用转义字符,如‘\n’为换行字符。也可以使用八进制或者十六进制表示字符,八进制使用反斜杠加3位数字表示,例如’\141’表示字母a。十六进制使用\u加上4为十六进制的数表示,如’\u0061’表示字符a。也就是说,通过使用转义字符,可以表示键盘上的有的或者没有的所有字符。常见的转义字符序列有:
    \ddd(八进制) 、 \uxxxx(十六进制Unicode字符)、\’(单引号)、\”(双引号)、\ (反斜杠)\r(回车符) \n(换行符) \f(换页符) \t(制表符) \b(回格符)

      字符串字面值则使用双引号,字符串字面值中同样可以包含字符字面值中的转义字符序列


    (4) 特殊字面值

      null 是一种特殊的类型(type),可以将它赋给任何引用类型变量,表示这个变量不引用任何东西。如果一个引用类型变量为null,表示这个变量不可用。

      还有一种特殊的 class literal,用 type name 加上 .class 表示,例如 String.class。 首先,String是类Class(java.lang.Class)的一个实例(对象),而”This is a string”是类String的一个对象。然后,class literal用于表示类Class的一个对象,比如String.class用于表示类Class的对象String。简单地说,类字面值(class literal)就是诸如String.class 、Integer.class这样的字面值,它所表示的就是类String、类Integer。如果输出Integer.class,你会得到class java.lang.Integer。List.class的输出为interface java.util.List。总之,class literal 用于表示类型本身


    特别需要注意:

    • 在数值型字面值 中可以 中可以使用下划线(JDK7开始,可以在数值型字面值(包括整型字面值和浮点字面值)插入一个或者多个下划线。但是下划线只能用于分隔数字下划线只能用于分隔数字,不能分隔字符与字符,也不能分隔字符与数字);
    int x = 123_456_789;  // 在编译的时候,下划线会自动去掉。
    float f = 1.22___33__44;   //可以连续使用下划线
    int = _123;  // Error
    long = 1_L;  // Error

    三. 自动转型与强制转型

    1、 自动转型

    自动转型总原则:byte,short,char(同级)-> int -> long -> float -> double (由低精度到高精度)


    (1) 由低精度到高精度的自动转换

    具体可分为以下两种情形:

    • 从位数低的类型向位数高的类型转换
        byte b = 1;
        char c = 1;
        short s = 1;
        int i = 1;
    
        c = b;  // Error,同级
        c = s;  // Error,同级
        s = c;  // Error,同级
        i = c;  // OK
    • 从整型向浮点型的转换———-

    • 从整型向浮点型的转换

        int i = 1long t = 1;
        float f = 1;
        double d = 1;
    
        f = i;  //  Ok
        f = t;  //  Ok
        d = f;  // Ok
    

    (2) 运算符对基本类型的影响

    具体可分为以下两种情形:

    1) 当使用 +、-、*、/、%、==、>、< 等 等运算符对基本类型进行运算时,遵循如下规则:

      两个操作数中,先考虑是否有一个是double类型的。如果有,另一个操作数和结果 将会被转换成double类型。再依次考虑float,long。除此之外,两个操作数(包括byte、short、int、char)都将会被转换成int类型。

    byte b1 = 10 ;  //OK,会检查发现10没有超过byte类型的最大值
    byte b2 = 12;   //OK,会检查发现12没有超过byte类型的最大值
    
    byte b = b1 + b2; //Error,byte类型在计算时会自动提升为int类型,此时就会报错,因为b1+b2实际上是int类型,但是左侧的变量为byte类型。
    
    short s1=1; //OK,会检查发现1没有超过short类型的最大值
    s1=s1+1;    //Error,因为s1+1 结果int,但左侧变量为 short,报错
    
    s1++;      //OK,不会报错,与s1=s1+1不同!!!,会检查发现2没有超过short类型的最大值
    
    s1=1+1;   //OK,1+1 是个编译时可以确定的常量,'+'运算在编译时就被执行了,而不是在程序执行的时候,这个语句的效果等同于s1=2

    2) 当使用 +=、-=、*=、/=、%= i++、 ++i 运算符对基本类型进行运算时,遵循如下规则:

      运算符右边的数值将首先被强制转换成与运算符左边数值相同的类型,然后再执行运算,且运算结果与运算符左边数值类型相同。自增(减)运算也类似。

    short s1=1; // OK,会检查发现1没有超过short类型的最大值
    short s2;
    
    s1+=1;    // OK,正确,1首先被强制转换为short型,然后再参与运算,并且结果也是short类型
    
    s2 = ++s1;     // OK,正确,s2的值为2

    2、强制转型
      强制转换的格式是在需要转型的数据前加上 “( )”, 然后在括号内加入需要转化的数据类型。主要发生于以下两种情形:

    • 由高精度向低精度转换

    • 一种类型到另一种类型转换,则必须使用强制类型转化(同级之间:byte,short,char)

     byte b = 3;
     int i = 3;
     long t = 3;
     float f = 3;
     char c = 3;
     short s = 3;
    
     i = (int) f;  // OK,由高精度向低精度转换
     t = (long) f;  // OK,由高精度向低精度转换
     b = (byte) i;  // OK,由高精度向低精度转换
    
     i = b; // OK,由低精度向高精度转换,自动转型
     System.out.println(c==s);  // OK,true,c 和 s 自动转型为int,然后比较
    
     b = (byte) s;  // OK,一种类型到另一种类型转换
     c = (char) b;  // OK,一种类型到另一种类型转换
     c = (char) s;   // OK,一种类型到另一种类型转换

      特别需要注意的是,强制转换常常会导致二进制位的截取,甚至会导致意想不到的结果:

     int i = 128;
     byte b = (byte)i;
     System.out.println(b);           // -128(即-0)

    四. 自动装箱与拆箱(Autoboxing and Unboxing)

    1、什么是装箱?什么是拆箱?

      Java为每种基本数据类型都提供了对应的包装器类型。在 Java SE5 之前,如果要 创建一个数值为10的Integer对象,必须这样进行:

    Integer i = new Integer(10);

      而从 Java SE5 之后就提供了自动装箱的特性,如果要 创建一个数值为10的Integer对象,只需要这样就可以了:

    Integer i = 10;

      这个过程中会自动根据数值创建对应的 Integer对象,这就是装箱

      那什么是拆箱呢?顾名思义,跟装箱对应,就是自动将包装器类型转换为基本数据类型:

    Integer i = 10;  //装箱
    int n = i;   //拆箱

      简单一点说,装箱就是自动将基本数据类型转换为包装器类型拆箱就是自动将包装器类型转换为基本数据类型


    2、装箱和拆箱是如何实现的

     上一小节了解装箱的基本概念之后,这一小节来了解一下装箱和拆箱是如何实现的。我们就以Interger类为例,下面看一段代码:

    public class Main {
        public static void main(String[] args) {
    
            Integer i = 10;
            int n = i;
        }
    }

    反编译class文件之后得到如下内容: 

            装箱拆箱反编译.jpg-59.5kB
               
      从反编译得到的字节码内容可以看出,在装箱的时候自动调用的是Integer的valueOf(int)方法。而在拆箱的时候自动调用的是Integer的intValue方法

      对于其他的包装器类,比如Double、Character,也同样适用。

      因此,可以用一句话总结装箱和拆箱的实现过程:

      装箱过程是通过调用包装器的valueOf方法实现的,而拆箱过程是通过调用包装器的 xxxValue方法实现的(xxx代表对应的基本数据类型)。


    3、valueOf、xxxValue 方法在JDK中的实现

    (1) 在 Byte,Character,Short,Integer,Long 中的实现(以 Integer 为例)

    • public static Integer valueOf(int i)类方法
    public static Integer valueOf(int i) {
            if(i >= -128 && i <= IntegerCache.high)
                return IntegerCache.cache[i + 128];
            else
                return new Integer(i);
        }
    
        private static class IntegerCache {
            static final int high;
            static final Integer cache[];
    
            static {                                         // 静态代码块  
                final int low = -128;
    
                // high value may be configured by property
                int h = 127;
                if (integerCacheHighPropValue != null) {
                    // Use Long.decode here to avoid invoking methods that
                    // require Integer's autoboxing cache to be initialized
                    int i = Long.decode(integerCacheHighPropValue).intValue();
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - -low);
                }
                high = h;
    
                cache = new Integer[(high - low) + 1];
                int j = low;
    
                for(int k = 0; k < cache.length; k++)                      // 初始化  
                    cache[k] = new Integer(j++);
            }
    
            private IntegerCache() {}
        }

      在装箱时,valueOf方法会被自动调用:如果整型字面值在[-128,127]之间,便返回 IntegerCache.cache(在类加载时就自动创建) 中已经存在的对象的引用;否则,创建一个新的Integer对象并返回。

    • public int intValue()实例方法
    public int intValue() {
        return value;
    }

     从这段代码可以看出,在拆箱时,Integer对象会自动调用其 intValue 方法,返回该对象对应的 int 值。
     
    下面代码可以很好说明这一点:

    public class Main {
        public static void main(String[] args) {
    
            Integer i1 = 100;
            Integer i2 = 100;
            Integer i3 = 200;
            Integer i4 = 200;
    
            System.out.println(i1==i2);          // true
            System.out.println(i3==i4);          // false
        }
    }

    (2) 在 Float, Double 中的实现(以 Double 为例)

    • public static Double valueOf(double d) 类方法
       public static Double valueOf(double d) {
            return new Double(d);
        }

      在装箱时,valueOf方法会被自动调用,从而创建相应的Double对象并返回。

    • public int intValue()实例方法
     public double doubleValue() {
        return value;
    }

      从这段代码可以看出,在拆箱时,Double对象会自动调用其 doubleValue 方法,返回该对象对应的 double 值。
      
      下面代码可以很好说明这一点:

    public class Main {
        public static void main(String[] args) {
    
            Double i1 = 100.0;
            Double i2 = 100.0;
            Double i3 = 200.0;
            Double i4 = 200.0;
    
            System.out.println(i1==i2);          // false
            System.out.println(i3==i4);          // false
        }
    }

      为什么Double类的valueOf方法会采用与Integer类的valueOf方法不同的实现呢?原因很简单,在某个范围内的整型数值的个数是有限的,而浮点数却不是


    (3) 在 Boolean 中的实现

    • public static Boolean valueOf(boolean b) 类方法
    public static final Boolean TRUE = new Boolean(true);
    public static final Boolean FALSE = new Boolean(false);
    
    public static Boolean valueOf(boolean b) {
            return (b ? TRUE : FALSE);
    }

      在装箱时,valueOf方法会被自动调用,从而创建相应的Boolean对象并返回。

    • public boolean booleanValue()实例方法
     public boolean booleanValue() {
        return value;
        }
    }

      从这段代码可以看出,在拆箱时,Boolean对象会自动调用其 booleanValue 方法,返回该对象对应的 boolean 值。
      
      下面代码可以很好说明这一点:

    public class Main {
        public static void main(String[] args) {
    
            Boolean i1 = false;
            Boolean i2 = false;
            Boolean i3 = true;
            Boolean i4 = true;
    
            System.out.println(i1==i2);          // true
            System.out.println(i3==i4);          // true
        }
    }

     总之,

    • Integer、Short、Byte、Character、Long 这几个类的valueOf方法的实现是类似的,有限可列举,共享[-128,127]

    • Double、Float的valueOf方法的实现是类似的,无限不可列举,不共享

    • Boolean的valueOf方法的实现不同于以上的整型和浮点型,只有两个值,有限可列举,共享


    4、Integer i = new Integer(xxx)Integer i =xxx;的区别

    • 第一种方式不会触发自动装箱的过程,而第二种方式会触发;

    • 在执行效率和资源占用上的区别。第二种方式的执行效率和资源占用在一般性情况下([-128,127])要优于第一种情况(注意这并不是绝对的)。


    5、“==”运算符

      当使用“==”运算符在基本类型和其包装类对象之间比较时,涉及到自动装箱、拆箱机制,遵循如下规则:

       1). 只要两个操作数中有一个是基本类型或表达式(即包含算术运算符),就是比较它们的数值是否相等。
       2). 否则,就是判断这两个对象的内存地址是否相等,即是否是同一个对象。


    // 代码片段1
    public class Main {
        public static void main(String[] args) {
    
            Integer i01=59;
            int i02=59;
            Integer i03=Integer.valueOf(59);
            Integer i04=new Integer(59);
    
            System.out.println(i01==i02);  // true,拆箱
            System.out.println(i01==i03);  // true,同一对象
            System.out.println(i03==i04);  // false,不同对象
            System.out.println(i02==i04);  // true,拆箱
        }
    }

    // 代码片段2
    public class Main {
        public static void main(String[] args) {
    
            Integer a = 1;
            Integer b = 2;
            Integer c = 3;
            Integer d = 3;
            Integer e = 321;
            Integer f = 321;
            Long g = 3L;
            Long h = 2L;
    
            System.out.println(c==d);  // true
            System.out.println(e==f);  // false
            System.out.println(c==(a+b));  // true
            System.out.println(c.equals(a+b));  // true
            System.out.println(g==(a+b));  // true
            System.out.println(g.equals(a+b));  // false
            System.out.println(g.equals(a+h));  // true
        }
    }
    • 第一个和第二个输出结果没有什么疑问;

    • 第三个打印语句由于 a+b 包含了算术运算,因此会触发自动拆箱过程(会调用intValue方法),因此它们比较的是数值是否相等;

    • 对于c.equals(a+b)会先触发自动拆箱过程,再触发自动装箱过程,也就是说a+b,会先各自调用intValue方法,得到了加法运算后的数值之后,便调用Integer.valueOf方法,再进行equals比较;

    • 对于g==(a+b),会分别触发 Integer 和 Long 的自动拆箱过程,然后 int 自动转为 long,进行比较;

    • 对于g.equals(a+b),最终会归结于 Long对象与Integer对象的比较,由于二者不为同一类型,直接返回 false ;

    • 对于g.equals(a+h),最终会归结于 Long对象与Long对象的比较,由于 -128 <= 3 <= 127, 二者为同一对象,直接返回 true 。


    6、小结

    • 使用“==”运算符在基本类型和其包装类对象之间比较时,只要两个操作数中有一个是 基本类型 表达式(即包含算术运算符),就是比较它们的数值是否相等。否则,就是判断这两个对象的内存地址是否相等,即是否是同一个对象

    • 如果一个 方法中参数类型为原生数据类型 ,所传入的参数类型为其封装类对象,则会自动对其进行 拆箱 ;相应地,如果一个方法中 参数类型为封装类型对象 ,所传入的参数类型为其原始数据类型,则会自动对其进行 装箱 ,例如上述的equals方法。

        至于什么时候装箱,什么时候拆箱主要取决于:在当前场景下,你需要的是引用类型还是原生类型。若需要引用类型,但传进来的值是原生类型,则自动装箱(例如,使用equals方法时传进来原生类型的值);若需要的是原生类型,但传进来的值是引用类型,则自动拆箱(例如,使用运算符进行运算时,操作数是包装类型)。


    引用

    Java基础-字面值
    Java基本数据类型详解
    JAVA的八种基本类型 复习笔记
    深入剖析Java中的装箱和拆箱

    展开全文
  • Java泛型知乎,关于原生类型

    千次阅读 2017-05-04 23:18:45
    众所周知,raw type(原生类型)这一概念是为了在Java推出泛型以后,依然兼容过去的代码所发明的。因此,我们可以得出一条推论,就是假如一个类C已经泛型化了,而你却在使用它的raw type,那说明你压根不知道它是个...
    众所周知,raw type(原生类型)这一概念是为了在Java推出泛型以后,依然兼容过去的代码所发明的。因此,我们可以得出一条推论,就是假如一个类C已经泛型化了,而你却在使用它的raw type,那说明你压根不知道它是个泛型的类,因此编译器有必要提醒你,哎这里类型需要显式转换一下。

    什么叫泛型化(generified type)呢?就以我上面贴的那段代码为例。假如它是Java 5以前创建的类,那时候一定是这么写的:

      public class SomeClass {
          List getListOfPropertyName() { ... }
      }
    

    在Java 5以后,假如它一直没有改成泛型的版本,那么调用它的人必须显式地做类型转换才能获得List<String>:

      SomeClass obj = new SomeClass();
      List<String> list = (List<String>) obj.getListOfPropertyName();
    

    假如后来这个类型后来被泛型化了:

      public class SomeClass<T> { // 类型名字不变
          List<String> getListOfPropertyName() { ... }
      }
    

    调用的人还不知道它已经泛型化了,因此还在使用raw type。那么编译器就仍然按照泛型化之前的方式,提醒你显式类型转换。


    作者:GuoGin
    链接:https://www.zhihu.com/question/58800149/answer/159649487
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    展开全文
  • Guava处理原生类型的数据

    千次阅读 2017-04-09 18:19:08
    概述Java的原生类型就是指基本类型:byte、short、int、long、float、double、char和boolean。 基本类型byte: 8位 -128~127 基本类型char char 是字符数据类型 ,是无符号型的,占2字节(Unicode码),大小范围 是0—...
  • Java的原生类型就是指基本类型:byte、short、int、long、float、double、char和boolean。 在从Guava查找原生类型方法之前,可以先查查Arrays类,或者对应的基础类型包装类,如Integer。 原生类型不能当作对象或...
  • js五种原生数据类型

    2019-08-11 21:21:30
    五种原生数据类型 Number String Boolean Null Undefined 判断数据类型 使用typeof进行判断 console.log(typeof 11); //number console.log(typeof NaN); //number console.log(typeof "aaa...
  • 数据库中常用的日期类型:日期类型存储空间日期格式日期范围date3 bytesYYYY-MM-DD1000-01-01 ~ 9999-12-31datetime8 bytesYYYY-MM-DD HH:MM:SS1000-01-01 00:00:00 ~ 9999-12-31 23:59:59timestamp4 bytes YYYY-MM...
  • java反射之dynamic invocation与原生类型

    千次阅读 2016-08-28 18:15:47
    java反射之dynamic invocation与原生类型 java中的方法参数或者返回值可能为原生类型,反射调用方法的时候,理解在反射invoke方法中如何使用原生类型很重要。  如果方法的参数为原生类型,involve方法第二个数组...
  • Java的原生数据类型(8种)

    千次阅读 2013-05-30 17:54:30
    Java 原生数据类型(8种) Java中的原生数据类型(Primitive DataType)共有8种: 1)整型: 使用int表示(32位)。 2)字节型: 使用byte表示(从-128到127之间的256个整数)。 3)短整型: 使用short表示...
  • 如题,用eclipse怎么查看呢?还是因为是封装好的,所以查看不了呢![图片说明](http://forum.csdn.net/PointForum/ui/scripts/csdn/Plugin/001/face/32.gif)
  • 原生类型 和 参数化类型

    千次阅读 2007-01-24 19:32:00
    一个原生类型很像其对应的参数化类型,但是它的所有实例成员都要被替换掉, 而替换物就是这些实例成员被擦除掉对应部分之后剩下的东西。具体地说,在一 个实例方法声明中出现的每个参数化的类型都要被其对应的原生...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 260,913
精华内容 104,365
关键字:

原生类型