Java 变量之变量数据类型

简介: Java 变量之变量数据类型

Java数据类型图:

20160826103646745.jpg

1.基本数据类型


基本数据类型,也称内置类型,是可以在栈直接分配内存的,Java保留基本数据类型最大的原因也在此:性能。关于这一点可以参考:Java为什么需要保留基本数据类型。

 另外,要注意,Java是基于JVM的,所以,其所占字节固定,与机器平台无关,所有地方统一占用内存大小(除了boolean,以及byte/short/boolean数组的时候每个单元所占的内存是由各个JVM自己实现的)。

 总共有四类八种基本数据类型(注1):

1).整型:全部是有符号类型。

1.byte:1字节(8bit),高位为符号位,其余7位为数据位,范围:-2的7次方~2的7次方-1(1111,1111~0111,1111),即-128~127(下面的计算方式相同);


<span style="color:#000000"><span style="background-color:#f6f8fa"><code>注意:<span style="color:#000088 !important">byte</span>类型虽然在语义(逻辑)上是占用<span style="color:#006666 !important">1</span>字节,但实际上,JVM中是将其当做<span style="color:#000088 !important">int</span>看
的,也就是事实上是占用了<span style="color:#006666 !important">32</span>位,<span style="color:#006666 !important">4</span>字节的,所以其运算效率和<span style="color:#000088 !important">int</span>没区别,<span style="color:#000088 !important">short</span>也一样。
之所以要有<span style="color:#000088 !important">byte</span>/<span style="color:#000088 !important">short</span>类型,一是因为某些地方要明确使用这些范围类型,二是,
在<span style="color:#000088 !important">byte</span>[]数组中,JVM存储的则是真的<span style="color:#006666 !important">1</span>字节,<span style="color:#000088 !important">short</span>[]<span style="color:#006666 !important">2</span>字节。(但也有的JVM其<span style="color:#000088 !important">byte</span>[]
数组也是<span style="color:#006666 !important">4</span>字节<span style="color:#006666 !important">1</span>位)</code></span></span>


2.short:2字节(16bit),高位为符号位,其余15位为数据位,范围:-2的15次方~2的15次方-1,即-32768~32767;

3.int:4字节(32bit),范围-2的31次方~2的31次方-1;Java默认的整型类型,即:


<span style="color:#000000"><span style="background-color:#f6f8fa"><code><span style="color:#000088 !important">long</span> l = <span style="color:#006666 !important">0xfffffffffff</span>;<span style="color:#880000 !important"><em>//0x表示这个数是16进制数,0表示8进制。</em></span>
<span style="color:#880000 !important"><em>//编译器报错,因为右边默认是int,但其超出了范围(没超出int范围的话</em></span>
<span style="color:#880000 !important"><em>//编译器会隐式将int转为long),故报错(同样的错误也会出现在float)。</em></span></code></span></span>


同样的还有:


<span style="color:#000000"><span style="background-color:#f6f8fa"><code><span style="color:#000088 !important">short</span> s = <span style="color:#006666 !important">123</span>;<span style="color:#880000 !important"><em>//(这个123也是int类型,这里,= 操作编译器能隐式转换) </em></span>
s = s + <span style="color:#006666 !important">123</span>;<span style="color:#880000 !important"><em>//编译器报错,那是因为s+1是int类型(编译器先将s转化为int,再+1),</em></span>
<span style="color:#880000 !important"><em>//这里,+ 操作编译器不能隐式转换(会提示失真,即精度可能会受损),正确的做法:</em></span>
s = (<span style="color:#000088 !important">short</span>)(s + <span style="color:#006666 !important">123</span>)<span style="color:#880000 !important"><em>//注意,不是(short)s + 123。</em></span></code></span></span>


类型转化详见:Java 数据类型转化

4.long:8字节(64bit),范围:-2的63次方~2的63次方-1;声明大的long方法:


