Java基础01 数据类型和运算符

  • 什么是数据类型呢?为什么需要数据类型呢?

    熟悉了Java的基本语法后我们可能已经习惯了数据类型这一观念,那么我们是否想过为什么会有数据类型呢?

    说说我的理解。构成世界需要一种最基本的元素或者单位,这是一种哲学观点。数据在计算机中采用二进制进行表达,那么就可以说二进制位是表达数据的最基本的单位,当然最基本的存储单位是字节。我们编程的时候,也需要一个基本的单位,或者说构成我们编程世界的基本元素,它就是数据类型。每种语言的设计者们都有他们自己的世界观,在Java中,编程世界就是由数字、字符、布尔这三大基本类型所组成,其他的所有类型都是它们的有机组成而已。所以说数据类型就是编程世界的基本元素,他规定了一个变量的存储方式,也就规定了一个变量可以表示什么样的数据,这使得编程更加富有结构性和逻辑性。

  • 什么是变量呢?
    目前阶段我们可以简单地认为变量存储在栈空间中,每个变量名对应栈空间的一块内存的地址,这块空间存储变量的值

  • 基本数据类型——变量存储数据本身
注:boolean单独使用时被JVM解析为 int,boolean数组被解析为byte数组
  • 引用类型——变量存储地址 

  • 比较基本类型和引用类型
    • 存储类型差异:基本类型的变量在栈空间中直接存储数据本身,引用类型变量在栈空间中存储对象实例的堆空间地址
    •  内存分配:声明变量的时候,无论是基本类型还是引用类型,变量在栈空间的内存大小就可以确定了;基本类型可以根据其所需字节数分配空间(其实是分配槽);引用类型存储的是地址,而存储地址所需空间大小根据不同机器的不同而不同,但也是确定的。引用类型变量在编译时并不确定存储的地址值,因为在堆空间为对象开辟空间的操作是在运行时发生的,所以当开辟完堆空间后引用类型变量才会被赋值地址值(我认为这极大的增强了语言的灵活性,比如在Java中我们可以用变量指定数组长度就是基于此原理)
    • 关于赋值:其实赋值无非就是将一个变量保存的值拷贝到另一个变量的内存空间,这无关于基本类型还是引用类型,知道了这个道理,关于赋值导致的等值判断就没什么

  • 数组
    • 数组类型属于引用类型,存储第一个元素的地址
    • 数组的一个重要特性是声明时确定所存储的元素类型,案例分析:
      A[] arr = new A[10];
      arr = new B[10];//B是A的子类
      arr[0] = new A();
      声明数组时,编译器会认为数组中每一个元素都是A类型;而子类数组赋值给基类数组在Java中是允许的,毕竟也是多态性的体现;这时arr[0]实际上是B类型的引用,但编译器仍认为它是A类型的引用,所以最后的赋值在编译期不会报错,运行时就会ArrayStoreEXception(类型擦除会导致这种机制出现有意思的问题,在Java基础06  泛型中讨论)
  •  一些容易出错的运算符
    • == 运算符 : 比较两个变量保存的值是否相等,所以才有“对象比较时比较的是对象在堆空间的地址”
    • 三元运算符:布尔值?表达式1:表达式2 
      • 从前往后执行
      • 两个表达式需要类型匹配,自动将表达式的返回值向高精度转换
      • 据我测试,包装类在三元运算符中并不一定会自动拆箱,而是当一个表达式中需要自动拆箱的时候,另一个表达式依据类型匹配和是否需要执行决定是否拆箱,本质上还是类型匹配
        Integer n1 = 1;
        Integer n2 = null;
        System.out.println(true ? n1 : n2);//正确,没有自动拆箱
        System.out.println(false ? n1 : n2);//正确,没有自动拆箱
        System.out.println(true ? n1 * 2 : n2);//正确,表达式1自动拆箱,表达式2没有执行本应该自动拆箱但没有执行到
        System.out.println(true ? n1 : n2 * 2);//正确,表达式二本应该因为自动拆箱报错,但没机会执行
        System.out.println(false ? n1 * 2: n2);//错误,表达式1执行自动拆箱,表达式2由于类型匹配也执行自动拆箱导致空指针异常

西瓜要挖着吃

一个通往大佬之路的男人

You may also like...

发表评论

电子邮件地址不会被公开。 必填项已用*标注