第一章 Java开发入门
-
Java三个技术平台:JavaSE JavaEE JavaME
-
Java语言的特点:
- 简单易用
- 安全可靠
- 跨平台
- 面向对象
- 支持多线程
-
什么是JDK?
Java开发环境叫JDK,包括Java编译器、Java运行环境、Java文档生成器、Java打包工具等
什么是JRE?
Java运行环境
-
关于系统环境变量
PATH:告知系统去指定路径寻找JDK
CLASSPATH:告知JDK到指定路径去查找类(.class)文件
-
关于 javac.exe & java.exe
-
编译java源文件:
javac helloworld.java(完整的文件名)
之后生成:helloworld.class文件
-
运行java程序:
java helloworld(类名)
-
第二章 Java编程基础
2.1 Java基本语法
- 标识符规范:
- 包名所有的字母一律小写
- 类名和接口名每个单词首字母都要大写
- 常量名所有字母都大写,单词之间用下划线连接
- 变量名和方法名第一个单词首字母都小写,从第二个单词开始首字母都大写
- 使用有意义的单词表示
2.2 变量的数据结构
基本数据类型,和引用数据类型。
基本数据类型:
-
数值型(整数类型[byte short int long] 浮点类型[float double])
-
字符型 char
-
布尔型 boolean
引用数据类型:
- 类(class)
- 接口(interface)
- 数组
- 枚举(enum)
- 注解(Annotation)
2.3 Java中的运算符
逻辑运算符
- &&:短路与,当左边为false,右边就不会运算了
- &:与,不论左边是true还是false,右边都会运算
- ||:短路或,当左边为true的时候,右边就不会运算了
- |:或,不论左边是true还是false,右边都会运算
运算符的优先级
- . [] ()
- ++ – ~ !
- * / %
- + -
- « » »>
- < > <= >=
- == !=
- &
- ^
- |
- &&
- ||
- ?:
- = *= /= += -= «= »= »>= &= ^= |=
2.4 选择结合语句
// if—else结构
if(...){
...
}else{
...
}
// if—else if-else结构
if(...){
...
}else if(...){
}else if(...){
}else{
...
}
// switch条件语句
switch(...){
case ...:
...
break;
case ...:
...
break;
case ...:
...
break;
default:
...
break;
}
2.5循环结构语句
循环语句
// while
while(...){
...
}
// do-while
do{
...
}while(...);
// for
for(初始化表达式; 循环条件; 操作表达式){
...
}
// 循环嵌套
for(...; ...; ...){
...
for(...; ...; ...){
...
}
...
}
跳转语句
-
break:在switch-case中,终止某个case并且跳出switch结构
在循环语句中,跳出当前循环
break跳出多层循环
outer: for(int i = 1; i <= 9; i++){
for(int j = 1; j <= i; j++){
if(i >= 3){
break outer; //直接跳出outer循环
}
}
}
- continue:在循环中,终止本次循环,执行下一次循环
2.6数组
数组定义
三种语法:
数组类型[] 数组名 = new 数组类型 [数组长度];
数组类型[] 数组名 = new 数组类型 []{e0, e1, e2, ...};
数组类型[] 数组名 = {e0, e1, e2, ...}
int[] ids = new int[100];
String[] name = new String[] {"张三", "Tom", ...};
Object[] object = {"张三", "tom", ...};
int[] ids;
ids = new int[100];
多维数组
int[][] arr = new int[3][4];
int[][] arr = new int[3][];
int[][] arr = {{1, 2},{3,4,5,6},{7,8,9}};
基本操作
-
数组遍历
-
数组求最值
-
数组排序(冒泡)
第三章 面向对象(上)
3.1面型对象概述
- 封装
- 继承
- 多态
3.2类与对象
类的定义
// 类的定义
[修饰符] class 类名 [extends 父类名] [implements 接口名]{
// 类成员及方法
}
//类成员变量声明
[修饰符] 数据类型 变量名 [=值];
private String name;
private int age = 20;
// 类成员方法声明
[修饰符] [返回值类型] 方法名 (参数列表){
...
...
return 返回值;
}
对象的创建与使用
类名 对象名称 = new 类名();
// 例如
class Person{
}
Person p = new Person();
访问控制符
- private(当前类访问级别):只能被该类的其他成员所访问,其他类无法直接访问
- default(包访问级别):如果一个类或者类的成员不使用任何访问控制修饰符,则成为默认访问级别,这个类或者类成员只能被本包中的其他类访问
- protected(子类访问级别):这个成员既可以被同一包下的其他类访问也能被不同包下该类的子类所访问
- public(公共访问级别):这个类和类成员可以被所有类所访问,不管是不是在同一个包中
3.3 类的封装
具体实现是:在定义一个类时,将类中的属性私有化,即使用private关键字来修饰,私有属性只能在它所在的类中被访问;如果外界想访问私有属性,需要提供一些使用public修饰的公有方法。
3.4 方法的重载和递归
方法的重载
public class Example{
// 两个整数相加
public static int add(int x, int y){
return x+y;
}
// 三个整数相加
public static int add(int x, int y, int z){
return x+y+z;
}
// 两个小数相加
public static double(double x, double y){
return x+y;
}
}
方法的重载:
- 方法名称相同
- 参数个数或者参数类型不同
- 与返回值无关
方法的递归
递归必须要有结束条件,否则会陷入无限递归状态
public class Example{
public static int getSum(int n){
if(n==1){
return 1;
}
int temp = getSum(n-1);
return temp + n;
}
public static void main(String[] args){
int sum = getSum(4);
}
}
3.5构造方法
构造方法的定义
满足三个条件:
- 方法名与类名相同
- 方法名前面没有返回值类型的声明
- 在方法中不能用return来返回一个值,但是可以单独的写return语句来作为方法的结束
[修饰符] 方法名 (参数列表){
...
}
// 构造无参
class Person{
public Person(){
// 无参构造方法
}
}
Person p = new Person();
// 构造有参
class Person{
public Person(int a){
// 有参构造方法
}
}
Person p = new Person(18);
构造方法的重载
只要每个构造方法的参数类型和个数不同即可
class Person{
String name;
int age;
public Person(int a){
age = a;
}
public Person(String n, int a){
name = n;
age = a;
}
}
Person p1 = new Person(18);
Person p2 = new Person("张三", 18);
- 注意:
- Java中每个类都至少有一个构造方法,如果在一个类中没有显示地定义构造方法,系统就会自动为这个类创建一个默认构造方法
- 一旦为该类定义构造方法,系统将不再提供默认的无参构造方法
3.6 this关键字
Java中提供了一个关键字this来指代当前对象,用于在方法中访问该类型的其他成员
// this调用成员变量
class Person{
int age;
public Person(int age){
this.age = age;
}
}
// this调用成员方法
class Person{
public void openMouth(){
...
}
public void speak(){
this.openMouth();
}
}
// this调用构造方法
/*
注意:
1.只能在构造方法中使用this调用其他构造方法,不能在类的成员方法中调用
2.在构造方法中,使用this调用构造方法必须是该方法的第一条执行语句,且只能出现一次
3.不能在一个类的两个构造方法中使用this互调
*/
class Person{
public Person(){
...
}
public Person(int age){
this(); // 调用无参构造方法
}
}
3.7static关键字
静态变量
静态变量所定义的对象可以被所有实例共享。
类名.变量名;
class Student {
static String schoolName;
}
public class Example {
public static void main(String[] args){
Student s1 = new Student();
Student s2 = new Student();
Student.schoolName = "西安交通大学";
System.out.println("我是" + s1.schoolName + "的学生");
System.out.println("我是" + s2.schoolName + "的学生");
}
}
/*
输出结果:
我是西安交通大学的学生
我是西安交通大学的学生
*/
- 注意:static关键字只能修饰成员变量,不可以修饰局部变量
静态方法
有时候,开发人员希望在不创建对象的情况下就可以调用某个方法,这种情况下可以使用静态方法。
静态方法的定义十分简单,只需在类中定义的方法前面加上static关键字即可。
// 访问 类名.方法 or 实例对象名.方法
class Person{
public static void say(){
...
}
}
public class Example{
public static void main(String[] args){
Person.say();
// 或者
Person p = new Person();
p.say();
}
}
静态代码块
static {
...
}
// 静态代码块只在类的第一次使用时会被加载,并且只会被加载一次
第四章 面向对象(下)
4.1 类的继承
继承的概念
语法格式
/*
[修饰符] class 子类名 extends 父类名{
...
}
修饰符可选,默认default
*/
class Animal{
...
}
class Dog extends Animal{
...
}
/*
1.子类在继承父类时,会自动拥有父亲所有公共的成员
2.Java中,类只支持单继承,不允许多重继承,也就是一个类只有一个父亲
3.多个类可以继承同一个父类
4.可以多层继承,一个类的父类可以再继承另外的父类
*/
重写父类方法
- 子类中重写的方法需要和父类被重写的方法具有相同的方法名、参数列表以及返回值类型
- 不能使用比父类重写方法更加严格访问权限
super关键字
-
使用super关键字调用父类的成员变量和成员方法
super.成员变量
super.成员方法([参数1, 参数2…])
-
使用super关键字调用父类构造方法,并且只能放在子类第一行,只能出现一次
super([参数1, 参数2, …])
4.2 final关键字
特性:
- final修饰的类不能被继承
- final修饰的方法不能被子类重写
- final修饰的变量是常量,只能赋值一次
4.3抽象类和接口
抽象类
基本语法格式
/*
// 定义抽象类
[修饰符] abstract class 类名{
// 定义抽象方法
[修饰符] abstract 返回值类型 方法名 (参数列表);
// 其他方法和属性
}
*/
- 包含抽象方法的类必须定义为抽象类,但是抽象类中可以不包含任何抽象方法
- 抽象类不可以被实例化,如果要调用可以定义一个子类,在子类中实现
接口
- 如果一个类中所有方法都是抽象的,那么这个类是接口(JDK8中重新定义,还可以有默认方法和静态方法,默认方法使用default修饰,静态方法使用static修饰,而且这两种方法都允许有方法体)
- 与定义类不同的是,定义接口不再使用class关键字,而是使用interface关键字来声明
[修饰符] interface 接口名 [extends 父接口1, 父接口2, ...]{
[public] [static] [final] 常量类型 常量名 = 常量值;
[public] [abstract] 方法返回值类型 方法名 (参数列表);
[public] default 方法返回类型值 方法名 (参数列表){
...
}
[public] static 方法返回值类型 方法名 (参数列表){
...
}
}
- 定义接口实现类
[修饰符] class [extends 父类名] [implements 接口1, 接口2, ...]{
...
}
- 当一个类实现接口,如果这个类是抽象类,只需要实现接口中的部分抽象方法即可,否则需要实现所有抽象方法
- 一个类可以通过implements实现多个接口
class A extends B implements C{
// 需要先继承再实现接口,extends需要放在implements前面
...
}
4.4多态
多态是指不同类的对象在调用一个方法时所呈现的不同动行为。解决方法同名的问题,并且使程序更加灵活,从而有效的提高了程序的可拓展性和可维护性。
对象类型的转换
涉及到子类对象当作父类类型使用的情况,“向上转型”
Animal an1 = new Cat(); // Cat 类当作 Animal 类型来使用
Animal an2 = new Dog(); // Dog 类当作 Animal 类型来使用
// 注意,此时不能通过父类去调用子类特有的方法
instanceof 判断一个对象是否为某个类/接口的的实例或者子类实例
/*
对象(或对象引用变量)instanceof 类(或接口)
*/
if (an1 instanceof Cat){
Cat cat = (Cat)an1;
}
4.5 内部类
成员内部类
在一个类中除了可以定义变量、成员方法还可以定义类,这样的类称为内部类。
class Outer{
int m = 0;
void test1(){
...
}
class Inner{
int n = 1;
void show1(){
}
void show2(){
}
}
// 定义外部类方法,访问内部类变量和方法
void test2(){
Inner inner = new Inner();
}
}
// 测试类
public static void main(String[] args){
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner(); // 注意这里有两种情况创建内部类
/*
1.如果已有初始化的外部类对象:
Outer.Inner inner = outer.new Inner();
2.如果没有已经初始化的外部类对象:
Outer.Inner inner = new Outer().new Inner();
*/
inner.show1();
outer.test2();
}
局部内部类
局部内部类,也叫方法内部类。就是在定义到某个局部范围中的类;它和局部变量一样,都是在方法中进行定义,其有效值仅限于方法内部。
class Outer{
void test1(){
...
}
void test2(){
class Inner{
void show(){
test1();
}
}
}
}
局部类可以访问外部类所有成员,而只有包含在局部内部类的方法才可以访问内部类中的所有成员。
静态内部类
静态内部类就是使用static关键字修饰的成员内部类。
- 形式上:静态内部类前增加了static关键字
- 功能上:静态内部类只能访问外部类的静态成员,同时,通过外部类访问静态内部类成员时。可以跳过外部类直接通过内部类访问
/*
外部类名.静态内部类名 变量名 = new 外部类名.静态内部类名();
*/
// 定义外部类
class Outer{
static int m = 0;
static class Inner{
void show(){
...
}
}
}
public class Example{
public static void main(String[] args){
// 静态内部类可以直接通过外部类创建
Outer.Inner inner = new Outer.Inner();
inner.show();
}
}
匿名内部类
在Java中调用某个方法时,如果该方法的参数是一个接口类型,除了可以传入一个参数接口实现类,还可以使用匿名内部类实现接口来作为该方法的参数。
/*
new 父接口(){
//匿名内部类实现部分
}
*/
interface Animal{
void shout();
}
public class Example{
public static void main(String[] args){
String name = "小花";
// 定义匿名内部类作为参数传递给Animal shout方法
animalShout (new Animal(){
// 实现shout方法
public void shout(){
...
}
});
}
// 定义静态方法animalShout,接受接口类型参数
public static void animalShout(Animal an){
an.shout();
}
}
4.6 JDK8的Lambda表达式
使用简洁的表达式来表达一个接口,同时Lambda表达式也简化了对集合以及数组数据的遍历、过滤、提取等操作。
入门
一个Lambda表达式由三个部分组成,分别为参数列表、"->“和表达式主体。
/*
([数据类型 参数名, 数据类型 参数名, ...]) -> {表达式主体}
*/
interface Animal{
void shout();
}
public class Example{
public static void main(String[] args){
String name = "xiaohua";
animalShout(()->System.out.println("..."));
}
public static void animalShout(Animal an){
...
}
}
函数式接口
接口中有且只有一个抽象方法时才可以使用Lambda表达式代替匿名内部类
// 这个例子有些瞎写噢~
package review;
@FunctionalInterface
interface ann{
void shout();
}
interface cc{
int sum(int a, int b);
}
public class test{
public static void main(String[] args){
as(()->System.out.println("asd"));
s(10, 20, (x, y)->x+y);
}
private static void as(ann a){
a.shout();
}
private static void s(int x, int y, cc c){
c.sum(x, y);
}
}
方法引用和构造器引用
看课本我没多少印象就不写啦
4.7异常
- Error:错误类,表示Java运行时产生的系统内部错误或者资源耗尽的错误,是比较严重的
- Exception:异常类,表示程序本身可以处理的错误
异常的类型
- 编译时的异常
- 运行时的异常
try…catch 和 finally
异常捕获
try{
// 可能出现异常的地方
}catch(Exception 类或者其子类 e){
// 异常捕获处理
}finally{
// 有些时候,我们希望有些语句无论是否发生异常都要执行,就使用finally
throws关键字和throw关键字
垃圾回收
第五章 Java中的常用类
5.1 String类和StringBuffer类
String类的初始化
String name = "...";
String name = new String("...");
方法声明 | 功能描述 |
---|---|
String() | 创建一个内容为空的字符串0 |
String(String value) | 根据指定字符串内容创建对象 |
String(char[] value) | 根据指定的字符数组创建对象 |
String str1 = new String();
String str2 = new String("abc");
char[] arr = new char[]{'A', 'B', 'C'};
String str3 = new String(arr);
String类的常见操作
方法声明 | 功能描述 |
---|---|
int index(int ch) | 返回字符在字符串中第一次出现位置的索引 |
int lastIndex(int ch) | 最后一次出现位置的索引 |
int indexOf(String str) | 返回指定子串在字符串中第一次出现的位置索引 |
int lastIndexOf(String str) | 子串最后一次出现位置的索引 |
char charAt(int index) | 返回index位置上的字符 |
boolean endsWith(String str) | 判断字符串是否以指定字符串结尾 |
int length() | 返回长度 |
boolean equals | 字符串与指定字符串比较 |
boolean isEmpty() | 当且仅当字符串长度为零时,返回true |
boolean startsWith(String str) | 字符串是否以指定字符串开头 |
boolean contains(CharSequence cs) | 字符串是否包含指定字符序列 |
String toLowerCase() | 字符串转化成小写 |
String toUpperCase() | 转化为大写 |
static String valueOf(int i) | 返回int参数的字符串表示形式 |
char[] toCharArray() | 字符串转化为一个字符数组 |
String replace(CharSequence oldstr,CharSequence newstr) | 返回新的字符串,newstr代替旧字符串中所有的oldstr |
String[] split(String regex) | 根据参数regex(一个正则表达式)分割成若干字符串 |
String substring(int beginIndex) | 返回从beginIndex角标开始的字符串直到最后 |
String substring(int beginIndex, int endIndex) | 返回从 beginIndex 到 endIndex-1 的角标字符串 |
String trim() | 返回新字符串,去掉首尾空格 |
StringBuffer类
为了便于对字符串进行修改,在JDK中提供了一个StringBuffer类(也称字符串缓冲区)来操作字符串。
StringBuffer类的内容和长度是可以改变的,类似于一个字符容器,在进行添加删除时不会产生新的StringBuffer对象。
方法声明 | 功能描述 |
---|---|
StringBuffer append(char c) | 添加字符到字符串末尾 |
StringBuffer insert(int offset, String str) | 在StringBuffer对象中offset位置插入字符串str |
StringBuffer deleteCharAt(int index) | 移出指定位置的字符 |
StringBuffer delete(int start, int end) | 删除对象中指定范围的字符串或者字符串 |
StringBuffer replace(int start, int end, String s) | 将StringBuffer对象中指定范围内的字符或者字符串用新的字符串s表示 |
void setCharAt(int index, char ch) | 修改指定位置处的字符 |
String toString() | 返回StringBuffer缓冲区的字符串对象 |
StringBuffer reverse() | StringBuffer对象用其反转形式取代 |
String和StringBuffer的不同
- String长度不可以改变,StringBuffer可以改变
- String类重写了equals()方法,StringBufer没有重写
- String类对象可以用“+”操作符进行连接,但是StringBuffer不可以
5.2System类与Runtime类
System类
方法声明 | 功能描述 |
---|---|
static void exit(int status) | 终止当前正在运行的Java虚拟机,statues为状态码,非0异常终止 |
static void gc() | 运行垃圾回收器回收垃圾 |
static native long currentTimeMillis() | 返回以毫秒为单位的当前时间 |
static void arraycopy(Object scr, int scrPos, Object dest, int destPos, int length) | 从scr引用的指定原数组拷贝到dest引用的数组,拷贝从指定位置开始,到目标数组指定位置结束 |
static Properties getProperties() | 获取当前的系统属性 |
static String getProperties() | 获取当前的系统属性 |
static String getProperty(String key) | 获取指定键描述的系统属性 |
Runtime类
Runtime run = Runtime.getRuntime();
run.availableProcessors(); // 处理器个数
run.freeMemory(); // 空闲内存大小
run.maxMemory(); // 最大可用内存大小
5.3 Math类与Random类
Math类
package example5;
public class example15 {
public static void main(String[] args) {
System.out.println("计算绝对值的结果:" + Math.abs(-1));
System.out.println("计算正弦的结果:" + Math.sin(1.57));
System.out.println("计算余弦的结果:" + Math.cos(2.0));
System.out.println("计算正切的结果:" + Math.tan(0.8));
System.out.println("计算平方根的结果:" + Math.sqrt(4));
System.out.println("计算立方根的结果:" + Math.cbrt(9));
System.out.println("计算乘方的结果:" + Math.pow(2, 2));
System.out.println("求大于参数的最小整数:" + Math.ceil(4.6));
System.out.println("求小于参数的最大整数:" + Math.floor(-5.2));
System.out.println("对小数进行四舍五入后的结果:" + Math.round(-8.6));
System.out.println("求两个数中的最大值:" + Math.max(5.1, 5.5));
System.out.println("求两个数的最小值:" + Math.min(5.1, 5.5));
System.out.println("生成一个大于0.0小于1.0的随机值:" + Math.random());
}
}
/*
控制台输出:
计算绝对值的结果:1
计算正弦的结果:0.9999996829318346
计算余弦的结果:-0.4161468365471424
计算正切的结果:1.0296385570503641
计算平方根的结果:2.0
计算立方根的结果:2.080083823051904
计算乘方的结果:4.0
求大于参数的最小整数:5.0
求小于参数的最大整数:-6.0
对小数进行四舍五入后的结果:-9
求两个数中的最大值:5.5
求两个数的最小值:5.1
生成一个大于0.0小于1.0的随机值:0.5382268154233723
*/
Random类
两个构造方法
Random() // 用于创建一个随机数生成器,每次实例化Random对象会生成不同的随机数
Random(long seed) // 使用long型的随机数种子创建伪随机数生成器,当seed相同时,每次实例化Random对象 会生成相同的随机数
常用类方法
方法声明 | 功能描述 |
---|---|
boolean nextBoolean() | 随机生成boolean类型的随机数 |
double nextBoolean() | 随机生成double类型的随机数 |
float nextFloat() | 随机生成float类型的随机数 |
int nextInt() | 随机生成int类型的随机数 |
int nextInt(int n) | 随机生成[0, n)之间的int类型的随机数 |
long nextLong() | 随机生成long类型的随机数 |
5.4包装类
package example5;
public class example18 {
public static void main(String[] args) {
//通过String.valueOf()方法将基本类型转换为字符串
int num=123;
String string = String.valueOf(num);
System.out.println("将 int 变量转换为字符串的结果:" + string);
//通过包装类的静态方法将基本数据类型和字符串类型转换为对应的包装类
String str = "998";
Integer integer = Integer.valueOf(num);
Integer integer2 = Integer.valueOf(str);
System.out.println("将 int 变量转换为对应包装类的结果:" + integer);
System.out.println("将字符串变量转换为对应包装类的结果:" + integer2);
//通过包装类的构造方法将基本数据类型和类型匹配的转换为包装类;
Integer integer3 = new Integer(num);
Integer integer4 = new Integer(str);
System.out.println("通过构造器将 int 类型的变量转换为包装类的结果:" + integer3);
System.out.println("通过构造器将字符串变量转换为包装类的结果:" + integer4);
//通过包装类的parse···()方法将,字符串变量转换为基本类型
int parseInt = Integer.parseInt(str);
System.out.println("将字符串换为基本类型的结果:" + parseInt);
//通过包装类的toString()方法将包装类转换为字符串
String string2 = integer.toString();
System.out.println("将包装类转换为字符串的结果:" + string2);
}
}
/*
控制台输出:
将 int 变量转换为字符串的结果:123
将 int 变量转换为对应包装类的结果:123
将字符串变量转换为对应包装类的结果:998
通过构造器将 int 类型的变量转换为包装类的结果:123
通过构造器将字符串变量转换为包装类的结果:998
将字符串换为基本类型的结果:998
将包装类转换为字符串的结果:123
*/
5.5日期与时间类
Date类
在JDK的java.util包中,提供了Date类表示日期和时间。
// 构造方法
Date();
Date(long date); // date时是1970/01/01 00:00以来的时间戳
Calender类
抽象类,不可以被实例化
Calendar calendar = Calendar.getInstance();
int get(int field); // 返回指定日历字段的值
void add(int field, int amount); // 为日历字段增加或者减去指定的时间量
void set(int field, int value); // 为指定日历设置值
void set(int year, int month, int date); // 设置Calendar对象的年、月、日三个字段的值
void set(int year, int month, int date, int hour, int min, int sec); // 设置年月日时分秒
// 获取当前计算机时间
package example5;
import java.util.*;
public class example20 {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1;
int day = calendar.get(Calendar.DATE);
int hour = calendar.get(Calendar.HOUR);
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);
System.out.println("当前的时间为:" + year + "年" + month + "月" +
day + "日" + hour + "时" + minute + "分" + second + "秒");
}
}
/*
控制台输出:
当前的时间为:2019年6月8日2时25分13秒
*/
5.6 格式化类
DateFormat类
常用方法
方法声明 | 功能描述 |
---|---|
static DateFormat getDateInstance() | 创建默认日期格式器 |
static DateFormat getDateInstance(int style) | 创建指定格式化风格的日期格式器 |
static DateFormat getDateTimeInstance() | 创建默认风格的日期/时间格式器 |
static DateFormat getDateTimeInstance(int dataStyle, int timeStyle) | 创建制定格式化风格的时间/日期格式器 |
String format(Date date) | 将一个Date格式化为日期。时间字符串 |
Date parse(String source) | 将指定字符串解析为一个日期 |
package example5;
import java.text.*;
import java.util.*;
public class example24 {
public static void main(String[] args) {
Date date = new Date();
//full格
DateFormat fullFormat = DateFormat.getDateInstance(DateFormat.FULL);
//Long格式
DateFormat longFormat = DateFormat.getDateInstance(DateFormat.LONG);
//MEDIUM格式
DateFormat mediumFormat = DateFormat.getDateInstance(DateFormat.MEDIUM );
//SHORT格式
DateFormat shortFormat = DateFormat.getDateInstance(DateFormat.SHORT);
//下面打印格式化之后的日期时间
System.out.println("当前时间的完整格式为:" + fullFormat.format(date));
System.out.println("当前时间的长格式为:" + longFormat.format(date));
System.out.println("当前时间的普通格式为:" + mediumFormat.format(date));
System.out.println("当前时间的短格式为:" + shortFormat.format(date));
}
}
SimpleDateFormat类
package example5;
import java.text.DateFormat;
import java.text.ParseException;
public class example25 {
public static void main(String[] args) throws ParseException {
DateFormat dt1 = DateFormat.getDateInstance();
//long
DateFormat dt2 = DateFormat.getDateInstance(DateFormat.LONG);
//String str1 = "2018-01-27";
String str2 = "2018年01月27日";
//输出解析成date对象后的结果
//System.out.println(dt1.parse(str1));
System.out.println(dt2.parse(str2));
}
}
// Sat Jan 27 00:00:00 CST 2018
DateTimeFormatter类
相当于DateFormat和SimpleDateFormat类的合体
完成时间和日期格式化:
package example5;
import java.time.*;
import java.time.format.*;
public class example28 {
public static void main(String[] args) {
LocalDateTime date = LocalDateTime.now();
//创建DateTimeFormatter
System.out.print("使用常量创建 DateTimeFormatter:");
DateTimeFormatter dtf1 = DateTimeFormatter.ISO_DATE_TIME;
System.out.println(dtf1.format(date));
//MEDIUM
System.out.print("使用MEDIUM类型风格的DateTimeFormatter:");
DateTimeFormatter dtf2 = DateTimeFormatter
.ofLocalizedDateTime(FormatStyle.MEDIUM);
System.out.println(dtf2.format(date));
System.out.print("根据模式字符串创建 DateTimeFormatter:");
DateTimeFormatter dtf3 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(date.format(dtf3));
}
}
/*
使用常量创建 DateTimeFormatter:2019-06-08T14:49:04.400044
使用MEDIUM类型风格的DateTimeFormatter:2019年6月8日 下午2:49:04
根据模式字符串创建 DateTimeFormatter:2019-06-08 14:49:04
*/
解析字符串:
package example5;
import java.time.*;
import java.time.format.*;
import java.util.Date;
public class example29 {
public static void main(String[] args) {
//两种格式
String str1 = "2018-01-27 12:38:36";
String str2 = "2018年01月29日15时01分20秒";
//定义解析格式器
DateTimeFormatter f1 = DateTimeFormatter
.ofPattern("yyyy-MM-dd HH:mm:ss");
DateTimeFormatter f2 = DateTimeFormatter.
ofPattern("yyyy年MM月dd日HH时mm分ss秒");
//LocalDateTime的parse方法解析
LocalDateTime l1 = LocalDateTime.parse(str1, f1);
LocalDateTime l2 = LocalDateTime.parse(str2, f2);
//输出结果
System.out.println(l1);
System.out.println(l2);
}
}
/*
2018-01-27T12:38:36
2018-01-29T15:01:20
*/
第六章 集合
6.1 集合概述
集合按照存储结构分为两大类:
- Collection:单列集合的根接口,用于存储一系列符合某种规则的元素
- Collection集合有两个重要的子接口,分别是List和Set
- List集合的特点是元素有序、可重复
- Set集合的特点是元素无序且不可重复
- List接口实现类主要有ArrayList和LinkedList
- Set类接口的主要实现类有HashSet和TreeSet
- Map:双列集合的根接口,用于存储具有键(Key)、值(Value)映射关系的元素
- Map的每个元素都包含一对键值
- Key是唯一的,使用Map集合时可以通过指定的Key值找到对应的Value
- Map的接口实现类主要有HashMap和TreeMap
6.2 Collection接口
定义了单列结合所有方法(List和set)一些通用方法,可用于操作所有单列集合
方法声明 | 功能描述 |
---|---|
boolean add(Object o) | 向集合中添加一个元素 |
boolean addAll(Collection c) | 将指定c中的所有元素添加到该集合中 |
void clear() | 删除该集合中所有元素 |
boolean remove(Object o) | 删除该集合中指定的元素 |
boolean removeAll(Collection) | 删除该集合中包括指定集合c中的所有元素 |
boolean isEmpty() | 判断该集合是否为空 |
boolean contains(Object o) | 判断集合中是否包含某个元素 |
boolean contains(Colleciton c) | 判断集合中是否包含指定集合c中的所有元素 |
Iterator iterator() | 返回在该集合的元素上进行迭代的迭代器,用于遍历集合所有元素 |
int size() | 获取该集合元素个数 |
Stream<E> stream() | 将集合源转换为有序元素的流对象 |
6.3 List接口
List接口简介
List集合中允许出现重复的元素,所有的元素是按照一种线性方式进行存储的。
List集合中元素有序,即存入顺序和取出顺序一致
List集合特有方法
方法声明 | 功能描述 |
---|---|
void add(int index, Object element) | 将元素插到指定位置 |
boolean addAll(int index, Collection c) | 将集合c中的所有元素插到指定位置 |
Object get(int index) | 返回索引位置的元素 |
Object remove(int index) | 删除索引位置的元素 |
Object set(int index, Object element) | 将索引位置处的元素替换为element,并返回替换后的元素 |
int indexOf(Object o) | 返回对象o在List集合中首次出现的位置索引 |
int lastIndexOf(Object o) | 返回对象o在集合中最后一次出现的位置索引 |
List subList(int fromIndex, int toIndex) | 返回子集合,从fromIndex(包括)到toIndex(不包括) |
Object[ ] toArray() | 将集合元素转化为数组 |
default void sort(Comparator<? super E> c) | 根据指定的比较器集合对元素进行排序 |
ArrayList集合
内部数据结构数组形式,在遍历和查找时高效,不适合做大量的增删
LinkedList集合
内部有双向循环链表,增删操作高效
特有方法
方法声明 | 功能描述 |
---|---|
void add(int index, E element) | 指定位置插入元素 |
void addFirst(Object o) | 指定元素插入集合开头 |
void addLast(Object o) | 元素插入集合结尾 |
Object getFirst() | 返回集合的第一个元素 |
Object getLast() | 返回集合的最后一个元素 |
Object removeFirst() | 移除并返回集合的第一个元素 |
Object removeLast() | 移除并返回集合的最后一个元素 |
boolean offer(Object o) | 指定元素添加到集合结尾 |
boolean offerFirst(Object o) | 指定元素添加到集合开头 |
boolean offerLast(Object o) | 指定元素添加到集合结尾 |
Object peek() | 获取集合第一个元素 |
Object peekFirst() | 获取集合第一个元素 |
Object peekLast() | 获取集合最后一个元素 |
Object poll() | 移除并返回集合第一个元素 |
Object pollFirst() | 移除并返回集合第一个元素 |
Object pollLast() | 移除并返回集合最后一个元素 |
void push(Object o) | 指定元素添加到集合开头 |
Object pop() | 移出并返回集合第一个元素 |
6.4 Collection集合遍历
Iterator遍历集合
Iterator是集合框架一员,但是它是主要用于迭代访问(即遍历)Collection中的元素,因此Iterator对象也被称为迭代器。
package example6;
import javax.swing.text.html.HTMLDocument;
import java.util.ArrayList;
import java.util.Iterator;
public class example3 {
public static void main(String[] args){
ArrayList list = new ArrayList();
//添加字符串
list.add("data_1");
list.add("data_2");
list.add("data_3");
//获取Iterator对象
Iterator iterator = list.iterator();
while (iterator.hasNext()){ //判断集合中是否存在下一个元素
Object obj = iterator.next();
System.out.println(obj);
}
}
}
/*
data_1
data_2
data_3
*/
foreach遍历集合
/*
for(容器中元素类型 临时变量 : 容器变量){
// 执行语句
}
*/
package example6;
import java.util.ArrayList;
public class example4 {
public static void main(String[] args){
ArrayList list = new ArrayList();
list.add("data_1");
list.add("data_2");
list.add("data_3");
//foreach遍历集合
for (Object obj:list){
System.out.println(obj);
}
}
}
/*
data_1
data_2
data_3
*/
- 注意:使用foreach进行循环遍历时不可以改变数组中元素的值
JDK8中的forEach遍历集合
根据Lambda表达式增加的方法
import java.util.ArrayList;
public class Example{
public static void main(String[] args){
ArrayList list = new ArrayList();
list.add("data_1");
list.add("data_2");
list.add("data_3");
System.out.println(list);
list.forEach(obj->System.out.println("迭代集合元素:" + obj));
}
}
/*
[data_1, data_2, data_3]
迭代集合元素:data_1
迭代集合元素:data_2
迭代集合元素:data_3
*/
6.5 Set接口
Set接口和List接口一样,同样继承自Collection接口,它与Collection接口中的方法基本一致。
Set接口中的元素无序,并且都会以某种规则保证存入的元素不出现重复。
Set接口主要有两个实现类,分别是HashSet和TreeSet:
- HashSet:根据对象的Hash值来确定对象在集合中的存储位置,具有良好的存取和查找性能。
- TreeSet:以二叉树的方式来存储元素,可以实现对集合元素中所有元素进行排序。
HashSet集合
- 如果元素类型是自定义类型,则使用此集合不会消除重复元素,这就需要我们重写hashCode()和equals()方法
TreeSet集合
TreeSet集合是Set接口的另一个实现类,内部采用平衡二叉树存储元素,可以保证集合中无重复元素,并且可以对元素进行排序
TreeSet集合在继承Set集合接口的基础上一些特有的方法
方法声明 | 功能描述 |
---|---|
Object first() | 返回TreeSet集合的首个元素 |
Object last() | 返回集合最后一个元素 |
Object lower(Object o) | 返回集合中小于给定元素的最大元素,如果没有返回null |
Object floor(Object o) | 返回集合中小于等于给定元素的最大元素,如果没有返回null |
Object higher(Object o) | 返回集合中大于给定元素的最小元素,如果没有返回null |
Object ceiling(object o) | 返回集合中大于等于给定元素的最小元素,如果没有返回null |
Object pollFirst() | 移除并返回集合中第一个元素 |
Object pollLast() | 移出并返回集合中最后一个元素 |
通过Compare接口实现CompareTO()方法进行排序,其中重写函数定制排序,P209
6.6 Map接口
Map接口简介
双列集合,每个元素包含 Key 和 Value,存在映射关系。
Map集合常用方法
方法声明 | 功能描述 |
---|---|
void put(Object key, Object value) | 向Map集合中添加Key-Value映射对象 |
int size() | 返回键值对个数 |
Object get(Object key) | 返回键所映射的值,没有返回null |
boolean containsKey(Object key) | 查看是否包含指定的键对象key |
boolean containsValue(Object value) | 查看是否包含指定的值对象value |
Object remove(Object key) | 删除并返回Key对象键值映射元素 |
void clear() | 清空键值映射元素 |
Set keySet() | 以Set形式返回集合中所有键对象Key |
Collection values() | 以Collection形式返回Map集合中所有值对象Value |
Set<Map.Entry<Key,Value»entry set() | 将Map集合转化成存储元素类型为Map的Set集合 |
boolean replace(Object key, Object value) | 指定键值所映射的值改为value |
boolean remove(Object key, Object value) | 删除Map中键值同时匹配的元素 |
HashMap集合
HashMap是Map接口的一个实现类,用于存储键值映射关系,集合键值允许为空,但是键不能重复,而且集合中的元素是无序的。
底层由哈希表组成,其实是“数组+链表”,对于元素的增、删、查、改操作效率都比较高。
package example6;
import java.util.HashMap;
import java.util.Map;
public class example14 {
public static void main(String[] args){
Map map = new HashMap();
map.put("1","Jack");
map.put("2","Rose");
map.put("3","Lucky");
map.put("4","Lucky");
map.put("1","Tom");
System.out.println(map);
// 查看键对象是否存在
System.out.println(map.containsKey("1"));
System.out.println(map.get("1"));
System.out.println(map.keySet());
System.out.println(map.values());
map.replace("1","Tom2");
System.out.println(map);
map.remove("1");
System.out.println(map);
}
}
/*
{1=Tom, 2=Rose, 3=Lucky, 4=Lucky}
true
Tom
[1, 2, 3, 4]
[Tom, Rose, Lucky, Lucky]
{1=Tom2, 2=Rose, 3=Lucky, 4=Lucky}
{2=Rose, 3=Lucky, 4=Lucky}
*/
- Map集合中键具有唯一性,当向集合中添加已存在的键值元素时,会覆盖以前的键值元素,如果需要可以返回原来的旧值
Map集合遍历
- Iterator迭代器遍历
// 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();
while(it.hasNext()){
Map.Entry entry = (Map.Entry) (it.next());
// 获取键
Object key = entry.getKey();
// 获取值
Object value = entry.getValue();
System.out.println(key + ":" + value);
}
- forEach方法遍历
map.forEach((key, value)->System.out.println(key + ":" + value));
- LinkedHashMap可以顺序存入和读出
TreeMap集合
用来存储键值映射关系且不允许出现重复的键
- 可以通过自定义比较器Comparator方式对所有的键进行定制排序 P221
Properties集合
Hashtable类的子类Properties,主要用于配置文件
6.7泛型
P223(dbq我整理不完了…)
6.8常用工具类
P255
6.9聚合操作
P232
第七章 I/O流
7.1 I/O流概述
I/O流有很多种,按照不同的方式可以分为以下三类:
1.字节流和字符流
根据操作的数据单位不同,可以分为字节流和字符流。
2.输入流和输出流
根据流传输方向不同,分为输入流和输出流。其中输入流只能从流中读取数据,而不能向里写入数据;输出流只能向流中写入数据,而不能从中读取数据。
3.节点流和处理流
- 根据流的功能不同,可以分为节点流和处理流。节点流也称为低级流;处理流(直连数据源)也成为高级流(对节点流封装)。
Java的I/O流主要在java.io包中,其中4个类为流的顶级类:
字节流 | 字符流 | |
---|---|---|
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
这4个顶级类都是抽象类,并且是所有流类型的父类。
7.2字节流
字节流概述
字节流两个抽象类InputStream和OutputStream是字节流的顶级父类。所有字节输入流继承自InputStream,所有字节输出流继承自OutputStream。
- InputStream从源输入到程序
- OutputStream从程序输出到目标设备
- 注意:都是相对于程序而言
方法声明 | 功能描述 |
---|---|
int read() | 从输入流中读取一个8位的字节,转换为0~255之间的整数,并且返回一个整数。当没有字节可读时,将返回-1 |
int read(by) | 从输入流中读取若干个字节,把它们保存到参数b指定的字节数组中,返回读取字节的数目 |
int read(byte[] b, int off, int len) | 从输入流中读取若干字节保存在参数b指定的字节数组中,off是数组开始保存数据起始下标,len为读取字节数目 |
void close() | 关闭此输入流并释放与该流相关的所有系统资源 |
方法声明 | 功能描述 |
---|---|
void write(int b) | 向输出流写一个字节 |
void write(byte[] b) | 把参数b指定的字节数字的所有字节写到输出流 |
void write(byte[] b, int off, int len) | 把b数组从偏移量off开始的len个字节写道输出流 |
void flush() | 刷新此输出流并强制写出所有缓冲流的输出字节 |
void close() | 关闭此输出流并释放与此流相关的所有系统资源 |
InputStream和OutputStream虽然提供了一系列读写数据方法,单号是这两个类是抽象类,不能被实例化,因此提供了不同的子类:
字节流读写文件
针对文件读写,JDK专门提供了两个类:
- FileInputStream
- FileOutputStream
// 使用FielInputStream输入流读取文件
FileInputStream in = new FileInputStream("test.txt");
int b = 0;
// 通过循环读取文件
while((b = in.read()) != -1){
System.out.println(b)
}
// 关闭流
in.close();
// 使用FileOutputStream输出流写入文件
FileOutputStream out = new FileOutputStream("out.txt");
String str = "hello";
// 将字符串转化成字节数组写入,注意,如果向一个已经存在的文件操作,文件的数据首先会被清空
// 如果以追加的形式写入
// FileOutputStream out = new FileOutputStream("out.txt", true);
out.write(str.getBytes());
// 关闭流
out.close();
- 通常将close()放在finally代码块中
文件的拷贝
FileInputStream in = new FileInputStream("test.txt");
FileOutputStream out = new FileOutputStream("out.txt");
int len = 0;
while((len = in.read()) != -1){
out.write(len);
}
in.close();
out.close();
字节流缓冲区
可以一次性读取多个字节数据,将数据先保存在字节数组中,然后将字节数组一次性的写入文件中
FileInputStream in = new FileInputStream("source/scr.jpg");
FileOutputStream out = new FileOutputStream("target/dest.jpg");
int len = 0;
byte[] buff = new byte[1024];
while((len = in.read(buff)) != -1){
out.write(buff, 0, len);
}
in.close();
out.close();
字节缓冲流
I/O包中提供了两个带缓冲的字节流,分别是BufferedInputStream和BufferedOutputStream,它们的构造方法中分别接受InputStream和OutputStream类型的参数作为对象,在读写数据时提供缓冲功能。
// 使用缓冲流进行文件拷贝
BufferedInputStream bis = new BufferedInputStream(
new FileInputStream("source/scr.jpg")
);
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("target/dest.jpg")
);
int len = 0;
while((bis.read()) != -1 ){
bos.write(len);
}
bis.close();
bos.close();
7.3 字符流
字符流概述
字符流有两个顶级的父类:
- Reader:字符输入流,从某个源设备读取字符
- Writer:字符输出流,向某个目标设备写入字符
其中FileReader和FileWriter用于读写文件,BufferedReader和BufferedWriter是具有缓冲功能的流,可以提高读写效率
字符流操作文件
如果想从文件中读取字符便可以使用字符输入流FileReader,通过此流可以从文件中读取一个或者一组字符
FileReader fileReader = new FileReader("reader.txt");
int len = 0;
while((len = fileReader.read()) != -1){
System.out.println((char)len);
}
fileReader.close();
如果要向文件中写入字符就需要使用FileWriter类
// 同样如果原文件存在则会先清空再写入
// 如果追加
// FileWriter fileWriter = new FileWriter("writer.txt", true);
FileWriter fileWriter = new FileWriter("writer.txt");
fileWriter.write("轻轻的我走了,\r\n");
// 关闭流
fileWriter.close();
使用字符流缓冲区实现文件拷贝
FileReader fileReader = new FileReader("reader.txt");
FileWriter fileWriter = new FileWriter("writer.txt");
int len = 0;
char[] buff = new char[1024];
while((len = fileReader.read(buff)) != -1){
fileWriter.write(buff, 0, len);
}
fileReader.close();
fileWriter.close();
使用字符输入输出缓冲流进行文件拷贝
BufferedReader br = new BufferedReader(
new FileReader("reader.txt")
);
BufferedWriter bw = new BufferedWriter(
new FileWriter("writer.txt")
);
String str = null;
// 循环时每次读取一行文本
while((str = br.readLine()) != null){
bw.write(str);
// 写入一个换行符
bw.newLine();
}
br.close();
bw.close();
转换流
- InputStreamReader
- OutputStreamWriter
将字节输出流转化成字符输出流,方便直接写入字符
7.4 File类
File类的常用方法
方法声明 | 功能描述 |
---|---|
File(String pathname) | 通过指定的一个字符串类型的文件路径来创建一个新的File对象 |
File(String parent, String child) | 根据一个指定的字符串类型的父路径和一个字符串类型的子路径(包括文件名称)创建一个File对象 |
File(File parent, String child) | 根据指定的File类的父路径和字符串类型的子路径(包括文件名称)创建一个File对象 |
方法声明 | 功能描述 |
---|---|
boolean exists() | 判断File对象对应的文件是否存在 |
boolean delete() | 删除File对象对应的文件或目录 |
boolean createNewFile() | 当File对象对应的文件不存在时,新建一个此File对象所指定的文件 |
String getName() | 返回文件名或者文件夹名 |
String getPath() | 返回对应路径 |
String getAbsolutePath() | 获得绝对路径 |
String getParent() | 返回对应的父目录 |
boolean canRead() | 对象对应的文件或者目录是否可读 |
boolean canWrite() | 对应的文件或者目录是否可写 |
boolean isFile() | 判断是否是文件(不是目录) |
boolean isDirectory() | 判断是否是目录(不是文件) |
boolean isAbsolute() | 判断对应文件或者目录是否为绝对路径 |
long lastModified() | 返回自1970/1/1 00:00 到文件最后修改时间的毫秒值 |
long length() | 返回文件内容长度 |
String[] list() | 列出指定目录的所有内容,只是列出名称 |
String[] list(FilenameFilter filter) | 接受一个FilenameFilter参数,只列出符合条件的文件 |
File[] listFiles() | 返回一个包含File对象所有子文件和子目录的File数组 |
7.5 RandomAccessFile
P266
7.6 对象序列化
P268
7.7 NIO
P269
7.8 NIO.2
P275