Java从零开始系列01:Java入门

学习目标:

  • 什么是Java
  • Java特性
  • Java程序设计环境
  • Java的基本程序设计结构

1.什么是Java

Java是一门面向对象的编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程。

2.Java特性

在白皮书中,Java被冠以以下特性:1)简单性、2)面向对象、3)分布式、4)健壮性、5)安全性、6)体系结构中立、7)可移植性、8)解释型、9)高性能、10)多线程、11)动态性
白皮书:https://www.oracle.com/java/technologies/language-environment.html
特性解释:https://horstmann.com/corejava/java-an-overview/7Gosling.pdf

3.Java程序设计环境

这里了解几个相关术语:

术语名 缩写 解释
Java Development Kit JDK 编写Java程序的程序员使用的软件
Java Runtime Environment JRE 运行Java程序的用户使用的软件
Standard Edition(标准版) SE 用于桌面或简单服务器应用的Java平台
Enterprise Edition(企业版) EE 用于复杂服务器应用的Java平台
Micro Edition(微型版) ME 用于小型设备的Java平台

推荐使用IDEA进行Java程序的编写,Java环境配置及IDEA的安装可参考:Java/JDK下载安装与环境配置(Windows 10 超详细的图文版教程 )

4.Java的基本程序设计结构

(1)一个简单的Java程序

public class FirstSample {
    public static void main(String[] args) {
        System.out.println("We will not use 'Hello world!'");
    }
}

这是一个简单的Java应用程序,它只发送一条消息到控制台窗口中。
若要在cmd环境下运行,可以使用以下代码:

javac FirstSample.java
java FirstSample

(2)命名规则

java定义函数、类等时遵循以下命名规则:
1.类成员变量:首字母小写和驼峰原则:monthSalary
2.局部变量:首字母小写和驼峰原则
3.常量:大写字母和下划线:MAX_VALUE
4.类名:首字母大写和驼峰原则:Man,GoodMan
5.方法名:首字母小写和驼峰原则:run(),runRun()

(3)注释

1.单行注释:/ /
2.多行注释:/* */
3.文档注释:/** */
注:/* */ 注释不能嵌套

(4)数据类型

Java共有8种基本类型,其中有4种整形、2种浮点类型、1种字符类型和1种表示真值的boolean类型。

整形

类型 存储需求 取值范围
int 4字节 -2 147 483 648~2 147 483 647
short 2字节 -32 768~32 767
long 8字节 -9 223 372 036 854 775 808~9 223 372 036 854 775 807

Java是强类型的,整形的范围与运行Java代码的机器无关,所有数值类型占用的字节数是固定的

浮点型

类型 存储需求 取值范围
float 4字节 大约 ± \pm ± 3.402 823 47E+38F(有效位数为6~7位)
double 8字节 大约 ± \pm ± 1.797 693 134 862 315 70E+308(有效位数为15位)

所有浮点数值计算都遵循IEEE 754规范,溢出和出错情况表示为:正无穷大、负无穷大、NaN(不是一个数字)
注:浮点数不适用于无法接收舍入误差的计算。

char类型

在Java中,char类型描述了UTF-16中的一个代码单元。
char类型的字面值要用单引号括起来,如’A‘是编码值为65的字符常量,要注意与“A”的区分。
char类型的值可以表示为16进制值,范围从 \u0000到 \uFFFF

boolean类型

boolean(布尔)类型有两个值:false和true,用来判定逻辑条件。整型值和布尔值直接不能相互转换。

(5)变量与常量

声明变量

在Java中,每个变量都有一个类型type,在声明变量时,要先声明变量的类型,如:

double salary;
int vacationDays;
long earthPopulation;
boolean done;

变量声明后,必须用赋值语句对变量进行显示初始化。如:

int vacationDays1;
vacationDays1 = 12;
int vacationDays2 = 12; 

在Java中可以将声明变量放在代码中任何地方。
注:
1.变量名对大小写敏感,且不能用Java保留字作变量名。
2.从Java10开始,对于局部变量,如果可以从变量的初始值推断出它的类型,就不需要声明类型。只需要使用关键字var,如:

var vacationDays = 12; 		// int
var greeting = "Hello"; 	// String

常量

利用关键字final指示常量,如:

final double CM_PER_INCH = 2.54;

常量只能被赋值一次,且被赋值后不能更改,习惯上,常量名使用全大写。
在Java中,经常希望某个变量可以在一个类中的多个方法中使用,通常将这些变量称为类常量(class constant),使用关键词static final进行设置,如:

public static final double CM_PER_INCN = 2.54;

需要注意,类常量的定义位于main方法的外部。

枚举类型

