Java
程序是一种纯粹的面向对象的程序设计语言,Java
程序必须以类 class
的形式存在,class
是 Java
程序的最小程序单位。Java
程序不允许可执行性语句、方法等成分独立存在,所有的程序部分都必须放在类定义里。
public class Hello { // 类名是 Hello
// ...
}
Java 源文件的命名规则
Java
程序源文件的扩展名必须是.java
,不能是其他文件扩展名Java
源文件的文件名必须与该public
类的类名相同整数类型:
byte
、short
、int
、long
byte
占一个字节short
占两个字节int
占四个字节long
占八个字节
- 浮点数类型:
float
、double
float
占四个字节double
占八个字节
- 字符类型:
char
char
占两个字节
- 布尔类型:
boolean
计算机内存的最小存储单元是字节,一个字节就是一个 8 位二进制数,即 8 个bit。它的二进制范围从 00000000 ~ 11111111,换算成十进制是 0~255,换算成十六进制是 00~ff。
Java
所有的数值型变量可以相互转换,分为自动类型转换和强制类型转换。当把一个范围小的数值或变量直接赋给另外一个范围大的数值时,系统会进行自动类型转换。强制类型转换使用圆括号()运算符
整型
四种整型的取值范围
byte
:一个byte
类型整数在内存里占 8 位,取值范围是 -128(-2)~ 127(2-1)short
:一个short
类型整数在内存里占 16 位,取值范围是 -2~(2-1)int
:一个int
类型整数在内存里占 32 位,取之范围是 -2~(2-1)long
:一个long
类型整数在内存里占 64 位,取值范围是 -2~(2-1)整数值默认是 int 类型。声明 long 类型整数时,通常在后缀添加 L
整数运算
Java
的整数运算遵循四则运算规则,可以使用任意嵌套的小括号
- 整数运算永远是精确的。两个整数相除
/
仅返回结果的整数部分,求余运算使用%
- 由于整数存在范围限制,如果计算结果超出了范围,会产生溢出,并且溢出不会出错,返回以下特殊值
NaN
表示 Not a NumberInfinity
表示无穷大-Infinity
表示负无穷大
- 自增/自减运算中,
++n
表示先加 1 再引用 n,n++
表示先引用 n 再加 1,一般不建议使用自增/自减运算,容易混淆 - 移位运算中,左移
<<
就是不断的x2
,右移>>
就是不断的÷2
- 位运算是按位进行与、或、非和异或的运算
- 与
&
运算规则:必须两个数同时为 1,结果才为 1 - 或
|
运算规则:只要任意一个数为 1,结果就为 1 - 非
~
运算规则:0 和 1 互换 - 异或
^
运算规则:如果两个数不同,结果为 1,否则为 0
- 与
- 整数进行位运算实际上就是按位对齐,然后依次对每一位进行运算
浮点型
浮点类型的数就是小数。double
类型的精度高于float
类型,double
类型代表双精度浮点数,float
类型代表单精度浮点数。double
类型最大表示 1.79x10,float
类型最大表示 3.4x10。声明
float
类型时,需要添加后缀f
。若doule
类型精度无法满足使用时,一般使用BigDecimal
类
字符型
char
类型表示一个字符,Java
的 char
类型除了表示标准的 ASCII
外,还可以表示一个 Unicode
字符。Java
没有提供表示字符串的基本数据类型,而是通过 String
类型来表示字符串,一个字符串由多个字符组成。
声明 char 类型必须使用单引号(‘)括起来。而字符串使用双引号(“)括起来
布尔型
布尔类型 boolean
只有 true
和 false
两个值,用于表示逻辑上的 “真” 或 “假”。
理论上存储布尔类型只需要 1 bit,但是通常 JVM 内部会把 boolean 表示为 4 字节整数
运算优先级
Java
的计算表达式中,运算优先级从高到低依次是
()
!
~
++
--
*
/
%
+
-
<<
>>
>>>
&
|
+=
-=
*=
/=
引用类型
除了基本类型的变量,其他的都是引用类型。基本类型的变量是“持有”某个数值,引用类型的变量是“指向”某个对象;String
字符串是最常用的引用类型。Java
的字符串具有不可变特性。运行String
类型变量赋值语句后,变的不是字符串,而是变量的“指向”,原来字符串的值还存在,只是无法通过变量访问它
数组
Java
的数组类型是一种引用类型的变量,数组内的所有元素一定是相同的数据类型
- 数组所有元素初始化为默认值,整型都是
0
,浮点型是0.0
,布尔型是false
- 数组一旦创建后,大小就不可改变
- 数组索引从
0
开始,索引最大值为数组长度减去1
- 定义二维数组实际上是定义了一个数据内元素类型是数组的一维数组
public class Main {
public static void main(String[] args) {
String[] names = {"ABC", "XYZ", "zoo"};
String s = names[1];
names[1] = "cat";
System.out.println(s); // s是"XYZ"还是"cat"?
}
}
只要类型相互兼容,就可以让一个数组变量指向另一个实际的数组,这种操作实际并不是修改来数组的长度,而是将数组的引用指向了另一个数组,原数组指向的堆内存依赖存在,需要等到下次垃圾回收时才会被回收。
内存堆栈
当一个方法执行时,每个方法都会建立自己的内存栈,在这个方法内定义的变量将会逐个放入这块栈内存中,随着方法的执行结束,这个方法的内存栈也将自然销毁。因此,所有在方法中定义的局部变量都是放在栈内存中的;在程序中创建一个对象时,这个对象将被保存到运行时数据区中以便反复利用,运行时数据区即为堆内存。堆内存中的对象不会随方法的结束而销毁,即使方法结束后,这个对象还可能被另一个引用变量所引用,则这个对象依然不会被销毁。只有当一个对象没有任何引用变量引用它时,系统的垃圾回收器才会在合适的时候回收它。
为来让垃圾回收机制回收一个数组所占的内存空间,可以将数组变量赋为 null,切断数组引用变量和实际数组之间的引用关系,使实际数组变成垃圾
数组排序
对数组排序实际上是修改了数组本身。基本类型数组排序后数组变量指向新的数组内容,而引用类型排序后,内存堆中没有变化,但是每个元素的指向发生了变化
冒泡排序
冒泡排序的特点是,每一轮循环后,最大的一个数被交换到末尾,因此,下一轮循环就可以“刨除”最后的数,每一轮循环都比上一轮循环的结束位置靠前一位。
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] ns = { 28, 12, 89, 73, 65, 18, 96, 50, 8, 36 };
// 排序前:
System.out.println(Arrays.toString(ns));
for (int i = 0; i < ns.length - 1; i++) {
for (int j = 0; j < ns.length - 1 - i; j++) {
if (ns[j] > ns[j+1]) {
// 交换ns[j]和ns[j+1]:
int tmp = ns[j];
ns[j] = ns[j+1];
ns[j+1] = tmp;
}
}
}
// 排序后:
System.out.println(Arrays.toString(ns));
}
}
JDK
中java.util
包下提供了Arrays.sort()
快速排序方法