重学Java(Day2)注释、流程控制、方法、数组
重学Java(Day2)
Java注释概述
Java的三种注释
-
单行注释:// 注释内容
-
多行注释:/*… 注释内容….*/
-
文档注释:/**.. 注释内容….*/
这种注释可以用来自动地生成文档。在JDK中有个javadoc的工具,可以由源文件生成一个HTML文档。使用这种方式注释源文件的内容,显得很专业,并且可以随着源文件的保存而保存起来。也就是说,当修改源文件时,也可能对这个源代码的需求等一些注释性的文字进行修改,那么,这时候可以将源代码和文档一同保存,而不用再另外创建一个文档。
文档注释位置
(1)类注释。类注释用于说明整个类的功能、特性等,它应该放在所有的“import”语句之后,在class定义之前。这个规则也适用于接口(interface)注释。
(2)方法注释。方法注释用来说明方法的定义,比如,方法的参数、返回值及说明方法的作用等。方法注释应该放在它所描述的方法定义前面。
(3)属性注释。默认情况下,javadoc只对公有(public)属性和受保护属性(protected)产生文档——通常是静态常量。
(4)包注释。类、方法、属性的注释都直接放到Java的源文件中,而对于包的注释,无法放到Java文件中去,只能通过在包对应的目录中添加一个package.html的文件来达到这个目的。当生成HTML文件时,package.html文件的和部分的内容将会被提取出来当做包的说明。
(5)概要注释。除了包注释外,还有一种类型的文档无法从Java源文件中提取,就是对所有类文件提供概要说明的文件。同样的,也可以为这类注释单独新建一个HTML文件,这个文件的名字为“overview.html”,它的和标记之间的内容都会被提取。
@author:作者。
@version:版本。
@docroot:表示产生文档的根路径。
@deprecated:不推荐使用的方法。
@param:方法的参数类型。
@return:方法的返回类型。
@see:用于指定参考的内容。
@exception:抛出的异常。
@throws:抛出的异常,和exception同义
@since:最早使用jdk的版本
文档注释的作用
当开发一个大型软件时,需要定义成千上万个类,而且需要很多人参与开发。每个人都会开发一些类,并在类里定义一些方法和域提供给其他人使用,但其他人怎么知道如何使用这些类和方法呢?
这时就需要提供一份说明文档,用于说明每个类、每个方法的用途。当其他人使用一个类或者一个方法时,他无需关心这个类或这个方法的具体实现,他只要知道这个类或这个方法的功能即可,然后使用这个类或方法来实现具体的目的,也就是通过调用应用程序接口(API)来编程。
API文档就是用来说明这些应用程序接口的文档。对于java语言而言,API文档通常详细的说明了每个类、每个方法的功能及用法。
生成自己的API文档
1、使用javadoc命令生成文档
- 在代码中写javadoc注释
/**
* 添加书籍
* @param books
* @return
* @version 1.0
* @since 1.8
*/
- 在类文件所在的文件夹打开cmd窗口,输入命令:
javadoc -encoding UTF-8 -charset UTF-8 BookServiceImpl.java #javadoc 编码格式 字符格式 生成文档的类
会在这里生成很多文件

打开index.html

注释的信息可以在API文档中看到

2、使用idea生成文档
(1)点击顶部的菜单栏的Tools,选择Generate Java Doc...

(2)进行配置

这里的命令行参数很重要,因为只有使用 utf-8 编码才能保证生成时可以正常处理中文字符,所以一定要加上:
-encoding utf-8 -charset utf-8
还有一点需要注意,即不要勾选“Include test sources”,勾选后,生成时会造成很奇怪的错误。
Java流程控制
Scanner对象
java.util.Scanner 是 Java5 的新特征,我们可以通过 Scanner 类来获取用户的输入。
下面是创建 Scanner 对象的基本语法:
Scanner s = new Scanner(System.in);
通过 Scanner 类的 next() 与 nextLine() 方法获取输入的字符串,在读取前我们一般需要 使用 hasNext 与 hasNextLine 判断是否还有输入的数据
使用next的方式接收数据:
public static void main(String [] args) {
//创建一个扫描器对象,用来接收键盘数据
Scanner scanner = new Scanner(System.in);
System.out.println("使用next的方式接收,请输入字符串:");
//判断用户有没有输入字符串
if(scanner.hasNext()){
//使用next方式接收
String str = scanner.next();
System.out.println("您输入的信息为:"+str);
}
//凡是属于IO流的类,不关闭会一直占用资源,用完就关掉
scanner.close();
}
输出:

使用nextLine的方式接收数据:
public static void main(String [] args) {
//创建一个扫描器对象,用来接收键盘数据
Scanner scanner = new Scanner(System.in);
System.out.println("使用nextLine的方式接收,请输入字符串:");
//判断用户有没有输入字符串
if(scanner.hasNext()){
//使用nextLine方式接收
String str = scanner.nextLine();
System.out.println("您输入的信息为:"+str);
}
//凡是属于IO流的类,不关闭会一直占用资源,用完就关掉
scanner.close();
}
输出:

使用next接收数据只接收到了输入 Hello World 中的Hello,而nextLine方式接收到了全部的字符
next() 与 nextLine() 区别
next():
- 一定要读取到有效字符后才可以结束输入。
- 对输入有效字符之前遇到的空白,next() 方法会自动将其去掉。
- 只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。
- next() 不能得到带有空格的字符串。
nextLine():
- 以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符。
- 可以获得空白。
如果要输入 int 或 float 类型的数据,在 Scanner 类中也有支持,但是在输入之前最好先使用 hasNextXxx() 方法进行验证,再使用 nextXxx() 来读取:
ps:在测试Scanner的时候第一次是写在Junit4测试类中的,测试方法运行后会遇到控制台不能输入的问题,写到main方法里面则可以正常输入,具体原因不详...
顺序结构
顺序结构是最简单的程序结构,也是最常用的程序结构,只要按照解决问题的顺序写出相应的语句就行,它的执行顺序是自上而下,依次执行。
Java的基本结构就是顺序结构,除非特别指明,否则就按照顺序一步一步执行。
它是任何算法都离不开的一种基本算法结构
选择结构
- if单选结构
if(布尔表达式){
//如果布尔表达式为true执行的语句
}

- if双选结构
if(布尔表达式){
//如果布尔表达式为true执行的语句
}else{
//如果布尔表达式为false执行的语句
}

- if多选结构
if(布尔表达式1){
//如果布尔表达式1为true执行的语句
}else if(布尔表达式2){
//如果布尔表达式2为true执行的语句
}else if(布尔表达式3){
//如果布尔表达式3为true执行的语句
}else{
//如果以上布尔表达式的值都为false执行的语句
}

- 嵌套if结构
if(布尔表达式1){
//如果布尔表达式1为true执行的语句
if(布尔表达式2){
//如果布尔表达式2为true执行的语句
}
}
- switch多选结构

expression表达式结果可以是字符串类型
public static void main(String[] args) {
//jdk7新特性,表达式结果可以是字符串类型
String str = "中国加油";
switch (str) {
case "中国加油":
System.out.println(str);
break;
default:
break;
}
}
字符的本质也是数字,从class文件反编译得到的代码:
public static void main(String[] args) {
String str = "中国加油";
byte var3 = -1;
switch(str.hashCode()) {
case 618291337:
if (str.equals("中国加油")) {
var3 = 0;
}
default:
switch(var3) {
case 0:
System.out.println(str);
default:
}
}
}
循环结构
- while 循环
while(布尔表达式){
//循环内容
}
只要布尔表达式为true,循环就会一直执行下去
我们大多数情况是会让循环停止下来的,需要一个让表达式失效的方式来结束循环
@Test
public void test(){
int i = 0;
while(i<3){
System.out.println("i="+i);
i++;
}
}
输出:
i=0
i=1
i=2
- do…while循环
对于while语句而言,如果不满足条件,则不能进入循环。但有时候我们需要即使不满足条件,也至少 执行一次。
do…while循环和while循环相同,不同的是,
do…while循环至少会执行一次。
@Test
public void test(){
int i = 0;
do {
System.out.println("i="+i);
}while (i>0);
}
输出:
i=0
- for循环
虽然所有循环结构都可以用while或者do…while表示,但java提供了另一种语句(for循环),使一些循环结构变得更简单。
for ( 1初始化; 2布尔表达式; 4更新){
//3代码语句
}
打印乘法表:
@Test
public void test2(){
//打印乘法表
for (int i = 9; i >=0; i--) {
for(int j = 1;j<=i ;j++){
System.out.print(j+"*"+i+"="+i*j+'\t');
}
System.out.println();
}
}
输出:
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*4=4 2*4=8 3*4=12 4*4=16
1*3=3 2*3=6 3*3=9
1*2=2 2*2=4
1*1=1
- 增强for循环
for(声明语句:表达式){
//代码语句
}
遍历:
@Test
public void test3() {
int[] num = {1, 2, 3, 4, 5}; //定义一个数组
//遍历数组的元素
for(int i:num){
System.out.println(i);
}
}
打印正三角形:
@Test
public void test4() {
//打印一个正三角形
//定义三角形行数
int n = 5;
for (int i = 0; i < n; i++) {
//1.先打印左面的空白倒三角
for (int j = n; j > i; j--) {
System.out.print(" ");
}
//2.打印中间的三角
for(int j = 0;j<=i;j++){
System.out.print("*");
}
//3.打印剩余的三角
for(int j = 0;j<i;j++){
System.out.print("*");
}
System.out.println();
}
}
输出:
*
***
*****
*******
*********
图解:

- 先打印1组成的三角形
- 再打印由2组成的三角形
- 最后打印由3组成的三角形
Java的方法
方法是用来完成特定功能的代码片段,方法包含一个方法头和方法体。
方法的定义
修饰符 返回值类型 方法名(参数类型 参数名){
...
方法体
...
return 返回值;
}
方法的重载
重载就是在一个类中,有相同的函数名称,但形参不同的函数。
方法重载的规则
- 方法名称必须相同
- 参数列表必须不同(个数不同、类型不容、参数排序不同等)
- 方法的返回类型也可以不相同
- 仅仅返回类型不同不足以成为方法的重载
命令行传递参数
在命令行运行class文件可以传递参数,以空格的方式隔开
可变参数
虽然从1.5中提供了Varargs(variable arguments)机制,允许直接定义能和多个实参相匹配的形参。从而,可以用一种更简单的方式,来传递个数可变的实参。但在平时编程过程中很少使用可变参数作为方法的参数。
可变参数方法的定义
public int add(int... numbers){
int sum = 0;
for(int num : numbers){
sum += num;
}
return sum;
}
但需要注意的是可变参数只能作为函数的最后一个参数,但其前面可以有也可以没有任何其他参数。
可变参数方法的调用
add(); // 不传参数
add(1); // 传递一个参数
add(2,1); // 传递多个参数
add(new Integer[] {1, 3, 2}); // 传递数组
递归
递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。
递归就是A方法调用A方法,自己调用自己。
递归结构包含两个部分:
- 递归头:什么时候不调用自身方法;如果没有头,将陷入死循环。
- 递归体:什么时候需要调用自身方法。
阶乘:
//递归
//阶乘 n!= n*(n-1)*(n-2)*...*1
static int f(int n){
if(n==1){
return 1;
}else{
return n*f(n - 1);
}
}
@Test
public void test5(){
System.out.println(f(5)); //120
}

学习递归的思想,尽量少用这种算法,方便了程序员,苦了机器;java每次调用一个方法都会增加内存占用,当递归的基数非常大的时候就会内存溢出
Java的数组
数组概述
数组的定义
相同类型数据的有序集合
每个数据称作一个数组元素,可以通过下标访问
数组的四个基本特点
- 长度是确定的,数组一旦创建,大小不可更改
- 元素必须相同类型
- 元素类型可以是任何类型,包括基本类型和引用类型
- 数组本身就是对象,Java中的对象是存在堆中的
数组声明创建
必须声明数组变量,才能在程序中使用数组
dataType[] arrayRefVar; //首选方法
dataType arrayRefVar[]; //效果相同
java使用new操作符来创建数组
dataType[] arrayRefVar = new dataType[arraySize];
三种初始化
1、静态初始化
//静态初始化:创建+赋值
int[] = {1,2,3};
Man[] mans = {new Man(1,1),new Man(2,2)};
2、动态初始化
//动态初始化:包含默认初始化
int[] a = new int[2];
a[0] = 1;
a[1] = 2;
3、默认初始化
数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。
Java内存分析

数组创建流程

数组使用
- 普通的For循环
- For-Each循环
- 数组作方法入参
- 数组作为返回值
反转数组:
//反转数组
public static int[] reverse(int arrays[]) {
int[] reverse = new int[arrays.length];
//反转操作
for (int i = 0, j = arrays.length - 1; i < arrays.length; i++, j--) {
reverse[j] = arrays[i];
}
return reverse;
}
@Test
public void test6() {
int[] arrays = {1,2,3,4,5};
int[] reverse = reverse(arrays);
for (int i = 0; i < reverse.length; i++) {
System.out.print(i+" "); //0 1 2 3 4
}
}
多维数组
多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。
二维数组
int a[][] = new int[3][2]; //一个三行两列的数组
图解:

Arrays类
JDK中提供了一个专门用于操作数组的工具类,即Arrays类,位于java util 中。
Arrays类常用方法
| 返回类型 | 方法 | 说明 |
|---|---|---|
| String | toString(array) | 将数组array转换成字符串 |
| void | sort(array) | 对数组进行升序排列 |
| void | fill(arr,val) | 将数组arr全部元素赋值为val |
| boolean | equals(arr1,arr2) | 判断两个数组是否相等 |
| 与arr类型相同 | copyOf(arr,length) | 将数组arr复制成一个长度为length的新数组 |
| int | binarySearch(arr, val) | 查询元素val在arr中的下标值 |
排序(sort)填充(fill)
@Test
public void test7() {
int[] a = {14, 255, 3, 444, 521};
//数组升序排序
Arrays.sort(a);
System.out.println(Arrays.toString(a));
//数组下标2-4的元素被6填充
Arrays.fill(a,2,4,6);
System.out.println(Arrays.toString(a));
}
稀疏数组
当一个数组中的大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组。
稀疏数组的处理方式是:
- 记录数组一共有几行几列,有多少个不同值
- 把具有不同值的元素和行列及值记录在一个小规模数组中,从而缩小程序规模。
如下图,左面是原始数组,右面是稀疏数组

稀疏数组的创建与还原:
@Test
public void test9() {
//稀疏数组 模拟五子棋
//1.创建一个二维数组 11*11 0:没有棋子 1:黑棋 2:白棋
int[][] array1 = new int[11][11];
array1[2][2] = 1;
array1[4][3] = 2;
//输出原始的数组
System.out.println("原始数组:");
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
System.out.print(array1[i][j] + " ");
}
System.out.println();
}
//转换为稀疏数组保存
// 有效值个数 | row | col |value
// ------------------
// 有效值1 |
// 有效值2 |
//获取有效值的个数
int sum = 0;
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if (array1[i][j] != 0) {
sum++;
}
}
}
System.out.println("有效值个数:" + sum);
//2.创建一个稀疏数组的数组
int[][] array2 = new int[sum + 1][3];
//给稀疏数组第一行赋值 [原数组高度 原数组宽度 有效值个数]
array2[0][0] = 11;
array2[0][1] = 11;
array2[0][2] = sum;
int count = 1; //表示稀疏数组的第二行
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if (array1[i][j] != 0) {
//给稀疏数组赋值 [横坐标 纵坐标 值]
array2[count][0] = i;
array2[count][1] = j;
array2[count][2] = array1[i][j];
count++;
}
}
}
System.out.println("稀疏数组:");
for (int i = 0; i < array2.length; i++) {
for (int j = 0; j < 3; j++) {
//输出的时候占两个位置,左对齐
System.out.print(String.format("%-2d", array2[i][j]) + " ");
}
System.out.println();
}
//稀疏数组还原
int[][] array3 = new int[array2[0][0]][array2[0][1]];
for (int i = 1; i < array2.length; i++) {
//原数组赋值,根据稀疏数组每行的坐标
array3[array2[i][0]][array2[i][1]] = array2[i][2];
}
//打印还原后的数组
System.out.println("还原后的数组:");
for (int i = 0; i < array3.length; i++) {
for (int j = 0; j < array3[i].length; j++) {
System.out.print(array3[i][j] + " ");
}
System.out.println();
}
}
控制台输出:
原始数组:
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 2 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
有效值个数:2
稀疏数组:
11 11 2
2 2 1
4 3 2
还原后的数组:
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 2 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
冒泡排序
//冒泡排序
public static int[] sort(int[] array) {
int flag = 0;
//外层循环控制,控制要走多少次
for (int i = 0; i < array.length - 1; i++) {
//内层循环,比较前后两个数,进行位置转换
for (int j = 0; j < array.length - 1 - i; j++) {
if (array[j] > array[j + 1]) {
flag = array[j];
array[j] = array[j + 1];
array[j + 1] = flag;
}
}
}
return array;
}

浙公网安备 33010602011771号