<span style="color:#000000"><span style="background-color:#f6f8fa"><code><span style="color:#000088 !important">long</span> l = <span style="color:#006666 !important">0xfffffffffff</span>L;<span style="color:#880000 !important"><em>//即在后面加上L或l。</em></span>
<span style="color:#880000 !important"><em>//(强制转化:long l = (long)0xfffffffffff也没用)</em></span></code></span></span>


2).浮点型

5.float:4字节(32bit),单精度,数据范围:(-2^128)~(-2^(-23-126))-(0)-(2^-149)~2^128。浮点数,通俗来说就是小数,但是,这是有精度要求的,即在这区间float可不是能表达任意小数的,而是在一定精度下,比如float有效位7~8位(包括整数位和小数位,有效小数位是6~7位,这里为什么是7~8(6~7),参考:Java中float/double取值范围与精度),即0.123456789后面的9JVM是不认识的(8能认识,整数位为0则不算是有效位,例如12.1234567后面的7也不认识,只有6位有效小数位(注意,看的是有效位,不是有效小数位,float有7~8位有效位)),即:


<span style="color:#000000"><span style="background-color:#f6f8fa"><code><span style="color:#000088 !important">if</span>(<span style="color:#006666 !important">0.123456781</span>f == <span style="color:#006666 !important">0.123456789</span>f){<span style="color:#880000 !important"><em>//注意后面加f/F,否则就是double</em></span>
    System.<span style="color:#000088 !important">out</span>.println(<span style="color:#009900 !important">"true"</span>);
}<span style="color:#000088 !important">else</span>{
    System.<span style="color:#000088 !important">out</span>.println(<span style="color:#009900 !important">"false"</span>);
}
<span style="color:#880000 !important"><em>//打印结果:true</em></span>
<span style="color:#880000 !important"><em>//事实上,浮点数值的比较是不能直接用==判断的,这里原因就要追究到浮点数的内存结构</em></span>
<span style="color:#880000 !important"><em>//浮点数比较可以用一个差值,但这种情况只是近似的比较</em></span>
<span style="color:#880000 !important"><em>//如果想要精确,可以使用BigDecimal</em></span>
System.<span style="color:#000088 !important">out</span>.println(Float.MIN_VALUE);<span style="color:#880000 !important"><em>//1.4E-45 = 2^-149</em></span>
<span style="color:#880000 !important"><em>//这里的“最小值”意味float能表示的最小小数,实际上float最小值等于最大值取负</em></span>
System.<span style="color:#000088 !important">out</span>.println(Float.MAX_VALUE);<span style="color:#880000 !important"><em>//3.4028235E38 = 2^128</em></span></code></span></span>


6.double:8字节(64bit),双精度,范围:-2^1024~(-2^(-1022-52))-0-(2^-1074)~2^1024,Java默认的浮点类型,即若后面不加f/F,默认是double类型,即:


<span style="color:#000000"><span style="background-color:#f6f8fa"><code><span style="color:#000088 !important">float</span> f = <span style="color:#006666 !important">1.23</span>;<span style="color:#880000 !important"><em>//编译报错,因为</em></span>
<span style="color:#000088 !important">float</span> f = <span style="color:#006666 !important">1.23f</span>;<span style="color:#880000 !important"><em>//或float f = 1.23F;</em></span>
<span style="color:#880000 !important"><em>//默认是double,1.23(double)转成float,做隐式转换,但是double转成float是</em></span>
<span style="color:#880000 !important"><em>//取值范围大的转成取值范围小的会损失精度,因此不能转换(详见Java数据类型转换)</em></span>
<span style="color:#880000 !important"><em>//那为什么,int可以转换成byte、short,int范围更大不是?</em></span>
<span style="color:#880000 !important"><em>//前面已经说过了,byte、short实际在JVM上就是int,因此编译器是不会认为会损失精度的</em></span>
<span style="color:#880000 !important"><em>//但是int是不能转换成boolean,虽然boolean也是4字节(一般JVM),但在JVM认为这</em></span>
<span style="color:#880000 !important"><em>//两者完全是两个东西,当然不能转换(强制也不行,你不能把猫强制转换成鸟,完全两个物种),而byte、short都是整型,同int是一个类型</em></span></code></span></span>


