基本数据类型和变量
一、变量
1、变量本质
- 是一个容器,装什么和装多少是核心问题
- 我们使用一个变量就是在内存中开辟一个空间来存放数据
2、变量分类
- 局部变量必须先初始化才能使用
- 静态的成员变量在类加载的时候就会自动初始化
- 实例变量会在创建对象的时候自动初始化
- 关于变量最保险的使用方法还是显式初始化再使用
二、常量
- 具体的数字、字符、字符串、true、false 都是常量,就是程序运行过程中不会发生改变的量
- 变量加 final 修饰也可以转换成常量:在类中通常都是用 static final 来修饰常量,一般都是全大写来表示
关于标识符
- 标识符可以是字母、下划线、美元符和数字的任意组合,数字不能开头;
- 标识符大小写敏感,采用 unicode 字符集,标识符可以包含汉字,但是不建议使用;
三、基本数据类型
1、数据类型
总结:三大类八小类
进制:二进制 0b 开头;八进制 0 开头;十六进制 0x 开头;
2、基本数据类型
整型
- byte 类型的范围 -128到127
- 默认 int,long 型赋值后面要加 L;
浮点型
- 默认 double,float 后面要加 F;
- 浮点数是不精确的,计算时可能会得到不精确的结果
- 涉及更精确的计算,可以使用 BigInteger 和 BigDecimal;
字符型
- 字符单引号中有且只能有 1 个,不能为空;
- 字符型占两个字节的原因,java 采用的是 unicode 字符集;
布尔型
- 占一位,而不是一个字节;true 和 false 不能等价与 0 和 非 0
3、类型转换
自动转换
- 沿着途中的箭头的方向都是可以进行数据类型的自动转换的
- 实线箭头方向是小的转大的,不会有精度的损失
- 虚线方向箭头可能会出现结果的溢出
强制转换
- 一般的情况是大的转小的,可能会有精度的损失
其他说明
- 转换的特例:可以将整型常量直接赋值给 byte、 short、char 等类型变量,而不需要进行强制类型转换,只要不超出其表数范围即可;
- char 和 int 的相互转换通过查码表来实现;
- 基本的数据类型中除了boolean以外其他的数据类型都是可以相互转换的,本质都是可以转换为数值的
运算符
一、运算符分类
二、算术运算符
- 数值运算会有一个类型提升,具体来说就是会按照自动类型转换的图中箭头方向提升表达式的结果的类型
- 取模运算:余数的符号和左边的操作数一样:
-7%3=-1,7%-3=1
;
三、赋值运算符
四、关系运算符
== !=
是所有数据类型都可以使用instanceof
也是关系运算符,适用于引用类型- 其他的关系运算符基本都是适用于数值类型
五、逻辑运算符
- 异或的逻辑是:同零异一
- 短路与
&&
和短路或||
的特点
六、位运算符
注意:
&
和|
既是逻辑运算符,也是位运算符。如果两侧操作数都是boolean类型,就作为逻辑运算符;如果两侧的操作数是整数类型,就是位运算符;
七、三目条件运算符
- 替代简单的 if–else 逻辑
运算符的优先级
- 不用记,提升优先级可以用小括号来实现;
- 逻辑与、逻辑或、逻辑非的优先级(逻辑非>逻辑与>逻辑或);
数组
- 数组是相同类型数据的有序集合
- 长度是确定的,元素必须是相同类型,可以是基本类型和引用类型
- 数组是对象,所以是存储在堆内存中的
一、一维数组
1、创建
int[] a = { 1, 2, 3 };// 静态初始化基本类型数组;
Man[] mans = { new Man(1, 1), new Man(2, 2) };//引用类型数组;
int[] a1 = new int[2];//动态初始化数组,先分配空间;
2、遍历
- 增强 for 循环:不能修改元素、不能操作索引
3、拷贝
public class Test {
public static void main(String args[]) {
String[] s = {"阿里","京东","搜狐","网易"};
String[] sBak = new String[6];
System.arraycopy(s,0,sBak,0,s.length);
for (int i = 0; i < sBak.length; i++) {
System.out.print(sBak[i]+ "\t");
}
}
}
二、多维数组
1、二维数组创建
int[][] a = { { 1, 2, 3 }, { 3, 4 }, { 3, 5, 6, 7 } };
int[][] a = new int[3][];
a[0] = new int[] { 1, 2 };
a[1] = new int[] { 2, 2 };
a[2] = new int[] { 2, 2, 3, 4 };
2、二维数组长度
- arr.length 和 arr[0].length
三、操作数组
1、冒泡排序
基础算法
public static void bubbleSort(int[] values) {
int temp;
for (int i = 0; i < values.length; i++) {
for (int j = 0; j < values.length - 1 - i; j++) {
if (values[j] > values[j + 1]) {
temp = values[j];
values[j] = values[j + 1];
values[j + 1] = temp;
}
}
}
}
优化算法
public static void bubbleSort(int[] values) {
int temp;
int i;
// 外层循环:n个元素排序,则至多需要n-1趟循环
for (i = 0; i < values.length - 1; i++) {
// 定义一个布尔类型的变量,标记数组是否已达到有序状态
boolean flag = true;
/*内层循环:每一趟循环都从数列的前两个元素开始进行比较,比较到无序数组的最后*/
for (int j = 0; j < values.length - 1 - i; j++) {
// 如果前一个元素大于后一个元素,则交换两元素的值;
if (values[j] > values[j + 1]) {
temp = values[j];
values[j] = values[j + 1];
values[j + 1] = temp;
//本趟发生了交换,表明该数组在本趟处于无序状态,需要继续比较;
flag = false;
}
}
//根据标记量的值判断数组是否有序,如果有序,则退出;无序,则继续循环。
if (flag) {
break;
}
}
}
2、二分查找
public static int binarySearch(int[] array, int value){
int low = 0;
int high = array.length - 1;
while(low <= high){
int middle = (low + high) / 2;
if(value == array[middle]){
return middle; //返回查询到的索引位置
}
if(value > array[middle]){
low = middle + 1;
}
if(value < array[middle]){
high = middle - 1;
}
}
return -1; //上面循环完毕,说明未找到,返回-1
}
3、Arrays 工具类
排序
- 基本类型:Arrays.sort();
- 引用类型:该引用类型要实现 Comparable 接口
class Man implements Comparable {
int age;
String name;
public Man(int age, String name) {
super();
this.age = age;
this.name = name;
}
public String toString() {
return this.name;
}
public int compareTo(Object o) {
Man man = (Man) o;
if (this.age < man.age) {
return -1;
}
if (this.age > man.age) {
return 1;
}
return 0;
}
}
查找:二分查找
Arrays.sort(arr); //使用二分法查找,必须先对数组进行排序;
Arrays.binarySearch(arr, 12);
填充:Arrays.fill(arr, 2, 4, 100)
打印:Arrays.toString(arr)
流程控制
一、条件开关语句
1、if---else if---else
2、switch开关语句
- 表达式的数据类型只能是 byte、short、char、int 四种整形类型,枚举类型和 String 类型;
- switch 语句具有穿透性,即有一个 case 匹配之后,会一直往后执行,直到遇到 break;
switch (表达式) {
case 值1:
语句序列1;
[break];
case 值2:
语句序列2;
[break];
default:
默认语句;
}
二、循环语句
1、while | do-while | for
2、break | continue
- 带标签的 break 和 continue;
public class BianLiang {
public static void main(String[] args) {
outer:for (int i = 101; i < 150; i++) {
for (int j = 2; j < i / 2; j++) {
if(i % j == 0)continue outer;
}
System.out.print(i+" ");
}
}
}
其他补充
一、语句块
- {}括起来的,作为一个整体执行,规定了变量的作用域;
- 语句块支持嵌套,但是嵌套的语句块里不支持同名变量,不是说约束了作用域吗?
二、递归
- 本质就是自己调用自己;
- 递归的关键在于结束条件的确定,不然直接陷入无限的递归
- 递归执行效率不高,递归的次数过多的时候可以使用迭代代替
// 求n!
public static int diGui(int n){
if(n == 1){
return 1;
}else{
return n*diGui(n-1);
}
}