Java系列(一)| 基础语法
Java 概述
什么是 Java?
Java 是一门面向对象的编程语言,不仅吸收了 C++
语言的各种优点,还摒弃了 C++
里难以理解的多继承、指针等概念,因此 Java
语言具有功能强大和简单易用两个特征。Java
语言作为静态面向对象编程语言的优秀代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程 。
Java 语言有哪些特点?
Java 语言有很多优秀(可吹)的特点,以下几个是比较突出的:
- 面向对象(封装,继承,多态);
- 平台无关性:Java 是 “【一次编写,到处运行(
Write Once,Run any Where
)】” 的语言,因此采用Java
语言编写的程序具有很好的可移植性,而保证这一点的正是Java
的虚拟机机制。在引入虚拟机之后,Java
语言在不同的平台上运行不需要重新编译。 - 支持多线程:
C++
语言没有内置的多线程机制,因此必须调用操作系统的多线程功能来进行多线程程序设计 - 编译与解释并存;
JVM、JDK 和 JRE 有什么区别?
JVM
:Java Virtual Machine
,Java
虚拟机,Java
程序运行在 Java
虚拟机上。针对不同系统的实现(Windows,Linux,macOS
)不同的 JVM
,因此 Java
语言可以实现跨平台。
JRE
:Java
运⾏时环境。它是运⾏已编译 Java
程序所需的所有内容的集合,包括【 Java
虚拟机(JVM
)、Java
类库、Java
命令和其他的⼀些基础构件】。但是,它不能⽤于创建新程序。
JDK
: Java Development Kit
,它是功能⻬全的 Java SDK。
它拥有 JRE
所拥有的⼀切,还有编译器(javac
)和⼯具(如 javadoc
和 jdb
)。它能够创建和编译程序。
简单来说,JDK > JRE > JVM
说说什么是跨平台性?原理是什么
所谓跨平台性,是指 Java
语言编写的程序,一次编译后,可以在多个系统平台上运行。
实现原理:Java
程序是通过 Java
虚拟机在系统平台上运行的,只要该系统可以安装相应的 Java
虚拟机,该系统就可以运行 java
程序。
什么是字节码?采用字节码的好处是什么?
所谓的字节码,就是 Java
程序经过编译之类产生的. class
文件,字节码能够被虚拟机识别,从而实现 Java 程序的跨平台性。
Java 程序从源代码到运行主要有三步:
- 编译:将我们的代码(
.java
)编译成虚拟机可以识别理解的字节码 (.class
) - 解释:虚拟机执行
Java
字节码,将字节码翻译成机器能识别的机器码 - 执行:对应的机器执行二进制机器码
只需要把 Java
程序编译成 Java
虚拟机能识别的 Java
字节码,不同的平台安装对应的 Java
虚拟机,这样就可以可以实现 Java
语言的平台无关性。
为什么说 Java 语言 “编译与解释并存”?
编译型:一次性翻译
解释性:逐行翻译
Java 程序 先编译 后解释 【.java –>.class –>机器码】
高级编程语言按照程序的执行方式分为编译型和解释型两种。
- 编译型语言:指编译器针对特定的操作系统将源代码一次性翻译成可被该平台执行的机器码;
- 解释型语言:指解释器对源程序逐行解释成特定平台的机器码并立即执行。
Java 语言既具有编译型语言的特征,也具有解释型语言的特征。因为 Java 程序要经过先编译,后解释两个步骤。
编译:
.java
编译.class
。Java
编写的程序需要先经过编译步骤,生成字节码(.class
文件)解释:这种字节码必须再经过
JVM
,解释成操作系统能识别的机器码,在由操作系统执行。因此,我们可以认为 Java 语言编译与解释并存。
基础语法
Java 有哪些数据类型?
定义:Java
语言是强类型语言,对于每一种数据都定义了明确的具体的数据类型,在内存中分配了不同大小的内存空间。
Java
语言数据类型分为两种:基本数据类型和引用数据类型。
基本数据类型:
- 数值型
- 整数类型
(byte、short、long)
- 浮点类型
(float、long)
- 字符型
(char)
- 布尔型
(boolean)
Java
基本数据类型范围和默认值:
基本类型 | 位数 | 字节 | 默认值 |
---|---|---|---|
int | 32 | 4 | 0 |
short | 16 | 2 | 0 |
long | 64 | 8 | 0L |
byte | 8 | 1 | 0 |
char | 16 | 2 | 'u0000' |
float | 32 | 4 | 0f |
double | 64 | 8 | 0d |
boolean | 1 | false |
引用数据类型:
- 类(
class
) - 接口(
interface
) - 数组 (
array
[])
自动类型转换、强制类型转换?看看这几行代码?
Java
所有的数值型变量可以相互转换。
当把一个表数范围小的数值或变量直接赋给另一个表数范围大的变量时,可以进行自动类型转换;反之,需要强制转换。
这就好像,小杯里的水倒进大杯没问题,但大杯的水倒进小杯就不行了,可能会溢出。
下面是一个例子:
float f=3.4
,对吗?
不正确。3.4 是单精度数,将双精度型(double
)赋值给浮点型(float
)属于下转型(down-casting,
也称为窄化)会造成精度损失,因此需要强制类型转换float f =(float)3.4;
或者写成float f =3.4F
short s1 = 1; s1 = s1 + 1;
对吗?short s1 = 1; s1 += 1;
对吗?
对于 short s1 = 1; s1 = s1 + 1;
编译出错,由于 1 是 int
类型,因此 s1+1
运算结果也是 int 型,需要强制转换类型才能赋值给 short
型。
而 short s1 = 1; s1 += 1
; 可以正确编译,因为 s1+=
1; 相当于 s1 = (short(s1 + 1)
; 其中有隐含的强制类型转换。
什么是自动拆箱 / 封箱?
- 装箱:将基本类型用它们对应的引用类型包装起来;
- 拆箱:将包装类型转换为基本数据类型;
Java
可以自动对基本数据类型和它们的包装类进行装箱和拆箱。
举例:
Integer i = 10; //装箱
int n = i; //拆箱
& 和 && 有什么区别?
- & :【逻辑与】两边都是
true
,结果为true
;反之为false
;不管如何两边都会计算 - && :【短路与】左边为 false ,不计算右边,结果为
false
;左边为true
,才计算右边,若为true
结果为true
;反之为 false
例如在验证用户登录时判定用户名不是 null 而且不是空字符串,应当写为
username != null &&!username.equals("")
二者的顺序不能交换,更不能用 & 运算符,因为第一个条件如果不成立,根本不能进行字符串的 equals 比较,否则会产生 NullPointerException
异常。
注意:逻辑或运算符(|)和短路或运算符(||)的差别也是如此。
switch 是否能作用在 byte/long/String 上?
- Java5 以前 switch(expr) 中,expr 只能是 byte、short、char、int。
- Java 5 开始,Java 中引入了枚举类型, expr 也可以是
enum
类型。 - Java 7 开始,expr 还可以是字符串 (String),但是长整型(long) 在目前所有的版本中都是不可以的。
- java 17 开始,预览版,支持使用 Long
- java 21 开始,为正式版
break ,continue ,return 的区别及作用?
break
跳出整个循环,不再执行循环 (结束当前的循环体)continue
跳出本次循环,继续执行下次循环 (结束正在执行的循环 进入下一个循环条件)return
程序返回,不再执行下面的代码 (结束当前的方法 直接返回)
用最有效率的方法计算 2 乘以 8?
2 << 3
。位运算,数字的二进制位左移三位相当于乘以 2
的三次方。
说说自增自减运算?看下这几个代码运行结果?
在写代码的过程中,常见的一种情况是需要某个整数类型变量增加 1 或减少 1,Java
提供了一种特殊的运算符,用于这种表达式,叫做自增运算符(++)
和自减运算符(–)。
++ 和 --
运算符可以放在变量之前,也可以放在变量之后。
当运算符放在变量之前时 (前缀),先自增 / 减,再赋值;当运算符放在变量之后时 (后缀),先赋值,再自增 / 减。
例如,当 b = ++a
时,先自增(自己增加 1),再赋值(赋值给 b);当 b = a++
时,先赋值 (赋值给 b),再自增(自己增加 1)。也就是,++a 输出的是 a+1 的值,a++ 输出的是 a 值。
用一句口诀就是:“符号在前就先加 / 减,符号在后就后加 / 减”。
看一下这段代码运行结果?
int i = 1;
i = i++;
System.out.println(i);
答案是 1。有点离谱对不对。
对于 JVM
而言,它对自增运算的处理,是会先定义一个临时变量来接收 i 的值,然后进行自增运算,最后又将临时变量赋给了值为 2 的 i,所以最后的结果为 1。
相当于这样的代码:
int i = 1;
int temp = i;
i++;
i = temp;
System.out.println(i);
这段代码会输出什么?
int count = 0;
for(int i = 0;i < 100;i++)
{
count = count++;
}
System.out.println("count = "+count);
答案是 0。
和上面的题目一样的道理,同样是用了临时变量,count 实际是等于临时变量的值。
int autoAdd(int count)
{
int temp = count;
count = coutn + 1;
return temp;
}