知识屋:更实用的电脑技术知识网站
所在位置:首页 > 科技

Java 程序员面试笔试宝典 第 4 章 Java 基础知识:4.4 基本类型与运算

发表时间:2022-03-26来源:网络

4.4.1 Java 提供了哪些基本数据类型

Java 语言一共提供了 8 种原始的数据类型(byte,short,int,long,float,double,char,boolean),这些数据类型不是对象,而是 Java 语言中不同于类的特殊类型,这些基本类型的数据变量在声明之后就会立刻在栈上被分配内存空间。除了这 8 种基本的数据类型外,其他类型都是引用类型(例如类、接口、数组等),引用类型类似于 C++ 中的引用或指针的概念,它以特殊的方式指向对象实体,这类变量在声明时不会被分配内存空间,只是存储了一个内存地址而已。

原始数据类型在传递参数时都是按值传递,而封装类型是按引用传递的。其次,当封装类型和原始类型用作某个类的实例数据时,它们所指定的默认值不同。对象引用实例变量的默认值为 null,而原始类型实例变量的默认值与它们的类型有关(例如 int 默认初始化为 0)

除了以上需要注意的内容外,在 Java 语言中,默认声明的小数是 double 类型的,因此在对 float 类型的变量进行初始化时需要进行类型转换。float 类型的变量有两种初始化方法:float f=1.0f 或 float f=(float)1.0

引申:

1.在 Java 语言中 null 值是什么?在内存中 null 是什么?

null 不是一个合法的 Object 实例,所以编译器并没有为其分配内存,它仅仅用于表明该引用目前没有指向任何对象。

2.如何理解赋值语句 String x=null?

在 Java 语言中,变量被分为两大类型:原始值(primitive)与引用值(reference)。声明为原始类型的变量,其存储的是实际的值。声明为引用类型的变量,存储的是实际对象的地址(指针,引用)。

3.赋值语句 float f=3.4 是否正确?

答案:不正确。数据 3.4 默认情况下是 double 类型,即双精度浮点数,将 double 类型数值赋值给 float 类型的变量,会造成精度损失,因此需要对其进行强制类型转换,即将 3.4 转换成 float 类型或者将 3.4 强制写成 float 类型。所以,float f=(float)3.4 或者 float f=3.4F 写法都是可以的。

4.4.2 什么是不可变类

不可变类(immutable class)是指当创建了这个类的实例后,就不允许修改它的值了,也就是说,一个对象一旦被创建出来,在其整个生命周期中,它的成员变量就不能被修改了。它有点类似于常量(const),即只允许别的程序读,不允许别的程序进行修改。

在 Java 类库中,所有基本类型的包装类都是不可变类,例如 Integer、Float 等。此外,String 也是不可变类。

下面主要介绍如何创建一个不可变类。通常来讲,创建一个不可变类需要遵循下面 几条基本原则:

1)类中所有成员变量被 private 所修饰。

2)类中没有写或者修改成员变量的方法,例如 setxxx,只提供构造函数,一次生成,永不改变。

3)确保类中所有方法不会被子类覆盖,可以通过把类定义为 final 或者把类中的方法定义为 final 来达到这个目的。

4)如果一个类成员不是不可变量,那么在成员初始化或者使用 get 方法获取该成员变量时,需要通过 clone 方法来确保类的不可变性。

如果有必要,可使用覆盖 Object 类的 equals()方法和 hashCode()方法。在 equals()方法中,根据对象的属性值来比较两个对象是否相等,并且保证用 equals()方法判断为相等的两个对象的 hashCode()方法的返回值也相等,这可以保证这些对象能被正确地放到 HashMap 或 HashSet 集合中。

Java 语言中之所以设计有很多不可变类,主要是不可变类具有使用简单、线程安全、节省内存等优点。

 

4.4.3 值传递与引用传递有哪些区别

方法调用是编程语言中非常重要的一个特性,在方法调用时,通常需要传递一些参数来完成特定的功能。Java 语言提供了两种参数传递的方式:值传递和引用传递。

(1)值传递

在方法调用中,实参会把它的值传递给形参,形参只是用实参的值初始化一个临时的存储单元,因此形参与实参虽然有着相同的值,但是却有着不同的存储单元,因此对形参的改变不会影响实参的值。

(2)引用传递

在方法调用中,传递的是对象(也可以看作是对象的地址),这时形参与实参的对象指向同一块存储单元,因此对形参的修改就会影响实参的值。

在 Java 语言中,原始数据类型在传递参数时都是按值传递,而包装类型在传递参数时是按引用传递的。

常见笔试题:

下列说法中,正确的是( )。

A.call by value 不会改变实际参数的值              B.call by reference 能改变实际参数

C.call by reference 不能改变实际参数的地址   D.call by reference 能改变实际参数的内容

答案:A、C、D。见上面讲解。

 

 

 

4.4.4 不同数据类型的转换有哪些规则

