摘要:
虽然已经在实际工作中经常与java打交道,但是一直没系统地对java这门语言进行梳理和总结,掌握的知识也比较零散。恰好利用这段时间重新认识下java,并对一些常见的语法和知识点做个总结与回顾,一方面为了加深印象,方便后面查阅,一方面为了学好java打下基础。
java语言于1995年正式推出,最开始被命名为Oak语言,由James Gosling(詹姆斯·高斯林)在Sun Microsystems公司和同事共同研发,Microsystems如今已经被oracle收购。java语言具有以下特点:
Java文件运行过程如下:
注释用于解释程序,增强可读性,java中注释有以下几种:
// 单行注释
/*
多行注释
多行注释
*/
/**
* javadoc注释
*/
标识符用于标识类名,方法名,变量名,接口名等,命名需要满足以下规则:
java编程规范建议遵守驼峰命名法,类名和接口名首字母大写,变量和方法名首字母小写。Java采用unicode的编码方式,所以标识符也支持中文。
java定义一个类用class关键字,有以下几点需要注意:
数据类型的作用是指导JVM在运行程序的时候给该数据分配多大的内存空间,Java提供了以下八种基础数据类型:
序号 | 分类 | 类型 | 介绍 | 实例 |
---|---|---|---|---|
01 | 整数型 | byte | 8位有符号整数(取值范围:-128~127) | byte a = 128; |
02 | 整数型 | short | 16位有符号整数(取值范围:-32768~32767) | short num = 1314; |
03 | 整数型 | int | 32位有符号整数 | int n = 131400; |
04 | 整数型 | long | 64位有符号整数 | long sum = 10000L; |
05 | 浮点型 | float | 单精度、32位、符合IEEE 754标准的浮点数 | float f1 = 13.14f; |
06 | 浮点型 | double | 双精度、64 位、符合IEEE 754标准的浮点数 | double d1 = 13.1452; |
07 | 布尔型 | boolean | 一位用于表示真假,只能取true 和 false; | boolean isMan = true; |
08 | 字符型 | char | 一个单一的 16 位 Unicode 字符(0~65535) | char firstLetter = ‘a’; |
整型有三种表示方式,默认是十进制:
进制 | 表示方式 | 实例 |
---|---|---|
十进制 | 默认的表示方式,以非零数字开始 | int x = 10; // x = 10 |
八进制 | 以数字零"0"开始 | int x = 010; // x = 8 |
十六进制 | 以"0x"开始 | int x = 0x10; // x = 16 |
类型转换有如下规则:
对于强制类型转换,将long强转成int的语法如下:
long k = 6475201314L;
int num = (int) k;
注意:大容量转换成小容量编译无法通过,比如下面代码无法编译:
byte b = 19;
b = b + 13; // 相当于直接把整型赋值给byte型,报错
b += 13; // 可以编译,等同于 b = (byte)(b + 13)
在Java中使用String 类来创建和操作字符串,初始化一个String的语法如下:
// 常用,用双引号直接创建
String testStr = "Wasting time is robbing oneself";
// 不常用,使用char数组创建
char[] helloArray = {'h', 'e', 'l', 'l', 'o'};
String helloString = new String(helloArray);
由于字符串使用非常频繁,String类也提供了很多方法,下面介绍一些用的比较多的。
序号 | 方法 | 描述 |
---|---|---|
01 | String trim() | 返回字符串的副本,忽略前面空白和尾部空白。 |
02 | String intern() | 返回字符串对象的规范化表示形式。 |
03 | String toUpperCase() | 使用默认语言环境的规则将此 String 中的所有字符都转换为大写。 |
04 | String toUpperCase(Locale locale) | 使用给定的Locale规则将String中所有字符转换为大写。 |
05 | String toLowerCase() | 使用默认语言环境的规则将此 String 中的所有字符都转换为小写。 |
06 | String toLowerCase(Locale locale) | 使用给定 Locale 的规则将此 String 中的所有字符都转换为小写。 |
序号 | 方法 | 描述 |
---|---|---|
01 | boolean startsWith(String str1) | 字符串是否以指定的字符串str1开始。 |
02 | boolean startsWith(String str1, int toffset) | 字符串指定索引开始的子字符串是否以指定字符串str1开始。 |
03 | boolean endsWith(String str1) | 测试此字符串是否以指定的字符串str1结束。 |
04 | int indexOf(String str1) | 返回指定子字符串str1在此字符串中第一次出现处的索引。 |
05 | int indexOf(String str1, int fromIndex) | 从指定的索引开始,返回指定子字符串str1在此字符串中第一次出现处的索引。 |
06 | int lastIndexOf(String str1)) | 返回指定子字符串str1在此字符串中最右边出现处的索引。 |
07 | int lastIndexOf(String str1, int fromIndex) | 返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索 |
08 | boolean matches(String regex) | 测试此字符串是否匹配给定的正则表达式 |
09 | String replace(char oldChar, char newChar) | 返回一个用 newChar 替换此字符串中出现的所有 oldChar 得到的新字符串。 |
10 | String replaceAll(String regex, String replacement) | 使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串 |
序号 | 方法 | 描述 |
---|---|---|
01 | String substring(int beginIndex) | 返回一个新的从指定索引开始的字符串。 |
02 | String substring(int beginIndex, int endIndex) | 返回从索引beginIndex开始到endIndex结束的新的字符串 |
03 | String[] split(String regex) | 根据给定正则表达式的匹配拆分此字符串。 |
04 | String[] split(String regex, int limit) | 根据匹配给定的正则表达式来拆分此字符串。 |
序号 | 方法 | 描述 |
---|---|---|
01 | int compareTo(String anotherString) | 按字典顺序比较两个字符串,相等时候返回0。 |
02 | int compareToIgnoreCase(String str) | 按字典顺序比较两个字符串,不考虑大小写 |
03 | boolean contentEquals(StringBuffer sb) | 当且仅当字符串与指定的StringBuffer有相同顺序的字符时候返回真。 |
04 | boolean equals(Object anObject) | 将此字符串与指定的对象比较。 |
05 | boolean equalsIgnoreCase(String anotherString) | 将此 String 与另一个 String 比较,不考虑大小写。 |
序号 | 方法 | 描述 |
---|---|---|
01 | int length() | 按字典顺序比较两个字符串,相等时候返回返回此字符串的长度。 |
02 | String toString() | 转换成String对象 |
03 | String concat(String str) | 将指定字符串连接到此字符串的结尾。 |
04 | char[] toCharArray() | 将此字符串转换为一个新的字符数组。 |
05 | char charAt(int index) | 返回指定索引处的 char 值。 |
数组可以用于存放固定大小的同类型元素,声明一个数组的语法如下:
变量类型[] 数组名;
创建数组的语法:
数组名 = new 变量类型[数组大小];
变量类型[] 数组名 = {value0, value1, ..., valuek};
数组的变量类型可以是前面介绍八种基本数据类型以及复合数据类型,“数组名[索引]” 可以访问数组元素,下面是一个操作一维数组例子:
int[] primeNumbers = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
for (int num : primeNumbers) {
System.out.println("num: " + num);
}
操作二维数组的例子如下:
int[][] a = new int[2][3];
a[0][0] = 19;
String[][] s = new String[2][];
s[0] = new String[2]; // 第一个数组长度为2
s[1] = new String[3]; // 第二个数组长度为3
s[0][0] = "Hello";
s[0][1] = "World";
java.util.Arrays类能方便地操作数组,它提供的所有方法都是静态的,比较常见的方法有:
序号 | 方法 | 描述 |
---|---|---|
01 | public static int binarySearch(Object[] a, Object key) | 用二分查找算法在给定数组中搜索给定值的对象(Byte,Int,double等)。前提是数组在调用前必须排序好的。找到了则返回搜索键的索引;否则返回 (-(插入点) - 1)。 |
02 | public static void sort(Object[] a) | 对指定对象数组根据其元素的自然顺序进行升序排列。同样的方法适用于所有的其他基本数据类型(Byte,short,Int等)。 |
使用Arrays的sort方法进行排序的例子如下:
int[] primeNumbers = {7, 11, 5, 2, 3};
Arrays.sort(primeNumbers);
for (int num : primeNumbers) {
System.out.println("num: " + num);
}
Java语言提供了一个完善的集合框架,主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射
经常用到的集合有:
序号 | 类型 | 描述 |
---|---|---|
01 | ArrayList | 该类实现了List的接口,实现了动态数组,随机访问和遍历元素时,提供更好的性能,插入删除效率低。 |
02 | LinkedList | 该类实现了List接口,允许有null(空)元素。主要用于创建链表数据结构,插入删除效率高,查找效率较低。 |
03 | HashSet | 该类实现了set接口,不允许出现重复元素,不保证集合中元素的顺序。 |
04 | HashMap | HashMap 是一个散列表,它存储的内容是键值对(key-value)映射,具有很快的访问速度 |
ArrayList提供的常用方法有:
序号 | 分类 | 方法 | 描述 |
---|---|---|---|
01 | 增加 | boolean add(E object) | 向容器中添加指定数据类型的元素 |
02 | 增加 | boolean addAll([int index], Collection collection) | 向容器中指定的位置增加一个集合 |
03 | 获取 | E get(int location) | 获得容器中位置location的元素 |
04 | 删除 | E remove(int i) | 移除下标为i的元素,返回值是删除的数据元素 |
05 | 删除 | void clear() | 清空容器所有元素 |
06 | 统计 | int size() | 获得容器中元素的个数 |
07 | 判断 | boolean isEmpty() | 获得容器中是否有元素 |
08 | 修改 | E set(int location, E object) | 修改容器中指定位置元素的值 |
下面是操作一个java.util.ArrayList的例子:
ArrayList list = new ArrayList();
list.add(2);
list.add(3);
list.add(5);
for (int i = 0; i<list.size(); i++) {
System.out.println(list.get(i));
}
list.remove(1);
list.set(1, 19);
关于数据类型,最后再介绍下Java中常见的类型转换方法:
序号 | 方法 | 描述 | 实例 |
---|---|---|---|
01 | String.toCharArray() | String类型转换成char数组 | String str = “hello word”;char[] nums = str.toCharArray(); |
02 | Integer.parseInt() | String类型转换成int类型 | String numStr = “1314”;int num = Integer.parseInt(numStr); |
03 | Double.parseDouble() | String类型转换成Double类型 | String doubleStr = “13.14”;double d = Double.parseDouble(doubleStr); |
04 | Integer.toString() | int类型转换成String类型 | int num = 12;String numStr = Integer.toString(num); |
05 | Double.toString() | Double类型转换成String类型 | Double num = 13.14;String numStr = Double.toString(num); |
Java的运算符种类比较多,本文介绍几种常见的运算符:
java的算术运算符如下表(int a = 10; int b= 9;):
序号 | 操作符 | 描述 | 实例 |
---|---|---|---|
01 | + | 加法 - 对运算符两侧的值进行相加 | a + b = 19; |
02 | - | 减法 - 左操作数减去右操作数 | a - b = 1; |
03 | * | 乘法 - 对运算符两侧的值进行乘法运算 | a * b = 90; |
04 | / | 除法 - 左操作数除以右操作数 | a / b = 1; |
05 | % | 取余 - 左操作数除以右操作数的余数 | a % b = 1; |
06 | ++ | 自增: 操作数的值增加1 | ++a,a++均为11,前者先自增,再进行表达式运算,后者顺序相反 |
07 | – | 自减:操作数的值减少1 | –b,b-- 均为8,前者先自减,再进行表达式运算,后者顺序相反 |
基本的赋值运算符"=" 可以与前5种算术运算符组合成 +=,-=,*=,/=,%=等扩展的赋值运算符
int a = 10; a += 5; 等价于 a = (int)(a + 5);
其他的运算符类似,扩展运算符默认有类型转换,但是不改变运算结果类型
对于"+"运算符,只要两边的操作数有一个是字符串就会进行字符串连接运算生成一个新的字符串。
java中主要有以下六种关系运算符:
运算符 | 描述 | 运算符 | 描述 | 运算符 | 描述 |
---|---|---|---|---|---|
> | 大于 | >= | 大于等于 | < | 小于 |
<= | 小于等于 | == | 等于 | != | 不等于 |
关系运算符返回的结果是布尔型
主要有以下三种逻辑运算符(boolean a = true; boolean b = false):
序号 | 操作符 | 描述 | 实例 |
---|---|---|---|
01 | && | 逻辑与,只有两个操作数都为真才返回true | a && b 为false |
02 | || | 逻辑或,两个操作数只要有一个为真就返回true | a || b 为true |
03 | ! | 逻辑非,对操作数的状态取反 | !a 为false,!b为true |
位运算符对两个操作数的每一位进行运算,有以下几种常见的类型:
运算符 | 描述 | 运算符 | 描述 | 运算符 | 描述 |
---|---|---|---|---|---|
& | 按位与 | | | 按位或 | ^ | 按位异或 |
~ | 按位取反 | <>> | 按位左移/右移 | >>> | 指定位数右移,空位补零 |
三目元素符的语法规则:
布尔表达式 ? 表达式1 : 表达式2;
布尔表达式为真执行表达式1,为假执行表达式2,利用三目运算符求最大值的一个例子如下:
int a = 10;
int b = 9;
int max = (a > b) ? a : b;
System.out.println("max number is: " + max);
每种编程语言都少不了控制语句来控制代码流程,java语言也提供了丰富的控制语句。
if语句常见的语法:
// 第一种写法,else分支可以省略
if (布尔表达式) {
表达式为真要执行的语句;
} else {
其他条件要执行的语句
}
// 第二种写法,最后的else分支可以省略
if (布尔表达式) {
表达式为真要执行的语句;
} else if (布尔表达式1) {
表达式1为真要执行的语句
} else if (布尔表达式2) {
表达式2为真要执行的语句
} else {
除上述条件之外要执行的语句
}
switch语句的语法如下:
switch (expression) {
case value1 :
// 匹配value1成功之后执行的语句
break; // 可选
case value2 :
// 匹配value2成功之后执行的语句
break; //可选
...
default : // 可选
// 前面case分支都没匹配时执行的语句
}
其中expression支持byte、short、int、char以及字符串(String),byte、short、char会转换为int类型。程序只有遇到break语句才会跳出switch语句,缺少break的分支会继续往下面分支执行。
程序当中总会有些需要重复执行的代码片段,因此各个编程语言都支持循环语法。
for语句的语法如下:
for (初始化表达式; 布尔表达式; 更新表达式) {
// 要重复执行的代码片段
}
执行过程:
int sum = 0;
for (int i = 0; i <= 10; i++) {
sum += i;
}
System.out.println("the sum is: " + sum);
while语句的语法如下:
while (布尔表达式) {
// 循环内容
}
执行过程:
先判断布尔表达式的值,为真就执行循环体,为假则循环结束,循环体可能一次也不执行。
使用while循环计算数字1到10的和是:
int sum = 0;
int i = 0;
while (i <=10) {
sum += i;
i++;
}
System.out.println("The sum is: " + sum);
do…while循环的语法如下:
do {
// 循环内容
} while (布尔表达式);
do…while循环先执行循环内容再判断表达式,循环体至少会执行一次。
break使用在switch语句中终止switch执行,使用在循环语句中终止循环,跳出当前循环体。语法如下:
break;
continue表示直接进入下一次循环继续执行,语法如下:
continue;
在Java中,所有的变量在使用前必须声明。声明变量的基本格式如下:
type identifier = value;
value的数据类型必须和声明的变量类型一致,变量的值可变化,必须先声明再赋值才能访问。
java中的局部变量声明在方法内部,有以下特点:
局部变量存储在栈内存中。
成员变量在方法体之外声明,有以下特点:
成员变量在JVM的堆内存中存储,垃圾回收器主要针对堆内存处理。
静态变量用static关键字声明,需要记住以下特点:
不同类型变量在JVM中的存储情况如下表:
栈内存 | 堆内存 | 方法区内存 |
---|---|---|
局部变量/执行的方法 | 实例变量/new出来的对象 | 静态变量/代码片段 |
方法实质就是一段可以重复使用,完成某项特定功能的片段,和C语言中的函数类似。方法的语法如下:
[修饰符] 返回值类型 方法名(参数类型 参数名1, 参数类型 参数名2 ...) {
...
方法体;
...
return 返回值; // 可选,与返回值类型一致
}
比如常见的main方法如下:
public static void main(String []args) {
System.out.println("Hello World!");
}
方法有如下几个部分组成:
private static boolean isPrimeNumber(int num) {
boolean isPrime = true;
for (int i = 2; i < num; i++) {
if (num % i == 0) {
isPrime = false;
break;
}
}
return isPrime;
}
方法代码片段属于.class字节码文件的一部分,在调用方法的时候才会在栈中分配内存,称为压栈;方法执行结束释放方法的内存空间称为弹栈。方法执行完之后,方法内局部变量的空间也释放,因此局部变量只在方法内有效。JVM的栈中主要存储的是局部变量。
方法重载(overload)主要是是指方法名相同,参数列表不同,和返回值类型无关,和修饰符无关。要构成方法重载需要满足以下条件:
面向对象是Java核心的特点,主要有以下特性:
对象和类的定义:
对象和类的关系:
一个类进行实例化就形成了对象,对象抽象形成类。
类的语法如下:
[修饰符列表] class 类名 {
属性; // 对象的状态信息,通常采用变量方式定义,称为成员变量
方法; // 对象的动作信息
}
类实例化需要用new运算符,语法如下:
new 类名();
java中的类属于引用数据类型,new新建的java对象存储在JVM的堆内存中,new等号左侧类的变量名存储的是指向堆内存的地址。每个new出来的类的内存互相独立。
Java面向对象中相关的重要知识点有:
Java中声明一个接口的语法如下:
interface 接口名称 [extends 其他的接口名] {
全局常量;
抽象方法;
}
接着介绍Java中使用非常频繁的几个函数:
控制台的输出由 print() 和 println() 完成。这些方法都由类 PrintStream 定义,System.out 是该类对象的一个引用。print()打印指定的字符不换行,println()打印完成换一行。
下面是使用的例子:
System.out.print("Remember: ");
System.out.println("Haste makes waste");
Java中使用java.util.Scanner类获取用户的输入,使用前需要先创建Scanner对象。常用next() 与 nextLine() 方法获取输入的字符串,对应地用hasNext() 与 hasNextLine() 判断是否还有输入的数据。
下面是使用next函数获取用户输入字符串的例子:
// 创建scanner对象
Scanner scan = new Scanner(System.in);
// 判断是否还有输入
if (scan.hasNext()) {
String inputStr = scan.next();
System.out.println("you input:" + inputStr);
}
// 关闭scanner
scan.close();
还可以使用nextInt接收一个整数,Scanner常用的方法如下表:
序号 | 方法 | 描述 | 判断是否有数据方法 |
---|---|---|---|
01 | next() | 获取输入的字符串,不带空格 | hasNext() |
02 | nextLine() | 获取输入的一行字符串,支持空格,以Enter键结束 | hasNextLine() |
03 | nextInt() | 获取用户输入的整数 | hasNextInt() |
04 | nextFloat() | 获取用户输入的浮点数 | hasNextFloat() |
Java这门语言涵盖的知识点比较丰富,一篇文章是不可能将所有知识点都完全覆盖到的。本文的主要目的是梳理下基础常见的知识点,帮助大家一起复习下,学习一门语言打好基础是至关重要的。掌握了这些基础知识点,自己动手写一些小程序问题也不大。文章最后再附上一个完整代码的小例子,实现的功能是将用户输入的字符串逆序输出:
class Test{
public static void main(String args[]) {
Scanner scan = new Scanner(System.in);
String inputStr = scan.nextLine();
// String转换为char数组
char[] nums = inputStr.toCharArray();
for (int i = nums.length; i>0; i--) {
System.out.print(nums[i-1]);
}
System.out.println("");
}
}