常用Api
- 基本数据类型范围从小到大排序为:byte --> short/char --> int --> long --> float --> double
Object
/**
* Java中类层次结构的根类,定义了“对象”的基本行为,任何类都直接或间接地继承该类
* java.lang包是Java的核心包,由虚拟机自动导入
*/
java.lang.Object
// 默认比较俩对象的地址,重写后可比较俩对象的具体内容
public boolean equals(Object obj)
// Java官方规定俩对象equals后相等则hashCode也须相等
public native int hashCode()
// 获取对象的字符串表现形式,重写后可获取对象的具体内容
public String toString()
Wrapper
/**
* 为了满足万物皆对象的理念就需要对基本数据类型的变量进行打包封装处理成对象,而负责将这些变量进行对象化处理的相关类就叫做包装类
* 其中Byte/Short/Integer/Long/Float/Double都是java.lang.Number类的子类
* Java5前使用包装类进行运算时需使用繁琐的拆箱/装箱操作,Java5开始增加了自动拆箱/装箱功能
* 自动装箱池,在整数包装类的内部都提供了自动装箱池技术,当程序中使用-128至127间的整数时无须装箱即可直接取用自动装箱池内的对象
* 包装类都重写了equals()、hashcode()、toString()等方法
*/
java.lang.Byte/Short/Integer/Long/Float/Double/Boolean/Character
// 包装类对象拆分为基本类型数据
public static int parseInt(String s)
// 基本类型数据封装为包装类对象
public static Integer valueOf(String s)
// 大整数转十六进制
public static String toHexString(long i)
// 判断浮点数是否为非数字
public static boolean isNaN(float v)
// 字符转小写
public static char toLowerCase(char ch)
// 判断是否为大写
public static boolean isUpperCase(char ch)
// 判断是否为数字字符
public static boolean isDigit(char ch)
Math
/**
* 用于提供执行数学运算的方法
*/
java.lang.Math
// 取最大值
public static int max(int a, int b)
// 取最小值
public static double min(double a, double b)
// 取绝对值
public static double abs(double a)
// 四舍五入
public static long round(double a)
// a的b次方
public static double pow(double a, double b)
// 0至1间的随机数
public static double random()
BigDecimal
/**
* 由于浮点型数据在运算时可能会存在误差,若希望实现精确运算可使用该类
*/
java.math.BigDecimal extends Number implements Comparable<BigDecimal>
// 加法运算
public BigDecimal add(BigDecimal augend)
// 减法运算
public BigDecimal subtract(BigDecimal subtrahend)
// 乘法运算
public BigDecimal multiply(BigDecimal multiplicand)
// 除法运算,四舍五入
public BigDecimal divide(BigDecimal divisor, RoundingMode roundingMode)
BigInteger
/**
* 若希望表示比long范围还大的整数数据则可使用该类
*/
java.math.BigInteger extends Number implements Comparable<BigInteger>
// 加法运算
public BigInteger add(BigInteger val)
// 减法运算
public BigInteger subtract(BigInteger val)
// 乘法运算
public BigInteger multiply(BigInteger val)
// 除法运算
public BigInteger divide(BigInteger val)
// 求模运算
public BigInteger remainder(BigInteger val)
// 除法和求模运算
public BigInteger[] divideAndRemainder(BigInteger val)
String
/**
* 用于描述字符串,该类被final关键字修饰
* Java9开始底层不再使用char[]来存储数据,而是改用byte[]
*/
java.lang.String implements java.io.Serializable, Comparable<String>, CharSequence
“hello”常量池 new 堆区
常量优化机制 “abcd” "ab" + "cd"
集合
异常
反射
异常
基础语法
java.lang.Object ==> Java中类层次结构的根类,定义了“对象”的基本行为,任何类都直接或间接地继承该类
// 默认比较俩对象的地址,重写后可比较俩对象的具体内容
public boolean equals(Object obj)
// Java官方规定俩对象equals后相等则hashCode也须相等
public native int hashCode()
// 获取对象的字符串表现形式,重写后可获取对象的具体内容
public String toString()
包装类
为了满足万物皆对象的理念就需要对基本数据类型的变量进行打包封装处理成对象,而负责将这些变量进行对象化处理的相关类就叫做包装类。
java.lang.Byte/Short/Integer/Long/Float/Double ==>
java.lang.Boolean/Character ==>
集合
Java、JDK、JRE、JVM
- Java是美国Sun公司于1995年推出的(面向对象)高级编程语言;
- JDK是Java开发工具包、同时也是整个Java开发的核心,包含了JRE和Java开发工具,是用来编译和调试Java程序的;
- JRE是Java运行环境,包含了JVM和Java程序所需的核心类库,是用来运行Java程序的;
- JVM是Java虚拟机,同时也是整个Java实现跨平台最核心的部分,JVM本质上就是一个程序,当JVM启动后就开始执行字节码文件中的指令。
Java程序的编译、运行
- 编译是指将我们编写的Java源文件翻译成JVM认识的.class字节码文件,javac在编译过程中如果检查出我们所写的程序有错误的话会编译报错,没错则编译成功;
- 运行则是指将编译好的字节码文件交给JVM去执行。
关键字、标识符、注释
- 关键字是指Java中已经定义好的(小写)单词,是具有特殊含义的。
- 标识符是指我们自己定义的内容,如类名、方法名、变量名等都是标识符,标识符可以包含26个大小写字母、0-9数字、$以及_;标识符不能以数字开头、不能是关键字。
- Java中支持三种注释方式,单行注释、多行注释以及文档注释。
/**
* 文档注释,多用于类、方法和变量上,用于描述其作用
*/
public class Demo {
public static void main(String[] args) {
// 单行注释,只能注释一行内容
/* 多行注释,能注释很多行内容 */
}
}
牢记:命名规则为项目名、包名全小写;常量名全大写且单词间用_连接;文件名、类名使用大驼峰;方法名、变量名使用小驼峰。
常量、变量、直接量
- 常量是指在程序运行过程中其值固定不变的数据,通常使用final关键字修饰。
- 变量则是指在程序运行过程中其值可以改变的数据。
- 直接量是指在Java程序中直接写出的内容,如下面代码中出现的99、9.999都是直接量。
public class Demo {
public static void main(String[] args) {
final int CONSTANT = 99; // 定义一个int类型的常量
double variable = 9.999; // 定义一个double类型的变量
System.out.println("CONSTANT的值为:" + CONSTANT); // CONSTANT的值为:99
System.out.println("variable的值为:" + variable); // variable的值为:9.999
}
}
数据类型、类型转换
Java中的数据类型可分为基本数据类型和引用数据类型,基本数据类型又分为四类八种,分别是byte、short、int、long、float、double、char、boolean;引用数据类型分别为类、接口、枚举、数组等。
基本数据类型 | 数据范围 | 占用字节个数 |
---|---|---|
byte | -207 ~ 207-1 | 1 |
short | -215 ~ 215-1 | 2 |
int | -231 ~ 231-1 | 4 |
long(L) | -263 ~ 263-1 | 8 |
float(F) | ~ | 4 |
double | ~ | 8 |
char | 0 ~ 65535 | 2 |
boolean | true、false | 1 |
Java中char类型采用的是Unicode字符集编码,而Unicode中的0~127其实就是ASCII编码表。开发中常用的ASCII有48(0)、65(A)、97(a)、32(空格)、10(换行);常用的转义字符有换行(\n)、横向制表(\t)、双引号(\")、反斜杠(\\)等。
整数直接量的类型默认为int,浮点数直接量的类型默认为double。浮点数类型的数据在运算时可能会存在误差,float一般可以精确到7位有效数字,而double一般可以精确到16位有效数字。
基本数据类型范围从小到大排序:byte ~> shrot/char ~> int ~> float ~> double。在数据范围从小到大进行赋值时会发生自动类型转换;在数据范围从大到小进行赋值时需强制类型转换,即在需要强转的数据前加上 (数据类型) 即可,强转可能会发生精度损失、数据溢出,需谨慎使用。
public class Demo {
public static void main(String[] args) {
long l = 1234567890L; // 定义一个long类型的变量
float f = 3.1415926F; // 定义一个float类型的变量
int i = (int) l; // 强制类型转换
double d = f + 1; // 自动类型转换
byte b = 123; // 定义一个byte类型的变量
short s = 12; // 定义一个short类型的变量
char c = 'A'; // 定义一个char类型的变量
int n = (b + s + c); // 提升为int类型再计算并赋值
System.out.println("l的值为:" + l); // l的值为:1234567890
System.out.println("f的值为:" + f); // f的值为:3.1415925
System.out.println("i的值为:" + i); // i的值为:1234567890
System.out.println("d的值为:" + d); // d的值为:4.141592502593994
System.out.println("n的值为:" + n); // n的值为:200
System.out.print('0' + 'A' + 'a' + ' ' + '\n'); // 252
System.out.print((char) 10 + "\t" + "\"HelloWorld\\"); // Tab+"HelloWorld\
}
}
注意:byte/short/char数据类型在运算时都会被提升为int类型再计算(编译器优化)。
运算符
算数运算符,在算数运算过程中如果有不同类型的数据进行计算,那么运算后所得到的结果的数据类型将会是数据范围大的数据类型;在自增自减运算过程中如果是前自增就先加后用,后自增则先用后加,自减同理。运算符“+”既可以作为数值类型的相加运算也可以作为字符串的连接符,如果加号两边有一个数据是字符串类型的,则加号就会被当作字符串连接符处理。
加法 | 减法 | 乘法 | 除法 | 求模 | 自增 | 自减 |
---|---|---|---|---|---|---|
+ | - | * | / | % | ++ | – |
public class Demo {
public static void main(String[] args) {
int i = 13;
System.out.println(i + 2); // 15
System.out.println(i - 2); // 11
System.out.println(i * 2); // 26
System.out.println(i / 2); // 6
System.out.println(i % 2); // 1
System.out.println((double) i / 2); // 6.5
System.out.println((i * 1.0) / 2); // 6.5
int x = 100, y = x++;
System.out.println(x++ + ++x); // 204
System.out.println(--y + ++x); // 203
System.out.println(1 / 0.0); // Infinity(无穷)
System.out.println(0 / 0.0); // NaN(Not a Number)
System.out.println(100 / 0); // java.lang.ArithmeticException: / by zero
}
}
注意:两个整数相除只保留结果的整数部分,若希望保留小数部分只需将其中一个整数强转为浮点数类型就可以了,或者让其中一个整数乘以1.0也可以实现。
赋值运算符,直接量是不能进行赋值的,而在赋值运算中其实是隐含着类型转换的(编译器优化)。
等于 | 加等 | 减等 | 乘等 | 除等 | 模等 |
---|---|---|---|---|---|
= | += | -= | *= | /= | %= |
public class Demo {
public static void main(String[] args) {
int i = 100;
System.out.println(i += 9); // 109
System.out.println(i -= 9); // 100
System.out.println(i *= 9); // 900
System.out.println(i /= 9); // 100
System.out.println(i %= 9); // 1
byte b = 10;
// b = b + 2; // int = byte + int 编译报错,类型不匹配
b = (byte) (b + 2); // byte = byte (int) 需手动强转
b += 2; // byte = byte (int) 隐含着强转
System.out.println(b); // 14
}
}
比较运算符,比较运算的结果一定是一个布尔值,成立就是true、不成立则为false。
等等 | 大于 | 小于 | 大等 | 小等 | 不等 |
---|---|---|---|---|---|
== | > | < | >= | <= | != |
public class Demo {
public static void main(String[] args) {
int x = 10, y = 11;
System.out.println(9 == y); // false
System.out.println(x > y); // false
System.out.println(x < y); // true
System.out.println(x >= y); // false
System.out.println(x <= y); // true
System.out.println(x != y); // true
}
}
逻辑运算符,逻辑与(全为真才是真)、逻辑或(一个为真就是真)、逻辑非(非真即假),逻辑运算只能用于布尔值。
与 | 或 | 非 |
---|---|---|
&& | || | ! |
public class Demo {
public static void main(String[] args) {
int x = 10, y = 11;
System.out.println(x++ > y && x < ++y); // false
System.out.println(x + " " + y); // 11 11
System.out.println(++x > y || x < y++); // true
System.out.println(x + " " + y); // 12 11
System.out.println(!true); // false
}
}
注意:逻辑与和逻辑或都存在短路的特性,当逻辑与左边的表达式为假时,右边的表达式直接不执行;当逻辑或左边的表达式为真时,右边的表达式也不会执行。
三元运算符,需要三个数据才可以进行操作的运算符叫做三元运算符,三元运算符必须保证所有表达式都符合左侧数据类型的要求,且结果必须被使用。
public class Demo {
public static void main(String[] args) {
int x = 10, y = 11;
int max = x > y ? x : y; // x大于y?是就将x赋值给max,否则将y赋值给max
System.out.println(max); // 11
}
}
移位运算符,左移运算符(将数据的二进制位向左移动,右边补0);右移运算符(将数据的二进制位向右移动,左边补符号位);逻辑右移运算符(将数据的二进制位向右移动,左边补0)。左移N位的结果为原值乘以2的N次方;右移N位的结果则为原值除以2的N次方。
左移 | 右移 | 逻辑右移 |
---|---|---|
<< | >> | >>> |
public class Demo {
public static void main(String[] args) {
long x = 23, y = -23;
// 23 0001,0111 0101,1100 92
System.out.println((byte) x << 2);
// -23 0001,0111 1110,1000 1110,1001 1111,1111,1111,1101 1111,1100 0000,0011 3 -3
System.out.println((short) y >> 3);
// -23 0001,0111 1110,1000 1110,1001 0001......1111,1101(32) 536870909
System.out.println((int) y >>> 3);
// -23 0001,0111 1110,1000 1110,1001 0001......1111,1101(64) 2305843009213693949
System.out.println(y >>> 3);
}
}
位运算符,按位与(全为1才是1)、按位或(一个为1就是1)、按位取反(非1即0)、按位异或(相同就是0)。
public class Demo {
public static void main(String[] args) {
byte x = 11; // 0000,1011
byte y = 13; // 0000,1101
System.out.println(x & y); // 0000,1001 9
System.out.println(x | y); // 0000,1111 15
System.out.println( ~ x); // 1111,0100 1111,0011 0000,1100 12 -12
System.out.println(x ^ y); // 0000,0110 6
}
}
流程控制
顺序结构,顺序结构是最简单的程序结构,其执行顺序为自上而下,依次执行。
public class Demo {
public static void main(String[] args) {
System.out.println("一"); // 一
System.out.println("二"); // 二
System.out.println("三"); // 三
}
}
选择结构,选择结构可以分为单if条件语句、if···else条件语句、if···else if···else多分支条件语句以及switch多分支条件语句。
public class Demo {
public static void main(String[] args) {
switch (2) {
case 0 :
if (1 < 2) {
System.out.println("一");
}
break;
case 1 :
if (1 > 2) {
System.out.println("二");
} else {
System.out.println("三");
}
break;
default:
if (1 > 2) {
System.out.println("四");
} else if (1 > 3) {
System.out.println("五");
} else if (1 > 4) {
System.out.println("六");
} else {
System.out.println("七"); // 七
}
break;
}
}
}
注意:switch()中支持的数据类型可以是byte、short、char、int,JDK1.5开始支持枚举类型;JDK1.7开始支持String类型;在switch中多个case后面的数据不可以重复。
循环结构,循环结构可以分为for循环、while循环和do···while循环等。如果条件从未满足过,for循环和while循环一次都不会执行,而do···while循环会至少执行一次。在for循环和while循环后加个分号时,for循环的循环体在不报错的情况下只会执行一次,而while循环则会因为步进表达式的不存在而陷入死循环中。
public class Demo {
public static void main(String[] args) {
// 打印九九乘法口诀表
do {
for (int i = 1; i <= 9; i++)/*;*/ {
int j = 1;
while (j <= i)/*;*/ {
System.out.printf("%d X %d = %-4d", i, j, i * j);
j++;
}
System.out.println();
}
} while (false);
}
}
注意:循环次数或范围确定的话多用for循环,否则多用while循环。
break、continue、标号,break用于switch中的作用为终止switch,用于循环中的作用为终止循环;continue用于循环中的作用为跳过本次循环而马上开始下一次循环;在嵌套循环中break终止的是与其最近的那个循环,如需终止外层循环可以使用标号的方式来解决,continue同理。
public class Demo {
public static void main(String[] args) {
// 打印六六乘法口诀表
label:
for (int i = 1; i <= 9; i++) {
int j = 1;
while (j <= i) {
if (7 == i) continue label;
if (8 == i) break label;
if (9 == i) break;
System.out.printf("%d X %d = %-4d", i, j, i * j);
j++;
}
System.out.println();
}
}
}
数组
数组是一种可以同时存放多个相同数据类型元素的容器;数组的长度在程序运行期间不可改变;数组可以简易地分为一维数组(一行多列)、二维数组(多行多列)和多维数组。
开发中如果不确定数组中的具体内容就用动态初始化,否则就用静态初始化。使用动态初始化创建的基本类型数组中的元素会自动拥有默认值(0、0.0、false);静态初始化创建的数组其实也有默认值的过程,只不过系统立马将其默认值替换成了大括号内的具体内容。
import java.util.Arrays;
public class Demo {
public static void main(String[] args) {
int arr1[] = new int[3]; // 不推荐使用,与变量的声明类似/C的写法
int[] arr2 = new int[3]; // 动态初始化,指定数组元素个数
int[] arr3 = new int[] {1, 0, 3}; // 静态初始化,指定数组元素内容
int[] arr4 = {1, 2, 3}; // 静态初始化,简易写法
arr2[0] = 1; // 把1赋值给arr2数组中下标为0的元素
arr3[1] = 2; // 把2赋值给arr3数组中下标为1的元素
System.out.println(Arrays.toString(arr1)); // [0, 0, 0]
System.out.println(Arrays.toString(arr2)); // [1, 0, 0]
System.out.println(Arrays.toString(arr3)); // [1, 2, 3]
System.out.println(Arrays.toString(arr4)); // [1, 2, 3]
{
int[][] arr5 = {{1, 2, 3}, {1, 2, 3}}; // 静态初始化二维数组
arr5 = new int[2][]; // 动态初始化二维数组,2行多列
arr5[0] = new int[] {1, 2, 3}; // 将一维数组赋值给arr5数组中下标为0的元素
arr5[1] = new int[] {4, 5}; // 将一维数组赋值给arr5数组中下标为1的元素
// 遍历二维数组
for (int i = 0; i < arr5.length; i++) {
for (int j = 0; j < arr5[i].length; j++) {
if (0 == j) {
System.out.print("[" + arr5[i][j] + ", ");
} else {
if (arr5[i].length - 1 == j) {
System.out.print(arr5[i][j] + "]");
} else {
System.out.print(arr5[i][j] + ", ");
}
}
}
System.out.println();
}
}
}
}
扩展:二维数组中的每个元素都是一维数组,而一维数组中的每个元素才是数据内容。
面向对象
何为面向对象?Java是一种面向对象的程序设计语言,而面向对象是一种程序设计思想,这里的对象泛指现实中的一切事物,每种事物都具备自己的属性和行为。面向对象就是在编程时参照现实中的事物并将事物的属性特征和行为特征抽象出来描述成计算机事件的设计思想,它区别于面向过程思想强调的是通过调用对象来实现功能,而不是自己一步步去操作实现。面向对象是一种更符合我们思考习惯的思想,它可以将复杂的事情简单化,并将我们从执行者变成指挥者,面向对象的三大特征为封装、继承、多态。
类、对象、方法
类是一组相关属性和行为的集合,可以看成是一类事物的模板,用事物的属性特征和行为特征来描述该类事物,属性是该类事物的状态信息,也就是直接定义在类里面的变量(成员变量);行为是该事物能够做什么,也就是定义在类里面的方法(成员方法)。而对象则是一类事物的具体体现,具备该类事物的属性和行为。可以说类就是对一类事物的描述,是抽象的;而对象是一类事物的实例,是具体的,一句话概括就是:“万物皆可为对象,类是对象的模板,对象是类的实体”。
方法的本质其实就是将通用的代码抽取出来形成一个单独的功能,当我们需要使用这个功能的时候就可以进行调用,这样既解决了代码的复用性,也解决了代码冗余的现象。方法定义的先后顺序无所谓;方法定义后需要调用才会执行;方法的声明包括返回值类型、方法名以及参数列表等;一个方法的形参列表中最多只能声明一个可变参数,可变参数需放在参数列表的末尾,否则编译报错。
public class Person { // 定义一个Person类
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void getInfo(int index, String... features) { // 定义一个含有可变参数的成员方法
String feature = features[index];
System.out.println("我是" + name + ",今年" + age + "岁了,是一个" + feature + "的人!");
}
}
public class Demo {
public static void main(String[] args) { // main方法,Java程序的入口
Person person = new Person("ZhangSan", 18); // 创建一个Person类对象
person.getInfo(1, "开朗", "自律", "努力"); // 我是ZhangSan,今年18岁了,是一个自律的人!
}
}
构造方法、匿名对象
构造方法是专门用来创建对象的,当我们通过new关键字来创建对象时其实就是在调用构造方法来实现成员变量的初始化操作。匿名对象就是只有等号右边的对象,没有左边的名字和赋值运算符,如果确定一个对象只需使用唯一的一次,那么匿名对象就是不二的选择。
public class Person {
String name;
public Person() { // 默认无参构造方法,在不新增其他构造方法的情况下系统会默认赠送
}
public Person(String name) { // 定义一个有参构造方法
this.name = name;
}
public void getInfo() {
System.out.println("我是" + name);
}
}
public class Demo {
public static void main(String[] args) {
new Person().getInfo(); // 我是null
new Person("ZhangSan").getInfo(); // 我是ZhangSan
}
}
注意:构造方法的名称必须与所在类的类名称完全相同,且构造方法无需返回值。
// TODO
// Overload、Override、this、super、权限修饰符static、final、封装、继承、多态、抽象、接口、内部类······