一、概述

我们通过编程解决一个具体问题时,首先要做的工作是用各种“数据结构”表示问题中的实体对象,而后才能着手研究描述具体业务逻辑的算法。这也正印证了”程序 = 数据结构 + 算法“。而这里的数据结构,便对应着各种数据类型。

数据类型指的是一组值以及相关的一组操作。Java中有两大类数据类型:一类是原始(primitive)数据类型,包括boolean、int、double等等;还有一类是引用类型,也就是类(class),包括Java类库提供给我们的类和我们自己使用关键字class定义的类。Java中的类按功能来分又可以分为抽象数据类型和静态代码库。

二、原始数据类型

1. 声明与初始化

原始数据类型作为变量使用的场景主要有两种:

一是作为局部变量使用,这时我们必须声明并且初始化后才能使用,否则会报错:

public static void main() {
int a;
int b = a + 1; //错误,局部变量a没有初始化
...
}

第二种场景是作为实例变量或类变量使用,这时声明后若不初始化系统会“隐式初始化”(具体来说是整型初始化为0,浮点型初始化为0.0,布尔型初始化为false):

public class Counter {
private int id;
private int count; public Counter(int id) { //在构造器中没有显示初始化count,count在新创建的对象中会被系统隐式初始化为0
this.id = id;
}
...
}

2. 原始类型数组

    在上面我们提到过,Java中除了原始数据类型便是引用类型,因此Java中的数组是一种引用类型。引用类型与原始数据类型的本质区别在于:引用类型变量存放的是一个引用,这里的引用也就是内存地址。 考虑下面的代码片段:

...
int a = 12345;
int b = a;
b = 123456; //a的值不变,仍为12345
...
int[] d = {1, 2, 3};
int[] e = d;
e[0] = 0; //改变了e的同时也改变了d,即现在d = {0, 2, 3}
...

在上面的代码中,”int b = a"这句会创建一个a的副本,并把它赋值给b,由于是原始数据类型,所以修改b的值不会影响到a。

而“int e = d”同样也先创建一个d的副本,再把他赋值给e,然而d的值实际上是整型数组的引用(也就是地址),所以e的值也变成了同一个整型数组的地址。所以通过e对该整形数组做的改变会反映到d上。这个现象叫做起别名,也就是内存中同一个整型数组现在有不只一个变量存放着它的地址,这俩变量都能对它就行修改。

三、引用类型

正如上文提到的,Java中的引用类型变量的值是一个引用,也就是实际对象的地址。Java中的引用类型也就是我们常说的类(class),类主要有两种用途:一是用来描述一种抽象数据类型(Abstract Data Type,ADT);另一种是用来容纳一组静态方法,也就是用做静态代码库(比如,Java类库中的Math类)。

1. 内存模型

    Java中的引用类型的内存占用情况,不如原始类型来的直观。原始类型变量不需要保存除了它本身的值之外的任何信息。而一个Java对象往往占用了更多的内存,它需要保存它的所有实例变量以及一些额外信息(包括指向对象的类的引用、垃圾收集信息、同步信息)。考虑以下的Java类:

public class Rect {
private int l;
private int w;
...
}

一个Rect类型的对象在一个典型的64位机器上会占用24字节的内存,其中包括8字节的指向Rect类的引用、8字节的垃圾收集信息及同步信息和两个int类型的实例变量各占4字节。

2. 相等性

    “==”运算符对两个对象默认比较行为是检测他们的标识(即引用)是否相等。而在多数情况下,我们对两个对象相等的定义是,这两个对象的状态(各个实例变量的值)相等。要想实现这种我们想要的行为,只需要重写equals()方法。

这个方法定义在Object类(一切Java类的父类),Java标准要求这个方法的实现必须接受一个Object类型参数,并满足以下性质:

(1)自反性:即x.equals(x)必须返回true

(2)对称性:x.equals(y)与y.equals(x)的返回结果必须相同

(3)传递性:若x.equals(y), y.equals(z)均返回true,那么x.equals(z)也必须返回true

(4)一致性:若x与y引用的对象没变,那么无论多少次调用x.equals(y)都应返回一致的结果

(5)非空性:对于任何的非空引用x,x.equals(null)总是返回false

拿以上提到的Rect类为例:

public class Rect {
private int w;
private int l; public Rect(int w, int l) {
...
} public boolean equals(Object otherObject) {
if (otherObjcet == null) {
return false;
} else if (this == otherObject) {
return true; //标识相同,直接返回true
}
if (this.getClass() != otherObject.getClass()) {
return false;
}
Rect rect = (Rect) otherObject;
if ((this.getW() == rect.getW()) && ((this.getL() == rect.getL())) {
return true;
}
return false;
}
}

这里需要注意的是,在实际应用中,不同对象的相等性定义往往是具体场景而定,这里我们定义两个矩形对象相等是指两者的长和宽分别相等。

    3.不变性