3).字符型

7.char:2字节(16bit),表示一个字符(可以是汉字),字符编码采用Unicode(说的更准确点,字符集(charset)采用UCS-2,编码(encoding)采用UTF-16),实际上就是一个16位的无符号整型,但是,要注意的是,因为随着发展,char所能代表的字符个数(UCS-2字符集)被限定死了,所以并不推荐使用。(更多内容,以及关于Unicode、UTF8/16参考:Unicode、UTF8以及Java char。)


<span style="color:#000000"><span style="background-color:#f6f8fa"><code><span style="color:#000088 !important">char</span> c = <span style="color:#006666 !important">3</span>+<span style="color:#006666 !important">5</span>;<span style="color:#880000 !important"><em>//正确,char是无符号整型,但不能这样</em></span>
<span style="color:#000088 !important">int</span> a1 = <span style="color:#006666 !important">3</span>;<span style="color:#000088 !important">int</span> a2 = <span style="color:#006666 !important">5</span>;<span style="color:#000088 !important">char</span> c0 = a1+a2;<span style="color:#880000 !important"><em>//这里需要强制转换才行</em></span>
<span style="color:#000088 !important">char</span> c1 = -<span style="color:#006666 !important">3</span>;<span style="color:#880000 !important"><em>//编译错误,char不能表示负数,即使</em></span>
<span style="color:#000088 !important">char</span> c2 = (<span style="color:#000088 !important">char</span>)-<span style="color:#006666 !important">3</span>;<span style="color:#880000 !important"><em>//编译正确,但无意义(乱码)</em></span>
<span style="color:#000088 !important">char</span> c3 = <span style="color:#009900 !important">'3'</span>;<span style="color:#880000 !important"><em>//正确,输出字符3</em></span>
<span style="color:#000088 !important">char</span> c4 = <span style="color:#009900 !important">"3"</span>;<span style="color:#880000 !important"><em>//编译错误,双引号,表示的是字符串</em></span>
<span style="color:#000088 !important">char</span> c5 = <span style="color:#009900 !important">'65'</span>;<span style="color:#880000 !important"><em>//编译错误,这里65是两个字符</em></span></code></span></span>


4).布尔型

8.boolean:逻辑上:1bit,但是实际上,boolean并没有具体规定,完全是看各个JVM实现,不过《Java虚拟机规范》给出了4个字节(同byte解释)和boolean数组一个字节的定义。


注1:

(1).这种分法是一种比较流行的分法,事实上应该为两种:数值类型与布尔型。数值类型分为整型和浮点型。整型包括:byte、short、int、long、char;浮点型:float、double;布尔型boolean。之所以将char认为是整型是因为char在JVM就是以无符号整型存在的。

(2).事实上Java中除去这8种以及对象类型,还有一种比较特殊的类型存在,那就是Void。java.lang.Void,是一个占位符类,不可实例化,保存着Java关键字void的Class对象。为什么说它特殊呢?明明是一个类,难道不是对象类型?那是因为void.class.isPrimitive()(这个方法是用来判断一个Class对象是否是基本类型的)返回的是true,所以Void也算是基本类型的一个了(错了),只不过它比较特殊,不能算是一种数据,只是一种象征。

20160921 改:上面弄错了,把Void和void两个混为一体了,事实上,可以简单的把这两者的关系看成类似包装类和基本类型的关系,像Integer和int的关系,java.lang.Void是一个不可实例化的占位符类来保存一个引用代表了Java关键字void的Class对象:


<span style="color:#000000"><span style="background-color:#f6f8fa"><code><span style="color:#000088 !important">public</span> <span style="color:#000088 !important">static</span> <span style="color:#000088 !important">final</span> Class<Void> TYPE = Class.getPrimitiveClass(<span style="color:#009900 !important">"void"</span>);</code></span></span>