有时候,变量的取值只在一个有限的集合内,可以自定义枚举类型,如:

enum Size{SMALL,MEDIUM,LARGE,EXTRA_LARGE};
Size s = Size.MEDIUM;

(6)运算符

Java提供了一组丰富的算数和逻辑运算符以及数学函数

算术运算符

常见的算术运算符有+、-、*、/等,整数的求余操作用%表示。
注:整数被0整除会产生一个异常,而浮点数被0整除会得到无穷大或NaN结果。

数学函数与常量

Math类中,包含了各种各样的数学函数。在编写不同类别的程序时,可能需要的函数也不同。具体可以参考联机API文档

数值类型之间的转换

当用一个二元运算符连接两个值时,要先将连个操作数转换为同一类型,然后再进行计算:
①如果两个数有一个是double类型,另一操作数就会转换为double类型
②如果两个数有一个是float类型,另一操作数就会转换为float类型
③如果两个数有一个是long类型,另一操作数就会转换为long类型
④否则,两个操作数都转换为int类型

强制类型转换

在Java中,允许进行数值之间的类型转换,可能会丢失一些信息。如:

double x = 9.997;
int nx = (int) x;

如果相对浮点数进行舍入运算,可以使用Math.round方法:

double x = 9.997;
int nx = (int) Math.round(x);

结合赋值和运算符

可以在赋值中使用二元运算符,如:

x += 4;

等价于:

x = x + 4;

注:如运算符得到一个值,其类型与左侧类型不同,则会发生强制类型转换。

自增和自减

与C语言的i++、i–相同,Java也引入了自增自减操作,但不建议使用

关系运算符

常用的关系运算符有:==、<、>、<=、>=、&&(与)、||(或)、!=(非)等。
此外还有三元运算符:condition ? expression1 : expression2

位运算符

位运算符包括:&(”and“)、|(”or“)、^(”xor“)、~(”not“)
另外,还有<<和>>运算符表示位模式左移或右移。
最后,>>>运算符会用0填充高位,这与>>不同,它会用符号位填充高位。不存在<<<运算符。

括号与运算符的级别

Java从零开始系列01:Java入门_第1张图片注:Java没有逗号运算符。

(7)字符串

从概念上讲,字符串就是Unicode字符序列。Java类库中提供了一个预定类String。

子串

String类的substring方法可以从一个较大的字符串提取一个子串。如:

String greeting = "Hello";
String s = greeting.substring(0,3);

创建一个由字符”Hel“组成的字符串。

拼接

Java语言允许使用+连接(拼接)两个字符串:

String expletive = "Expletive";
String PG13 = "deleted";
String message = expletive + PG13;

当一个字符串与一个非字符串的值进行拼接时,后者会转换为字符串。
在Java11中,还提供了一个repeat方法:

String repeated = "Java".repeat(3);	// repeated is "JavaJavaJava"

不可变字符串

String没有提供修改字符串中某个字符的方法,可以通过以下操作实现:

String greeting = "Hello";
greeting = greeting.substring(0,3) + "p!";

检查字符串是否相等

可以用equals方法检测两个字符是否相等。如:

"Hello".equals(greeting)

想要检测两个字符串是否相等而不区分大小写,可以使用equalsIgnoreCase方法:

"Hello".equalsIgnoreCase("hello")

注:不要用 == 判断字符串是否相等

空串与Null串

空串 “” 是长度为0的字符串,可以调用以下代码检查一个字符串是否为空:

if (str.length() == 0)
if (str.equals(""))

空串是一个Java对象,有自己的串长度(0)和内容(空)。不过,String变量还可以存放一个特殊的值null,表示目前没有任何对象与该变量关联,可以调用以下代码检查一个字符串是否为null:

if (str == null)

有时要检查一个字符串既不是空串也不是null,可以用如下条件:

if (str != null && str.length() !=0)

首先要检查str不为null。

码点与代码单元

码点(codepoint)是指与一个编码表中的某个字符对应的代码值。在Unicode标准中,码点采用十六进制书写,并加上前缀U+,例如U+0041就是拉丁字母A的码点。

Unicode的码点可以分为17个代码平面(code plane)。第一个代码平面称为基本多语言平面(basic multilingual plane),包括从U+0000到U+FFFF的“经典”Unicode代码;其余16个平面的码点为从U+10000到U+10FFFF,包括辅助字符(supplementary character)。

UTF-16编码采用不同长度的编码表示所有的Unicode码点。在基本多语言平面中,每个字符用16位表示,通常称为代码单元(code unit)。

Java字符串由char值序列组成,char数据类型是一个采用UTF-16编码表示Unicode码点的代码单元。最常用的Unicode字符使用一个代码单元就可以表示,辅助字符需要一对代码单元表示。

