面试(1)——Java 数据类型和语法基础
Java 语法是 Java 编程的根基,掌握好 Java 语法基础,能为后续深入学习 Java 编程打下坚实的基础。本文将围绕 Java 语法基础的各个核心模块展开讲解,帮助你全面理解 Java 语法的核心要点。
一、数据类型
(一).基本数据类型:简单数据的直接表示
基本数据类型是 Java 预先定义好的、不可再分的简单数据类型,用于直接存储简单的数据值。Java 共有 8 种基本数据类型,可分为整数类型、浮点类型、字符类型和布尔类型。
(1)整数类型
整数类型用于表示没有小数部分的整数,包括 byte
、short
、int
、long
四种。
byte
:字节类型,是 Java 中最小的整数类型,占用 1 个字节(8 位),取值范围是-128
到127
。由于其取值范围小,通常用于节省内存空间的场景,比如在处理大量字节数据(如文件读写、网络传输中的字节流)时。short
:短整型,占用 2 个字节(16 位),取值范围是-32768
到32767
。它比byte
能表示的数值范围大一些,但在实际开发中,使用频率不如int
高,不过在一些对内存要求较为严格,且数值范围又超过byte
所能表示的场景下会用到,例如某些硬件设备的通信数据。int
:整型,是 Java 中最常用的整数类型,占用 4 个字节(32 位),取值范围是-2147483648
到2147483647
。在处理一般的整数计算、数组索引等场景时,int
是默认的选择。long
:长整型,占用 8 个字节(64 位),取值范围是-9223372036854775808
到9223372036854775807
。当需要表示的整数范围超过int
所能容纳的范围时,就需要使用long
类型,使用时需要在数值后面加L
或l
标识,例如表示较大的计数值(如时间戳,以毫秒为单位时,可能会超过int
的范围)。
(2)浮点类型
浮点类型用于表示有小数部分的数值,包括 float
和 double
两种。
float
:单精度浮点型,占用 4 个字节(32 位),可以表示大约 6 - 7 位有效数字。由于其精度相对较低,且在 Java 中使用时需要在数值后面加F
或f
标识,所以一般在对精度要求不高,且需要节省内存的场景下使用,比如一些简单的科学计算或图形处理中对精度要求不高的部分。double
:双精度浮点型,占用 8 个字节(64 位),可以表示大约 15 - 17 位有效数字,是 Java 中默认的浮点类型。在大多数需要浮点数的场景下,如金融计算、科学模拟等对精度要求较高的情况,都会使用double
类型。
(3)字符类型:char
char
类型用于表示单个字符,占用 2 个字节(16 位),采用 Unicode 编码,可以表示世界上几乎所有的字符。字符常量用单引号括起来,例如 'A'
、'中'
等。
(4)布尔类型:boolean
boolean
类型用于表示逻辑值,只有 true
(真)和 false
(假)两个取值,主要用于条件判断。在 Java 中,boolean
类型的具体实现细节没有严格规定,通常在字节码层面可能用 1 位或 1 个字节等方式存储,但在编程时,我们只需要关注其逻辑意义即可。
(二)、引用数据类型:复杂对象的间接引用
引用数据类型用于表示对对象的引用,它不像基本数据类型那样直接存储数据值,而是存储对象在内存中的地址(引用)。Java 中的引用数据类型主要包括类(class
)、接口(interface
)和数组(array
)。
(1)类(class
)
类是 Java 中面向对象编程的核心概念,是创建对象的模板。一个类定义了对象所具有的属性(成员变量)和行为(成员方法)。当我们通过 new
关键字创建一个类的实例时,就得到了一个对象,而引用数据类型的变量存储的就是这个对象在堆内存中的地址。
例如,我们定义一个 Person
类:
class Person {String name;int age;public void sayHello() {System.out.println("Hello, my name is " + name + ", I'm " + age + " years old.");}
}
然后创建 Person
类的对象并使用:
Person person = new Person();
person.name = "Tom";
person.age = 20;
person.sayHello();
在这里,person
就是一个引用类型变量,它存储的是 new Person()
创建的对象在内存中的地址,通过 person
我们可以访问和操作 Person
对象的属性和方法。
(2)接口(interface
)
接口是一种特殊的引用数据类型,它定义了一组方法的规范,但没有方法的具体实现(在 Java 8 之前是这样,Java 8 及以后允许接口中有默认方法和静态方法,但核心的抽象方法规范特性仍在)。类可以实现(implements
)接口,从而获得接口中定义的方法规范,并提供具体的实现。接口主要用于实现多态和定义组件之间的契约。
例如,定义一个 Flyable
接口:
interface Flyable {void fly();
}
然后创建一个实现该接口的 Bird
类:
class Bird implements Flyable {@Overridepublic void fly() {System.out.println("Bird is flying.");}
}
使用时:
Flyable flyable = new Bird();
flyable.fly();
这里的 flyable
是一个接口类型的引用变量,它可以引用任何实现了 Flyable
接口的类的对象,体现了多态的特性。
(3)数组(array
)
数组是一种用于存储多个相同类型数据的容器。数组本身是一个对象,数组变量存储的是数组对象在内存中的地址。数组可以存储基本数据类型的元素,也可以存储引用数据类型的元素。
例如,创建一个整型数组:
int[] arr = new int[3];
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
for (int i = 0; i < arr.length; i++) {System.out.println("数组元素:" + arr[i]);
}
这里的 arr
是数组引用变量,它指向了在堆内存中创建的、包含 3 个 int
元素的数组对象。
(三)、基本类型与引用类型的核心区别
(1)存储方式
- 基本数据类型:变量直接存储具体的数值,存储在栈内存中(对于局部变量而言)。
- 引用数据类型:变量存储的是对象在堆内存中的地址(引用),对象的实际数据存储在堆内存中,引用本身存储在栈内存(局部变量时)或方法区(静态变量时)等。
(2)默认值
- 基本数据类型:每种基本数据类型都有默认值,例如
int
的默认值是0
,boolean
的默认值是false
等。 - 引用数据类型:默认值是
null
,表示没有引用任何对象。
(3)传递方式
- 基本数据类型:在方法调用时,是按值传递,即传递的是变量的副本,方法内对参数的修改不会影响到方法外的变量。
- 引用数据类型:在方法调用时,是按引用传递,传递的是对象的引用(地址),方法内通过引用对对象的修改会影响到方法外的对象。
二、关键字
关键字是 Java 预先定义、有特殊含义的单词,不能用作标识符(如类名、变量名、方法名等)。常见关键字有 public
、class
、static
、void
、int
、double
、if
、else
、for
、while
等。
三、Java 中的注释
注释用于解释代码,提升可读性,编译器会忽略注释内容。Java 有三种注释:
- 单行注释:以
//
开头,注释到行尾。
// 单行注释示例
int a = 10;
- 多行注释:以
/*
开头,*/
结尾,可注释多行。
/*多行注释示例跨越多行
*/
double b = 3.14;
- 文档注释:以
/**
开头,*/
结尾,用于生成 API 文档,可通过javadoc
工具生成。
/*** 文档注释示例,描述方法功能* @param num 传入的整数参数* @return 返回 num 的平方*/
public int square(int num) {return num * num;
}
四、运算符
运算符用于对数据进行运算操作,Java 中的运算符包括:
- 算数运算符:
+
(加)、-
(减)、*
(乘)、/
(除)、%
(取余)、++
(自增)、--
(自减)。例如:
int a = 10, b = 3;
System.out.println(a + b); // 13
System.out.println(a / b); // 3(整数相除,结果取整)
a++;
System.out.println(a); // 11
- 赋值运算符:
=
(赋值)、+=
(加等于)、-=
(减等于)、*=
(乘等于)、/=
(除等于)、%=
(取余等于)等。例如a += b;
等价于a = a + b;
。 - 比较运算符:
==
(等于)、!=
(不等于)、>
(大于)、<
(小于)、>=
(大于等于)、<=
(小于等于),用于比较两个值的关系,返回boolean
类型的值(true
或false
)。例如a > b
返回true
。 - 逻辑运算符:
&&
(逻辑与)、||
(逻辑或)、!
(逻辑非),用于进行逻辑运算,操作数和结果都是boolean
类型。&&
表示两边都为true
时结果才为true
;||
表示两边有一个为true
时结果就为true
;!
是取反操作。例如:
boolean flag1 = true, flag2 = false;
System.out.println(flag1 && flag2); // false
System.out.println(flag1 || flag2); // true
- 三元运算符:
条件 ? 表达式1 : 表达式2
,如果条件为true
,则返回表达式 1 的值,否则返回表达式 2 的值。例如int max = a > b ? a : b;
,用于获取a
和b
中的较大值(下集详细介绍位运算符)。 位运算符:用于对整数的二进制位进行操作,包括
&
(按位与)、|
(按位或)、^
(按位异或)、~
(按位取反)、<<
(左移)、>>
(右移)、>>>
(无符号右移)。例如a & b
是将a
和b
的每一位进行与操作。
(详情可见Java运算符详解一篇)
五、类型转换
- 自动转换:当把范围小的类型赋值给范围大的类型时,会自动进行转换。例如
int i = 10; double d = i;
,int
类型的i
会自动转换为double
类型后赋值给d
。
Java 基本数据类型的表示范围从小到大排序如下(boolean
类型特殊,不参与转换):byte
(1 字节) → short
(2 字节)→ char
(2 字节)→ int
(4 字节)→ long
(8 字节)→ float
(4 字节)→ double
(8 字节)
注意:
char
是无符号类型(范围 0~65535),与byte
(-128~127)、short
(-32768~32767)的范围有重叠但不兼容,因此char
不能直接自动转换为byte
或short
,反之亦然。
- 强制转换:当把范围大的类型赋值给范围小的类型时,需要进行强制转换,语法为
(目标类型)值
。强制转换可能会导致精度丢失或数据溢出。例如double d = 3.14; int i = (int)d;
,d
强制转换为int
类型后,i
的值为 3,小数部分被舍弃。
类型 | 转换方向 | 是否需要手动干预 | 安全性 | 典型场景 |
---|---|---|---|---|
自动转换 | 小范围 → 大范围 | 否(编译器自动) | 安全(无溢出,可能丢精度) | int → long 、float → double |
强制转换 | 大范围 → 小范围 | 是(需显式声明) | 不安全(可能溢出或丢精度) | double → int 、long → byte |