文章目录
java学习的开始
环境的搭建
请参考如下文章:
【Java】java 环境配置(详细教程)_java配置环境教程-CSDN博客
常用的DOS命令:
- 按下win+R
- 输入cmd
操作 | 说明 |
---|---|
盘符名称: | 盘符切换。E:回车,表示切换到E盘 |
dir | 查看当前路径下的内容 |
cd 目录 | 进入单级目录 |
cd… | 退回到上级目录 |
cd 目录1\目录2 \ … | 进入多级目录 |
cd\ | 退回到盘符目录 |
cls | 清屏 |
exit | 退出命令提示符窗口 |
HelloWorld案例
-
新建一个文本文档文件,修改名称为HelloWorld.java
-
用记事本打开HelloWorld.java文件,输入程序内容
public class HelloWorld{ public static void main(String[] args){ System.out.println("HelloWorld"); } }//保存文件Crtl + s
-
打开命令提示符窗口,进入HelloWorld.java所在的目录。输入指令编译和执行
编译:javac 文件名.java 范例:javac HelloWorld.java 执行:java 类名 范例: java Hello World
编译工具的下载:
Other Versions - IntelliJ IDEA (jetbrains.com)
方法
概述:
方法(method)是将具有独立功能的代码块组织成为一个整体,使其具有特殊功能的代码集
注意:
- 方法必须先创建才能使用,该过程成为方法的定义
- 方法创建后并不是直接使用,需要手动使用后才会执行,该过程成为方法的调用
构造方法
构造方法是一个特殊的方法(方法名为类名的方法)
作用:创建对象
格式:
public class 类名{
修饰符 类名(参数){
//注意:如果使用带参的构造方法,必须先创一个无参的构造方法
}
}
功能:主要是完成对象数据的初始化
构造方法的注意事项
构造方法的创建
- 如果没有定义构造方法,系统将会给一个默认的无参构造方法
- 如果定义了构造方法,系统将不会提供默认的构造方法
构造方法的重载
- 如果定义了带参构造方法,还要使用无参构造方法,就必须再写一个无参构造方法
推荐的使用方式
- 无论是否使用,都手工书写无参构造方法
类和对象
什么是对象:
万物皆为对象,客观存在的事物都是对象
什么是类:
类是对现实生活中一类具有共同属性和行为的事物的抽象
类的特点:
- 类是对象的数据类型
- 类是具有相同属性和行为的一组对象的集合
什么是对象的属性
属性:
对象具有的各种特征,每个对象的每个属性都拥有特定的值
什么是对象的行为
行为:
对象能够执行的操作
类和对象的关系
类是对象的抽象,对象是类的实体
ArrayList
创建对象
ArrayList<数据类型> 对象 = new ArrayList<>()
添加方法(E e是元素的意思)
public boolean add(E e);
将指定的元素追加到此集合的末尾
public void add(int index,E element);
在此集合中指定位置插入指定元素
public booleam remove(Object o);
删除指定元素,返回删除是否成功
public E remove(int index);
删除指定索引处的元素,返回被删除的元素
public E set(int index,E element);
修改指定位置的元素,返回被修改的元素
public E get(int index);
返回指定索引处元素
public int size();
返回集合元素的个数
LinkedList集合
特有功能(方法)
方法名 | 说明 |
---|---|
public void addFirst(E e) | 在该列表开头插入指定的元素 |
public void addLast(E e) | 将指定的元素追加到此列表的末尾 |
public E getFirst() | 返回此列表中的第一个元素 |
public E getLast() | 返回此列表中最后一个元素 |
public E removeFirst() | 从此列表中删除并返回第一个元素 |
public E removeLast() | 从此列表中删除并返回最后一个元素 |
LinkedHashSet集合
特点
- 哈希表和链表实现的Set接口,具有可预测的迭代次序
- 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的
- 由哈希表保证元素唯一,也就是说没有重复的元素
Set集合
概述:
特点:
- 不包含重复元素的集合
- 没有带索引的方法,所以不能使用普通for循环遍历
HashSet()集合
HashSet集合特点
- 底层数据结构是哈希表
- 对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
- 没有索引的方法,所以不能使用普通for循环遍历
- 由于是Set集合,所以是不包含重复元素的集合
HashSet集合保证元素唯一性源码分析(太多了,也不是特别重要,自己了解)
TreeSet集合
特点:
- 元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法
- TreeSet():根据去元素的自然排序进行排序
- TreeSet(Comparator comparator):根据指定的比较器进行排序
- 没有带索引的方法,所以不能使用普通for循环遍历
- 由于是Set集合,所以不包含重复元素的集合
自然排序Comparable的使用
- 用TreeSer集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的
- 自然排序,就是让元素所属的类实现Comparable接口,重写comparaTo(T o)方法
- 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
比较器排序Comparator的使用
- 用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的
- 比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compara(T o1,T o2)方法
- 重写方法时,一定要注意排序规则必须按照要求的主要要求和次要条件来来写
Collection
Collection集合概述:
- 是单例集合的顶层接口,他表示一组对象,这些对象也称为Collection的元素
- JDK不提供此接口的任何直接实现,他提供更具体的子接口(如Set和List)实现
创建Collection集合的对象
- 多态的方式
- 具体的实现类ArrayList
常用方法
方法名 | 说明 |
---|---|
boolean add(E e) | 添加元素 |
boolean remove(Object o) | 从集合中移除指定的元素 |
void clear() | 清空集合中的元素 |
boolean contains(Object o) | 判断集合中是否存在指定的元素 |
boolean isEmpty() | 判断集合是否为空 |
in size() | 集合的长度,也就是集合中的元素的个数 |
Collection集合的遍历
Iterator
- Iteratoriterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到
- 迭代器是通过集合的iterator()方法得到的,所以我们说它是依赖于集合而存在的
Iterator中的常用方法
- E next():返回迭代中的下一个元素
- boolean hasNext():如果迭代具有更多元素,则返回true
Collections类
概述
是针对集合操作的工具类
常用方法
public static <T extends Comparable<?super T>> void sort(List<T> list)
将指定的列表按升序排序
public static void reverse(List<?>list)
反转指定列表中元素的顺序
public static void shuffle(List<?>list)
使用默认的随机源随机排列指定的列表
List集合
概述:
- 有序集合(也称为序列),用户可以精确控制列表中的每个元素的插入位置。用户可以通过整数索引访问元素,并搜索元素
- 与Set集合不同,列表通常允许重复的元素
List集合特点
- 有序:存储和取出的元素顺序一致
- 可重复:存储的元素可以重复
List集合特有方法
方法名 | 说明 |
---|---|
void add(int index,E element) | 在此集合中的指定位置插入指定的元素 |
E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 |
E get(int index) | 返回指定索引处的元素 |
并发修改异常(ConcurrentModificationException)
产生原因:
迭代器遍历的过程中,通过集合对象修改了集合中元素的长度,造成了迭代器获取元素中判断预期修改值和实际修改值不一致
解决方案:
用for循环遍历,然后用集合对象做对应的操作即可
ListIterator(列表迭代器)
作用:
- 通过List集合的listIterator()方法得到,所以说它是List集合特有的迭代器
- 用于允许程序员沿任意方向遍历列表的列表迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置
ListIterator中常用方法:
- E next();返回迭代中的下一个元素
- boolean hasNext();如果迭代具有更多元素,则返回true
- E previous();返回列表中上一个元素
- boolean hasPrevious();如果此列表迭代器在相反方向遍历列表时具有更对元素,则返回true
- void add(E e);指定的元素插入列表
List集合子类特点
常用子类:ArrayList,LinkedList
- Array List:底层数据结构是数组,查询快,增删慢
- LinkedList:底层数据结构是链表,查询慢,增删快
Map集合
概述:
- Interface Map<k,V> K:键的类型 V:值的类型
- 将键映射到值的对象:不能包含重复的键:每个键可以映射到最多一个值
- 举例: 学生的学号(键)和姓名(值)
基本方法
方法名 | 说明 |
---|---|
V put (K key,V value) | 添加元素 |
V remove(Object key) | 根据键删除键值对元素 |
void clear() | 移除所有的键值对元素 |
boolean containsKey(Object key) | 判断集合是否包含指定的键 |
boolean containsValue(Object value) | 判断集合是否包含指定的值 |
boolean isEmpty() | 判断集合是否为空 |
int size() | 集合的长度,也就是集合中键值对的个数 |
获取功能
方法名 | 说明 |
---|---|
V get(Object key) | 根据键获取值 |
Set keySet() | 获取所有键的集合 |
Collectionvalues() | 获取所有值的集合 |
Set<Map.Entry<K,V>>entrySet() | 获取所有键值对对象的集合 |
增强for循环
作用:
- 简化了数组和Collection集合的遍历
- 实现了Iterable接口的类允许其对象成为增强型for语句的目标
- 它是JDK5之后出现的,其内部原理是一个Iterator迭代器
格式:
for(元素数据类型 变量名:数组或者Collection集合){
//在此处使用变量即可,该变量就是元素
}
范例:
int[] arr = {1,2,3,4,5};
for(int i:arr){
System.out.println(i);
}
数据结构
概述:
数据结构是计算机存储、组织数据的方式。是指相互之间存在一种或多种特定关系的数据元素的集合(通常情况下,精心选择的数据结构可以带来更高的运行或着存储效率)
常见数据结构之栈
栈是一种数据先进后出的数据模型,有栈顶元素和栈低元素
数据进入栈模型的过程称为:压/进栈
数据离开栈模型的过程称为:弹/出栈
常见数据结构之队列
队列是一种数据先进先出的模型,入队列方向为后端,出队列方向为前端
数据从后端进入队列模式的过程称为:入队列
数据从前端离开队列模型的过程称为:出队列
常见数据结构之数组
概述:数组是一种查询快,增删慢的模型
- 查询数据通过索引定位,查询任意数据耗时相同,查询效率高
- 删除数据时,要将原始数据删除,同时后面每个数据前移,删除数据效率低
- 添加数据是,添加位置后的每个数据后移,在添加元素,添加效率极低
常见数据结构之链表
概述:有头结点,有结点,结点由数据(是存储具体的数据,也是这个结点的存储位置)和地址(下个结点的地址)构成,头结点由head和^(指空地址,节点指向空地址表示结束)
特点:
链表是一种增删快的模型(对比数组)
链表是一种查询慢的模型(对比数组)
常见数据结构之哈希表
概述:JDK8之前,底层采用数据+链表实现,可以说是一个元素为链表的数组,JDK8以后,在长度比较长的时候,底层实现了优化
如何存储数据:
哈希表默认由16个单位容量(0-15),然后将存储的数据的哈希值对16取余,对应的余数放进列表,然后在列表里依次判断是否重复,如果没有,则添加
System类
概述:System包含几个有用得类字段和方法,它不能被实例化
常用方法:
方法名 | 说明 |
---|---|
public static void exit(int status) | 终止当前运行得Java虚拟机,非零表示异常终止 |
public static long currentTimeMillis() | 返回当前时间(以毫秒为单位) |
封装
概述:
- 是面向对象三大特征之一(封装,继承,多态)
- 是面向对象编程语言对客观世界的模拟,客观世界里成员变量都在影藏在对象内部的,外界无法直接操作
原则
- 将类的信息隐藏在内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问
- 成员变量private,提供了对应的getXxx()/setXxx()方法
优点
- 通过方法来控制成员变量的操作,提高了代码的安全性
- 把代码用的方法进行封装,提高了代码的复用性
extends
使用格式
public class 子类名 extends 父类{}
继承中子类的特点
- 子类可以有父类的内容
- 子类还可以有自己特有的内容
继承中变量的访问特点(在子类方法中访问一个变量)
- 子类局部范围找
- 子类成员范围找
- 父类成员范围找
- 如果没有就报错(不考虑父亲的父亲…)
继承中构造方法的访问特点
子类中所有的构造方法默认都会访问父类中的无参的构造方法,这是为什么?
- 因为子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成数据的初始化
- 每一个子类构造方法的第一条语句默认都是:super()
如果父类中没有无参构造方法,只有带参构造方法,该这么办呢?
- 通过使用super关键字去显示调用父类的带参构造方法
- 在父类中自己提供一个无参构造方法(推荐自己给出无参构造方法)
继承中成员方法的访问特点
通过子类对象访问一个方法
- 子类成员范围找
- 父类成员范围找
- 如果没有就报错(不考虑父亲的父亲…)
java中继承的注意事项
- Java中类只支持单继承,不支持多继承
- Java中类支持多层继承
this
访问本类成员变量
this.成员变量
访问本类构造方法
this(...)
访问本类成员方法
this.成员方法(...)
super
访问父类成员变量
super.成员变量
访问父类构造方法
super(...)
访问父类成员方法
super.成员方法(...)
@Override(重写)
- 是一个注解
- 可以帮助我们检查重写方法声明的正确性
方法重写注意事项
- 私有方法不能被重写(父类私有成员子类是不能被继承的)
- 子类方法访问权限不能更低(public>默认>私有)
多态
多态中成员访问特点
- 成员变量:编译看左边,执行看左边
- 成员方法:编译看左边,执行看右边
为什么成员变量和成员方法的访问不一样?
- 因为成员方法有重写,而成员变量没有
多态的好处与弊端
- 多态的好处:提高了编程的扩展性(具体表现:定义方法的时候,使用父类型作为参数,将来在使用的时候,使用具体的子类型参与操作)
- 多态的弊端:不能使用子类的特有功能
多态中的转型
-
向上转型:从子到父,父类引用指向子类对象
fu a = new zi()
-
向下转型:从父到子,父类引用转为子类对象
zi b = (zi)a
抽象类(abstract)
抽象类的特点
-
抽象类和方法必须使用abstract关键字修饰
public abstract class 类名{} public abstract void eat()
-
抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
-
抽象类不能实例化
抽象类如何实例化呢?参照多态的方法,通过子类对象实例化,这叫抽象类多态
-
抽象类的子类
要么重写抽象类中的所有抽象方法 要么是抽象类
抽象类的成员特点
- 成员变量可以是变量,也可以是常量
- 可以有构造方法,但是不能实例化,构造方法的作用是用于子类访问父类数据的初始化
- 成员方法中的抽象方法可以限定子类必须完成某些动作,而那些非抽象方法是为了提高代码的复用性
接口
概念
接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用,而Java中的接口更多体现在对行为的抽象
接口的特点
-
接口关键字interface修饰
public interface 接口名 {}
-
类实现接口用implements表示
public class 类名 implements 接口名 {}
-
接口不能实例化
接口如何实例化呢?参照多态的方式,通过实现类对象实例化,这叫接口多态 多态的形式:具体类多态,抽象类多态,接口多态 多态的前提:有继承或者实现关系;有方法重写;有父(类/接口)引用指向(子/实现)类对象
-
接口的实现类
要么重写接口中的所有抽象方法 要么是抽象类
接口的成员特点
-
成员变量
只能是常量 默认修饰符:public static final
-
构造方法
接口没有构造方法,因为接口主要是对行为进行抽象的,是没有具体存在 一个类如果没有父类,就默认继承Object类
-
成员方法
只能是抽象方法 默认修饰符:public abstract
类和接口的关系
- 类和类的关系
- 继承关系,只能单继承,但是可以多层继承
- 类和接口的关系
- 实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
- 接口和接口的关系
- 继承关系,可以单继承,也可以多继承
抽象类和接口的区别
- 成员区别
- 抽象类:变量,常量,有构造方法,有抽象方法,也有非抽象方法
- 接口:常量,抽象方法
- 关系区别
- 类与类:继承,单继承
- 类与接口:实现,可以单实现,也可以多实现
- 接口与接口:继承,单继承,多继承
- 设计理念区别
- 抽象类:对类抽象,包括属性、行为
- 接口:对行为抽象,主要是行为
形参和返回值
类名作为形参和返回值
- 方法的形参是类名,其实需要的是该类的对象
- 方法的返回值是类名,其实返回的是该类的对象
抽象类名作为形参和返回值
- 方法的形参是抽象类名,其实需要的是该抽象类的子类对象
- 方法的返回值是抽象类名,其实返回的是抽象类的子类对象
接口名作为形参和返回值
- 方法的形参是接口名。其实需要的是该接口的实现类对象
- 方法的返回值是接口名,其实返回的是该接口的实现类对象
package
作用
本质就是文件夹,对类进行分类管理
包得定义格式
格式:package 包名;(多级包用.分开)
范例:package com.itheima;
带包得java类编译和执行
手动建包
-
按照以前的格式编译Java文件
javac HelloWorld.java
-
手动创建包
在E盘建立文件夹com,然后在com下建立文件夹itheima
-
把calss文件放到包的最里面
把HelloWorld.class文件放到com下的itheima这个文件夹下
-
带包执行
java com.itheima.HelloWorld
自动建包
javac -d. HelloWorld.java
导包的概述和使用
使用不同包下的类的时,使用的时候要写类的全路径,写的太麻烦了。为了简化带包的操作,Java就提供了导包的功能
导包格式
- 格式:import 包名
- 范例:import cn.itcast,Teacher
权限修饰符
修饰符 | 同一个类中 | 同一个包中子类无关类 | 不同包的子类 | 不同包的无关类 |
---|---|---|---|---|
private | √ | |||
默认 | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
final
final关键字时最终的意思,可以修饰成员方法,成员变量,类
final修饰的特点
- 修饰方法:表明该方法是最终方法,不能被重写
- 修饰变量:表明该变量时常量,不能被再次赋值
- 修饰类:表明该类是最终类,不能被继承
final修饰局部变量
- 变量是基本类型:final修饰指的是基本类型的数据值不能发生改变
- 变量是引用类型:final修饰指的是引用类型的地址值不能变,但是地址里面的内容是可以发生改变的
static
static关键字是静态的意思,可以修饰成员方法,成员变量
static修饰的特点
- 被类的所有对象共享(这也是我们判断是否使用静态关键字的条件)
- 可以通过类名调用(当然可以用对象名调用,推荐使用类名调用)
static访问特点
非静态的成员方法
- 能访问静态的成员变量
- 能访问非静态的成员变量
- 能访问静态的成员方法
- 能访问非静态的成员方法
静态的成员方法(总结成一句话就是:静态成员方法只能访问静态成员)
- 能访问静态的成员变量
- 能访问静态的成员方法
内部类
概念
就是在一个类中定义一个类。举例:在一个类A中定义一个类B,类B就被称为内部类
内部类的访问特点
- 内部类可以直接访问外部类的成员,包括私有
- 外部类要访问内部类的成员,必须创建对象
成员内部类
成员内部类,外界如何创建对象使用?
格式:外部类名.内部类名 对象名 = 外部类名对象.内部类对象;
范例:Outer.Inner oi = new Outer().new Inner();
局部内部类
概述:局部内部类是在方法中的定义的类,所以外界是无法直接使用,需要在方法内部创建对象并使用,该类可以直接访问外部类的成员,也可以访问内部的局部变量
匿名内部类
前提:存在一个类或接口,这里的类可以是具体类也可以是抽象类
格式:
new 类名或接口名 (){
重写方法;
};
范列:
new Inter(){
public void show(){
}
};
本质:是一个继承了该类或实现该接口的子类匿名对象
Math类
Math类的常用方法
方法名 | 说明 |
---|---|
public static int abs(int a) | 返回参数的绝对值 |
public static double ceil(double a) | 返回大于或等于参数的最double值,等于一个整数 |
public static double floor(double a) | 返回小于或等于参数的最大double值,等于一个整数 |
public static int round(float a) | 按照四舍五入返回最接近参数的int |
public static int max(int a,int b) | 返回两个int值中的较大值 |
public static int min(int a,int b) | 返回两个int值中的较小值 |
public static double pow(double a,double b) | 返回a的b次幂的值 |
public static double random() | 返回值为double的正值,[0.0,1.0) |
Object类
概述:Object是类层次结构的根,每个类都可以将Object作为超类。所有类都直接或间接的继承自该类
构造方法:
public Object()
为什么说子类的构造方法默认访问的是父类的无参构造方法?
以为它们的顶级父类只有无参构造方法
toString
方法名:public String toString()
作用:返回对象的字符串表示形式。结果应该是一个简明扼要的表达,容易让人阅读。建议所有子类覆盖此方法,自动生成。
equals()
方法名:public booleaan equlas(Object obj)
作用:比较对象是否相等。默认比较地址,重写方法可以比较内容,推荐重写,自动生成。
冒泡排序
- 如果有n个数据进行排序,总共需要比较n-1次
- 每一次比较完毕,下一次的比较就会少一个数据参与
Arrays类
Arrays类包含用于操作数组的各种方法
方法名 | 说明 |
---|---|
public static String toString(int[] a) | 返回指定数组的内容的字符串表示形式 |
public static void sort(int[] a) | 按照数字顺序排列指定数组 |
工具类的设计思想:
- 构造方法用private修饰
- 成员用public static修饰
基本类型包装类
概述:将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据
常用的操作之一:用于基本数据类型与字符串类型之间的转换
基本数据类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
Integer类
概述:Integer 包装一个对象中的原始数据类型int的值
方法名 | 说明 |
---|---|
public Integer(int value) | 根据int值创建个一integer对象(过时) |
public Integer(String s) | 根据String值创建Integer对象(过时) |
public static Integer valueOf(int i) | 返回表示指定的int值的integer实例 |
public static Integer valueOf(String s) | 返回一个保存指定值的Integer对象String |
int和String的相互转换
基本类型包装类的最常见操作就是:用于基本类型和字符串之间的相互转换
int转换为String
public static String valueOf(int i):返回int参数的字符串表示形式。该方法是String类中的方法
String转换为int
public static int parseInt(String s):将字符串解析为int类型。该方法是Integer类中的方法
自动装箱和拆箱
装箱:把基本数据类型转换为对应的包装类类型
拆箱:把包装类类型转换为对应的基本数据类型
Integer i = 100; //自动装箱
i += 200; //i = i + 200; i + 200 自动拆箱;i = i + 200;是自动装箱
注意:在使用包装类类型的时候,如果做操作,最好先判断是否为null,我们推荐的是,只要是对象,在使用前就必须进行不为null的判断
Date类
常用的方法
方法名 | 说明 |
---|---|
public long getTime() | 获取的是日期对象从1970年1月1日00:00:00到现在的毫秒 |
public void setTime(long time) | 设置时间,给的是毫秒值 |
SimpleDateFormat类
概述:SimpleFormat是个具体的类,用于以区域设置敏感的方式格式化和解析日期。
日期和时间格式由日期和时间模式字符串指定,在日期和时间模式字符串中,从‘A’到‘Z’以及从‘a’到’z’引号的字母被解释为表示日期或时间字符串的组件的模式字母
常用的模式字母及对应关系如下:
- y -年
- M-月
- d-日
- H-时
- m-分
- s-秒
方法名 | 说明 |
---|---|
public SimpleDateFormat() | 构造一个SimpleDateFormat,使用默认模式和日期格式 |
public SimpleDateFormat(String pattern) | 构造一个SimpleDateFormat使用给定的模式和默认的日期格式 |
SimpleDateFormat格式化和解析日期
格式化(从Date到String)
public final String format(Date date):将日期格式化成日期/时间字符串
解析(从String到Date)
public Date parse(String source):从给定字符串的开始解析文本以生成日期
Calendar类
概述:Calendar为某一时刻和一组日历字段之间的转换提供了一些方法,并为操作日历字段提供了一些方法
Calendar提供了一个类方法getInstance用于获取Calendar对象,其日历字段已使用当前日历和时间初始化:
Calendar rightNow = Calendar,gerInstance();
常用方法
方法名 | 说明 |
---|---|
public int get(int field) | 返回给定日历字段的值 |
public abstract void add(int field,int amount) | 根据日历的规矩,将指定的时间两添加或减去给定的日历字段 |
public final void set(int year,int mouth,int date) | 设置当前日历的年月日 |
异常
概述:就是成语出现了不正常的情况
异常体系:
Throwable
- Error
- Exception
- RuntimeException
- 非RuntimeException
Error:严重问题,不需要处理
Exception:称为异常类,他表示程序本身可能可以处理的问题
- RuntimeException:在编译是不检查的,出现问题后,需要我们回来修改代码
- 非RuntimeException:编译期就必须处理的,否则程序不能通过编译,就更不能zhengchangyunxing了
JVM的默认处理方案
如果程序出现了问题,我们没有做任何处理,最终JVM会做出默认的处理
- 把异常的名称,异常原因及异常出现的位置等信息输入在了控制台
- 程序停止执行
异常处理之 try…catch…
格式:
try{
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码;
}
执行流程:
程序从try里的代码开始执行,出现异常,会自动生成一个异常对象,该异常对象将被提交给java运行时系统,当java运行时系统接受到异常对象时,会到catch中找匹配的异常类,找到后进行异常的处理,执行完毕之后,程序该可以继续往下执行
Throwable的成员方法
方法名 | 说明 |
---|---|
public String getMessage() | 返回此throwable的详细消息字符串 |
public String toString() | 返回此可抛出的简短描述 |
public void printStackTrace() | 把异常的错误信息输出在控制台 |
编译时异常和运行时异常的区别
java中的异常被分为两大类:编译时异常和运行时异常,也被称为受检异常和非受检异常,所有的RuntimeException类及其子类被称为运行时异常,其他的异常都是编译时异常
- 编译时异常:必须显示处理,否则程序就会发生错误,无法通过编译
- 运行时异常:无需显示处理,也可以和编译时异常一样处理
异常处理之 throws
虽然我们通过try…catch…可以对异常进行处理,但是并不是所有的情况都有权限进行异常的处理,也就是说,有些情况可能出现的异常是我们处理不了的,这个时间该怎么办呢?针对这种情况,Java提供了throws的处理方案
格式:
throws 异常类名;
注意:这个格式是跟在方法的括号后面的
- 编译时异常必须要进行处理,两种处理方案:try…catch…或者throws,如果采用throws这种方案,将来谁调用谁处理
- 运行时异常可以不处理,出现问题后,需要我们回来修改代码
自定义异常
格式:
public class 异常类名 Exception{
无参构造方法
带参构造方法
}
范例:
pubilc class ScoreExecption extends Exception{
public ScoreException(){}
public ScoreException(String message){
super(message);
}
}
throws和throw的区别
throws | throw |
---|---|
用在方法声明后面,跟的是异常类名 | 用在方法体内,跟的是异常对象名 |
表示抛出异常,由该方法的调用者来处理 | 表示抛出异常,有方法体内的语句处理 |
表示出现异常的一种可能性,并不一定会发生这些异常 | 执行throw一定抛出了某种yi’chan |
哈希值
概述:
是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
Object类中有个方法可以获取对象的哈希值
- public int hashCode():返回对象的哈希值
对象的哈希值特点
- 同一个对象多次调用hashCode()方法返回的哈希值是相同的
- 默认情况下,不同对象的哈希值是不同的,重写hashCode()方法,可以实现让不同对象的哈希值相同
泛型
本质
是参数化类型,也就是说所操作的数据类型被指定为一个参数
泛型的定义格式:
- <类型>:指定一种类型的格式。这里的类型可以看成是型参
- <类型1,类型2…>:指定多种类型的格式,多种类型之间用逗号隔开。这里的类型可以看成 是形参
- 将来具体调用时候给定的类型可以看成是形参,并且实参的类型只能是引用数据类型
泛型的好处:
- 把运行时期的问题提前到了编译期间
- 避免了强制类型转换
泛型类
格式:
格式:修饰符 class 类名 <类型>{}
范例:public class Generic<T>{}
此处T可以随便写为任意的标识,常见的如T,E,K,V等形式的参数常用于表示泛型
泛型方法
定义格式:
格式:修饰符<类型>返回值类型 方法名(类名 变量名){}
范例:public <T> void show(T t){}
泛型接口
定义格式:
格式:修饰符 interface 接口名<类型>{}
范例:public interface Generic<T>{}
类型通配符
为了表示各种泛型List的父类,可以使用类型通配符
- 类型通配符:<?>
- List<?>:表示元素类型未知的List,它的元素可以匹配任何的类型
- 这种带通配符的List仅表示它是各种泛型List的父类,并不能把元素添加到其中
如果说我们不希望List<?>是任何泛型List的父类,只希望它代表某一类泛型List的父类,可以使用类型通配符的上限
- 类型通配符上限:<? extends 类型>
- List<? extends Number>:它表示的类型是Number或者其父类型
除了可以指定类型通配符的上限,我们也可以指定类型通配符的下限
- 类型通配符下限:<? super 类型>
- List<?super Number>:它表示的类型是Number或者其父类型
可变参数
概述:可变参数又称参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的了
格式:修饰符 返回值类型 方法名(数据类型……变量名){}
范例:public static int sum(int... a){}
可变参数注意事项:
- 这里的变量其实是一个数组
- 如果一个方法有多个参数,包含可变参数,可变参数要放在最后面
可变参数的使用:
Arrays工具类中有个静态方法:
public static <T> asList(T... a):返回由指定数组支持的固定大小的列表
返回的集合不能做增删操作,可以做修改操作
List接口中有一个静态方法:
public static <E>List<E> of(E... elements):返回包含任意数量元素的不可变列表
返回的集合不能做增删改操作
Set接口中有一个静态方法:
public static <E>Set<E> of(E...elements):返回一个包含任意数量元素的不可变集合
在给元素的时候,不能给重复元素
返回的集合不能做增删操作,没有修改的方法
File类
概述
File:它是文件和目录路径名的抽象表示
- 文件和目录是可以通过File封装成对象的
- 对于File而言,其封装的并不是一个正真存在的文件,仅仅是一个路径名而已,它可以是存在的,也可以是不存在的。将来是要通过具体操作把这个路径的内容转换为具体存在的
方法名 | 说明 |
---|---|
File(String pathname) | 通过将给定的路径名字符串转换为抽象路径名来创建新的File实例 |
File(String parent,String child) | 从父路径名字符串和子路径名字字符串创建新的File实例 |
File(File parent,String child) | 从父抽象路径名和子路径名字符串创建新的File实例 |
创建功能
方法名 | 说明 |
---|---|
public boolean createNewFile() | 当具有该名称的文件不存在时,创建一个由该抽象路径名命名的新空文件 |
public boolean mkdir() | 创建由此抽象路径名命名的目录 |
public boolean mkdirs() | 创建由此抽象路径命名的目录,包括任何必需但不存在的父目录 |
判断和获取功能
方法名 | 说名 |
---|---|
public boolean isDirectory() | 测试此抽象路径名表示的File是否为目录 |
public boolean isFile() | 测试此抽象路径名表示的File是否为文件 |
pubilc boolean exists() | 测试此抽象路径名表示的File是否存在 |
public String getAbsolutePath() | 返回此抽象路径名的绝对路径名字符串 |
public String getPath() | 将此抽象路径名转换为路径名字符串 |
public String getName() | 返回由此抽象路径名表示的文件或目录的名称 |
public String[] list() | 返回此路径名表示的目录中的文件和目录的名称字符串数组 |
public File[] listFiles() | 返回此抽象路径名表示的目录中文件和目录的File对象数组 |
File类删除功能
方法名 | 说明 |
---|---|
public boolean delete() | 删除由此抽象路径名表示的文件或目录 |
绝对路径和相对路径的区别
- 绝对路径:完整的路径名,不需要任何其他信息就可以定位它所表示的文件。例如:E://itcast//java.txt
- 相对路径:必须使用取自其他路径名的信息进行解释。例如:myFile//java.txt
删除目录时的注意事项:
- 如果一个目录中有内容(目录,文件),不能直接删除,应该先删除目录中的内容,最后才能删除目录
特殊操作流
标准输入输出流
System类中有两个静态的成员变量:
- public static final InputStream in:标准输入流。通常该流对应于键盘输入或主机环境或用户指定的另一个输入源
- public static final PrintStream out:标准输出流。通常该流对应于显示输出或由主机环境或用户指定的另个输出目标
自己实现键盘录入数据:
- BufferedReader br = new Bufferer(new InputStreamReader(System.in));
写起来太麻烦了,java就提供了一个类实现键盘录入
- Scanner sc = new Scanner(System.in);
输出语句的本质:是一个标准的输出流
- PrintStream ps = System.out;
- PrintStream类有的方法,System.out都可以使用
进程
概述:是正在运行的程序
- 是系统进行资源分配和调用的独立单位
- 每一个进程都有它自己的内存空间和系统资源
线程
概叙:
是进程中的单个顺序控制流,是一条执行路径
- 单线程:一个进程如果只有一条执行路径,则称为单线程程序
- 多线程:一个进程如果有多条执行路径,则称为多线程程序
多线程的实现方式
方法一:继承Thread类
- 定义一个类MyThread继承Thread类
- 在MyThread类中重写run()方法
- 创建MyThread类对象
- 启动线程
方法二:实现Runnable接口
- 定义一个类MyRunable实现Runnable接口
- 在MyRunnable类中重写run()方法
- 创建MyRunnable类的对象
- 创建Thread类的对象,把MyRunnable对象作为构造方法的参数
- 启动线程
多线程的实现方案有两种
- 继承Thread类
- 实现Runnable接口
相比继承Thread类,实现Runnable接口的好处
- 避免了Java单继承的局限性
- 适合多个相同程序的代码去处理同一个资源的情况,把线程和程序的代码、数据有效分离,较好的体现了面向对象的设计思想
两个小问题
-
为什么要重写run()方法?
因为run()用来封装被线程执行的代码
-
run()方法和statrt()方法的区别
run():封装线程执的代码,直接调用,相当于普通方法的调用
start():启动线程,然后由JVM调用此线程的run()方法
设置和获取线程名称
Thread类中设置和获取线程名称的方法
- void setName(String name):将此线程的名称更改为等于参数name
- String getName():返回此线程的名称
如何获取main()方法所在的线程的名称?
- public static Thread currentThread()返回对当前正在执行的线程对象的引用
线程调度
线程有两种调度模型
- 分时间模型:所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间片
- 抢占式调度模型:优先让优先级高的线程使用cpu,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的cpu时间片相对多一些
java使用的是抢占式调都模型
假如计算机只有一个CPU,那么CPU在某个时刻只能执行一条指令,线程只有得到CPU时间片,也就是使用权,才可以执行指令。所以说多线程程序的执行是有随机性,因为谁强到CPU的使用权是不一样的
Thread类中设置和获取线程优先级的方法
- public final int getPriority():返回此线程的优先级
- public final void setPriority(int newPriority):更改此线程的优先级
线程默认优先级是5;线程优先级的范围是:1-10
线程优先级高级仅仅表示获取的CPU时间片的几率高,但是要在次数比较多,或者多次运行的时候才能看到你想要的效果
线程控制
方法名 | 说明 |
---|---|
static void sleep(long millis) | 使当前正在执行的线程停留(暂停执行)指定的毫秒数 |
void join() | 等待这个线程死亡 |
void setDaemon(boolean on) | 将此线程标记为守护线程,当运行的线程都是守护线程时,Java虚拟机将退出 |
线程生命周期
要点:
- 由新建,就绪,运行或堵塞,死亡组成
- start()使线程具有执行资格
- 抢到CPU的线程具有执行权
- sleep()可以堵塞线程
数据安全问题
为什么出现问题?(这也就是判断多线程是否会出现数据安全问题的标准)
- 是否是多线程环境
- 是否有共享数据
- 是否有多条语句操作共享数据
同步代码块
锁定多条语句操作共享数据,可以使用同步代码块实现
-
格式:
synchronrized(任意对象){ 多条语句操作共享数据的代码 }
-
synchronized(任意对象):就相当于给代码加锁了,任意对象就可以看成是一把锁
同步的好处和弊端
- 好处:解决了多线程的数据安全问题
- 弊端:当线程很多时,因为每个线程都会去判断同步上锁,这是很耗费资源的,无形中会降低程序的运行效率
同步方法
同步方法:就是把synchronized关键字加到方法上
-
格式:
修饰符 synchronized 返回值类型 方法名(方法参数){}
同步方法的锁对象时什么呢?
- this
同步静态方法:就是把synchronized
-
格式:
修饰符 static synchronized 返回值类型 方法名(方法参数){}
同步静态方法的锁对象时什么呢?
- 类名.class
线程安全的类
StringBuffer
- 线程安全,可变的字符序列
- 从版本JDK5开始,被StringBuilder替代。通常应该使用StringBuilder类,因为它支持所有相同的操作,但它更快,因为它不执行同步
Vector
- 从Java2平台v1.2开始,该类改进了List接口,使其成为Java CollectionsFramework的成员,与新的集合实现不同,Vector被同步。如果不需要线程安全的实现,建议使用ArrayList代替Vertor
Hashtable
- 给类实现了一个哈希表,它将键映射到值。任何非null对象都可以用作键或者值
- 从java2平台v1.2开始,该类进行了改进,实现了Map接口,使其成为Java Collections Framework的成员。与新的集合实现不同,Hashtable被同步。如果不需要线程安全的实现,建议使用HashMap替代Hashtable
Look锁
虽然我们可以理解同步代码块和同步方法的锁对象问题,但是我们并没有直接看到哪里加了锁,在哪里释放了锁,为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock
Lock实现提供比使用synchronized方法和语句可以获得更广泛的锁定操作
Lock中提供了获得锁和释放锁的方法
- void lock():获得锁
- void unlock():释放锁
Lock是接口不能直接实例化,这里采用它的实现类ReentrantLock来实例化
ReentrantLock的构造方法
- ReentrantLock():创建一个ReentrantLock的实例
生产者消费者模式概述
为了体现生产和消费过程中的等待和唤醒,Java就提供了几个方法供我们使用,值几个方法在Object类中
Object类的等待和唤醒方法:
方法名 | 说明 |
---|---|
void wait() | 导致当前线程等待,直到另一个线程调用对象的notify()方法或者notifyAll()方法 |
void notify() | 唤醒正在等待对象监视器的单个线程 |
void notifyAll() | 唤醒正在等待对象监视器的所有线程 |