length方法将返回采用UTF-16编码表示给定字符串所需要的代码单元的数量:

String greeting = "Hello";
int n = greeting.length();	// is 5

想要得到实际长度,即码点数量,可以调用:

intcpCount = greeting.codePointCount(0,greeting.length());

调用s.charAt(n)将返回位置n的代码单元,n介于0~s.length()-1之间:

char first = greeting.charAt(0);	// first is 'H'
char last = greeting.charAt(4);		// last is 'o'

想要得到第i个码点,可以使用:

int index = greeting.offsetByCodePoints(0,i);
int cp = greeting.codePointAt(index);

如果想要遍历一个字符串,并且依次查看每一个码点,可以:

int cp = sentence.codePointAt(i);
if (Character.isSupplementaryCodePoint(cp))
	i += 2;
else
	i++;

可以使用下列语句实现反向编译:

i--;
if (Character.isSurrogate(sentence.charAt(i)))
	i--;
int cp = sentence.codePointAt(i);

这么做很麻烦,可以使用codePoints方法,会生成一个int值的“流”,每个int值对应一个码点,可以将它转换为一个数组,再完成遍历:

int[] codePoints = str.codePoints().toArray();

反之,要把一个码点数组转换为一个字符串,可以使用构造器:

String str = new String(codePoints, 0, codePoints.length);

更多信息可以查看联机API

构建字符串

如果需要用许多小段的字符串来构建一个字符串,那么应该按下列步骤进行。首先,构建一个空的字符串构建器:

StringBuilder builder = new StringBuilder();

每次需要添加一部分内容时,就调用append方法:

builder.append(ch);		// append a single character
builder.append(str);	// appends a string

在字符串构建完成时调用toString方法,将可以得到一个String对象:

String completedString = builder.toString();

(8)输入与输出

读取输入

要想通过控制台进行输入,首先要构造一个与“标准输出流”System.in关联的Scanner对象

Scanner in = new Scanner(System.in)

现在,就可以使用Scanner类的各种方法读取输入了。例如,nextLine方法将读取一行输入:

System.out.print("What is your name?");
String name = in.nextLine();

这里使用nextLine方法是因为在输入行中可能包含空格。要想读取一个单词,可以使用:

String firstName = in.next();

要想读取一个整数,就调用nextInt方法:

int age = in.nextInt();

与此类似,想要读取一个浮点数,就调用nextDouble方法:
Scanner类定义在java.util包中。

格式化输出

可以使用语句 System.out.print(x) 将数值输出到控制台。同时,Java5沿用了C语言函数库的printf方法。
还可以使用静态的String.format方法创建一个格式化的字符串,而不打印输出:

String message = String.format("Hello, %s. Next year, you'll be %d", name, age);

其他转换符这里不作详述。

文件的输入与输出

想要读取一个文件,需要构造一个Scanner对象:

Scanner in = new Scanner(Path.of("myfile.txt"), StandardCharsets.UTF_8);

要想写入文件,就需要构造一个PrintWriter对象。在构造器(constructor)中,需要提供文件名和字符编码:

PrintWriter out = new PrintWriter("myfile.txt", StandardCharsets.UTF_8);

如果文件不存在,创建该文件。可以像输出到System.out一样使用print,println以及printf命令。

(9)控制流程

块作用域

块(block)即复合语句,是指若干条Java语句组成的语句,用一对大括号括起来。一个块可以嵌套在另一个块中,但不能在嵌套的两个块中声明同名的变量。如:

public static void main(String[] args)
{
	int n;
	...
	{
		int k;
		int n;	// ERROR -- can't redefine n in inner block
	}
}

条件语句

在Java中,条件语句的形式为:

if (condition) statement

这里的条件必须用小括号括起来
此外还有 if … else , if … else if … else语句

循环

当条件为true时,while循环执行:

while (condition) statement

此外还有 do … while 语句

确定循环

for循环语句是支持迭代的一种通用结构:

for (int i = 1; i <= 10; i++)
	System.out.println(i);

多重选择:switch语句

Java的switch语句与C语言类似:

switch (choice)
{
	case 1:
		...
		break;
	case 2:
		...
		break;
	...
	default:
		// bad input
		...
		break;
}

case标签可以是:
①类型为char、byte、short或int的常量表达式
②枚举常量
③从Java7开始,case标签还可以是字符串字面量。

中断控制流程的语句

尽管Java的设计者将goto作为保留字,但实际上并没有打算在语言中使用它。

与C语言不同,Java还提供了一种带标签的break语句,用于跳出多重嵌套的循环语句。

