抽象
抽象类针对的是类
接口针对的是行为和方法
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。
父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。
在 Java 中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。
声明抽象方法会造成以下两个结果:
- 如果一个类包含抽象方法,那么该类必须是抽象类。
- 任何子类必须重写父类的抽象方法,或者声明自身为抽象类。
- 继承抽象方法的子类必须重写该方法。否则,该子类也必须声明为抽象类。最终,必须有子类实 现该抽象方法,否则,从最初的父类到最终的子类都不能用来实例化对象。
接口
接口是标准是规范
接口里的方法都是抽象方法
接口里面有:常量,抽象方法
接口无法实例化
接口可以多继承
一个实现类可以实现多个接口
接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。
除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。
接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。
接口与类相似点:
- 一个接口可以有多个方法。
- 接口文件保存在 .java 结尾的文件中,文件名使用接口名。
- 接口的字节码文件保存在 .class 结尾的文件中。
- 接口相应的字节码文件必须在与包名称相匹配的目录结构中。
接口与类的区别: - 接口不能用于实例化对象。
- 接口没有构造方法。
- 接口中所有的方法必须是抽象方法,Java 8 之后 接口中可以使用 default 关键字修饰的非抽象方法。
- 接口不能包含成员变量,除了 static 和 final 变量。
- 接口不是被类继承了,而是要被类实现。
- 接口支持多继承。
接口特性 - 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public
abstract,其他修饰符都会报错)。 - 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用
private 修饰会报编译错误)。 - 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。
抽象类和接口的区别
- 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
- 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
- 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
- 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
异常
要理解Java异常处理是如何工作的,你需要掌握以下三种类型的异常:
- 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
- 运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
- 错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
所有的异常类是从 java.lang.Exception 类继承的子类。
Exception 类是 Throwable 类的子类。除了Exception类外,Throwable还有一个子类Error 。
Java 程序通常不捕获错误。错误一般发生在严重故障时,它们在Java程序处理的范畴之外。
Error 用来指示运行时环境发生的错误。
例如,JVM 内存溢出。一般地,程序不会从错误中恢复。
异常类有两个主要的子类:IOException 类和 RuntimeException 类。
捕获异常
try{
// 程序代码
}catch(ExceptionName e1){
//Catch 块
}
多重捕获块
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}catch(异常类型3 异常的变量名3){
// 程序代码
}
throws/throw 关键字:
- 如果一个方法没有捕获到一个检查性异常,那么该方法必须使用 throws 关键字来声明。throws 关键字放在方法签名的尾部。
- 也可以使用 throw 关键字抛出一个异常,无论它是新实例化的还是刚捕获到的。
finally关键字
- finally 关键字用来创建在 try 代码块后面执行的代码块。
- 无论是否发生异常,finally 代码块中的代码总会被执行。
- 在 finally 代码块中,可以运行清理类型等收尾善后性质的语句。
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}finally{
// 程序代码
}
注意下面事项:
- catch 不能独立于 try 存在。
- 在 try/catch 后面添加 finally 块并非强制性要求的。
- try 代码后不能既没 catch 块也没 finally 块。
- try, catch, finally 块之间不能添加任何代码。
声明自定义异常
在 Java 中你可以自定义异常。编写自己的异常类时需要记住下面的几点。
- 所有异常都必须是 Throwable 的子类。
- 如果希望写一个检查性异常类,则需要继承 Exception 类。
- 如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。
class MyException extends Exception{
}
集合
ArrayList
ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。
ArrayList 继承了 AbstractList ,并实现了 List 接口。
- 添加元素: .add(“哈哈”);
- 访问元素: .get(0); // 访问第1个元素
- 修改元素: .set(0, “呵呵”); // 第一个参数为索引位置,第二个为要修改的值
- 删除元素: .remove(3); // 删除第四个元素
迭代数组列表:
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("1");
list.add("2");
list.add("3");
Iterator iterator = list.iterator();
while (iterator.hasNext()){
Object next = iterator.next();
System.out.println(next);
}
}
Java ArrayList 方法
Java ArrayList 常用方法列表如下:
- add() 将元素插入到指定位置的 arraylist 中
- addAll() 添加集合中的所有元素到 arraylist 中
- clear() 删除 arraylist 中的所有元素
- clone() 复制一份 arraylist
- contains() 判断元素是否在 arraylist
- get() 通过索引值获取 arraylist 中的元素
- indexOf() 返回 arraylist 中元素的索引值
- removeAll() 删除存在于指定集合中的 arraylist 里的所有元素
- remove() 删除 arraylist 里的单个元素
- size() 返回 arraylist 里元素数量
- isEmpty() 判断 arraylist 是否为空
- subList() 截取部分 arraylist 的元素
- set() 替换 arraylist 中指定索引的元素
- sort() 对 arraylist 元素进行排序
- toArray() 将 arraylist 转换为数组
- toString() 将 arraylist 转换为字符串
- ensureCapacity() 设置指定容量大小的 arraylist
- lastIndexOf() 返回指定元素在 arraylist 中最后一次出现的位置
- retainAll() 保留 arraylist 中在指定集合中也存在的那些元素
- containsAll() 查看 arraylist 是否包含指定集合中的所有元素
- trimToSize() 将 arraylist 中的容量调整为数组中的元素个数
- removeRange() 删除 arraylist 中指定索引之间存在的元素
- replaceAll() 将给定的操作内容替换掉数组中每一个元素
- removeIf() 删除所有满足特定条件的 arraylist 元素
- forEach() 遍历 arraylist 中每一个元素并执行特定操作
LinkedList
Java LinkedList(链表) 类似于 ArrayList,是一种常用的数据容器。
与 ArrayList 相比,LinkedList 的增加和删除的操作效率更高,而查找和修改的操作效率较低。
以下情况使用 ArrayList :
- 频繁访问列表中的某一个元素。
- 只需要在列表末尾进行添加和删除元素操作。
以下情况使用 LinkedList :
-
你需要通过循环迭代来访问列表中的某些元素。
-
需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。
常用方法:
- public boolean add(E e) 链表末尾添加元素,返回是否成功,成功为 true,失败为 false。
- public void add(int index, E element) 向指定位置插入元素。
- public boolean addAll(Collection c) 将一个集合的所有元素添加到链表后面,返回是否成功,成功为
true,失败为 false。 - public boolean addAll(int index, Collection
c) 将一个集合的所有元素添加到链表的指定位置后面,返回是否成功,成功为 true,失败为 false。 - public void addFirst(E e) 元素添加到头部。
- public void addLast(E e) 元素添加到尾部。
- public boolean offer(E e) 向链表末尾添加元素,返回是否成功,成功为 true,失败为 false。
- public boolean offerFirst(E e) 头部插入元素,返回是否成功,成功为 true,失败为 false。
- public boolean offerLast(E e) 尾部插入元素,返回是否成功,成功为 true,失败为 false。
- public void clear() 清空链表。
- public E removeFirst() 删除并返回第一个元素。
- public E removeLast() 删除并返回最后一个元素。
- public boolean remove(Object o) 删除某一元素,返回是否成功,成功为 true,失败为 false。
- public E remove(int index) 删除指定位置的元素。
- public E poll() 删除并返回第一个元素。
- public E remove() 删除并返回第一个元素。
- public boolean contains(Object o) 判断是否含有某一元素。
- public E get(int index) 返回指定位置的元素。
- public E getFirst() 返回第一个元素。
- public E getLast() 返回最后一个元素。
- public int indexOf(Object o) 查找指定元素从前往后第一次出现的索引。
- public int lastIndexOf(Object o) 查找指定元素最后一次出现的索引。
- public E peek() 返回第一个元素。
- public E element() 返回第一个元素。
- public E peekFirst() 返回头部元素。
- public E peekLast() 返回尾部元素。
- public E set(int index, E element) 设置指定位置的元素。
- public Object clone() 克隆该列表。
- public Iterator descendingIterator() 返回倒序迭代器。
- public int size() 返回链表元素个数。
- public ListIterator listIterator(int index) 返回从指定位置开始到末尾的迭代器。
- public Object[] toArray() 返回一个由链表元素组成的数组。
- public T[] toArray(T[] a) 返回一个由链表元素转换类型而成的数组。
HashSet
-
HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合。
-
HashSet 允许有 null 值。
-
HashSet 是无序的,即不会记录插入的顺序。
-
HashSet 不是线程安全的, 如果多个线程尝试同时修改 HashSet,则最终结果是不确定的。 您必须在多线程访问时显式同步对
HashSet 的并发访问。 -
HashSet 实现了 Set 接口。
操作:
- 添加元素:.add(“哈哈”); // 重复的元素不会被添加
- 判断元素是否存在: .contains(“哈哈”);
- 删除元素:.remove(“哈哈”); // 删除元素,删除成功返回 true,否则为 false
- 删除集合中所有元素可以使用 clear 方法:.clear();
- 计算大小: .size()
迭代 HashSet:
// 引入 HashSet 类
import java.util.HashSet;
public class RunoobTest {
public static void main(String[] args) {
HashSet<String> sites = new HashSet<String>();
sites.add("Google");
sites.add("Runoob");
sites.add("Taobao");
sites.add("Zhihu");
sites.add("Runoob"); // 重复的元素不会被添加
for (String i : sites) {
System.out.println(i);
}
}
}
HashMap
- HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
- HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为null,不支持线程同步。
- HashMap 是无序的,即不会记录插入的顺序。
- HashMap 继承于AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口。
操作:
- 添加元素:.put(1, “哈哈”);
- 访问元素: .get(1);
- 删除元素: .remove(1);
- 删除所有键值对(key-value)可以使用 clear 方法:.clear();
- 计算大小: .size();
迭代 HashMap:
// 引入 HashMap 类
import java.util.HashMap;
public class RunoobTest {
public static void main(String[] args) {
// 创建 HashMap 对象 Sites
HashMap<Integer, String> Sites = new HashMap<Integer, String>();
// 添加键值对
Sites.put(1, "哈哈");
Sites.put(2, "呵呵");
Sites.put(3, "呃呃");
Sites.put(4, "请求");
// 输出 key 和 value
for (Integer i : Sites.keySet()) {
System.out.println("key: " + i + " value: " + Sites.get(i));
}
// 返回所有 value 值
for(String value: Sites.values()) {
// 输出每一个value
System.out.print(value + ", ");
}
}
}
Java HashMap 方法:
- clear() 删除 hashMap 中的所有键/值对
- clone() 复制一份 hashMap
- isEmpty() 判断 hashMap 是否为空
- size() 计算 hashMap 中键/值对的数量
- put() 将键/值对添加到 hashMap 中
- putAll() 将所有键/值对添加到 hashMap 中
- putIfAbsent() 如果 hashMap 中不存在指定的键,则将指定的键/值对插入到 hashMap 中。
- remove() 删除 hashMap 中指定键 key 的映射关系
- containsKey() 检查 hashMap 中是否存在指定的 key 对应的映射关系。
- containsValue() 检查 hashMap 中是否存在指定的 value 对应的映射关系。
- replace() 替换 hashMap 中是指定的 key 对应的 value。
- replaceAll() 将 hashMap 中的所有映射关系替换成给定的函数所执行的结果。
- get() 获取指定 key 对应对 value
- getOrDefault() 获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值
- forEach() 对 hashMap 中的每个映射执行指定的操作。
- entrySet() 返回 hashMap 中所有映射项的集合集合视图。
- keySet() 返回 hashMap 中所有 key 组成的集合视图。
- values() 返回 hashMap 中存在的所有 value 值。
- merge() 添加键值对到 hashMap 中
- compute() 对 hashMap 中指定 key 的值进行重新计算
- computeIfAbsent() 对 hashMap 中指定 key 的值进行重新计算,如果不存在这个 key,则添加到 hasMap中
- computeIfPresent() 对 hashMap 中指定 key 的值进行重新计算,前提是该 key 存在于 hashMap 中。
泛型
Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
java 中泛型标记符:
- E - Element (在集合中使用,因为集合中存放的是元素)
- T - Type(Java 类)
- K - Key(键)
- V - Value(值)
- N - Number(数值类型)
- ? - 表示不确定的 java 类型