    在Java中,用final修饰的数据类型具有“不变性”。而这个不变性对于原始数据类型和引用类型来说有着不同的含义。对于原始数据类型变量来说,所谓的不变性是指它的值不可改变;对于引用类型变量来说,不变性指的是它所引用的对象不可发生改变,但是它所引用的对象的内容可以改变。另外,final修饰的类不可以再派生子类。比如以下代码段:

public Class Test {
public static final int a = 5; //a的值将一直为5,不可更改
public final double[] b; //double数组对象b的标识(引用)不可边,但是它指向的double数组可以更改
...
}

【这篇博文简单的记录下自己的一些学习所得,如有不准确之处欢迎大家指正:)】

 

深入理解Java之数据类型的更多相关文章

  1. 深入理解 Java 基本数据类型

    深入理解 Java 基本数据类型

  2. Java基础系列1:深入理解Java数据类型

    Java基础系列1:深入理解Java数据类型 当初学习计算机的时候,教科书中对程序的定义是:程序=数据结构+算法,Java基础系列第一篇就聊聊Java中的数据类型. 本篇聊Java数据类型主要包括四个 ...

  3. Java内存管理-你真的理解Java中的数据类型吗(十)

    勿在流沙筑高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 作为Java程序员,Java 的数据类型这个是一定要知道的! 但是不管是那种数据类型最 ...

  4. 《深入理解 java虚拟机》学习笔记

    java内存区域详解 以下内容参考自<深入理解 java虚拟机 JVM高级特性与最佳实践>,其中图片大多取自网络与本书,以供学习和参考.

  5. 深入理解Java:注解

    注解作用:每当你创建描述符性质的类或者接口时,一旦其中包含重复性的工作,就可以考虑使用注解来简化与自动化该过程. Java提供了四种元注解,专门负责新注解的创建工作. 元注解 元注解的作用就是负责注解 ...

  6. 理解Java虚拟机体系结构

    1 概述 众所周知,Java支持平台无关性.安全性和网络移动性.而Java平台由Java虚拟机和Java核心类所构成,它为纯Java程序提供了统一的编程接口,而不管下层操作系统是什么.正是得益于Jav ...

  7. 理解Java中的引用传递和值传递

    关于Java传参时是引用传递还是值传递,一直是一个讨论比较多的话题,有论坛说Java中只有值传递,也有些地方说引用传递和值传递都存在,比较容易让人迷惑.关于值传递和引用传递其实需要分情况看待,今天学习 ...

  8. (6) 深入理解Java Class文件格式(五)

    前情回顾 本专栏的前几篇博文, 对class文件中的常量池进行了详细的解释. 前文讲解了常量池中的7种数据项, 它们分别是: CONSTANT_Utf8_info CONSTANT_NameAndTy ...

  9. (5) 深入理解Java Class文件格式(四)

    转载:http://blog.csdn.net/zhangjg_blog/article/details/21658415 前情回顾   在上一篇博客深入理解Java Class文件格式(三) 中, ...

随机推荐

  1. 使用Scala开发Apache Kafka的TOP 20大好用实践

    本文作者是一位软件工程师,他对20位开发人员和数据科学家使用Apache Kafka的方式进行了最大限度得深入研究,最终将生产实践环节需要注意的问题总结为本文所列的20条建议. Apache Kafk ...

  2. python3 练习题100例 (二)

    题目二:企业发放的奖金根据利润提成.利润(I)低于或等于10万元时,奖金可提10%:利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可提成7.5%:20万到40万 ...

  3. ruby中的字符串分隔符--split

    当字符串是以“:”隔开时,可以这样写: column = str.split(/:/) 这样,column就是字符串每栏的值所构成的数组. eg: str = "Ruby in a shel ...

  4. C语言#ifdef等宏的妙用

    这几个宏是为了进行条件编译.一般情况下,源程序中所有的行都参加编译.但是有时希望对其中一部分内容只在满足一定条件才进行编译,也就是对一部分内容指定编译的条件,这就是“条件编译”.有时,希望当满足某条件 ...

  5. C#LINQ集合操作

    LINQ的集合运算 List<int> lstOne = new List<int>() { 1, 55, 223, 25 }; List<int> lstTwo ...

  6. Excelファイルを扱う方法

    概要 データをローカルに落としたいという要件がある場合.ユーザーはExcelを希望するケースが多いだろう.そんな時は以下の汎用モジュールを使用して簡単に作る事ができます.使用方法は.GUI_UPLOA ...

  7. 使用JAX-WS(JWS)发布WebService(一)

    JAX-WS概述: 通过Main发布一个简单WebService: JAX-WS(Java API for XML Web Services)规范是一组XML web services的JAVA AP ...

  8. 【8086汇编-Day8】实验九

    Lab1 代码 ; 在屏幕上输出内存单元中的十进制两位数 assume cs:code, ds:data data segment db db , ; 前一个字节用于保存商,后一个字节用于保存余数 d ...

  9. 利用cross-entropy cost代替quadratic cost来获得更好的收敛

    1.从方差代价函数说起(Quadratic cost) 代价函数经常用方差代价函数(即采用均方误差MSE),比如对于一个神经元(单输入单输出,sigmoid函数),定义其代价函数为: 其中y是我们期望 ...

  10. 武汉Uber优步司机奖励政策(1月11日~1月17日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...