标签必须放在希望跳出的最外层循环之前,并且必须紧跟一个冒号:

Scanner in = new Scanner(System.in);
int n;
read_data:
while(...)
{
	...
	for(...)
	{
		if(...)
			break read_data;
	}
}
...

break和continue语句的使用与C语言类似,不作阐述

(10)大数

如果基本的整数和浮点数精度不能够满足需求,可以使用java.math包中的两个类:BigInteger 和 BigDecimal。可以处理包含任意长度数字序列的数值。BigInteger 用于实现任意精度的整数运算,BigDecimal用于实现任意精度的浮点数运算。

使用静态的valueOf方法可以将普通的数转换为大数:

BigInteger a = BigInteger.valueOf(100);

对于更大的数,可以使用一个带字符串参数的构造器:

BigInteger reallyBig = new BigInteger("23231431152531251235113251241241513241321");

另外还有一些常量:BigInteger.ZERO、BigInteger.ONE和 BigInteger.TEN,Java9之后又添加了BigInteger.TWO
不能使用人们熟悉的算术运算符处理大数,而要使用大数类中的add和multiply方法:

BigInteger c = a.add(b);	// c = a + b
BigInteger d = c.multiply(b.add(BigInteger.valueOf(2)));	// d = c * (b + 2)

(11) 数组

声明数组

数组是一种数据结构,用来存储同一类型值得集合。
创建数组:

int[] a = new int[100];	// or var a = new int[100];

数组得长度不要求是常量,但一旦创建了数组,就不能再改变它得长度。若程序运行过程中经常需要扩展数组得大小,则应该使用另一种数据结构–数组列表(array list)。

在Java中,提供了一种创建数组对象并同时提供初始值得简写形式。如:

int[] smallPrimes = { 2, 3, 5, 7, 11, 13 };

该方法不需要使用new,也不用指定长度。且最后一个值后允许有逗号,可以方便不断为数组增加值。

还可以声明一个匿名数组:

smallPrimes = new int[] { 2, 3, 5, 7, 11, 13 };

这是下列语句得简写形式:

int[] anonymous = { 2, 3, 5, 7, 11, 13 };
smallPrimes = anonymous;

访问数组元素

创建一个数字数组时,所有元素初始化为0;boolean数组初始化为false;对象数组初始化为null。

想要获得数组中得元素个数,可以使用 array.length

for each 循环

Java提供了一种很强得循环结构可以用来一次处理数组中每个元素。而不必考虑下标值:

for (variable : collection) statement

它定义了一个变量用于暂存集合中得每个元素,并执行相应得语句。collection这一集合表达式必须是一个数组或者是一个实现了Iterable接口的类对象(例如ArrayList)。如:

for (int element : a)
	System.out.println(element);

打印每个数组元素,一个元素占一行。
或者使用传统的for循环:

for (int i = 0; i < a.length; a++)
	System.out.println(a[i]);

数组拷贝

Java中允许将一个数组变量拷贝到另一个数组变量,两个变量将引用同一个数组:

int[] luckyNumbers = smallPrimes;
luckyNumbers[5] = 12;	// now smallPrimes[5] is also 12

若希望将一个数组的所有值拷贝到一个新的数组中去,就要使用Arrays类的copyOf方法:

int[] copiedLuckyNumbers = Arrays.copyOf(luckyNumbers, luckyNumbers.length);

第二个参数是新数组的长度,这个方法通常用于增加数组的大小:

luckyNumbers = Arrays.copyOf(luckyNumbers, 2 * luckyNumbers.length);

命令行参数

每一个应用程序都有一个带String arg[]参数的main方法,这个参数表明main方法将接收一个字符串数组。

数组排序

对数组进行排序可以使用Arrays类中的sort方法:

int[] a = new int[10000];
...
Arrays.sort(a)

这个方法使用了优化的快速排序(QuickSort)方法

多维数组

多维数组将使用多个下标访问数组元素,它适用于表示表格或更加复杂的排列形式。
声明一个二维数组:

double[][] balances;

对数组进行初始化前是不能使用的,可以通过如下代码进行初始化:

balances = new double[NYEARS][NYEARS]

另外,如果知道数组元素,就可以不调用new,如:

int[][] magicSquare = { {16, 3, 2, 13}, {5, 10, 11, 8}, {4, 15, 14, 1}};

一旦数组初始化,就可以利用两个中括号访问各个元素。如:balances[i][j]。

不规则数组

Java实际上没有多维数组,只有一维数组。多维数组被解释为“数组的数组”。


参考资料:

狂神说Java
Java核心技术 卷I(第11版)


下一章:Java从零开始系列02:对象与类

你可能感兴趣的:(java)