在 Java 语言中,当参与运算的两个变量的数据类型不同时,就需要进行隐式的数据类型转换,转换的规则为:从低精度向高精度转换,即优先级满足 byte<short<char<int<long<float<double,例如,不同数据类型的值在进行运算时,short 类型数据能够自动转为 int 类型,int 类型数据能够自动转换为 float 类型等。反之,则需要通过强制类型转换来实现。

在 Java 语言中,类型转换可以分为以下几种类型:

(1)类型自动转换

低级数据类型可以自动转换为高级数据类型,表 4-3 给出了常见的自动类型转换的规则。

 

当类型自动转换时,需要注意以下几点:

1)char 类型的数据转换为高级类型(如 int,long 等),会转换为其对应的 ASCII 码。

2)byte、char、short 类型的数据在参与运算时会自动转换为 int 型,但当使用「+=」运算时,就不会产生类型的转换(将在下一节中详细介绍)。

3)另外,在 Java 语言中,基本数据类型与 boolean 类型是不能相互转换的。

总之,当有多种类型的数据混合运算时,系统会先自动地将所有数据转换成容量最大的那一种数据类型,然后再进行计算。

(2)强制类型转换

当需要从高级数据类型转换为低级数据类型时,就需要进行强制类型转换,表 4-4 给出了强制类型转换的规则。

需要注意的是,在进行强制类型转换时可能会损失精度。

对于下述代码结果强制类型转换后,变量 a 和 b 的值分别为( )。

short a=128;

byte b=(byte)a

答案:a=128,b=-128。short 类型变量占两个字节,a 对应的二进制为:00000000 10000000,由于 byte 只占一个字节,在强制转换为 byte 的时候只截取低字节:10000000,10000000 是-128 的补码,因此 b 的值为-128。

4.4.5 强制类型转换的注意事项有哪些

Java 语言在涉及 byte、short 和 char 类型的运算时,首先会把这些类型的变量值强制转换为 int 类型,然后对 int 类型的值进行计算,最后得到的值也是 int 类型。因此,如果把两个 short 类型的值相加,最后得到的结果是 int 类型;如果把两个 byte 类型的值相加,最后也会得到一个 int 类型的值。如果需要得到 short 类型的结果,就必须显式地把运算结果转换为 short 类型,例如对于语句 short s1=1;s1=s1+1,由于在运行时会首先将 s1 转换成 int 类型,因此 s1+1 的结果为 int 类型,这样编译器会报错,所以,正确的写法应该 short s1=1;s1=(short)(s1+1)

4.4.6 运算符优先级是什么

Java 语言中有很多运算符,由于运算符优先级的问题经常会导致程序出现意想不到的结果,表 4-5 详细介绍了运算符的优先级。

 

在实际使用时,如果不确定运算符的优先级,最好运用括号运算符来控制运算顺序。

4.4.7 Math 类中 round、ceil 和 floor 方法的功能各是什么

round、ceil 和 floor 方法位于 Math 类中,Math 是一个包含了很多数学常量与计算方法的类,位于 java.lang 包下,能自动导入,而且 Math 类里边的方法全是静态方法。下面重点介绍这 3 个方法代表的含义。

1)round 方法表示四舍五入。round,意为「环绕」,其实现原理是在原来数字的基础上先增加 0.5 然后再向下取整,等同于(int)Math.floor(x+0.5f)。它的返回值类型为 int 型,例如,Math.round(11.5)的结果为 12,Math.round(-11.5)的结果为-11。

2)ceil 方法的功能是向上取整。ceil,意为「天花板」,顾名思义是对操作数取顶,Math.ceil(a),就是取大于 a 的最小的整数值。需要注意的是,它的返回值类型并不是 int 型,而是 double 型。若 a 是正数,则把小数「入」,若 a 是负数,则把小数「舍」。

3)floor 方法的功能是向下取整。floor,意为「地板」,顾名思义是对操作数取底。Math.floor(a),就是取小于 a 的最大的整数值。它的返回值类型与 ceil 方法一样,也是 double 型。若 a 是正数,则把小数「舍」;若 a 是负数,则把小数「入」。

 

 

4.4.9 如何实现无符号数的右移操作

此外,需要特别注意的是,在对 char、byte、short 等类型的数进行移位操作前,编译器都会自动地将数值转化为 int 类型,然后才进行移位操作。由于 int 型变量只占 4Byte(32bit),因此当右移的位数超过 32bit 时,移位运算没有任何意义。所以,在 Java 语言中,为了保证移动位数的有效性,以使右移的位数不超过 32bit,采用了取余的操作,即

 

 

在 Java 语言中,默认使用的 Unicode 编码方式,即每个字符占用两个字节,因此可以用来存储中文。虽然 String 是由 char 所组成的,但是它采用了一种更加灵活的方式来存储,即英文占用一个字符,中文占用两个字符,采用这种存储方式的一个重要作用就是可以减少所需的存储空间,提高存储效率。 

收藏
  • 人气文章
  • 最新文章
  • 下载排行榜
  • 热门排行榜