而Integer也有类似的语句:


<span style="color:#000000"><span style="background-color:#f6f8fa"><code><span style="colo



区别只是,Void仅仅是为void服务,即所谓的占位符类,不做他用。所以Void类只是一个普通类,而void则可以认作为如同int一样的基本类型。


2.引用数据类型


 也称对象变量类型,复合数据类型,包含类、接口、数组(除了基本类型外,就是引用类型)。引用类型与基本类型最大的区别在于:


<span style="color:#000000"><span style="background-color:#f6f8fa"><code><span style="color:#000088 !important">int</span> a = <span style="color:#006666 !important">5</span>;<span style="color:#880000 !important"><em>//这里的a是对象(严格来说不算是对象,只是个符号标识),5是数值</em></span>
Integer a = <span style="color:#006666 !important">5</span>;<span style="color:#880000 !important"><em>//这里的a是一个引用,5才是一个对象,更形象常见的是:</em></span>
<span style="color:#4f4f4f !important">Object</span> o = <span style="color:#000088 !important">new</span> <span style="color:#4f4f4f !important">Object</span>();<span style="color:#880000 !important"><em>//o是引用(栈中),new Object()是对象(堆中)</em></span>
<span style="color:#880000 !important"><em>//第二行代码中,5被自动包装成Integer对象</em></span></code></span></span>


  这里的引用有点像C/C ++中的指针,但是同指针不同的是,你不能通过改变它的值从而去改变它所指向的值。即


<span style="color:#000000"><span style="background-color:#f6f8fa"><code>ClassA p = <span style="color:#000088 !important">new</span> ClassA();<span style="color:#880000 !important"><em>//C++中,这个时候是可以这样操作的:</em></span>
p = p + <span style="color:#006666 !important">1</span>;<span style="color:#880000 !important"><em>//向前移动一个单元,Java则不能</em></span>
<span style="color:#880000 !important"><em>//这种操作,其实是对内存直接的操作,很显然,Java是不允许程序员做这种操作的</em></span></code></span></span>


其实质就是,Java的引用不支持对内存直接操作,而指针则可以,所以,Java用起来更安全,但不够灵活,而指针,自由度大,但同时,要更加小心因为指针操作不当而引起的各种内存问题。在Java中,任何对象都需要通过引用才能访问到,没有引用指向的对象被视为垃圾对象,将会被回收。

 引用,其实质同指针一样(可以理解为受限制的指针),存放的是一个地址,至于是实例对象的地址,还是一个指向句柄池的地址(这里可以参考:(3) Java内存结构),完全是看各个JVM的实现了。

 Java中的枚举类型,都是Enum类的子类,算是类中的一种,也是引用类型。

 引用类型又称为对象变量类型,是相对于基本数据类型来说的(基本数据类型不是对象),而又被称为复合数据类型,可以这样理解,引用类型的数据最终都是由基本数据类型构成的。而像接口,接口是不能实例化的,最终的实现还是由类实现的;数组在JVM中的实现也是通过类实现的,每个类型的一维数组,二维数组……都是一个类,只是这是一个特殊的类,它的对象头有别于一般对象的对象头(最主要的就是,数组对象头有对象长度)。

 另外,关于Java引用可以参考:Java中的引用。

