- Java SE 容易忘记的点记录
- 1. 访问权限
- public
- default
- protected
- public
- 2. 一维数组
- 三种初始化方式
- 内容
- 数组的遍历
- 二维数组
- 初始化
- 遍历
- java 三大特征:继承、封装、多态
- 内部类
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类
- 枚举类
- 异常
- 范型
- 二叉树
- 容器
- 继承关系图
- List
- Set
- Map
| 关键字 | private | default | protected | public |
|---|---|---|---|---|
| 同一类 | √ | √ | √ | √ |
| 同一包中的类 | ✕ | √ | √ | √ |
| 子类 | ✕ | ✕ | √ | √ |
| 其他包中的类 | ✕ | ✕ | ✕ | √ |
一个成员对象会在哪些地方被访问呢,首先是自己类的方法、代码块等地方,这时候无论什么权限都是可以进行访问的。
其次就是其他类中,通过成员对象所在类的实例进行访问,这时其他类相较于所在类就会出现两种情况,一个是在同一个包内,一个是不在同一个包内,这时只有private关键字对这种情况进行区分,不在同一个包内是无法访问private关键字修饰的成员变量的。
最后就是当这个类被继承后,子类是否能访问该成员变量,使用protected进行约束,public和protected是可以访问的,而default和private是无法访问的。
方法的权限控制与方法是相同的。
而类的权限控制只有public和default两种,内部类除外,内部类四种都是可以进行设置的。
public使用public进行权限修饰的时候是在任何地方都可以访问的
default使用default时只能在同一包下进行访问,同一包下的另一个类继承这个类时,也是无法直接使用这个变量或者方法的,这个时候是按照子类的权限进行判断的,而同一包下这个含义指的是能否通过实例直接通过.进行访问。
protected相比于default多了子类可以访问,就是子类继承之后可以直接使用这个变量
public对比protected多了包外访问的权限。
2. 一维数组 三种初始化方式int[] list = new int[10];
int[] list1 = {1,2,3};
int[] list2 = new int[]{1,2,3};
内容
数组是一个类,拥有Object中的所有方法,都是可以使用的,并且含有成员变量length,并且length时final的,在初始化时会为length赋值,因此组数在初始化之后时定长的,长度无法改变。可以创建一个需要的长度的数组重新赋值给这个引用。
int[] list = new int[10]; // ... list = new int[20];数组的遍历
有两种方法,其实就是两种for循环
for(int i = 0;i < list.length; i++){
list[i] // ...
}
for(int i : list){
i // ...
}
第二种称为foreach,foreach的存在是有优势,但同样是存在劣势的,当你的for循环中指进行读取操作的时候,foreach简洁的风格,简易的代码是很好用的。但是foreach中无法对数组中的值进行修改,需要修改的时候需要使用第一种循环哦。
二维数组 初始化int[][] ll = new int[3][];
int[][] ll1 = {{1,2}};
int[][] ll2 = new int[][]{{1,2},{2,2,2,2,2}};
初始化和一维数组类似,可以直接用一个已经确定的二维数组进行赋值,也可以直接new,但是第二种方法和一维数组一样,只能在初始化时进行使用。
遍历其实就是两层的遍历,第一层得到的是一个int[]类型的,第二层是int的
for (int[] i : ll) {
for (int j : i) {
// 操作
}
}
java 三大特征:继承、封装、多态
多态中需要注意instanceof、final类
内部类存在在一个类里面的类就叫内部类,根据所处位置的不同、约束的不同,给内部类又取了不同的名字
成员内部类public class Test {
class Inner{ //类中定义的一个内部类
}
}
public static void main(String[] args) {
Test test = new Test();
Test.Inner inner = test.new Inner(); //写法有那么一丝怪异,但是没毛病!
}
静态内部类
public class Test {
static class Inner{
}
}
public static void main(String[] args) {
Test.Inner inner = new Test.Inner(); //不用再创建外部类对象了!
}
静态内部类并不是创建了一个类大家共用,而是可以直接用类名进行new
局部内部类public class Test {
public void test(){
class Inner{
}
Inner inner = new Inner();
}
}
匿名内部类
public static void main(String[] args) {
Eat eat = new Eat() {
@Override
public void eat() {
//DO something...
}
};
}
枚举类
本质上还是一个普通类,编译器做了优化,可以像正常类一样写对象、方法等,但是第一行需要输入的内容是枚举类的类别,即使一个状态都不存在也需要输入一个分号。
在枚举类第一行中声明的状态在编辑之后都会得到当前类的一个静态常量,并且使用的时候其实也是一个对象。
若枚举类的默认构造器被覆盖,则在第一行创建状态的时候需要用括号调用新的构造器。
并且Enum自带了一些方法,其中valueof用于将字符串转化为状态,values为返回所有状态的一个集合。
异常分为 编译时异常Exception 和 运行时异常RuntimeException
其中 Exception必须要求在编写代码期间通过try-catch进行捕获,可以是对异常进行处理,也可以再一次抛出,我觉得这里是否抛出throw的逻辑是,当前在写的方法是提供给他人调用的,还是该方法已经到处理实际逻辑阶段了,若是对可能发生异常方法的一层封装,那么抛出可能是比较合理的操作,由上层的调用者对异常进行合适的处理,而到实际逻辑处理阶段直接进行处理是比较合理的,否则可能会引起程序的中断运行。
Runtime Exception是可以不进行捕获的,但是一些常见的数组越界、除数为0等需要在编程的时候注意。
对于的异常的捕获try-catch,最重要的其实是保证程序的正常运行。
try-catch-finally的运行顺序是:首先运行try,若发生异常则运行catch,无论是否发生异常最后会运行finally,即使在try中已经return,同样会调用finally中程序。
当jdk提供的异常不够用时,我们可以自定义异常,一般定义的都是Exception,继承Exception类就可以,记得重写相应的构造方法哦!
范型范型本质上并不是JVM支持的语法,而是一种语法糖,在编译期间帮助你检查参数类型是否正确的一种手段,并且在编译中会进行类型擦除,实际在字节码文件中是不存在范型的。
一般需要使用范型地方是一个地方可能使用两种及以上类型的时候会使用范型,例如容器,在编写容器代码的时候并没有针对某一种类型进行来写代码,并且在使用时可以向容器中放入使用者所要求的类型的对象,这就是范型的作用。
二叉树是一种搜索树,顾名思义是用于搜索用的,所有二叉树有别于树,树是不带有左右之分的,但是二叉树因为是用于搜索,所以进行了左右的区分。
为什么要用二叉树进行搜索呢?主要是因为线性结构存在弊端,线性表在有序的情况下可以通过二分查找的方式进行搜索,但是在维护有序是的代价太够,插入和删除并不是线性表所擅长的,而链表则呈现了完全相反的特点,插入和删除十分的方便但是搜索只能进行线性的搜索,是在不够优秀。
由此就想到了树的结构进行存储与搜索,其实二分查找本质上就是一个平衡二叉树,不过这个查找与搜索的工作是在线性表中完成的。
二叉树的特点是每一层只比较一次,因此二叉树的时间复杂度与深度相关,普通二叉树可能会遇到插入时是线性的情况下,导致整树趋向于线性的存在,横向的空间没有充分利用。
因此提出了平衡二叉树,平衡二叉树要求每一个节点的左右子树高度差小于等于1,这个要求带来的好处是搜索非常迅速,横向空间充分利用,但随之而来的缺点就是插入和删除子节点的时候,需要进行大量的调整才能使得二叉树平衡。
在这种条件下就提出了红黑树
上图是红黑树调整的情况,根据红黑树的限制,黑节电是多于红节点的,并且插入时新节点为红节点,只有父节点是红色时才会进行平衡操作,所以在红黑树中调整操作是得以减少的。并且性能与平衡二叉树是类似的,所以很多地方都会选择红黑树而不是平衡。
集合类最顶层不是抽象类而是接口,因为接口代表的是某个功能,而抽象类是已经快要成形的类型,不同的集合类的底层实现是不相同的,同时一个集合类可能会同时具有两种及以上功能(既能做队列也能做列表),所以采用接口会更加合适,接口只需定义支持的功能即可。
继承关系图
图中展示了容器之间的一个继承关系,下面介绍一下总结结构,collection接口使用了iterable接口,这个接口的主要作用是实现了for-each循环以及迭代器的功能,list与set是具有迭代器的,但是map是没有实现这个方法的。
一般在使用的时候List
collection接口表示的是集合,其中List表示可重复集合,而Set表示的是不可重复集合,其中常用的List有ArrayList、LinkedList,其中LinkedList实现类Queue接口,可以当作队列进行使用。常用的Set有HashSet、TreeSet,并且Set底层是通过Map实现的。相同的Map中提供的实现与Set类似,是TreeMap、HashMap
咱这次先不讲具体某一个方法的实现原理,先介绍一下三个接口具体有哪些方法。
List| 编号 | 方法 | 作用 |
|---|---|---|
| 1 | int size() | 返回集合中的元素数量 |
| 2 | boolean isEmpty() | 判断集合是否为空 |
| 3 | boolean contains(Object o) | 集合中是否包含某一个元素 |
| 4 | Object[] toArray() | 返回由集合中所有的元素组成的新创建的数组 |
| 5 | T[] toArray(T[] a) | 将集合中的元素按照指定类型构造新的集合后返回 |
| 6 | boolean add(E e) | 添加元素 |
| 7 | boolean remove(Object o) | 移除指定元素 |
| 8 | boolean containsAll(Collection> c) | 如果此列表包含指定集合的所有元素,返回true |
| 9 | boolean addAll(Collection extends E> c) | 向集合中添加给定集合中的所有元素 |
| 10 | boolean removeAll(Collection> c) | 从此列表中删除包含在指定集合中的所有元素 |
| 11 | boolean removeIf(Predicate super E> filter) | 删除此集合中满足给定谓词的所有元素 |
| 12 | boolean retainAll(Collection> c) | 从这个列表中删除所有不包含在指定集合中的元素 |
| 13 | void clear() | 清除所有元素 |
| 14 | Stream stream() | 返回以此集合为源的顺序流 |
| 15 | List subList(int fromIndex, int toIndex) | 返回此列表在指定 fromIndex(包括)和 toIndex(不包括)之间部分的视图 |
| 16 | boolean addAll(int index, Collection extends E> c) | 将指定集合中的所有元素插入到指定位置 |
| 17 | void replaceAll(UnaryOperator operator) | 将此列表的每个元素替换为将运算符应用于该元素的结果 |
| 18 | void sort(Comparator super E> c) | 对集合中的元素进行排序 |
| 19 | E get(int index) | 获取指定位置的元素 |
| 20 | void add(int index, E element) | 在指定位置插入元素 |
| 21 | E remove(int index) | 移除指定位置的元素 |
| 22 | int indexOf(Object o) | 返回给定元素的位置 |
| 23 | int lastIndexOf(Object o) | 返回给定元素最后一次出现的位置索引 |
| 24 | ListIterator listIterator() | 迭代器 |
| 25 | ListIterator listIterator(int index) | 从给定位置开始的迭代器 |
| 26 | E set(int index, E element) | 设置置顶位置的元素 |



