资源下载
本篇文章用的软件或者安装包均可在分享的文件中找到,方便大家自取。
链接:https://pan.baidu.com/s/19ItNTI2lhMtAwCJSF7ryuA
提取码:qjmy
环境配置
Java的一个重要特点就是跨平台、可移植,而实现此机制离不开JVM(Java Virtual Machine,Java虚拟机),因此无论你是开发人员还是Java程序的用户,都需要在操作系统中配置Java环境,因此在写“Hello World”之前,需要完成Java开发环境配置,当然这里也会介绍下开源的开发工具Eclipse。
JDK的安装与环境变量配置
已经知道JVM是Java虚拟机,是实现跨平台和可移植的重要机制,那这里的JDK又是什么呢?
在解释这个名词之前,先要了解另外一个名词JRE(Java Runtime Environment,Java运行时环境 ),包括Java虚拟机和Java程序所需的核心类库等。而JDK(Java Development Kit)包含Java的开发工具,也包括JRE。它是提供给Java开发人员使用的。开发工具:编译器(javac.exe)、解释器(java.ext)、 打包工具(jar.exe)等。
因此,作为开发人员,需要在开发环境中安装JDK并进行环境变量配置,鉴于此类技术文档是海量的,可以自行搜索:JDK安装与环境变量配置,如果想要更详细一些,可以限制操作系统,比如:Win11环境下的JDK安装与环境变量配置。
你也可以参考:JDK 安装与环境变量配置(Win10详细版)
JDK版本推荐1.8。
开发工具
Java作为主流的开发语言,其较为成熟的开发工具有Eclipse、IDEA及MyEclipse。作为初学者而言,Eclipse即可满足大家的学习使用,如果后续需要开发项目,建议切换IDEA使用。
注:一般的算法比赛只提供Eclipse。
而Eclipse的运行也依赖于JDK,所以在开始Eclipse的安装配置前,需要先完成JDK的安装于环境变量设置。我这里在网盘中分享的Eclipse软件为一个压缩包,解压之后双击“eclipse.exe”即可使用。
温馨提示
每次启动Eclipse后,默认会提示你选择WorkSpace(工作目录,可以理解为Java项目的存放目录),可以选择为你熟悉的文件夹,最好是全英文路径。
Start Coding
让我们开始从零开始,拥抱Java的世界吧。
创建项目
既然已经选择Eclipse作为开发工具了,那么就先来创建一个Java工程吧。
在菜单栏可以找到File菜单,从该入口开始创建工程:File->New->Other->Java->Java Project。在创建项目的弹窗中,填写Project name,建议英文。之后就是在JRE版本选择上,选择本地安装的JDK1.8,当然你如果安装了更高版本的JDK,也可以选择。之后点击 Finish即可完成项目创建。
创建成功后的项目目录如下所示,其中src目录中是我们存放代码或者其他资源文件的地方:
类
Java是一门面向对象编程语言,区别于C语言这种面向过程编程语言,从字面上理解就是:面向对象编程语言在解决问题时,不关心问题的解决方案,而是关心问题有哪些对象来解决。我们可以拿采购产品这件事情来区分二者。
面向过程的思维解决问题:
- 提出采购计划
- 制定采购方案
- 发布竞标公告
- 遴选投标供应商
- 确定供应商
- 交付产品
- 采购结束
面向对象的思维解决问题:
- 采购主管提出采购计划
- 对接采购商进行采购
- 交付产品
- 采购结束
当然,咱这里就不再去对类以及对象的概念进行详细学习了,简单来说:具体某一个“采购主管”或“采购商”,称他们为对象,而将“采购主管”或“采购商”这个职业进行归纳总结,形成的就是类。
而在Java中,更是离不开类的概念,通俗点说,写的代码都在类中,那让我们先去创建一个ProcedureEntrance类吧。
在选中src目录后,右键->New->Class,在弹窗中填写类名即可,之后点击Finish完成ProcedureEntrance类的创建。
创建后的ProcedureEntrance类就长这个样子:
public class ProcedureEntrance {
}
它在工程目录中的位置如下:
注:Eclipse开启代码提示,参考该篇博客,可以完成代码提示的设置,帮助我们更高效的进行代码开发。
程序主入口
如同程序流程图的定义一样,一个程序有开始和结束,而这个开始,我们称它为:程序主入口,而在Java里,程序主入口的格式是固定的,一般长这个样子:
public static void main(String[] args) {
}
接着我们在ProcedureEntrance类中添加一个程序主入口,并且加上一些注释:
/**
* 文档注释
* @author yancielcn
*
*/
public class ProcedureEntrance {
/*
* 多行注释
* 程序主入口
*/
public static void main(String[] args) {
// 单行注释,程序从这里开始执行
}
}
输出
输出有很多种形式,比如输出到控制台(Console)、文件等等,这里我们只去学习怎么输出打印到控制台。
public class ProcedureEntrance {
// 程序主入口
public static void main(String[] args) {
// 输出打印 Hello World!
System.out.println("Hello World!");
}
}
这里我们使用System.out.println()方法完成输出打印到控制台,不仅可以打印字符串,你也可以尝试输出下其他内容,看看程序运行效果。
如何执行代码:光标移动到程序主入口所在的类->右键->Run as->Java Application。
注:
println():换行输出,输出后,光标移动到下一行继续输出其他内容。
print():不换行输出,输出后,光标移动到当前行末尾继续输出其他内容。
变量
为了存储计算结果,在编程语言中都有变量这个抽象概念,在Java里,变量涉及的知识点包括:数据类型、作用域、分类等。每一个知识点拿出来都能重新开一篇文章去讲了,既然为了能够开始入门,咱们直接看代码:
public class ProcedureEntrance {
// 程序主入口
public static void main(String[] args) {
// 定义一个变量
int number;
// 给变量赋初值
number = 1;
// 定义并初始化一个变量
float score = 0.1f;
}
}
int 和 float是基本数据类型中的整型和单精度浮点型,number 和 score 为变量名,其命名规则参考:Java中变量名的命名规范。1 和 0.1f 分别为两个变量的值。
在Java中,数据类型分为两类:基本数据类型和引用数据类型,其中基本数据类型包含:char \ byte \ short \ int \ long \ float \ double \ boolean。
输入
变量的值往往是由用户在程序的某一个节点进行输入,具体代码如下:
import java.util.Scanner;
public class ProcedureEntrance {
// 程序主入口
public static void main(String[] args) {
// 定义并初始化一个变量
double score = 0.0;
// 定义并初始化一个Scanner对象
Scanner scanner = new Scanner(System.in);
// 获取输入的值,并赋值给变量score
score = scanner.nextDouble();
}
}
这里我们使用Scanner类来帮助我们从控制台中读取用户输入的值,为了使用这个类,需要完成导包操作:
import java.util.Scanner;
之后我们使用new关键字创建一个名为scanner的Scanner对象:
Scanner scanner = new Scanner(System.in);
在Scanner中,有很多方法,比如:获取双精度浮点数,nextDouble();获取整数,nextInt()。大家可以自行尝试:
score = scanner.nextDouble();
方法
为了解决某一类问题,可以将代码封装到方法体内部,比如常见的加法操作,就可以将其封装到一个方法,方便随时调用:
import java.util.Scanner;
public class ProcedureEntrance {
// 程序主入口
public static void main(String[] args) {
// 定义并初始化一个变量
int number1 = 0;
int number2 = 0;
// 定义并初始化一个Scanner对象
Scanner scanner = new Scanner(System.in);
// 获取输入的值
number1 = scanner.nextInt();
number2 = scanner.nextInt();
// 求和并打印
int number3 = addOperation(number1, number2);
System.out.println(number3);
}
/*
* 完成两个整数的求和,并将结果返回
*/
public static int addOperation(int arg1, int arg2) {
int sum = arg1 + arg2;
return sum;
}
}
可以看到我们定义了一个名为addOperation的方法,其中方法名后的 (int arg1, int arg2) 是参数列表,方法名前的 int 表示该方法具有返回值,在方法体内部必须使用return关键字返回一个同类型的数值。当然,如果该方法没有返回值,就可以使用void来代替int:
public static void operation1() {
}
// 无返回值有参数的方法
public static void operation2(int arg1) {
}
相信大家已经关注到static这个关键字了,这里涉及到了另外一个概念:类方法和实例方法,这里不再展开去讲,具体可参考:
Java 方法-菜鸟教程
Java方法详解(Java基础)
这里补充一点:方法中的参数分为值传递和引用传递,基本数据类型的参数为值传递,引用数据类型的参数为引用传递。值传递的参数,在方法体内部变化不会影响参数本身。而引用传递的参数,在方法体内部与外部是一致的。
数组
数组的定义很简单,存储相同类型的有限个数据元素的集合,在Java中,可以把数组理解为一种引用型数据类型,定义及初始化相关代码如下:
public class ProcedureEntrance {
// 程序主入口
public static void main(String[] args) {
// 定义并初始化一个数组
int[] numbers = new int[10];
// 另外一种初始化方式
float[] scores = { 2.1f, 3.2f, 4.5f };
// 访问第3个元素,索引从0开始
numbers[2] = 5;
scores[2] = 4.4f;
}
}
对于数组需要注意的两点:
- 数组长度是确定的,在初始化时被确定;
- 以索引的方式访问数据元素,索引从0开始。
集合
定长的数组往往不能满足常见的需求,因此引入了集合的概念,而在Java中常见的集合有List、Map与Set,当然,Queue、Stack和Tree也是有具体实现的。
import java.util.ArrayList;
import java.util.List;
public class ProcedureEntrance {
// 程序主入口
public static void main(String[] args) {
// 定义并初始化一个字符串列表
List<String> names = new ArrayList<>();
// 增加数据
names.add("yxl");
// 移除数据
names.remove(0);
}
}
上述代码是实现类ArrayList的常规用法,而ArrayList是抽象类List的子类,这里使用子类对象初始化父类引用的作法叫做向上转型,相反地,把父类对象转为子类对象的操作称为向下转型。
类似的,还有HashMap、HashSet等实现,大家可尝试下。这里为什么不在给大家赘述呢?因为Java集合在设计之初就提出了高互操作性的要求,只要能掌握一种集合的用法,对于其他集合都能够轻松上手。
控制语句
程序的流程并不完全是顺序执行的,选择结构、循环结构与中断对流程能够进行控制。
if语句:
public class ProcedureEntrance {
// 程序主入口
public static void main(String[] args) {
int isOff = 1;
// if 表达式的值应为boolean值
if (isOff == 1) {
System.out.println("灯已打开");
}
// if-else
if (isOff == 1) {
System.out.println("灯已打开");
}else {
System.out.println("灯已关闭");
}
// if-elseif
if (isOff == 1) {
System.out.println("灯已打开");
} else if(isOff == 0) {
System.out.println("灯已关闭");
}else {
System.out.println("灯的状态异常");
}
}
}
switch语句:
public class ProcedureEntrance {
// 程序主入口
public static void main(String[] args) {
int isOff = 1;
// 表达式的值必须为整型
switch (isOff) {
case 1:
System.out.println("灯已打开");
break;
case 0:
System.out.println("灯已关闭");
break;
default:
System.out.println("灯的状态异常");
break;
}
}
}
for语句:
import java.util.ArrayList;
import java.util.List;
public class ProcedureEntrance {
// 程序主入口
public static void main(String[] args) {
// 定义并初始化一个字符串列表
List<String> names = new ArrayList<>();
// 集合的遍历
for (int i = 0; i < names.size(); i++) {
System.out.println(names.get(i));
}
// 集合的遍历
for (String name : names) {
System.out.println(name);
}
// 死循环
for (;;) {
}
}
}
for循环的基础语法为:for(初始化语句; 判断语句; 循环变量更新语句){ },其中初始化语句只会执行一次,判断语句每次循环前均会执行,返回为true时才会开始本次循环。而循环变量更新语句则是每次循环开始时就会执行。
在Java中还有while与do-while语句来实现循环,基本原理类似,这里不再做赘述。
实战演练
既然掌握了这些基础语法,让我们实现一些简单的排序算法吧。
冒泡排序
它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。参考详见:冒泡排序-菜鸟教程。
public class BubbleSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] numbers = { 12, 6, 8, 2, 4, 9, 7, 5, 1, 3, 11, 10 };
sort(numbers);
for (int i : numbers) {
System.out.print(i + "\t");
}
}
/*
* 冒泡排序:升序排序
*/
public static void sort(int[] numbers) {
for (int i = 0; i < numbers.length; i++) {
// 设定一个标记,若为false,则表示此次循环没有进行交换,也就是待排序列已经有序,排序已经完成。
boolean flag = false;
// 遍历未排序的部分:0 - numbers.length - i。 这里再减去1,是因为最后一个元素不需要再和它的下一个元素比较了
for (int j = 0; j < (numbers.length - 1 - i); j++) {
// 比较相邻两个大小
if (numbers[j] > numbers[j + 1]) {
// 交换
int tmp = numbers[j];
numbers[j] = numbers[j + 1];
numbers[j + 1] = tmp;
// 更新flag
flag = true;
}
}
if (!flag) {
// 结束for循环
break;
}
}
}
}
选择排序
参考详见:选择排序-菜鸟教程。
public class SelectionSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] numbers = { 12, 6, 8, 2, 4, 9, 7, 5, 1, 3, 11, 10 };
sort(numbers);
for (int i : numbers) {
System.out.print(i + "\t");
}
}
/*
* 选择排序:降序排序
*/
public static void sort(int[] numbers) {
// 需要N-1轮遍历
for (int i = numbers.length - 1; i > 0; i--) {
// 初始化最小值所在的索引值
int minIndex = i;
// 每轮需要比较的次数 N-i
for (int j = 0; j < i; j++) {
// 与最小值比较大小
if (numbers[j] < numbers[minIndex]) {
minIndex = j;
}
}
// 将找到的最小值和i位置所在的值进行交换
if (i != minIndex) {
int temp = numbers[i];
numbers[i] = numbers[minIndex];
numbers[minIndex] = temp;
}
}
}
}