title: Day02-Java基础
date: 2020-05-18 14:10:22
author:子陌
Java程序开发-- Hello World
- 将Java代码编写到扩展名为.java的文件中
- 通过javac命令对该Java文件进行编译
- 通过java命令对生成的class文件进行运行
class Demo {
public static void main(String[] args){
System.out.println("Hello World!");
}
}
- main()为主程序入口地址,只有一个
- 该函数被Java虚拟机JVM调用
- 有了该函数能保证一个类的独立运行
编译:javac(编译工具) ,实际上对java源文件进行语法检查
javac Demo.java ======= >>>>>> Demo.class
运行:java(运行工具),对应底层就是JVM,启动虚拟机,将文件加载进内存
java Demo.class(或Demo) ====== >>>>> Hello World!
Java语言基础组成
关键字
标识符
-
在程序中自定义的一些名称
-
由26个英文字母大小写、数字:0-9、符号:_和$组成
-
定义合法标识符规则:
1. 数字不可以开头
2. 不可以使用关键字
-
Java中严格区分大小写
-
注意:起名时,为了提高阅读性,尽量要有意义
注释
- 用于注解说明程序的文字就是注释
- 提高了代码的阅读性
- Java中的注释格式
- 单行注释
- 格式:
// 注释文字
- 格式:
- 多行注释
- 格式:
/*注释文字*/
- 格式:
- 文档注释
- 格式:
/** 注释文字 */
- 格式:
- 单行注释
常量和变量
1.常量
常量表示不能改变的数值
-
Java中常量的分类:
- 整数常量,所有整数
- 小数常量,所有小数
- 布尔常量,特有,只有两个数值:true,false
- 字符常量,将一个数字、字母用单引号(’ ')标识
- 字符串常量,将一个或多个字符用双引号(" ")标识
- null常量,只有一个数值:null
-
整数:四种形式
- 二进制: 0 - 1 , 满 2 进 1
- 八进制: 0 - 7 , 满 8 进 1 用0开头表示
- 十进制: 0 - 9 , 满 10 进 1
- 十六进制: 0 - 9, A - F, 满 16 进 1 用0x开头表示
2.变量
概念:内存中的一个存储区域,该区域有自己的名称(变量名)和类型(数据类型),该区域的数据可以在同一类型范围内不断变化,可以重复使用,可以暂时理解为数学中的未知数x。
使用注意: 变量的作用域范围(一对{}之间有效),变量初始值
定义变量的格式:
- 数据类型 变量名 = 初始化值;
- 注:格式是固定的
Java语言是强类型语言,对于每一种数据都定义了明确的具体数据类型,在内存总分配了不同大小的内存空间
class VarDemo{
public static void main(String[] args){
// 数据类型 变量名 = 初始化值
byte a = 1; // 128 ~ (-127)
short b = 2;
int c = 100000;
long d = 123456789;
long d = 12345678910123l; // 如果超过整数范围后面加一个字符l
float f = 2.3f; // 加个f声明为单精度
double e = 3.14; // 默认为双精度
char ch = 'a'; // '12' : err
char ch1 = '1'; // err 非法字符 把;改为;
boolean g = true;
g = false;
}
}
3.数据类型转换
- 自动类型转换(也叫隐式类型转换)
- 强制类型转换(也叫显式类型转换)
- 类型转换的原理
- 表达式的数据类型自动提升
- 所有的byte型、short型和char型的值将被提升到int
- 如果一个操作数是long型,计算结果就是long
- 如果一个操作数是float型,计算结果就是float
- 如果一个操作数是double型,计算结果就是double型
class VarDemo1{
public static void main(String[] args){
int a = 3;
byte b = 5
a = a + b; // ok b变量将被自动提升为int
byte c = 3;
c = c + 5; // err
c = (byte)(c + 5); // 强制类型转换 int 转 byte
byte aa = 4;
byte bb = 3;
byte cc = 5;
aa = bb + cc; // err 丢失精度
// 原因:aa bb 为变量 ,无法进行检查结果是否超过byte精度,所以报错 aa可能为127 bb可能为127 相加会超过精度
int x = bb + cc;
int d1 = Integer.MAX_VALUE; // 2147483647 (2^31 - 1)
int d2 = 3;
int d3 = d1 + d2; // ok
}
}
运算符
- 算术运算符: +、-、*、/、%、+(连接符)、++、–
class Demo{
public static void main(String[] args){
System.out.println(3+2); // 5
System.out.println(3-2); // 1
System.out.println(3*2); // 6
System.out.println(3/2); // 1
System.out.println(5%2); // 1
System.out.println(-5%2); // -1
System.out.println(5%-2); // 1
System.out.println(3+"2"); // 32
int a = 1,b;
a++; // a = a + 1;
System.out.println(a); // 2
++a;
System.out.println(a); // 3
b = a++; // 后置++会在内存中开辟临时变量存储
System.out.println(a+""+b); // a = 4 b = 3
b = ++a;
System.out.println(a+""+b); // a = 5 b = 5
int i = 3;
i = i++;
System.out.println(i); // 3
// tmp = i => 3; i++ i => 4; i = tmp => 3
}
}
- 赋值运算符:=、+=、-=、*=、/=、%=
class Demo{
public static void main(String[] args){
int a,b,c;
a = b = c = 4;
a += 2; // a = a + 2
b -= 3; // b = b - 3
short s = 3;
s += 4; // 7 ok
s = s + 4; // err 类型提升,精度丢失
s = (short)(s + 4); // ok
}
}
- 比较运算符:>、<、>=、<=、==、!=、instanceof
class Demo{
public static void main(String[] args){
/*
* 比较运算符,运算结果必须是true或者false
*/
System.out.println(3 = 2); // err = 赋值
System.out.println(3 == 2); // ok false
System.out.println(3!=2); // ok true
}
}
比较运算符结果都是boolean型,要么是true,要么是false
比较运算符”==“ 不要误写成”=“
- 逻辑运算符:&、|、^、!、&&、||
- &:与,一假即假(可以进行位运算)
- |:或,一真即真(可以进行位运算)
- ^:异或,相同为假,不同为真
- !:非,真假相反
- &&:双与结果和&相同,优先短路(左边一假,右边不运算)
- ||:双或结果和|相同,优先短路(左边一真,右边不运算)
class Demo{
public static void main(String[] args){
// 2 < x < 5
/*
* 用于连接两个boolean表达式
*/
int x = 3;
System.out.println(x > 2 & x < 5); // true
}
}
- 位运算符:<<、>>、>>>、&、|、^、~
- <<:右移
- >>:左移
- >>>:无符号右移
- &:与
- |:或
- ^:异或
- ~:取反
class Demo{
public static void main(String[] args){
int a = 3;
a = a << 2; // 12 3*2*2=12
int b = 3;
b = b >> 1; // 1 3/2=1
b = 3 >> 1; // 1 3/2=1
b = 6 & 3; // 2
b = 6 | 3; // 7
b = 6 ^ 3; // 5
b = ~6; // -7
System.out.println(x > 2 & x < 5); // true
// 不使用第三个变量交换数据
// 方法1: 不建议使用 可能超出范围,精度问题
int aa = 5,bb = 3;
a = a + b;
b = a - b;
a = a - b;
// 方法2: a = 3 b = 5
a = a ^ b; // a = 3 ^ 5
b = a ^ b; // b = (3 ^ 5) ^ 5 b = 3
a = a ^ b; // a = (3 ^ 5) ^ 3 a = 5
}
}
<<:相当于乘与2的倍数
>>:相当于除与2的倍数
移n位,就是对乘以或者除以2的n次幂
- 三元运算符:():()?()
- 格式:(条件表达式) ? 表达式1 : 表达式2;
- true:执行表达式1
- false:执行表达式2
- 格式:(条件表达式) ? 表达式1 : 表达式2;
class Demo{
public static void main(String[] args){
int a = 3, b = 4;
int max = a > b ? a : b;
}
}
语句
程序流程控制
- 判断结构
class Demo{
public static void main(String[] args){
/**
* 1、if (条件表达式){ 执行语句 }
* 2、if (条件表达式){ 执行语句 }else{ 执行语句 }
* 3、if (条件表达式){ 执行语句 }else if(条件表达式){ 执行语句 } ... else{ 执行语句 }
*/
int a = 3;
// 格式1:
if (a > 1){
System.out.println("a > 1");
}
// 格式2:
int b;
if (a > 3){
b = 10;
System.out.println("a > 3" + b);
}else{
b = 20;
System.out.println("a <= 3" + b);
}
// 等价于 三目运算符,是if else 的简化
// 三目运算符有局限性,是运算符,必须有结果,而if else 可以没有结果,有结果可以优化为三元运算符
b = a > 3 ? 10 : 20;
// 格式3:
if (a < 1){
System.out.println("a < 1");
}else if (a < 10){
System.out.println("a < 10");
}else if (a < 100){
System.out.println("a < 100");
}else{
System.out.println("其他情况");
}
// 语句的嵌套
int aa = 1; bb = 3;
if(aa == 1){
if(bb == 3){
System.out.println("aabb");
}else{
System.out.println("aa");
}
}else{
if(bb == 3){
System.out.println("bb");
}else{
System.out.println("");
}
}
if(false); // if语句结束
{
System.out.println("hello zimo");
}
if(false){
System.out.println("hello zimo");
}
// 局部代码块,可以定义局部变量的生命周期
{
int aaa = 10;
System.out.println(aaa);
}
System.out.println(aaa); // err aaa已经被释放了
}
}
- 选择结构
class Demo{
public static void main(String[] args){
/*
* switch(表达式){
* case 1:
* 执行语句;
* break;
* case 2:
* 执行语句;
* break;
* ......
* default:
* 执行语句;
* break;
* }
*/
int type = 3;
switch(type){
case 1:
System.out.println("1");
break;
case 2:
System.out.println("2");
break;
case 3:
System.out.println("3");
break;
default:
break;
}
}
}
- 循环结构
class Demo{
public static void main(String[] args){
/*
* while、do-while、for
*
* while(条件表达式){
* 执行语句;
* }
*
* 条件是否满足,循环体至少执行一次
* do{
* 执行语句;
* }while(条件表达式);
*
* for(初始化表达式; 循环条件表达式; 循环后操作的表达式){
* 执行语句;
* }
*/
int x = 1;
// 方式1:
while(x < 3){
System.out.println("x = " + x++);
}
// 方式2:
do{
System.out.println("x = " + x++);
}while(x < 3);
// 方式3:
for(int i = 1; i < 3; i++){
System.out.println("i = " + i);
}
int x = 1;
for(System.out.println("a"); x < 3; System.out.println("d")){
System.out.println("c");
}
/// a d c d c
for(int a =0,b = 1; b < 20;b++){}
// 无限循环 死循环
for(;;){}
while(true){}
do{}while(true);
}
}
if和switch的应用场景:
- if:
- 对具体的值进行判断
- 对区间判断
- 对运行结果是boolean类型的表达式进行判断
- switch:
- 对具体的值进行判断
- 值的个数通常是固定的
对于几个固定的值判断,建议使用switch语句,因为switch语句会将具体的答案都加载进内存,效率相对高一点。
for 和 while 的特点:
- for和while可以互换
- 格式上的不同,在使用上有些小区别
- 如果需要通过变量来对循环进行控制,该变量只作为循环增量存在时,区别就体现了,for循环使用完就会自动释放
函数
- 函数的定义
- 函数就是定义在类中的具有特定功能的一段独立小程序。
- 函数也称方法
定义函数的格式:
修饰符 返回值类型 函数名(参数类型 形式参数1,参数类型 形式参数2,...){
执行语句1;
执行语句2;
...
执行语句n;
return 返回值;
}
// 返回值类型:函数运行后的结果的数据类型
// 参数类型:是形式参数的数据类型
// 形式参数:是一个变量,用于存储调用函数时传递给函数的实际参数
// return:用于结束函数
// 返回值:该函数运算后的结果,该结果会返回给调用者
/*
* 特殊情况:功能没有具体返回值
* 1、直接结束:return;
* 2、返回值类型为:void
* 总结:
* 没有返回值类型时,返回值类型用void 表示,return语句也可以省略不写
*/
class Demo{
public static int add(int a, int b){
return a + b;
}
public static void main(String[] args){
add(4+5);
}
}
-
函数的特点
- 定义函数可以将功能代码进行封装
- 便于对该功能进行复用
- 函数只有被调用才会被执行
- 函数的出现提高了代码的复用性
- 对于函数没有具体返回值的情况,返回值类型用关键字void表示,那么该函数中的return语句如果再最后一行可以省略不写
- 注意事项
- 函数中智能调用函数,不可以在函数内部定义函数
- 定义函数时,函数的结果应该返回给调用者,交由调用者处理。
-
函数的应用
- 明确一:功能的结果是什么?
- 明确函数的返回类型
- 明确二:实现过程中是否需要未知内容参数参与运算?
- 明确参数列表
- 明确一:功能的结果是什么?
-
函数的重载
- 重载的概念:在同一个类中,允许存在一个以上的同名函数,只要它们的参数个数或者参数类型不同即可
- 重载的特点:与返回值类型无关,只看参数列表
- 重载的好处:方便于阅读,优化了程序设计
- 重载示例:
int add(int x, int y) { return x + y; }
返回两个整数和int add(int x, int y, int z) { return x + y + z; }
返回三个整数和- double add(doule x, double y) { return x + y; }` 返回两小数和
函数的功能一样,仅仅是参与运算的未知内容不同时,可以定义多函数,却使用统一函数名称,这样方便阅读,虚拟机通过参数列表不同来区分同名函数
/* * 函数的重载: * 1.同一个类中 * 2.同名函数 * 3.参数个数不同,或者参数类型不同 * 4.函数重载和返回值类型无关 * 5.java是严谨性语言,如果函数出现调用的不确定性,编译失败 */ class Demo{ public static double add(double a, double b){ return a + b; } public static int add(int a, int b){ return a + b; } public static int add(int a, int b, int c){ return a + b + c; } public static void main(String[] args){ } }
数组
-
数组的定义
- 数组的概念:同一种类型数据的集合。其实数组就是一个容器
- 数组的好处:可以自动给数组中的元素从开始编号,方便操作这些元素。
- 定义格式:
元素类型[] 数组名 = new 元素类型[元素个数或者数组长度];
例如:int[] arr = new int[5];
元素类型[] 数组名 = new 元素类型[] {元素1,元素2,......};
int[] arr = new int[]{1,3,5,7};
int[] arr = {1,3,5,7};
-
数组的内存分配及特点
大致内存分区:寄存器、本地方法区、方法区、栈内存、堆内存
-
栈内存:
-
存储的都是局部变量
-
变量所属作用域结束,该变量自动释放
-
-
堆内存
- 存储的是数组和对象(其实数据就是对象)凡是new建立的都在堆中
- 特点:
- 每个实体都有首地址值
- 堆内存中的每一个变量都有默认初始化值,根据类型不同而不同,整数:0、小数:0.0,0.0f、布尔:false、字符:’\u0000’
- 堆的内存自动回收机制
-
- 数组操作常见问题
class Demo{
public static void main(String[] args){
// 方式1:
int[] arr = new int[3];
// 方式2:
int[] arr1 = new int[]{1,3,4,6,7,9}; // 动态分配并初始化
int[] arr2 = {1,2,3,4,5}; // 静态初始化方式
// 问题1:当访问到数组中不存在的角标时,就会发生异常。ArrayIndexOutOfBoundsException
System.out.println(arr[3]); // err 运行时错误: 数组脚标异常,数组越界
// 问题2:当引用型变量没有任何实体指向时,还在用其操作实体,就会发生异常。NullPointException
arr = null;
System.out.println(arr[0]); // 空指针异常
}
}
- 数组常见操作
class Demo{
public static void main(String[] args){
/*
* 对数组操作最基本的动作就是存和取
* 核心思想:就是对角标的操作
*/
/// 【数组遍历】 ///
int[] arr = {1,2,3,4,5,6};
for(int i = 0; i < arr.length; i++){
System.out.println(arr[i]);
}
// 获取最值(最大值,最小值)
int Max = arr[0],Min = arr[0]; // 初始化为 数组数据
int maxIndex = 0, minIndex = 0; // 初始化为 数组脚标
for(int i = 1; i < arr.length; i++){
if(arr[i] > Max){
Max = arr[i];
maxIndex = i;
}
if(arr[i] < Min){
Min = arr[i];
minIndex = i;
}
}
System.out.println("Max = "+Max+",Min = "+Min);
System.out.println("Max = "+arr[maxIndex]+",Min = "+arr[minIndex]);
/// 【数组排序】(选择排序、冒泡排序)///
int[] array = {12,40,4,56,1};
// 选择排序
for(int i = 0; i < array.length; i++){
for(int j = i + 1; j < array.length; j++){
if(array[i] > array[j]){
int tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
}
}
// 选择排序优化
for(int i = 0; i < array.length; i++){
int num = array[i], index = i;
for(int j = i + 1; j < array.length; j++){
if(num > array[j]){
// 记录最值 不交换
num = array[j];
index = j;
}
}
if(index != i){
// 每轮只进行一次换位
int tmp = array[i];
array[i] = array[index];
array[index] = tmp;
}
}
// 冒泡排序
for(int i =0; i < array.length - 1; i++){
for(int j = 0; j < array.lenth - 1 - x; y++){
if(array[j] > array[j+1]){
int tmp = array[j];
array[j] = array[j+1];
array[j+1] = tmp;
}
}
}
/* 冒泡另一种写法
for(int x = arr.length - 1; x > 0; x--)
for(int y = 0; y < x; y++)
*/
// 封装交换算法
{
void swap(int[] arr, int x, int y){
int tmp = array[x];
array[x] = array[y];
array[y] = tmp;
}
}
/// 【数组查找】 ///
int[] arr = {1,3,5,7,9}, findValue = 5;
// 查找
for(int i = 0; i < arr; i++){
if(arr[i] == findValue){
return i;
}
}
// java提供的二分查找 如果存在返回:插入点下标 不存在返回:-脚标-1
Arrays.binarySearch(arr,9);
// 折半/二分查找(前提数组必须有序)
int[] arr1 = {10,23,35,47,59};
int min = 0,max,mid;
max = arr1.length - 1;
mid = (min + max) / 2;
// 11111111
{
while(arr[mid]!=findValue){
if(findValue > arr[mid]){
min = mid + 1;
}else if(findValue < arr[mid]){
max = mid - 1;
}
if(max < min){
return -1;
}
mid = (max + min) / 2;
}
}
// 22222222
{
while(min <= max){
mid = (max + min) >> 1;
if(findValue > arr[mid]){
min = mid + 1;
}else if(findValue < arr[mid]){
max = mid - 1;
}else{
return mid;
}
}
return -1
}
// 二进制转十六进制
{
// 1、传统转换 输出结果反,且多了0
public static void toHex(int num){
for(int i = 0; i < 8; i++){
int temp = num & 15;
if(temp > 9){
System.out.println((char)(temp-10 + 'A'));
}else{
System.out.println(temp);
}
num = num >>> 4;
}
}
// 2、数组查表法
public static void toHex1(int num){
if(num == 0){
System.out.println(num);
return;
}
// 对应关系表
char[] chs = {'0','1','2','3',
'4','5','6','7',
'8','9','A','B',
'C','D','E','F'
};
/*
for(int i = 0; i < 8; i++){
int temp = num & 15;
System.out.println(chs[temp]);
num = num >>> 4;
}*/
char[] arr = new char[8];
int pos = arr.length;
while(num != 0){
int temp = num & 15; // 转十六进制 与上 1111 每次取出四位
arr[--pos] = chs[temp];
num = num >>> 4;
}
for (int i = pos; i < arr.length; i++){
System.out.println(arr[i]);
}
}
// 通用进制转换 num 转换的值十进制数 base 转换的进制(2,8,16) offset 位运算偏移多少
public static void trans(int num, int base, int offset){
if(num == 0){
System.out.println(num);
return;
}
/*switch(base){
case 2:
offset = 1;
break;
case 8:
offset = 3;
break;
case 16:
offset = 4;
break;
}*/
base -= 1; // 方便位运算
// 对应关系表
char[] chs = {'0','1','2','3',
'4','5','6','7',
'8','9','A','B',
'C','D','E','F'
};
char[] arr = new char[32];
int pos = arr.length;
while(num != 0){
int temp = num & base;
arr[--pos] = chs[temp];
num = num >>> offset;
}
for (int i = pos; i < arr.length; i++){
System.out.println(arr[i]);
}
}
}
}
![数组查找
- 数组中的数组
二维数组 [ ] [ ]
格式1:int[][] arr = new int[3][2];
- 定义了名称为arr的二维数组
- 二维数组中有三个一维数组
- 每个一维数组有两个元素
- 一维数组名称分别为arr[0], arr[1], arr[2]
- 给第一个一维数组1角标位置赋值为78可表示为:arr[0] [1] = 78;
格式2:int[][] arr = new int[3][];
- 二维数组中有三个一维数组
- 每个一维数组都是默认初始化值null
- 可以对三个一维数组分别进行初始化
- arr[0] = new int[3];
- arr[1] = new int[1];
- arr[2] = new int[2];
class Demo{
public static void main(String[] args){
int[][] arr = new int[3][2];
int[][] arr1 = new int[3][];
// 分别对二维数组中的内一个小数组进行初始化
arr1[0] = new int[2];
arr1[1] = new int[1];
arr1[2] = new int[3];
int[][] arr2 = {{1,3,85},{5,9,1,7},{53,14}};
int sum = 0;
for(int i = 0; i < arr2.length; i++){
for(int j = 0; j < arr2[i].length; j++){
sum += arr2[i][j];
}
}
}
}