目录
相关文章
|
9天前
|
Java 程序员 容器
Java中的变量和常量:数据的‘小盒子’和‘铁盒子’有啥不一样?
在Java中,变量是一个可以随时改变的数据容器,类似于一个可以反复打开的小盒子。定义变量时需指定数据类型和名称。例如:`int age = 25;` 表示定义一个整数类型的变量 `age`,初始值为25。 常量则是不可改变的数据容器,类似于一个锁死的铁盒子,定义时使用 `final` 关键字。例如:`final int MAX_SPEED = 120;` 表示定义一个名为 `MAX_SPEED` 的常量,值为120,且不能修改。 变量和常量的主要区别在于变量的数据可以随时修改,而常量的数据一旦确定就不能改变。常量主要用于防止意外修改、提高代码可读性和便于维护。
|
1月前
|
Java 编译器
java“变量 x 可能未被初始化”解决
在Java中,如果编译器检测到变量可能在使用前未被初始化,会报“变量 x 可能未被初始化”的错误。解决方法包括:1. 在声明变量时直接初始化;2. 确保所有可能的执行路径都能对变量进行初始化。
|
2月前
|
Java
java基础(8)数据类型的分类
Java数据类型分为基本数据类型(8种)和引用数据类型。基本类型包括byte, short, int, long, float, double, boolean, char。每种类型有固定占用空间大小,如int占用4字节。字符编码如ASCII和Unicode用于将文字转换为计算机可识别的二进制形式。
72 2
|
2月前
|
存储 Java
java基础(7)变量以及变量的分类
Java变量是内存中存储数据的基本单元,包含数据类型、名称和字面值。变量的数据类型决定了分配的内存空间大小。变量声明格式为“数据类型 变量名;”,变量名应符合标识符命名规范。变量可以重新赋值,但数据类型需一致。变量可以一行声明多个,作用域决定了变量的可用范围。变量分为局部变量和成员变量,局部变量定义在方法体内,成员变量定义在方法体外、类体内。
40 2
|
16天前
|
Java 编译器
Java重复定义变量详解
这段对话讨论了Java中变量作用域和重复定义的问题。学生提问为何不能重复定义变量导致编译错误,老师通过多个示例解释了编译器如何区分不同作用域内的变量,包括局部变量、成员变量和静态变量,并说明了使用`this`关键字和类名来区分变量的方法。最终,学生理解了编译器在逻辑层面检查变量定义的问题。
Java重复定义变量详解
|
12天前
|
存储 缓存 Java
大厂面试必看!Java基本数据类型和包装类的那些坑
本文介绍了Java中的基本数据类型和包装类,包括整数类型、浮点数类型、字符类型和布尔类型。详细讲解了每种类型的特性和应用场景,并探讨了包装类的引入原因、装箱与拆箱机制以及缓存机制。最后总结了面试中常见的相关考点,帮助读者更好地理解和应对面试中的问题。
37 4
|
10天前
|
存储 消息中间件 NoSQL
使用Java操作Redis数据类型的详解指南
通过使用Jedis库,可以在Java中方便地操作Redis的各种数据类型。本文详细介绍了字符串、哈希、列表、集合和有序集合的基本操作及其对应的Java实现。这些示例展示了如何使用Java与Redis进行交互,为开发高效的Redis客户端应用程序提供了基础。希望本文的指南能帮助您更好地理解和使用Redis,提升应用程序的性能和可靠性。
24 1
|
25天前
|
Java
通过Java代码解释成员变量(实例变量)和局部变量的区别
本文通过一个Java示例,详细解释了成员变量(实例变量)和局部变量的区别。成员变量属于类的一部分,每个对象有独立的副本;局部变量则在方法或代码块内部声明,作用范围仅限于此。示例代码展示了如何在类中声明和使用这两种变量。
|
25天前
|
存储 Java 关系型数据库
[Java]“不同族”基本数据类型间只能“强转”吗?
本文探讨了不同位二进制表示范围的计算方法,重点分析了Java中int和char类型之间的转换规则,以及float与int类型之间的转换特性。通过具体示例说明了显式和隐式转换的条件和限制。
33 0
[Java]“不同族”基本数据类型间只能“强转”吗?
|
2月前
|
存储 Java Windows
java基础(9)数据类型中的char类型以及涉及到的转义字符
Java中的char类型可以存储一个中文字符,因为它占用两个字节。转义字符允许在代码中使用特殊字符,例如`\n`表示换行,`\t`表示制表符,`\\`表示反斜杠,`\'`表示单引号,`\"`表示双引号。可以使用`\u`后跟Unicode编码来表示特定的字符。
56 2
java基础(9)数据类型中的char类型以及涉及到的转义字符