一、Java开发入门
Java概述
什么是java
-
计算机语言分为:机器语言,汇编语言,高级语言
-
Java是一种高级计算机语言
-
三个技术平台:标准版(SE),企业版(EE),微型板(ME)
Java语言特点
-
简单易用
-
安全可靠
-
跨平台(JVM---Java虚拟机)
-
面向对象性
-
支持多线程
JDK的使用
-
Java Development Kit是一套Java开发环境
-
JDK是整个Java的核心,包括Java编译器,Java运行工具,Java文档生成工具,Java打包工具等
-
JRE是Java的运行环境
-
开发工具:是JDK中的核心功能模块,其中包含一系列Java程序所必须的可执行程序,如javac.exe、java.exe等,还包含了一个专用的JRE环境。
-
bin目录:该目录用于存放一些可执行程序。
如javac.exe(Java编译器)、java.exe(Java运行工具)、jar.exe(打包工具)和javadoc.exe(文档生成工具)等。
-
db目录:db目录是一个小型数据库
-
子目录
-
include目录:包含一些C语言的文件
-
jie目录:是Java运行环境的根目录
-
lib目录:包含lib包文件
-
javafx-src.zip:该压缩文件内存放的是Java FX所有核心类库的源代码
-
src.zip:为src文件夹的压缩文件
-
README等:说明性文档
-
javac.exe编译器工具
-
java.exe运行工具(JVM)
-
环境系统变量
-
PATH环境变量:用于告知操作系统到指定路径去寻找JDK
-
CLASSPATH环境变量:用于告知JDK到指定路径去查找类文件
第一个Java
public class HelloWorld{ public static void main(String[] args){ System.out.println("这是第一个Java"); } }
-
class是一个关键字,用于定义一个类
-
HelloWorld是类名称
-
public static void main(String[] args){}定义了一个main()方法,该方法是Java程序的执行入口
Java程序是由Java虚拟机负责解释执行的
包、import
-
Java引入了包(package)机制,程序可以通过声明包的方式对Java类定义目录。
-
在开发时,一个项目中可能会使用很多包,当一个包中的类需要调用另一个包中的类时,就需要使用import关键字引入需要的类。
-
improt 包名.类名;
-
注意:import通常出现在package语句之后,类定义之前。如果有时候需要用到一个包中的许多类,则可以使用“import 包名.*; ”来导入该包下所有类。
-
二、java编程基础
Java基本语法
基本语法格式
[修饰符] class 类名 { 程序代码; }
-
修饰符用于限定类的访问权限(可省略)
-
class声明类
-
类名通常使用首字母大写形式
注释
-
单行 //
-
多行
-
文档注释 /**... */
关键字
标识符
-
如:包名,类名,方法名,参数名,变量名
-
由任意顺序的大小写字母,数字,下划线和美元符号组成,但不能以数字开头,也不能是Java关键字
①包名所有字母一律小写。例如:com.itheima.example01。
②类名和接口名每个单词的首字母都要大写。例如:ArrayList、Iterator。
③常量名所有字母都大写,单词之间用下划线连接。例如:DAY_OF_MONTH。
④变量名和方法名的第一个单词首字母小写,从第二个单词开始每个单词首字母大写。例如:lineNumber、getLineNumber。
⑤在程序中,应该尽量使用有意义的英文单词来定义标识符,使得程序便于阅读。例如:使用userName表示用户名,password表示密码。
Java变量与常量
变量定义
变量类型 变量名 = 初始值;
变量数据类型
一个小数会被默认为double类型的值
在程序中也可以为一个浮点数类型变量赋予一个整数数值
变量类型转换
-
自动类型转换
-
强制类型转换
目标类型 变量名 = (目标类型) 值;
-
表达式类型自动提升
变量作用域
变量需要在它的作用范围内才可以被使用,这个作用范围称为变量的作用域。
常量
-
在Java中,常量包括整型常量、浮点数常量、布尔常量、字符常量等
-
Java中的常量,其实就是特殊的变量,也是固定不变的量,有且只能进行一次赋值。
-
Java中定义常量的语法也非常简单,只需要在定义变量的语法基础上加上一个final关键字修饰即可。
Java运算符
-
算术运算符
-
在进行取模(%)运算时,运算结果的正负取决于被模数(%左边的数)的符号,与模数(%右边的数)的符号无关。
-
-
赋值运算符
-
比较运算符
-
用来对两个数值或变量进行比较。
-
其结果是布尔类型的true或false。
-
-
逻辑运算符
-
是用于对布尔类型的值或表达式进行操逻辑判断的符号。
-
其返回值类型是布尔类型。
-
-
位运算符
-
条件运算符
-
也称作三元运算符(或三目运算符)
-
由符号“? :”组合构成。
-
选择结构语句
if
Switch
与if条件语句不同的是,switch 条件语句的控制表达式结果类型只能是byte、short、char、int、enum枚举以及String类型,而不能是boolean类型。
switch(控制表达式){ case 目标值1: 执行语句1 break; }
循环结构语句
while
do...while
for
循环嵌套
跳转语句
-
break(switch条件语句和循环结构语句)
-
当它出现在switch条件语句中时,作用是终止某个case并跳出switch结构;
-
当它出现在循环结构语句中时,作用是跳出当前循环结构语句,执行后面的代码。
-
-
continue(循环语句)
-
它的作用是终止本次循环,执行下一次循环
-
数组
-
定义
-
数组类型[] 数组名 = new 数组类型[数组长度];
-
数组类型[] 数组名 = new 数组类型[]{数组元素0,数组元素1,...};
-
数组类型[] 数组名 = {数组元素0,数组元素1,...};
-
-
二维数组
int[][] arr = new int[3][4]; int[][] arr = new int[3][]; int[][] arr = {{1,2},{3,4,5,6},{7,8,9}};
三、面向对象
面向对象概述
面向对象特点:封装,继承,多态
Java中类与对象
成员变量:
共同特征作为类的属性
成员方法:
共同行为作为类的方法
[修饰符] class 类名 [extend 父类名][implements 接口名]{ //类体,包括类的成员变量和成员方法 private String name; public int age = 20; [修饰符][返回值类型]方法名([参数类型 参数名...]){ 方法体; return; } }
-
声明成员方法修饰符对访问权限进行限定的(如public、protected、private);也有静态修饰符static,还有最终修饰符final等
-
定义在类中的变量被称为成员变量;
-
定义在方法中的变量被称为局部变量
对象的创建
Person p = new Person(); 类名 对象名 = new 类名();
Java将内存分为两种,即栈内存和堆内存。
其中栈内存用于存放基本类型的变量和对象的引用变量(如Person p),堆内存用于存放由new创建的对象和数组。
对象成员的调用
①通过对象的引用来访问对象所有的成员。
对象引用.对象成员
②直接使用创建的对象本身来引用对象成员。
new 类名().对象成员
访问控制符
类的封装
在定义一个类时,将类中的属性私有化,即使用private关键字来修饰,私有属性只能在它所在类中被访问,如果外界想要访问私有属性,需要提供一些使用public修饰的公有方法,其中包括用于获取属性值的getXxx()方法和设置属性值的setXxx()方法。
方法的重载递归
-
Java允许在一个程序中定义多个名称相同,但是参数的类型或个数不同的方法,这就是方法的重载。
-
方法的递归是指在一个方法的内部调用自身的过程
构造方法
-
构造方法(也被称为构造器)是类的一个特殊成员,它会在类实例化对象时被自动调用。
-
[修饰符] 方法名([参数列表]){ 方法体; }
-
定义构造方法时需同时满足以下三个条件:
①方法名与类名相同。
②在方法名的前面没有返回值类型的声明。
③在方法中不能使用return语句返回一个值,但是可以单独写return语句来作为方法的结束。
-
构造方法重载
在创建对象时,可以通过调用不同的构造方法来为不同的属性进行赋值。
this关键字
关键字this来指代当前对象,用于在方法中访问对象的其他成员。
-
通过this关键字调用成员变量,解决与局部变量名称冲突问题。
class Person { int age; // 成员变量age public Person(int age) {// 局部变量age this.age = age; // 将局部变量age的值赋给成员变量age } }
-
通过this关键字调用成员方法
class Person { public void openMouth() {...} public void speak() { this.openMouth(); //this可省略 } }
-
通过this关键字调用构造方法
class Person { public Person() {} public Person(int age) { this(); // 调用无参的构造方法 } }
-
在使用this调用类的构造方法时,应注意以下几点:
①只能在构造方法中使用this调用其他的构造方法,不能在成员方法中使用。
②在构造方法中,使用this调用构造方法的语句必须是该方法的第一条执行语句,且只能出现一次。
③不能在一个类的两个构造方法中使用this互相调用。
static关键字
被static关键字修饰的成员变量、方法可以被类直接访问,而不需要预先构造类的实例化对象
-
静态变量
-
在一个Java类中,可以使用static关键字来修饰成员变量,该变量被称作静态变量。
-
静态变量被所有实例共享,可以使用“类名.变量名”的形式来访问。
-
static关键字只能用于修饰成员变量,不能用于修饰局部变量,否则编译会报错。
-
继承
class 父类{...} class 子类 extends 父类{...}
-
子类只能访问父类中public和protected修饰的属性和方法
-
在Java中,类只能单继承,不允许多继承
-
多个类可以继承一个父类
-
多层继承是可以的,即一个类的父类可以再继承另外的父类
方法重写
-
子类需要对继承的方法进行一些修改,即对父类方法进行重写
-
在子类中重写的方法需要和父类被重写的方法具有相同的方法名,参数列表以及返回值类型
-
子类在重写父类方法时,不能使用比父类中被重写的方法更严格的访问权限
super关键字
当子类重写父类方法后,子类对象将无法访问父类中被子类重写过的方法
使用super关键字可以在子类中访问父类的非私有方法,非私有属性,构造方法
super.属性----------------------super.name super.方法(参数1,参数2...)-------super.shou() super(参数1,参数2...)-----------super(name,age)
-
通过super()调用父类构造方法的代码必须位于子类构造方法的第一行,并且只能出现一次
-
不能与this同时出现
final关键字
-
java中使用final关键字修饰的类不可以被继承,该类子类不能重写该方法
-
java中被final修饰的变量为常量,只能在声明时被赋值一次,变量名称要求全部字母大写
-
如果一个程序中变量使用public static final声明,则此变量成为全局常量
抽象类
abstract 返回值类型 方法名称(参数列表)
-
抽象方法在定义时不需要实现方法体
-
当一个类包含了抽象方法,该类就是抽象类,用abstract关键字修饰,不能使用private
-
如果非抽象类继承了抽象方法,那么该类必须实现抽象类中的全部抽象方法
接口
-
克服单继承的限制,一个类可以同时实现多个父接口
-
接口除抽象方法外,还可以定义默认方法和静态方法,
-
默认方法使用default
-
静态方法使用static
-
这两种方法都允许有方法体
-
public interface 接口名 [extends 接口1,接口2...]{ public static final 数据类型 常量名 = 常量; public abstract 返回值的数据类型 方法名(参数列表); public static 返回值的数据类型 方法名(参数列表){} public default 返回值的数据类型 方法名(参数列表){} }
一个类可以同时实现多个接口,实现多个接口时,多个接口需要使用英文逗号分隔
修饰符 class 类名 implements 接口1,接口2,...{} 修饰符 class 类名 extends 父类名 implements 接口1,接口2,...{}
注意:接口的实现类,必须实现接口的所有抽象方法
多态
多态指不同类的对象在调用同一个方法时表现出的多种不同行为
-
多态的两种形式:方法的重载,方法的重写
对象类型转换
-
对象向上转型:父类类型 父类对象 = 子类实例;
-
对象向下转型:父类类型 父类对象 = 子类实例; 子类类型 子类对象 = (子类) 父类对象;
instanceof
判断对象是否是某个类(或接口)的实例
对象 instanceof 类(或接口)
object类
object类是所有类的父类,通常被称为超类
object类中定义了一些常用方法:
-
boolean equals() 判断两个对象是否“相等”
-
int hashCode()返回对象的哈希值
-
String toString()返回对象的字符串表示形式
内部类
成员内部类
在一个类内部除了可以定义成员变量,成员方法,还可以定义类
-
成员内部类可以访问外部类的所有成员,无论外部类的成员是何种权限
-
如果想通过外部类访问内部类,则需要通过外部类创建内部类对象,
外部类名 外部类对象 = new 外部类名();
外部类名.内部类名 内部类对象 = 外部类对象.new 内部类名();
局部内部类
也叫方法内部类,指定义在某个局部范围内的类,他和局部变量都是在方法中定义的,有效范围只限于方法内部
-
局部内部类可以访问外部类的所有成员变量和成员方法
-
外部类中无法直接访问内部类中的变量和方法
静态内部类
用static关键字修饰成员内部类
静态内部类只能访问外部类的静态成员
外部类名.静态内部类名 变量名 = new 外部类名.静态内部类名();
匿名内部类
即没有名称的内部类
new 继承的父类或实现的接口名(){类体}
四、异常
什么是异常
Java中异常是指Java程序在运行时可能出现的错误或非正常情况
Throwable类:是所有异常类的父类,其两个直接子类Error类和Exception类
-
Error类:程序中产生的错误
-
Exception类:程序中产生的异常
-
RuntimeException类及其子类用于表示运行时异常---unchecked异常
-
其他子类用于编译时异常---checked异常
-
运行时异常
算数异常,索引越界异常,类型转换异常,空指针异常,数字格式化异常
编译时异常
处理方法:
-
使用try...catch对异常进行捕获处理
-
使用throws关键字声明抛出异常,调用者对异常进行处理
异常处理及语法
关键字:try,catch,finally,throw,throws
-
try...catch语句
try{ 代码块 }catch(Exception Type e){ 代码块 }
-
try代码块是必须的
-
catch代码块和finally代码块都是可选的,但catch代码块和finally代码块至少要出现一个
-
catch代码块可以有多个,但捕获父类异常的catch代码块必须位于捕获子类异常的catch代码块后面
-
catch代码块必须位于try代码块之后
-
在try代码块中,发生异常语句后面的代码是不会被执行的
-
finally语句
无论程序是否发生异常都要执行
try{ 代码块 }catch(Exception Type e){ 代码块 }finally{ 代码块 }
如果在try...catch中执行了System.exit(0)语句,finally代码块不再执行
抛出异常
-
throws关键字:声明该方法有可能发生异常
修饰符 返回值类型 方法名(参数1,参数2,...)throws 异常类1,异常类2...{ 方法体 }
-
throw关键字:用于方法体内,抛出的是一个异常实例,并且每次只能抛出一个异常实例
自定义异常
自定义异常必须继承自Exception或其子类
在实际开发中,如果没有实际要求,自定义的异常类只需继承Exception类,在构造方法中使用super()语句调用Exception的构造方法即可
throw Exception 异常对象
五、java API
字符串类
string
-
使用字符串常量直接初始化一个String对象
String 变量名 = 字符串;
-
调用String类的构造方法初始化字符串对象
String 变量名 = new String(字符串);
-
字符串连接运算符
"a" + str1 + "b";
-
String类的常用方法
-
获取字符串长度以及访问字符串中的字符
public class ex01 { public static void main(String[] args) { String s = "abcdccadcf";//定义字符串s System.out.println("字符串的长度为:" + s.length()); System.out.println("字符串的第一个字符为:" + s.charAt(0)); System.out.println("字符c第一次出现的位置:" + s.indexOf('c')); System.out.println("字符c最后一次出现的位置:" + s.lastIndexOf('c')); System.out.println("子字符串ab第一次出现的位置:" + s.indexOf("ab")); System.out.println("子字符串ab最后一次出现的位置:" + s.lastIndexOf("ab")); } }
-
字符串的转换操作
public class ex02 { public static void main(String[] args) { String str = "abcd"; System.out.println("将字符串转换为字符数组后的结果:"); char[] charArray = str.toCharArray(); for(int i = 0; i < charArray.length; i ++) { if(i != charArray.length - 1){ System.out.print(charArray[i] + ","); }else{ System.out.println(charArray[i]); } } System.out.println("将int值转换为String类型之后的结果:" + String.valueOf(12)); System.out.println("将字符串转换成大写之后的结果:" + str.toUpperCase()); System.out.println("将字符串转换成小写之后的结果:" + str.toLowerCase()); } }
-
字符串的替换和去空格操作
public class string { public static void main(String[] args) { String s = "itcast"; System.out.println("将it替换成cn.it的结果:" + s.replace("it","cn.it")); String s1 = " i t c a s t "; System.out.println("去除字符串两端空格后的结果:" + s1.trim()); System.out.println("去除字符串中所有空格后的结果:" + s1.replace(" ","")); } }
-
字符串判断
public class ex03 { public static void main(String[] args) { String s1 = "String"; String s2 = "string"; System.out.println("判断s1字符串对象是否以Sr开头:" + s1.startsWith("Sr")); System.out.println("判断s1字符串对象是否以ng结尾:" + s1.endsWith("ng")); System.out.println("判断s1字符串对象是否包含字符串tri:" + s1.contains("tri")); System.out.println("判断字符串是否为空:" + s1.isEmpty()); System.out.println("判断字符串s1,s2内容是否相同:" + s1.equals(s2)); System.out.println("忽略大小写情况下判断s1,s2内容是否相同:" + s1.equalsIgnoreCase(s2)); System.out.println("按对应字符的Unicode比较s1和s2的大小:" + s1.compareTo(s2)); } }
-
字符串的截取和分割
substring() split()
-
StringBuffer
-
它类似于一个字符容器,当在其中添加删除字符时,所操作的都是这个字符容器,因此并不会产生新的StringBuffer对象
-
StringBuffer类与String类最大区别在于它的内容和长度都是可变的
public static void add() { StringBuffer sb = new StringBuffer(); // 定义一个字符串缓冲区 sb.append("abcdefg"); // 在末尾添加字符串 sb.append("hij").append("klmn"); // 连续调用append()方法添加字符串 System.out.println("append添加结果:" + sb); sb.insert(2, "123"); // 在指定位置插入字符串 System.out.println("insert添加结果:" + sb); }
public static void remove() { StringBuffer sb = new StringBuffer("abcdefg"); sb.delete(1, 5); // 指定范围删除 System.out.println("删除指定位置结果:" + sb); sb.deleteCharAt(2); // 指定位置删除 System.out.println("删除指定位置结果:" + sb); sb.delete(0, sb.length()); // 清空缓冲区 System.out.println("清空缓冲区结果:" + sb); }
public static void alter() { StringBuffer sb = new StringBuffer("abcdef"); sb.setCharAt(1, 'p'); // 修改指定位置字符 System.out.println("修改指定位置字符结果:" + sb); sb.replace(1, 3, "qq"); // 替换指定位置字符串或字符 System.out.println("替换指定位置字符(串)结果:" + sb); System.out.println("字符串翻转结果:" + sb.reverse()); }
public static void sub() { StringBuffer sb = new StringBuffer(); // 定义一个字符串缓冲区 System.out.println("获取sb的初始容量:" + sb.capacity()); sb.append("itcast123"); // 在末尾添加字符串 System.out.println("append添加结果:" + sb); System.out.println("截取第7~9个字符:" + sb.substring(6,9));} }
添加add(),删除remove(),修改alter(),截取sub()
System类
将源数组中的元素复制到目标数组、获取当前系统的时间、获取当前系统的全部属性、进行垃圾回收
-
arraycopy()方法---将源数组中的元素复制到目标数
-
static void arraycopy(Object src,int srcPos,Object dest, int destPos,int length)
-
src:表示源数组。
dest:表示目标数组。
srcPos:表示源数组中复制元素的起始位置,即从哪个位置开始复制元素。
destPos:表示复制到目标数组的起始位置,即复制到目标数组的哪个位置。
length:表示复制元素的个数。
注意:在进行数组元素复制时,目标数组必须有足够的空间来存放复制的元素,否则会发生索引越界异常。
-
-
currentTimeMills()方法---获取当前系统的时间
-
getProperties()方法---获取当前系统的全部属性
-
getProperty()方法---根据系统的属性名获取对应的属性值
-
gc()方法---通知Java虚拟机立即进行垃圾回收
Runtime类
-
getRuntime()方法---获取当前虚拟机的相关信息
Runtime rt = Runtime.getRuntime(); // 创建Runtime对象 System.out.println("处理器的个数: " + rt.availableProcessors()+"个"); System.out.println("空闲内存数量: " + rt.freeMemory() / 1024 / 1024 + "M"); System.out.println("最大可用内存数量: " + rt.maxMemory() / 1024 / 1024 + "M"); System.out.println("虚拟机中内存总量: " + rt.totalMemory() / 1024 / 1024 + "M")
-
exec()方法---操作系统进程
Math类
因为Math类构造方法的访问权限是private,所以无法创建Math类的对象。
Math类中所有方法都是静态方法,可以直接通过类名调用Math类中的方法。
除静态方法外,Math类中还定义了两个静态常量PI和E,分别代表数学中的π和e。
public class Example15 { public static void main(String[] args) { System.out.println("计算-10的绝对值: " + Math.abs(-10)); System.out.println("求大于5.6的最小整数: " + Math.ceil(5.6)); System.out.println("求小于-4.2的最大整数: " + Math.floor(-4.2)); System.out.println("对-4.6进行四舍五入: " + Math.round(-4.6)); System.out.println("求2.1和-2.1中的较大值: " + Math.max(2.1, -2.1)); System.out.println("求2.1和-2.1中的较小值: " + Math.min(2.1, -2.1)); System.out.println("生成一个大于等于0.0小于1.0随机值: " +Math.random()); System.out.println("计算1.57的正弦结果: "+Math.sin(1.57)); System.out.println("计算4的开平方的结果: "+Math.sqrt(4)); } }
Random类
-
产生指定取值范围的随机数字
-
Random()---使用当前机器时间创建一个Random对象
-
Random(long seed)---使用参数seed指定的种子创建一个Random对象
-
使用无参构造方法来产生随机数
public static void main(String args[]) { Random random = new Random(); // 不传入种子 // 随机产生10个[0,100)之间的整数 for (int x = 0; x < 10; x++) { System.out.println(random.nextInt(100)); } }
-
使用有参构造方法产生随机数
public static void main(String args[]) { Random r = new Random(13); // 创建对象时传入种子 // 随机产生10个[0,100)之间的整数 for (int x = 0; x < 10; x++) { System.out.println(r.nextInt(100)); } }
当创建Random类对象时,如果指定了相同的种子,则每个对象产生的随机数序列相同。
-
public static void main(String[] args) { Random r = new Random(); // 创建Random实例对象 System.out.println("生成boolean类型的随机数: " + r.nextBoolean()); System.out.println("生成float类型的随机数: " + r.nextFloat()); System.out.println("生成double类型的随机数:" + r.nextDouble()); System.out.println("生成int类型的随机数:" + r.nextInt()); System.out.println("生成0~100之间int类型的随机数:" +r.nextInt(100)); System.out.println("生成long类型的随机数:" + r.nextLong()); }
Biglnteger类
BigInteger表示大整数类,定义在java.math包中,如果在开发时需要定义一个超出long类型的整型数据,可以使用BigInteger类的对象接收该数据。
public static void main(String[] args) { BigInteger bi1 = new BigInteger("123456789"); // 创建BigInteger对象 BigInteger bi2 = new BigInteger("987654321"); // 创建BigInteger对象 System.out.println("bi2与bi1的和: " + bi2.add(bi1)); System.out.println("bi2与bi1的差: " + bi2.subtract(bi1)); System.out.println("bi2与bi1的积: " + bi2.multiply(bi1)); System.out.println("bi2与bi1的商: " + bi2.divide(bi1)); System.out.println("bi2与bi1之间的较大值: " + bi2.max(bi1)); System.out.println("bi2与bi1之间的较小值: " + bi2.min(bi1)); //创建BigInteger数组接收bi2除以bi1的商和余数 BigInteger result[] = bi2.divideAndRemainder(bi1); System.out.println("bi2除以bi1的商: " + result[0]+":bi2除以bi1的余数:"+result[1]); }
BigDecimal类
在进行浮点数运算的时候,float类型和double类型很容易丢失精度,为了能够精确的表示、计算浮点数,Java提供了BigDecimal类
日期与时间类
Date类
-
Date():用于创建当前日期时间的Date对象。
-
Date(long date):用于创建指定时间的Date对象
Calendar类
它可以通过特定的方法设置和读取日期的特定部分,比如年、月、日、时、分、秒等。
-
getInstance()方法
Calendar calendar = Calendar.getInstance();
-
add()---添加日期时间
-
set()---修改日期时间
-
Calendar.DATE表示的是天数,当天数累加到当月的最大值时,如果继续累加,Calendar.DATE的天数就会从1开始计数,同时月份值会自动加1,这和算术运算中的进位类似。
Instant类
Instant 类代表的是某个瞬间的时间
-
now()---从系统时钟获取当前瞬间的时间。
-
now(Clock clock)---从指定时钟获取当前时间
LocalDate类
LocalDate类表示不带时区的日期,它所表示的日期包括年份和月份两部分
//按指定日期创建LocalDate对象 LocalDate date = LocalDate.of(2020, 12, 12); //从默认时区的系统时钟获取当前日期 LocalDate now1 = LocalDate.now();
日期与时间格式化类
DateFormat类
对日期和时间进行格式化
SimpleDateFormat类
根据日期模板格式化日期
六、集合
集合概述
-
集合可以存储任意类型对象,并且长度可变
-
注意:这些集合类都位于java.util包中,在使用时一定要注意导包的问题。
-
分类:
-
单列集合Collection
-
用于存储一系列符合某种规则的元素。
-
Collection集合有两个重要的子接口,分别是List和Set。
-
List集合的特点是元素有序、可重复。该接口的主要实现类有ArrayList和LinkedList。
-
Set集合的特点是元素无序并且不可重复。该接口的主要实现类有HashSet和TreeSet。
-
-
双列集合Map
-
用于存储具有键(Key)、值(Value)映射关系的元素。
-
Map集合中每个元素都包含一对键值,并且Key唯一,在使用Map集合时通过指定的Key找到对应的Value。
-
Map接口的主要实现类有HashMap和TreeMap。
-
-
List接口
-
元素有序,可重复
-
ArrayList集合
-
内部数据存储结构:数组形式
-
不适合做大量增删操作
-
在遍历和查找元素时非常高效
-
ArrayList list = new ArrayList(); list.add("stu1"); list.add("stu2"); System.out.println("集合的长度:" + list.size()); System.out.println("第2个元素是:" + list.get(1));
-
-
LinkedList集合
-
LinkedList内部包含有两个Node类型的first和last属性的双向循环链表结构
-
对元素的遍历和查找效率较低
-
对元素的增删操作效率很高
-
LinkedList link = new LinkedList(); link.add("stu1"); link.add("stu2"); link.offer("offer");// 向集合尾部追加元素 link.push("push");// 向集合头部添加元素 Object object = link.peek();//获取集合第一个元素 link.removeFirst();// 删除集合第一个元素 link.pollLast();// 删除集合最后一个元素
-
Collection集合遍历
Iterator遍历集合
Iterator iterator = list.iterator(); while (iterator.hasNext()) { Object obj = iterator.next(); // 取出ArrayList集合中的元素 System.out.println(obj); }
Iterator遍历集合时,内部采用指针的方式来跟踪集合中的元素。在调用next()方法之前,索引位于第一个元素之前,不指向任何元素。
-
第一次调用next()方法后,索引会向后移动一位,指向第一个元素并将该元素返回;
-
再次调用next()方法时,索引会指向第二个元素并将该元素返回;
-
以此类推,直到hasNext()方法返回false,表示到达了集合的末尾终止对元素的遍历。
foreach遍历集合
foreach循环是一种更加简洁的for循环,也称增强for循环,用于遍历数组或集合中的元素。
for(容器中元素类型 临时变量 :容器变量) { // 执行语句 } for (Object obj : list) { System.out.println(obj); }
foreach循环遍历集合和数组时,只能访问集合中的元素,不能对其中的元素进行修改。
forEach遍历集合
是JDK 8中新增的遍历集合元素的方法
list.forEach(obj ->System.out.println("迭代集合元素:"+obj));
Set接口
Set接口中的元素无序,并且都会以某种规则保证存入的元素不出现重复。
HashSet
-
当向HashSet集合中添加一个元素时,首先会调用该元素的hashCode()方法来确定元素的存储位置,然后再调用元素对象的equals()方法来确保该位置没有重复元素。
-
HashSet set = new HashSet(); set.add("Jack"); set.add("Eve"); ... set.forEach(o -> System.out.println(o));
TreeSet
-
无重复元素,可以对元素进行排序
Map接口
Map中的映射关系是一对一的,一个键对象Key对应唯一一个值对象Value,其中键对象Key和值对象Value可以是任意数据类型,并且键对象Key不允许重复,这样在访问Map集合中的元素时,只要指定了Key,就能找到对应的Value。
HashMap
HashMap集合是Map接口的一个实现类,它用于存储键值映射关系,该集合的键和值允许为空,但键不能重复,且集合中的元素是无序的。
-
HashMap集合对于元素的增、删、改、查操作表现出的效率都比较高。
Map集合遍历
-
使用Iterator迭代器遍历集合
-
KeySet()方法
Set keySet = map.keySet(); // 获取键的集合 Iterator it = keySet.iterator(); // 迭代键的集合 while (it.hasNext()) { Object key = it.next(); Object value = map.get(key); // 获取每个键所对应的值 System.out.println(key + ":" + value); }
-
entrySet()方法
Set entrySet = map.entrySet(); Iterator it = entrySet.iterator(); // 获取Iterator对象 while (it.hasNext()) { Map.Entry entry = (Map.Entry)(it.next()); Object key = entry.getKey(); // 获取Entry中的键 Object value = entry.getValue(); // 获取Entry中的值 System.out.println(key + ":" + value); }
-
JDK 8新方法
map.forEach((key,value) -> System.out.println(key + ":" + value));
-
values()方法
Collection values = map.values(); // 获取Map集合中value值集合对象 values.forEach(v -> System.out.println(v));
-
-
使用JDK 8提供的forEach(Consumer action)方法遍历集合
TreeMap
TreeMap中所有的键是按照某种顺序排列的。
为了实现TreeMap元素排序,可以参考TreeSet 集合排序方式,使用自然排序和定制排序。
Properties
Properties主要用来存储字符串类型的键和值,在实际开发中,经常使用Properties集合类来存取应用的配置项
常用工具类
Collections工具类
-
添加,排序操作
-
查找,替换操作
Arrays工具类
-
sort()方法排序;
-
binarySearch(Object[] a, Object key)方法查找元素;
-
copyOfRange(int[] original, int from, int to)方法拷贝元素;
-
fill(Object[] a, Object val)方法替换元素
Lambda表达式
表达式由 参数列表、箭头符号 -> 和方法体组成
七、泛型
泛型基础
-
其本质是参数化类型,即将具体的类型形参化
-
声明由一对尖括号和类型形参组成
-
好处:
-
提高类型安全性
-
消除强制类型转换
-
提高代码复用性
-
拥有更高的运行效率
-
泛型类
-
[访问权限] class 类名 <类型形参变量1,类型形参变量2,...,类型形参变量n>{...}
-
类型形参变量,可以是任意一个字母,建议:
-
E:Element(元素),如List<E>
-
K,V:Key,Value(Map的键值对)
-
N:Number(数字)
-
T:Type(类型),如String,Integer等
-
泛型接口
[访问权限] interface 接口名称 <类型形参变量>{...}
泛型方法
[访问权限修饰符][static][final]<类型形参> 返回值类型 方法名 (形式参数列表){}
-
访问权限修饰符(包括private,public,protected),static,final都必须写在类型形参列表前面
-
返回值类型必须写在类型形参列表的后面
-
泛型方法可以在泛型类中,也可以在普通类中
-
泛型形参可以用在方法体中修饰局部变量,也可以修饰方法的返回值
-
泛型方法可以是实例方法(没有static修饰,也叫非静态方法)也可以是静态方法
-
使用方式
对象名|类名.<类型实参>方法名(类型实参列表); 对象名|类名.方法名(类型实参列表);
类型通配符
-
?
-
设定类型通配符的上限
只想接收指定类型的子类
<? extends 类>
-
设定类型通配符的下限
<? super 类>