本篇 Java 的学习路线是参考韩顺平老师的教程
教程:零基础 30 天学会 Java
https://www.bilibili.com/video/BV1fh411y7R8
之前学习编程的时候并没有一个良好的记录习惯,这些技能平时工作上又用不上,导致时间长了基本都忘完了,不得已只好从头再学一遍
# Java 语言的特点
-
Java 语言是面向对象的(oop)
-
Java 语言是强类型语言,Java 的强类型机制、异常处理、垃圾的自动收集等是 Java 程序强壮性的重要保证
-
Java 是跨平台性的
通过 javac 编译源程序.java (源文件),生成源程序.class (字节码文件), 这个源程序.class 字节码文件可以通过 JVM 实现在不同的操作系统平台运行
- Java 是解释型语言
解释型语言和编译型语言的区别:解释型语言不能直接被机器执行,需要由解释器执行,编译型语言通过编译后的代码可以直接被机器执行
# Java API
API (Application Programming Interface) 是 JAVA 提供的基本编程接口,这些接口是 JAVA 自身提供的类和方法,可以直接调用,极大程度上减轻了开发者的工作量
中文在线文档 https://www.matools.com
-
How to use ?
-
Package --> Class --> Mathod
# 基础语法
和以往学过的任何编程语言一样,开头还是熟悉的 hello world
,语法结构大同小异,看不懂也没关系,前期靠的是多敲代码,熟悉基本的原理和基本的语法,程序能正常跑起来就行了,随着学习的深入,自然会了解每一行的代码的意思
这里有一件比较有意思的事,就是通过 javac
把源程序.java 编译成源程序.class, 使用 java
运行源程序.class 时不需要加上后缀,如果加上后缀的话程序会报错,提示找不到或无法加载主类源程序.class, 这是因为类并不总是从 .class 文件加载,有时它们来自 JAR 包,有时它们来自互联网,有时它们是由程序动态构建的等等,所以我们运行的时候,只需要执行类名即可
//public class Hello 表示 Hello 是一个属于 public 的类 | |
public class Hello{ | |
//public static void main (String [] args) 是程序的入口 | |
pubilc statis void main(String[] args){ | |
// System.out.println 表示把括号内的内容输出到屏幕并换行 | |
System.out.println("hello world"); | |
} | |
} |
# Java 开发规范
-
Java 源文件以.java 为扩展名,源文件的基本组成部分是类 (class)
-
Java 应用程序的执行入口是 main () 方法
-
Java 语言严格区分大小写
-
Java 方法由一条条语句构成,每个语句以 ";" 结束
-
大括号是成对出现的,缺一不可,需要养成先写 {} 再写代码的习惯
-
一个源文件中最多只能有一个 public 类,其它类的个数不限
-
如果源文件包含一个 public 类,则文件名必须按照该类名命名
-
一个源文件中最多只能有一个 public 类,其它类的个数不限,也可以将 main 方法写在非 public 类中,然后指定运行非 public 类,这样入口方法就是非 public 的 main 方法
# 文档注释
注释内容可以被 JDK 提供的工具 javadoc 解析,生成一套以网页文件形式体现的该程序说明文档
- example
/** | |
* @author Bob | |
* @version 1.0.0 | |
*/ | |
public class Comment{ | |
public static void main(String[] args){ | |
System.out.println("Comment example!"); | |
} | |
} |
// 使用 javadoc 生成说明文档 | |
javadoc -d /tmp/ -author -version Comment.java |
- 运行结果
这里有个警告,好像是说 main 方法没有注释,无需理会,打开生成的 index.html,可以看到 author 和 version 的信息已经出现在文档里面了
- index.html
# 转义字符
和其它语言一样,如果希望程序输出一些特殊的符号,需要使用转义字符将其输出,这里只挑几个常用的转义字符进行说明
转义字符 | 意义 |
---|---|
\t | 水平制表 (Tab 键) |
\n | 换行符 |
\ \ | 反斜线字符 "\" |
\' | 单引号 ' 字符 |
\" | 双引号 " 字符 |
\r | 回车 |
- example
public class Escape{ | |
public static void main(String[] args){ | |
System.out.println("China\tGuangDong\tGuangZhou"); | |
System.out.println("c:\\windows\\system32\\drivers"); | |
System.out.println("\"Lift is \'short\',your need keep \'learning\'\""); | |
System.out.println("89345\r12"); | |
} |
- 输出结果
水平制表符 | |
China GuangDong GuangZhou | |
反斜杠 | |
c:\windows\system32\drivers | |
单引号和双引号 | |
"Lift is 'short',your need keep 'learning'" | |
回车 | |
12345 |
- 运行结果
其它转义字符还是比较容易理解的,这个只讲解一下换行符和回车的区别,换行符相信大家都知道是光标移动到下一行字符的起始位置,而回车则是光标移动到当行的字符起始位置,所以代码中的 98345\r12 执行结果为 12345
# 变量
变量是程序的基本组成单位,变量由类型+名称+值组成,先申明变量类型,然后给变量赋值,也可以在申明变量类型的时候直接给变量赋值
public class Variables{ | |
public static void main(String[] args){ | |
int a; // 定义一个变量,数据类型为 int 整型,变量名称为 a | |
a = 5; // 把整数 5 赋值给变量 a | |
int b = 10; // 定义一个变量,数据类型为 int 整型,变量名称为 b,值为 10 | |
System.out.printlp(a + "\n" + b); // 输出变量 a 和 b 到屏幕 | |
} | |
} |
- 运行结果
+ 是连接符号,和 pythpon 一样,可以将不同的数据类型连接起来,相同数据类型结果相加,不同数据类型起到拼接作用,下面通过代码了解它的作用
public class Plus{ | |
public static void main(String[] args){ | |
// 两个整型为结果相加 | |
System.out.println(100 + 20); | |
// 整型和字符串为拼接作用,拼接后为字符串类型 | |
System.out.println(100 + "20"); | |
// 这里先计算整型结果,然后再和字符串拼接 | |
System.out.println(100 + 20 + "hello"); | |
// 这里先把 hello 和 100 拼接,拼接后结果依然是字符串,然后再和 20 拼接 | |
System.out.println("heloo" + 100 + 20); | |
} | |
} |
- 运行结果
不管是什么数据类型,只要和字符串类型拼接后,就会变成字符串类型
# 数据类型
不同的数据类型在内存中开启不同的空间大小 (字节),前面使用的 int 整型长度为 4 个字节,1 个字节由 8 位二进制组成,也就是说 int 有效值范围是 2^32,转换成有符号十进制数取值范围是 -2147483648 ~ 2147483647 , 日常计数一般是够用的了
- Java 数据类型
String 不是数据类型,String 是一个类,boolean 只能用 true 和 false 表示,不能用非 0 和 0 表示
- example
public class DataType{ | |
public static void main(String[] args){ | |
byte a = 1; | |
boolean b = true; | |
char c = 'c'; //char 本质上是整数,可以进行运算 | |
short d = 12345; | |
float e = 0.1234567890123f; | |
int f = 1234567890; | |
long g = 1234567890123456789L; | |
double h = 1.12345678901234567890; | |
System.out.println(a); | |
System.out.println(b); | |
System.out.println(c); | |
System.out.println(d); | |
System.out.println(e); | |
System.out.println(f); | |
System.out.println(g); | |
System.out.println(h); | |
} | |
} |
- 运行结果
整型赋值超出取值范围时,编译时报错,浮点型赋值超出取值范围时,编译通过,但尾数超出范围部分会丢失
# 浮点数陷阱
要避免使用浮点数进行运算比较,因为小数是一个近似值,并不是一个精准的数字,在计算中会丢失精度
- example
public class FloatDetail{ | |
public static void main(String[] args){ | |
double num1 = 2.7; | |
double num2 = 8.1 / 3; // 计算结果为一个无限接近 2.7 的小数 | |
if (num1 == num2){ | |
System.out.println("True!"); | |
}else{ | |
System.out.println("False!"); | |
} | |
} | |
} |
- 运行结果
如果一定要用浮点数的运算结果进行比较,正确的方法是使用 Math.abs () 函数返回 num1 减去 num2 差的绝对值进行判断,如果该返回值小于自定义的一个精度,那么我们可以认为这两个数是相等的
- example
public class FloatDetail{ | |
public static void main(String[] args){ | |
double num1 = 2.7; | |
double num2 = 8.1 / 3; // 计算结果为一个无限接近 2.7 的小数 | |
if (Math.abs(num1 - num2) < 0.00000001){ | |
System.out.println("True!"); | |
}else{ | |
System.out.println("False!"); | |
} | |
} | |
} |
- 运行结果
# 数据类型转换
当 Java 程序在进行赋值或者运算时,精度小的类型自动转换成精度大的数据类型
-
char --> int --> long --> float --> double
-
byte --> short --> int --> long --> float --> double
- example
// 程序先判断 'c' 为 char [1] 类型,a 为 int [4] 类型,由于 char [1] < int [4], 根据自动转换规则,char 会自动转换成 int 类型 | |
int a = 'c'; | |
double d = 80; // 同上 | |
// 这里编译出错,程序先判断 1.1 为 double [8] 类型,c 为 float [4] 类型,容量较大的 double 无法存放在容量较小的 float 内存中,程序报错 | |
float c = a + 1.1; | |
byte a1 = 10; //byte 取值范围在 -128 ~ 127,编译通过 | |
int a2 = 10; | |
byte a3 = a2; // 编译报错,a2 为 int [4] 类型 | |
short a4 = a1; // 编译报错,a1 为 byte [1] 类型,byte [1] 不能和 short [3] 实现转换 |
byte、short、char 三者可以进行计算,但是计算时首先转换成 int 类型
有多种类型的数据混合计算时,系统会自动将所有的书记转换成容量最大的数据类型,然后再进行计算
- example
public class AutoConvert{ | |
public static void main(String[] args){ | |
char a = 'a'; | |
short b = 80; | |
int c = 100; | |
double d =1.1; | |
System.out.println(a+b+c+d); | |
} | |
} |
- 运行结果
# 基本数据类型与字符串类型互转
- 基本类型转换字符串类型
- example
public class BasicToStr{ | |
public static void main(String[] args){ | |
int a = 10; | |
float b = 3.14f; | |
char c = 'a'; | |
String a1 = a + ""; | |
String b1 = b + ""; | |
String c1 = c + ""; | |
System.out.println(a1 + "\t" + b1 + "\t" + c1); | |
} | |
} |
- 运行结果
- String 类型转基本类型
String 类型转换基本类型通过调用包装类 parseXX 方法
- example
public class StrToBasic{ | |
public static void main(String[] args){ | |
String a = "100"; | |
int a1 = Integer.parseInt(a); | |
double a2 = Double.parseDouble(a); | |
float a3 = Float.parseFloat(a); | |
byte a4 = Byte.parseByte(a); | |
boolean a5 = Boolean.parseBoolean("true"); | |
System.out.println(a1); | |
System.out.println(a2); | |
System.out.println(a3); | |
System.out.println(a4); | |
System.out.println(a5); | |
// 字符串转字符通过 charAt () 函数取字符串中任意字符 | |
System.out.println(a.charAt(0)); | |
} | |
} |
- 运行结果
# 运算符
运算符这个没什么好说的,跟任何一门语言一样,都是算术运算符、逻辑运算符、关系运算符、赋值运算符和位运算符等,用法和优先级基本一样
# 算术运算符
算术运算符 | 描述 |
---|---|
+ | 加号、正号、连接符 |
- | 减号和负号 |
* | 乘号 |
/ | 除号 |
% | 取余 |
++ | 自增 |
-- | 自减 |
-
Exercise 1
程序输出假如还有 59 天放假,合计 XX 个星期零 XX 天
public class ArithmeticOperator{ | |
public static void main(String[] args){ | |
// 定义总天数、星期、天三个变量 | |
int days = 59; | |
int week = days / 7; | |
int day = days % 7; | |
System.out.println("还有" + days + "天放假,合计" + week + "个星期零" + day + "天"); | |
} | |
} |
- 运算结果
-
Exercise 2
定义一个变量保存华氏温度,华氏温度转摄氏度的公式为:5 / 9 * (华氏温度 - 100), 求华氏温度 234.5 对应的摄氏度
public class Fahrenheit{ | |
public static void main(String[] args){ | |
// 定义华氏度 | |
double f = 234.5; | |
// 定义华氏度转换摄氏度公式,需要注意不能直接把公式搬过来,因为如果是 int 类型的 5 / 9 结果等于 0 ,那么这个公式计算出来的结果就是 0,这里需要把 5 / 9 的结果转换成 double 类型,根据自动转换类型规则,只要其中一个数为 double 类型,其结果就是 double 类型 | |
double s = 5 / 9.0 * (f - 100); | |
System.out.println("华氏度 " + f + " 转换成摄氏度后为: " + s); | |
} | |
} |
- 运行结果
a % b 当 a 为小数时,公式为 a - (int) a /b * b
# 关系运算符
关系运算符 | 描述 |
---|---|
== | 相等于 |
!= | 不等于 |
< | 小于 |
> | 大于 |
<= | 小于等于 |
>= | 大于等于 |
instanceof | 检查是否是类的对象 |
该关系运算符过于简单,懒得敲代码
# 逻辑运算符
逻辑运算符 | 描述 |
---|---|
&& | 逻辑与,两个操作数都为真,结果为 true |
|| | 逻辑或,两个操作数其中一个为真,结果为真 |
! | 逻辑非,结果取反,true 为 false,false 为 true |
- && 例子
- true && true == true
- true && false == false
- flase && true == false
- flase && flase == false
- || 例子
- true || true == true
- true || flase == true
- flase || true == true
- flase || flase == flase
- ! 例子
- !true == false
- !false == true
- example
public class LogicOperator{ | |
public static void main(String[] args){ | |
int a = 10; | |
if ( a++ == 11 && a > 10 ){ | |
System.out.println("true"); | |
a = 100; | |
} | |
System.out.println("a = " + a); | |
} | |
} |
- 运行结果
逻辑运算符只有一个注意要点,就是短路问题,当第一个条件满足时,后面的条件不作执行
# 赋值运算符
赋值运算符 | 描述 |
---|---|
= | 给变量赋值 |
+= | 先加再赋值 |
-+ | 先减再赋值 |
*= | 先乘再赋值 |
/= | 先除再赋值 |
%= | 先取余再赋值 |
a += 10 == a = a + 10 // 其它类推
这里只需要注意一个点,就是类型转换的问题,复合赋值运算符会进行数据类型的强制转换转换
- example
public class GetType{ | |
public static void main(String[] args){ | |
byte a = 127; | |
byte b = 3; | |
System.out.println("a = " + a + " ,datatype is " + getType(a)); | |
System.out.println("b = " + b + " ,datatype is " + getType(b)); | |
a += 1; | |
b = b + 2; | |
System.out.println("a = " + a + " ,datatype is " + getType(a)); | |
System.out.println("b = " + b + " ,datatype is " + getType(b)); | |
a++; | |
b = b + 1; | |
System.out.println("a = " + a + " ,datatype is " + getType(a)); | |
System.out.println("b = " + b + " ,datatype is " + getType(b)); | |
} | |
public static String getType(Object a){ | |
return a.getClass().toString(); | |
} | |
} |
- 编译结果
从编译中可以发现 += 和 ++ 中结果会自动转换成 byte 类型,等价于 a = (byte)(a + 1), 如果拆分开来,数字将自动转换成 int 类型
# 三元运算符
表达式?表达式 1: 表达式 2;
- example
int a = 10; | |
int b =20; | |
int result = a > b ? a++: b--; |
# 位运算符
位运算符 | 描述 |
---|---|
>> | 算术右移,低位溢出,符号位不变,右移 1 位等于除于 2 |
<< | 算术左移,符号位不变,低位补 0,左移 1 位等于乘于 2 |
>>> | 无符号右移,低位溢出,高位补 0 |
~ | 按位取反,1 为 0,0 为 1 |
& | 按位与,两边都是 1,结果为 1,否则为 0 |
| | 按位或,两边只要有 1. 结果为 1,否则为 0 |
^ | 按位异或,两边不一样,结果为 1,否则为 0 |
位运算先求数的补码,将补码进行位运算,然后结果以原码返回
- Exercise
14 & (-8) = ?
-
14 的补码为 00000000 00000000 00000000 00001110
-
-8 的原码为 10000000 00000000 00000000 00001000
-8 的反码为 11111111 11111111 11111111 11110111
-8 的补码为 11111111 11111111 11111111 11111000
-
进行与运算
| 十进制 | 二进制 (补码)|
|:-😐:-😐
|14|00000000 00000000 00000000 00001110|
|-8|11111111 11111111 11111111 11111000|
| 与运算结果 | 00000000 00000000 00000000 00001000|由于结果最高位为 0,表示这个数是个正数,正数的补码原码一样,所以 14 & (-8) = 8
~-11 = ?
-
-11 的原码为 10000000 00000000 00000000 00001011
-
-11 的反码为 11111111 11111111 11111111 11110100
-
-11 的补码为 11111111 11111111 11111111 11110101
| 十进制 | 二进制 (补码)|
|:-😐:-😐
|-11|11111111 11111111 11111111 11110101|
| 取反结果 | 00000000 00000000 00000000 00001010|由于结果最高位为 0,表示这个数是个正数,正数的补码原码一样,所以 ~-11 = 10
~21 = ?
-
21 的补码为 00000000 00000000 00000000 00010101
| 十进制 | 二进制 (补码)|
|:-😐:-😐
|21|00000000 00000000 00000000 00010101|
| 取反结果 | 11111111 11111111 11111111 11101010|| 由于结果最高有效位为 1,表示这个数为负数,需要将补码转换成原码 ||
| 补码 | 11111111 11111111 11111111 11101010|
| 反码 | 11111111 11111111 11111111 11101001|
| 原码 | 10000000 00000000 00000000 00010110|所以 ~21 = -22
7 | 9 = ?
-
7 的补码为 00000000 00000000 00000000 00000111
-
9 的补码为 00000000 00000000 00000000 00001001
十进制 二进制 (补码) 7 00000000 00000000 00000000 00000111 9 00000000 00000000 00000000 00001001 或运算结果 00000000 00000000 00000000 00001111 由于结果最高位为 0,表示这个数是个正数,正数的补码原码一样,所以 7 9 = 15
4 ^ 3 = ?
-
4 的补码为 00000000 00000000 00000000 00000100
-
3 的补码为 00000000 00000000 00000000 00000011
十进制 二进制 (补码) 4 00000000 00000000 00000000 00000100 3 00000000 00000000 00000000 00000011 异或运算结果 00000000 00000000 00000000 0000111 由于结果最高位为 0,表示这个数是个正数,正数的补码原码一样,所以 4 ^ 3 = 7
- Code
public class BitOperator{ | |
public static void main(String[] args){ | |
System.out.print("14 & (-8) = "); | |
System.out.println( 14&-8 ); | |
System.out.print("~-11 = "); | |
System.out.println( ~-11 ); | |
System.out.print("~21 = "); | |
System.out.println(~21); | |
System.out.print("7 | 9 = "); | |
System.out.println( 7 | 9 ); | |
System.out.print("4 ^ 3 = "); | |
System.out.println( 4 ^ 3); | |
} | |
} |
- 运行结果
Java 中的数都是有符号数,Java 没有无符号数
# 控制结构
控制结构一般分为顺序控制、分支控制和循环控制三种
# 顺序控制
程序从上到下逐行执行,中间没有任何判断和跳转
- Code
int num1 = 100; | |
int num2 = num1++; |
# 分支控制
让程序有选择的执行
- 单分支
- 基本语法:
if (表达式){
执行代码语句;(可以多条语句)
}
当条件表达式为 true 时,执行 {} 的语句,当条件表达式为 false 的时候,语句不执行
- Code
import java.util.Scanner; | |
public class IfExercise{ | |
public static void main(String[] args){ | |
Scanner scanner = new Scanner(System.in); | |
System.out.print("请输入你的年龄:"); | |
int age = scanner.nextInt(); | |
if (age >= 18 && age < 30){ | |
System.out.println("恭喜你,你现在还是小鲜肉的年龄!"); | |
} | |
System.out.println("拜拜了您"); | |
} | |
} |
- 运行结果
- 双分支
- 基本语法:
if (表达式){
执行代码语句 1;
}else{
执行代码语句 2;
}
当条件表达式结果为 true 时,执行代码语句 1,当条件表达式为 false 的时候,执行代码语句 2
- Code
import java.util.Scanner; | |
public class IfElseExercise{ | |
public static void main(String[] args) throws InterruptedException{ | |
String s = "杰哥:“你看这个彬彬,才喝了几罐,就醉了,真是太逊了。”\n阿伟:“这个彬彬就是逊啦!”\n杰哥:“哦?这么说,你很勇哦?”\n阿伟:“开玩笑,我超勇的!超会喝的啦!”\n杰哥:“超会喝,很勇嘛,身材不错,蛮结实的嘛。”\n阿伟:“杰,杰哥,你干嘛?!”\n杰哥:“哎呦,都多大了,还害羞?我看你是完全不懂哦?”\n阿伟:“懂。。?懂什么啊?”\n杰哥:“你想懂?我房>里有些好康的。”\n阿伟:“好康?是新游戏哦?”\n杰哥:“哎呀什么游戏,比游戏还刺激,还能教你登duang郎哦?”\n\n"; | |
for (int i = 0; i < s.length();i++){ | |
System.out.print(s.charAt(i)); | |
Thread.sleep(100); | |
} | |
Scanner sc = new Scanner(System.in); | |
System.out.print("请输入数字 \"1\" 进入房间:"); | |
int answer = sc.nextInt(); | |
if( answer == 1 ){ | |
System.out.println("\n阿伟:“杰,杰哥,你干嘛啦? 不要啊!!!”"); | |
System.out.println("杰哥一拳过去:“听话!”"); | |
System.out.println("阿伟随即晕了过去,醒来后发现自己已经不干净了,此时阿伟才明白杰哥口中的duang郎真正的含义"); | |
System.out.println("\n通过这个故事,希望你要明白男孩子在外也一定要保护好自己哦"); | |
}else{ | |
System.out.println("\n恭喜你逃过一杰 ^_^"); | |
System.out.println("虽然你逃过了一杰,但是同时你也失去了duang郎的机会!"); | |
System.out.println("你个小屁孩,希望你下次可要考虑清楚了哦!!!"); | |
} | |
} | |
} |
- 运行结果
- 判断一个年份是否是闰年
判断闰年的条件为下面两条之中任意一条即可:
1. 年份能被 4 整除,但是不能被 100 整除
2. 能被 400 整除
import java.util.Scanner; | |
public class Leapyear{ | |
public static void main(String[] args){ | |
System.out.println("This a test leapyear little program..."); | |
Scanner sc = new Scanner(System.in); | |
System.out.print("请输入一个年份:"); | |
int year = sc.nextInt(); | |
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0){ | |
System.out.println(year + "是闰年"); | |
}else{ | |
System.out.println(year + "不是闰年"); | |
} | |
} | |
} |
- 运行结果
- 多分支
- 基本语法:
if (表达式 1){
执行代码语句 1;
} else if (表达式 2){
执行代码语句 2;
}...{
}else{
执行代码语句 n;}
当条件表达式结果为 true 时,执行代码语句 1,当条件表达式为 false 的时候,判断 else if 表达式是否为 true,true 执行里面的语句,判断到最后为 false 执行 else 语句
- Code
public class RandomEat{ | |
public static void main(String[] args){ | |
System.out.println("这是一个吃饭选择困难症患者和胖子减肥的福利小程序,希望你能坚持下去..."); | |
double random = Math.random() * 1000; | |
if ((int)random % 9 == 1){ | |
System.out.println("今天吃可乐泡饭"); | |
}else if((int)random % 9 == 2){ | |
System.out.println("今天喝豆汁伴咖啡"); | |
}else if((int)random % 9 == 3){ | |
System.out.println("今天吃臭豆腐炒鸭蛋"); | |
}else if((int)random % 9 == 4){ | |
System.out.println("今天吃烤榴莲"); | |
}else if((int)random % 9 == 5){ | |
System.out.println("今天吃鲱鱼罐头"); | |
}else if((int)random % 9 == 6){ | |
System.out.println("今天请全村人吃席"); | |
}else if((int)random % 9 == 7){ | |
System.out.println("今天吃纳豆炒皮蛋"); | |
}else{ | |
System.out.println("今天不吃减肥"); | |
} | |
} | |
} |
- 运行结果
# 循环控制
-
基本语法:
for (初始化表达式;条件表达式;尾部循环体){
执行语句块...;
} -
Exercise
打印棱形图案
public class ForExercise{ | |
public static void main(String[] args){ | |
/** * * | |
* * * *** | |
* * * ***** | |
* * * ******* | |
* * * | |
* * * ******* | |
* * * ***** | |
* * * *** | |
* * * | |
*/ | |
// 将棱形分成上下两部分 | |
// 上面为正三角,下面为倒三角 | |
// 定义上层和底层变量 | |
int upperlayer = 10, lowerlayer = upperlayer * 2 - 3; | |
for(int i = 1; i <= upperlayer; i++){ // 定义上层层数 | |
for(int k = 1; k <= upperlayer - i; k++){ // 控制每层第一个 * 前面的空格 | |
System.out.print(" "); | |
} | |
for(int j = 1; j <= i * 2 - 1; j++){ // 控制每层输出 * 的个数 | |
if(j == 1 || j == i * 2 - 1){ // 只打印本层第一个 * 和最后一个 *,中间用空格代替 | |
System.out.print("*"); | |
}else{ | |
System.out.print(" "); | |
} | |
} | |
System.out.println(); | |
} | |
for(int i1 = 1; i1 <= upperlayer; i1++){ // 定义下层层数 | |
for(int k1 = 1; k1 <= i1; k1++){ // 控制每层第一个 * 前面的空格 | |
System.out.print(" "); | |
} | |
for(int j1 = lowerlayer; j1 >= i1 * 2 -1 ; j1--){ // 控制每层输出 * 的个数 | |
if(j1 == i1 * 2 -1 || j1 == lowerlayer){ // 只打印本层第一个 * 和最后一个 *,中间用空格代替 | |
System.out.print("*"); | |
}else{ | |
System.out.print(" "); | |
} | |
} | |
System.out.println(); | |
} | |
} | |
} |
- 运行结果
# 数组
# 一维数组
数组可以存放多个同一类型数据,数组也是一种数据类型,是应用类型。
即数组就是一组数据
- 动态初始化
语法: 数据类型 数据名 [] = new 数据类型 [元素个数];
-
double a[] = new double[5];
申明变量和分配内存空间同时进行 -
double a []; // 申明变量
a = new double [5]; // 用 new 分配内存空间
- Exercise
统计一个班级 5 个学生的成绩,输出成绩总和,并输出最高分和最低分的成绩
import java.util.Scanner; | |
public class Array02{ | |
public static void main(String[] args){ | |
// 定义一个数组名为 scores,数据类型为 double,元素数量为 5 的数组 | |
double scores[] = new double[5]; | |
// 获取数组元素个数 | |
int length = scores.length; | |
// 定义一个变量统计成绩总和 | |
double sum = 0; | |
// 定义一个临时变量用于交换数组元素位置 | |
double temp = 0; | |
// 定义一个 Scanner 对象用于接收用户输入 | |
Scanner sc = new Scanner(System.in); | |
// 用 for 循环提示用户输入学生成绩 | |
for (int i = 0; i < scores.length; i++){ | |
System.out.print("请输入第" + (i+1) + "个学生成绩: "); | |
scores[i] = sc.nextDouble(); | |
} | |
// 统计成绩总数 | |
for (int i = 0; i < length; i++){ | |
sum += scores[i]; | |
} | |
System.out.println("学生总成绩分数为: " + sum); | |
// 用二层 for 循环判断成绩大小 | |
for (int i = 0; i < (length - 1); i++){ | |
for (int j = i+1; j < length; j++ ){ | |
// 将成绩分数从低到高从新排列 | |
if (scores[i] >= scores[j]){ | |
temp = scores[j]; | |
scores[j] = scores[i]; | |
scores[i] = temp; | |
} | |
} | |
} | |
System.out.println("学生成绩最高分数为: " + scores[length - 1]); | |
System.out.println("学生成绩最低分数为: " + scores[0]); | |
} | |
} |
- 运行结果
- 静态初始化
语法: 数据类型 数据名 [] = {元素值,元素值...};
int a[] = {1, 2, 3, 4, 5};
根据 {} 中的元素划分内存空间
等价于 int a [] = new int [5]; // 先申明数组和初始化内存空间
// 为每个元素赋值
a [0] = 1;
a[1] = 2;
a[2] = 3;
a[3] = 4;
a[4] = 5;
- 注意事项和细节
-
数组是多个相同类型数据的组合,实现对这些数据的统一管理
-
数组中的元素可以是任何数据类型,包括基本类型和引用类型,但是不能混用
-
数组创建后,如果没有赋值,有默认值
int 0, short 0, byte 0, long 0, float 0.0 double 0.0, char \u0000, blooean false, String null -
使用数组步骤:
1. 声明数组并开辟内存空间
2. 给数组各个元素赋值
3. 使用数组 -
数组下标必须在制定范围内使用,否则报下标越界异常
-
数组属引用类型,数组型数据是对象 (object)
- 数组赋值机制
- 值传递:基本数据类型赋值,这个值就是具体的数据,而且互相不影响
int n1 = 10; int n2 = n1;
n2 = 80; // 此时 n2 的变化不会影响到 n1 的值
- 引用传递:数组在默认情况下是引用传递,赋的值是地址
int [] arr1 = {1, 2, 3};
int[] arr2 = arr1;
arr2 [0] = 10; // 此时 arr2 的变化 arr1 也随着变化
# 二维数组
- 静态初始化
数据类型 [][] 数组名 = { {元素...},{元素...},{元素...} };
int[][] arr = { {1,2,3},{10,20},{100} };
int arr[][] = { {1,2,3},{10,20},{100} };
int[] arr[] = { {1,2,3},{10,20},{100} };
- 动态初始化
数据类型 [][] 数组名 = new int [][];
int[][] arr = new int[][];
public class TwoDimensionalArray01{ | |
public static void main(String[] args){ | |
/** 题目:动态创建下面二维数组,并输出 | |
* 1 | |
* 1 2 | |
* 1 2 3 | |
* . . . . | |
*/ | |
int[][] arr = new int[10][]; | |
for (int i = 0; i < arr.length; i++){ | |
arr[i] = new int[i + 1]; | |
for (int j = 0; j < arr[i].length; j++){ | |
arr[i][j] = j + 1; | |
} | |
} | |
for (int i = 0; i < arr.length; i++){ | |
for (int j = 0; j < arr[i].length; j++){ | |
System.out.print(arr[i][j] + " "); | |
} | |
System.out.println(); | |
} | |
} | |
} |
- 运行结果