# Java基础
# JAVA开发环境
# java编译运行过程
- 编译期:.java源文件,经过编译,生成.class字节码文件
- 运行期:JVM加载.class并运行.class
特点:跨平台、一次编程到处使用
# 名词解释
JVM:java虚拟机
加载.class并运行.class
JRE:java运行环境
除了包含JVM以外还包含了运行java程序所必须的环境
JRE=JVM+java系统类库(小零件)JDK:java开发工具包
除了包含JRE以外还包含了开发java程序所必须的命令工具
JDK=JRE+编译、运行等命令工具
说明:
2.1)运行java程序的最小环境为JRE
2.2)开发java程序的最小环境为JDK
- 配置环境变量
3.1)JAVA_HOME:指向jdk的安装目录
3.2)CLASSPATH:表示类的搜索路径,一般简写为.
3.3)PATH:指向jdk下的bin目录
# Eclipse
IBM、开源的、免费的、不需要安装仅需要解压即可
开发步骤:
- 新建Java项目/工程-------------------小区
- 新建Java包--------------------------楼号+单元号
- 新建Java类--------------------------房子
注释:解释性文本
- 单行注释://
- 多行注释:/* */
- 文档注释:/** */-----------------4月份
# 变量
变量:存数的
- 声明:
int a; //声明一个整型的变量,名为a int b,c,d; //声明三个整型的变量,名为b,c,d
- 初始化:第一次赋值
- 声明的同时初始化
int a = 250; //声明整型变量a并赋值为250
- 先声明后初始化
int a; //声明整型变量a a = 250; //给变量a赋值为250
- 使用:
- 对变量的就是对它所存的那个数的操作
int a = 5; int b = a+10; //取出a的值5,加10后,再赋值给整型变量b System.out.println(b); //输出变量b的值15 System.out.println("b"); //输出b,双引号中的原样输出 a = a+10; //取出a的值5,加10后,再赋值给a //在a本身基础之上增10 System.out.println(a); //15
- 变量的操作必须与数据类型匹配
int a = 3.14; //编译错误,数据类型不匹配
- 变量在用之前必须声明并初始化
System.out.println(m); //编译错误,m未声明 int m; System.out.println(m); //编译错误,m未初始化
- 命名:
- 只能包含字母、数字、_和$符,并且不能以数字开头
- 严格区分大小写
- 不能使用关键字
- 可以中文命名,但不建议
TIP
建议:"英文的见名知意"、"驼峰命名法"
- 变量的作用域
变量的作用域/范围: //作用域就是大括号
从变量的声明开始,到包含它最近的大括号结束变量的重名问题:
作用域重叠时,变量不能同名
- 声明:
//1.变量的声明:
int a; //声明一个整型的变量,名为a
int b,c,d; //声明三个整型的变量,名为b,c,d
//2.变量的初始化:第一次赋值
int e = 25; //声明整型变量e并赋值为25
int f; //声明整型变量f
f = 25; //给变量f赋值为25
//3.变量的使用:
int g = 5; //声明整型变量g并赋值为5
int h = g+10; //取出g的值5,加10后,再赋值给整型变量h
System.out.println(h); //输出变量h的值15
System.out.println("h"); //输出h,双引号中的原样输出
g = g+10; //取出g的值5,加10后,再赋值给g
//在g本身基础之上增10
System.out.println(g); //输出15
//int i = 34.567; //编译错误,数据类型不匹配
//System.out.println(m); //编译错误,m未声明
int m;
//System.out.println(m); //编译错误,m未初始化
//4.变量的命名:
int a1,a_5$,_b7,$_;
//int a*b; //编译错误,不能包含*号等特殊符号
//int 1a; //编译错误,不能以数字开头
int aa = 5;
//System.out.println(Aa); //编译错误,严格区分大小写
//int class; //编译错误,不能使用关键字
int 年龄; //正确,但不建议
int age; //建议"英文的见名知意"
int score,myScore,myJavaScore; //建议"驼峰命名法"
# 基本数据类型
# int:整型
4个字节,-21个多亿到21个多亿
- 整数直接量默认为int型,不能超出范围,超出范围则编译错误
- 两个整数相除,结果还是整数,小数位无条件舍弃(不会四舍五入)
- 整数运算时超出范围,则发生溢出(需要避免的)
//1.int:整型,4个字节,-21个多亿到21个多亿
int a = 250; //250为整数直接量,默认为int型
//int b = 10000000000; //编译错误,100亿默认为int型,但超出范围了
System.out.println(5/2); //2
System.out.println(2/5); //0
System.out.println(5/2.0); //2.5
int c = 2147483647; //int的最大值
c = c+1;
System.out.println(c); //溢出了,是需要避免的
# long:长整型
8个字节,很大很大很大
- 长整型直接量需在数字后加L或l
- 运算时若有可能溢出,建议在第1个数字后加L
- System.currentTimeMillis()用于获取自1970.1.1零时到此时此刻的毫秒数
//2.long:长整型,8个字节,很大很大很大
//long d = 10000000000; //编译错误,100亿默认为int型,但超出int范围了
long e = 10000000000L; //100亿L为长整型直接量
long f = 1000000000*2*10L;
System.out.println(f); //200亿
long g = 1000000000*3*10L;
System.out.println(g); //不是300亿
long h = 1000000000L*3*10;
System.out.println(h); //300亿
long i = System.currentTimeMillis();
System.out.println(i); //
# double:浮点型
8个字节,很大很大很大
- 浮点数直接量默认为double型,表示float需在数字后加F或f
- 浮点型数据在运算时,有可能会出现舍入误差
//3.double:浮点型,8个字节,很大很大很大
double j = 3.14; //3.14为浮点数直接量,默认为double型
float k = 3.14F; //3.14F为float直接量
double m=6.0,n=4.9;
System.out.println(m-n); //0.10000000000000009
# boolean:布尔型
1个字节
- 只能取值为true和false
//4.boolean:布尔型,1个字节
boolean b1 = true; //true为布尔型直接量
boolean b2 = false;
//boolean b3 = 25; //编译错误,布尔型只能存储true和false
# char:字符型
2个字节
- 采用的是Unicode字符集编码格式,每个字符都有一个对应的码(0到65535之间),表现的形式的是字符char,实质上是码int ASCII码('a'--97 'A'--65 '0'--48)
- 字符直接量必须放在单引号中,只能有一个
- 特殊符号需通过\来转义
//5.char:字符型,2个字节
char c1 = '女';
char c2 = 'f';
char c3 = '6';
char c4 = ' ';
//char c5 = 女; //编译错误,字符必须放在单引号中
//char c6 = ''; //编译错误,必须有字符
//char c7 = '女性'; //编译错误,只能有一个字符
char c8 = 65; //0到65535之间
System.out.println(c8); //A
char c9 = '\\';
System.out.println(c9); //\
# 基本数据类型间的转换
数据类型从小到大依次为:
byte,short,int,long,float,double
char
两种方式:
- 自动类型转换:从小类型到大类型
- 强制类型转换:从大类型到小类型
TIP
语法: (要转换成为的数据类型)变量
强转有可能会溢出或丢失精度两点规则:
- 整数直接量可以直接赋值给byte,short,char,但不能超出范围
- byte,short,char型数据参与运算时,先一律转换为int再运算
// 数据类型间的转换:
int a = 5;
long b = a; //自动类型转换
int c = (int)b; //强制类型转换
long d = 5; //自动类型转换
double e = 5; //自动类型转换
System.out.println(e); //5.0
long f = 10000000000L;
int g = (int)f;
System.out.println(g); //强转有可能会发生溢出
double h = 56.9876;
int i = (int)h;
System.out.println(i); //强转有可能会发生精度的丢失
byte b1 = 5;
byte b2 = 6;
byte b3 = (byte)(b1+b2);
System.out.println(2+2); //4
System.out.println('2'+'2'); //100,'2'的码50,加上,'2'的码50
//
# Scanner接收用户的输入:
1)在package下:
import java.util.Scanner;
2)在main方法中:
Scanner scan = new Scanner(System.in);
3)在第2步之下:
System.out.println("请输入年龄:");
int age = scan.nextInt();
System.out.println("请输入价格:");
double price = scan.nextDouble()
# 运算符
# 运算符
算术:+,-,*,/,%,++,--
- %:取模/取余,余数为0即为整除
System.out.println(5%2); //1,商2余1 System.out.println(8%2); //0,商4余0--整除 System.out.println(2%8); //2,商0余2
++/--:自增1/自减1,可在变量前也可在变量后
单独使用时,在前在后无差别
被使用时,在前在后有差别
TIP
a++的值为a
++a的值为a+1int a=5,b=5; //1)输出a--的值5 //2)a自减1变为4 System.out.println(a--); //5 System.out.println(a); //4 //1)输出--b的值4 //2)b自减1变为4 System.out.println(--b); //4 System.out.println(b); //4 int a=5,b=5; int c=a++; //1)将a++的值5赋值给c 2)a自增1变为6 int d=++b; //1)将++b的值6赋值给d 2)b自增1变为6 System.out.println(a); //6 System.out.println(b); //6 System.out.println(c); //5 System.out.println(d); //6 int a=5,b=5; a++; //相当于a=a+1 ++b; //相当于b=b+1 System.out.println(a); //6 System.out.println(b); //6
关系:>,<,>=,<=,==,!=。结果为 boolean型
int a=5,b=10,c=5; boolean b1 = a>b; System.out.println(b1); //false System.out.println(c<b); //true System.out.println(a>=c); //true System.out.println(a<=b); //true System.out.println(a==c); //true System.out.println(a!=c); //false System.out.println(a%2==0); //false
逻辑:&&,||,! boolean
&&:短路与(并且),两边都为真则为真,见false则false
当第1个数为false时,发生短路(后面的不执行了)||:短路或(或者),有一边为真则为真,见true则true
当第1个数为true时,发生短路(后面的不执行了)!:逻辑非(取反),非真则假,非假则真
逻辑运算是建立在关系运算的基础之上的
TIP
逻辑运算的结果也是boolean型
boolean b1 = b>=a && b<c; System.out.println(b1); //true&&false=false System.out.println(b<=c && a<b); //false&&true=false System.out.println(a==b && c>b); //false&&false=false System.out.println(a!=b && c<b); //true&&true=true System.out.println(b>=a || b<c); //true||false=true System.out.println(b<=c || a<b); //false||true=true System.out.println(a!=b || c<b); //true||true=true System.out.println(a==b || c>b); //false||false=false boolean b2 = !(a<b); System.out.println(b2); //!true=false System.out.println(!(a>b)); //!false=true 逻辑段路** int a=5,b=10,c=5; boolean b4 = a<b || c++>2; System.out.println(b4); //true System.out.println(c); //5,发生短路了 boolean b3 = a>b && c++>2; System.out.println(b3); //false System.out.println(c); //5,发生短路了
赋值:=,+=,-=,*=,/=,%=
- 简单赋值运算:=
- 扩展赋值运算:+=,-=,*=,/=,%=
int a = 5; a += 10; //相当于a=a+10 System.out.println(a); //15 a *= 2; //相当于a=a*2 System.out.println(a); //30 a /= 6; //相当于a=a/6 System.out.println(a); //5
字符串连接:+
- 若两边都是数字,则做加法运算
- 若两边出现了字符串,则做字符串连接
int age = 37; System.out.println("age="); //age= System.out.println(age); //37 System.out.println("age="+age); //age=37 System.out.println("我的年龄是:"+age); System.out.println("我今年"+age+"岁了"); System.out.println(10+20+""+30); //"3030" System.out.println(""+10+20+30); //"102030" System.out.println(10+20+30+""); //"60"
条件/三目:boolean?数1:数2
- 语法:
boolean?数1:数2
- 执行过程:
计算boolean的值:
若为true,则整个的结果为数1
若为false,则整个的结果为数2int a=8,b=55; int max = a>b?a:b; //求a和b的最大值 System.out.println("max="+max); int a=-5; int b = a>2?1:-1; System.out.println(b);
# 分支结构
if结构:1条路
int num = 6; if(num%2==0){ System.out.println(num+"是偶数"); } System.out.println("over");
if...else结构:2条路
int num = 5; if(num%2==0){ System.out.println(num+"是偶数"); }else{ System.out.println(num+"是奇数"); } System.out.println("over");
两个数的排序:
int a=8,b=55;
if(a>b){
int t=a;
a=b;
b=t; //追尾并绕环
}
System.out.println("a="+a);
System.out.println("b="+b);
if...else if结构:多条路
double score = scan.nextDouble(); if(score>100 || score<0){ System.out.println("您的输入有误"); }else if(score>=90){ System.out.println("成绩优秀"); }else if(score>=80){ System.out.println("成绩良好"); }else if(score>=70){ System.out.println("成绩中等"); }else if(score>=60){ System.out.println("成绩及格"); }else{ System.out.println("成绩不及格"); }
switch...case结构:多条路
- 优点:效率高、结构清晰
- 缺点:只能用于整数(不包括long)、判断相等。
- break:跳出switch
Scanner scan = new Scanner(System.in); System.out.println ("请选择功能: 1.显示全部记录 2.查询登录记录 0.退出"); int command = scan.nextInt(); switch(command){ case 1: System.out.println("显示全部记录"); break; case 2: System.out.println("查询登录记录"); break; case 0: System.out.println("欢迎下次再来!"); break; default: System.out.println("输入错误"); }
# 循环
反复执行一段相同或相似的代码(反复做事)
循环三要素:
循环变量的初始化
循环的条件(以循环变量为基础)
循环变量的改变(向着循环的结束变)
循环变量:在整个循环过程中所反复改变的那个数
循环结构:
- while:先判断后执行,有可能一次都不执行
//输出10遍行动是成功的阶梯 int times=0; //1.循环变量的初始化 while(times<10){ //2.循环的条件 System.out.println("行动是成功的阶梯"); times++; //3.循环变量的改变 } System.out.println("over");
- do...while:先执行后判断,至少执行一次
要素1与要素3相同时,首选do...while
int num = (int)(Math.random()*1000+1); //1到1000之内的随机数 //注意强转 System.out.println(num); //作弊 int guess; do{ System.out.println("猜吧!"); guess = scan.nextInt(); //1+3 if(guess==0){ break; } if(guess>num){ System.out.println("太大了"); }else if(guess<num){ System.out.println("太小了"); } }while(guess!=num); //2 if(guess==num){ System.out.println("恭喜你,猜对了!"); }else{ System.out.println("下次再来吧!"); }
- for:应用率高
//累加:1+2+3+4+...+99+100=? int sum = 0; //和 for(int i=1;i<=100;i++){ sum = sum+i; } System.out.println("sum="+sum); */ /* \* 执行过程: \* sum=0 \* i=1 sum=1 \* i=2 sum=1+2 \* i=3 sum=1+2+3 \* i=4 sum=1+2+3+4 \* ... \* i=100 sum=1+2+3+4+...+100 \* i=101 */
- break:跳出循环
- continue:跳过循环体中剩余语句而进入下一次循环
int sum = 0; for(int i=1;i<=100;i++){ if(sum>=4000){ break; //跳出循环 } sum = sum+i; } System.out.println("sum="+sum); //1到100的累加和,跳过个位为3的 int sum = 0; //和 for(int i=1;i<=100;i++){ if(i%10==3){ continue; } sum = sum+i; } System.out.println("sum="+sum); */ /* \* sum=0 \* i=1 sum=1 \* i=2 sum=1+2 \* i=3 \* i=4 sum=1+2+4 */
- 三种循环结构的更佳适用情况:
- while:不固定次数
要素1与要素3不同时,首选while - do...while:不固定次数
要素1与要素3相同时,首选do...while - for:应用率最高,固定次数循环
int score = 0; //得分 for(int i=1;i<=10;i++){ //10次 int a = (int)(Math.random()*100); //加数a int b = (int)(Math.random()*100); //加数b int result = a+b; //存答案 System.out.println("("+i+")"+a+"+"+b+"=?"); //1.出题 System.out.println("算吧!"); int answer = scan.nextInt(); //2.答题 if(answer==-1){ //3.判题 break; } if(answer==result){ System.out.println("答对了"); score += 10; //答对1题加10分 }else{ System.out.println("答错了"); } } System.out.println("总分为:"+score);
# 嵌套循环
- 循环中套循环,一般多行多列时使用,外层控制行,内层控制列
- 执行过程:外层走一次,内层走所有次
- 建议:循环层数越少越好,能用一层就不用两层,能用两层就不用三层
- break只能跳出一层循环
WARNING
若业务必须通过三层以上的循环来解决,说明你的设计有问题
for(int num=1;num<=9;num++){ //控制行
for(int i=1;i<=num;i++){ //控制列
System.out.print(i+"*"+num+"="+i*num+"\t");
}
System.out.println(); //换行
}
/*
\* 执行过程:
\* num=3
\* i=1 1*3=3
\* i=2 2*3=6
\* i=3 3*3=9
\* i=4
\* 换行
\* num=2
\* i=1 1*2=2
\* i=2 2*2=4
\* i=3
\* 换行
\* num=1
\* i=1 1*1=1
\* i=2
\* 换行
*/
# 程序=算法+数据结构
- 算法:解决问题的流程/步骤(顺序、分支、循环)
- 数据结构:将数据按照某种特定的结构来保存
数怎么存的问你题
设计良好的/合理的数据结构会导致好的算法
# 数组
- 是一种数据类型(引用类型)
- 相同数据类型元素的集合
- 数组的定义:
int[] arr = new int[10];
- 数组的初始化:
int[] arr = new int[3]; //0,0,0
int[] arr = {1,4,7}; //1,4,7
int[] arr = new int[]{1,4,7}; //1,4,7
int[] arr;
arr = {1,4,7}; //编译错误,此方式只能声明同时初始化
arr = new int[]{1,4,7}; //正确
- 数组的访问:
- 通过数组名.length来获取数组的长度(元素的个数)
int[] arr = new int[10]; System.out.println(arr.length); //10
- 通过下标/索引来访问元素
//下标从0开始,最大到(数组的长度-1) int[] arr = new int[3]; arr[0] = 10; arr[1] = 20; arr[2] = 30; arr[3] = 40; //数组下标越界异常 System.out.println(arr[arr.length-1]);
- 数组的遍历:
int[] arr = new int[10];
for(int i=0;i<arr.length;i++){
arr[i] = 100;
}
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
for(int i=arr.length-1;i>=0;i--){
System.out.println(arr[i]);
}
int[] arr = new int[10];
for(int i=0;i<arr.length;i++){
arr[i] = (int)(Math.random()*100);
System.out.println(arr[i]);
}
//找最大值标准代码
int max = arr[0]; //假设第1个元素为最大值
for(int i=1;i<arr.length;i++){ //遍历剩余元素
if(arr[i]>max){ //若剩余元素大于max
max=arr[i]; //修改max为较大的值
}
}
System.out.println("最大值为:"+max);
数组的复制:
- System.arraycopy(a,1,a1,0,4);
注意:第二的参数与最后一个参数合起来不能超范围; int[] a = {10,20,30,40,50}; int[] a1 = new int[6]; //0,0,10,20,30,0 //a:源数组 //1:源数组的起始下标 //a1:目标数组 //0:目标数组的起始下标 //4:要复制的元素个数 System.arraycopy(a,1,a1,0,4); //灵活性好、效率高 for(int i=0;i<a1.length;i++){ System.out.println(a1[i]); }
- int[] a1 = Arrays.copyOf(a,6);(原数组,扩展后数组的长度)
a = Arrays.copyOf(a,a.length+1); //数组的扩容
WARNING
注意:需要import
//7.数组的复制:
int[] a = {10,20,30,40,50};
//数组的扩容(创建了一个新的数组并将源数组数据复制进去)
a = Arrays.copyOf(a,a.length+1);
for(int i=0;i<a.length;i++){
System.out.println(a[i]);
}
int[] a = {10,20,30,40,50};
//a:源数组
//a1:目标数组
//6:目标数组的长度
int[] a1 = Arrays.copyOf(a,6); //灵活性差,效率低
for(int i=0;i<a1.length;i++){
System.out.println(a1[i]);
}
数组的排序:
- Arrays.sort(arr); //升序
int[] arr = {23,27,3,45,28,67}; Arrays.sort(arr); //升序 for(int i=0;i<arr.length;i++){ //把for到着来就是倒序 System.out.println(arr[i]); }
- 冒泡排序:
- 五个数冒四轮
- 每一轮都是从第1个元素开始冒
- 每一次都是和它的下一个元素比
- 冒出来的就不带它玩了
int[] arr = {23,27,3,45,28,67}; for(int i=0;i<arr.length-1;i++){ for(int j=0;j<arr.length-1-i;j++){ if(arr[j]<arr[j+1]){ int t = arr[j]; arr[j] = arr[j+1]; arr[j+1] = t; } //若前数大于后数则交换,保证前数小于后数(升序) //若前数小于后数则交换,保证前数大于后数(降序) } } for(int i=0;i<arr.length;i++){ System.out.println(arr[i]); }
# 方法
- 封装一段特定的业务逻辑功能
- 方法尽可能的独立,只干一件事
- 方法可以被反复多次的调用
- 减少代码重复,有利于代码的维护,有利于团队的协作开发
- 方法的定义:
修饰词 返回值类型 方法名(参数列表){
方法体
}
方法的调用:
- 无返回值: 方法名(有参传参);
- 有返回值: 数据类型 变量 = 方法名(有参传参);
return的用法:
- return 值; //1.1)结束方法的执行 1.2)返回结果给调用方
- return; //2.1)结束方法的执行;(用于在特殊情况下提前终止方法)
# 猜字符小游戏
设计数据结构:变量
- char[] chs; //随机字符数组
- char[] input; //用户输入的字符数组
- int[] result; //对比结果
- int score; //得分
设计程序结构:方法
- 主方法:
public static void main(String[] args){ ... }
- 生成随机字符数组chs:
public static char[] generate(){ char[] chs = new char[5]; //... return chs; }
- 对比:随机字符数组chs与用户输入的字符数组input
public static int[] check(char[] chs,char[] input){ int[] result = new int[2]; //... return result; }
- 设计算法:方法体
String str =”abc”;
- 将字符串转换为字符数组
Char[] input = str.toCharArray();
- 将字符数组转换为大写字母
Str = str.toUpperCase(); 将字符串转换为大写字母 Str = str.toLowerCase();
- 判断字符串内容是否相等
If(str.equals(“abc”)){ }
- 开关用在去掉重复(比如发牌)
String str = “....”; str.toCharArray(); //字符串转字符数组 str.toUpperCase(); Str.toLowerCase();//将字符串小写字母转换为大写字母 引用类型判断内容相等用equale();
import java.util.Scanner;
//猜字符的小游戏
public class GuessingGame {
//主方法
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
char[] chs=generate();//生成随机数组
System.out.println(chs);//作弊
int count=0;
while(true){
System.out.println("猜吧");
String str=scan.next().toUpperCase();
if(str.equals("EXIT")){
System.out.println("下次再来吧!");
break;
}
char[] input=str.toCharArray();
int[] result=check(chs,input);
if(result[0]==chs.length){
int score = 100*chs.length-count*10;
System.out.println("猜对啦!");
break;
}else{
count++;
System.out.println("猜错啦!字符对的个数为:"+result[1]+",位置对的个数为:"+result[0]);
}
}
}
//生成随机字符数组
public static char[] generate(){
char[] chs = new char[5];
char[] letters={ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z' };
boolean[] flag=new boolean[letters.length];
int[] index = new int[5];
for(int i=0;i<chs.length;i++){
do{
index[i]=(int)(Math.random()*letters.length);
}while(flag[index[i]]==true);
chs[i]=letters[index[i]];
flag[index[i]]=true;
}
return chs;
}
//对比:随机数组chs与用户输入的数组input对比
public static int[] check(char[] chs, char[] input){
int[] result = new int[2];//int数组1为对的个数,0为位置对的个数
for(int i=0; i<chs.length;i++){//遍历chs数组
for(int j=0; j<input.length;j++){//遍历input数组
if(chs[i]==input[j]){//对比是否相同
result[1]++;
if(i==j){//对比位置是否相同
result[0]++;
}
break;
}
}
}
return result;
}
}