目录
- Java的一些特性:
- Java关键字:
- 1. assert:断言,一般用在测试类中。
- 2. enum:是一个特殊的类,一般用来表示一组常量。
- 3. instanceof:Java中的二元运算符,左边是对象右边是类。
- 4. finally:和try catch一起用。无论程序是否正确执行,finally块都会被执行到。
- 5. strictfp:FP-strict,精确浮点。用来声明类,方法,接口。在声明的域内浮点数运算完全按照IEEE-754标准进行运算。防止出现不同硬件平台运算结果不一致的问题。用的很少。
- 6. super:用super();方法在子类构造方法中调用父类构造方法。如果父类的method()方法被子类重写,用super.method();在子类使用父类的方法。
- 7. synchronized:
- 8. throw:用来在方法体中抛出异常,需要和throws连用。
- 9. throws:用来申明该方法可能抛出的所有异常,使用该方法时需要用trycatch捕获。
- 10. transient:一个和序列化有关的关键字。更多细节:[Java transient关键字](https://www.runoob.com/w3cnote/java-transient-keywords.html)
- 11. native: 允许Java 代码调用其它编程语言编写的代码
- 11. volatile :总结一下就是:不保证原子性,一定程度上保证有序性,保证可见性。
- 12. final关键字:
- Java常用工具类
- Java集合
- Java字典
Java的一些特性:
继承:
- 子类无法继承父类的static方法和变量。
- 子类可以继承父类的private成员变量,但是看不到。但是可以用父类提供的public方法改变这个成员变量。
- 父类被final修饰的类可以被继承,不能被重写,至于能不能被看到取决于private。
//使用这种方法创建的对象son,只能使用Father拥有的变量和方法。
Father son = new Son();
多态:
- 多态通过继承、接口来实现。
- 当使用多态方式调用方法时,在编译阶段检查父类中是否有该方法,如果没有,则编译错误;如果有,则编译通过,在运行阶段调用子类的同名方法。
重载:
- 重载的方法,名称和返回值一定要相同,传入的参数一定要不同。
重写:
- 子类对父类可以访问的方法进行重写
- 返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类(Java7之后的特性)
- final修饰的方法不能重写。static修饰的方法子类可以重新声明。
- 被子类重写的方法访问权限不能低于父类。
Java关键字:
abstract、assert、boolean、break、byte、case、catch、char、class、continue、default、do、double、else、enum、extends、final、finally、float、for、implements、import、int、interface、instanceof、long、native、new、package、private、protected、public、return、short、static、strictfp、super、switch、synchronized、this、throw、throws、transient、try、void、volatile、while
1. assert:断言,一般用在测试类中。
2. enum:是一个特殊的类,一般用来表示一组常量。
//很多项目中都有一个专门的类来声明项目中用到的所有常量,所以enmu用的不多。
enum Color { //也可以声明在Test类中
RED, GREEN, BLUE;
}
public class Test{
public static void main(String[] args){
Color c1 = Color.RED;
System.out.println(c1);
}
}
3. instanceof:Java中的二元运算符,左边是对象右边是类。
这个关键字可以理解成:a is an instance of B?只要返回真,a就可以强制转换成B。
Java编程规范要求,如果要使用向下转型,最好使用instanceof关键字判断能否进行转换。这对避免ClassCastException很有用。
更多细节:Java instanceof用法详解
//注1:null和任何类都是false
String s = "";
System.out.println(s instanceof String); //返回true
4. finally:和try catch一起用。无论程序是否正确执行,finally块都会被执行到。
- finally块中有return时,将会覆盖try和catch块中的return。
- 如果try或catch中有return,程序先将返回值存在某个地方,再执行finally,因此在finally中改变返回值没有用。
- 在try中加System.exit(0)或者在try之外的地方出现错误,都会使得程序直接结束,不会执行finally
5. strictfp:FP-strict,精确浮点。用来声明类,方法,接口。在声明的域内浮点数运算完全按照IEEE-754标准进行运算。防止出现不同硬件平台运算结果不一致的问题。用的很少。
6. super:用super();方法在子类构造方法中调用父类构造方法。如果父类的method()方法被子类重写,用super.method();在子类使用父类的方法。
7. synchronized:
8. throw:用来在方法体中抛出异常,需要和throws连用。
9. throws:用来申明该方法可能抛出的所有异常,使用该方法时需要用trycatch捕获。
/*
throws相当于将出现的异常抛给上级。在上级中可以对异常进行捕获,
也可以继续往更上级抛出异常,在合适的地方进行处理
*/
class Test {
void test01() throws IOException, InterruptedException {
//抛出异常
throw new IOException("this is an IOException");
}
}
//不处理异常,继续向上级抛出。
class Main1 {
public static void main(String[] args) throws IOException, InterruptedException {
Test test = new Test();
test.test01();
}
}
//使用trycatch处理异常。
class Main2 {
public static void main(String[] args) {
Test test = new Test();
try {
test.test01();
} catch (IOExcpetion e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
10. transient:一个和序列化有关的关键字。更多细节:Java transient关键字
- ArrayList源码中的array就使用transient修饰了,原因是ArrayList自己提供了更高效合适的序列化方法。可以减小序列化开销。参考:Why does ArrayList use transient storage?
11. native: 允许Java 代码调用其它编程语言编写的代码
一个相关的概念是JNI:Java Native Interface
11. volatile :总结一下就是:不保证原子性,一定程度上保证有序性,保证可见性。
- 可见性:一个线程修改了变量,其他线程能够立即看得到修改后的值。
- 有序性:程序执行的顺序按照代码的先后顺序执行
- 对变量的写操作不依赖变量当前值、也不依赖其他变量的值时可以使用。
- 可用于多线程中的状态标记量、线程安全的单例模式的双重检查锁中。
更多细节:Java并发编程:volatile关键字解析
12. final关键字:
- final修饰的基本数据类型变量一旦初始化就不能被修改。
- final修饰的引用数据类型变量一旦初始化就不能改变其指向的地址。
- final修饰的类不能被继承
- final修饰的方法可以被继承,但不能被子类修改
更多细节:浅析Java中的final关键字
final Object obj = new Object();
Object obj2 = new Object();
obj = new Object; //会报错。
obj = obj2; //也会报错。
Java常用工具类
Arrays
- binarySearch:二分查找
- compare(a, b):比较两数组字典序,正数代表a字典序>b字典序compareUnsigned是将数组元素处理成无符号数。
- copyOf、copyOfRange:复制数组
- deepToString:返回数组的“深度内容”。用于多维数组打印内容
public static void main(String[] args) {
int a[] = {1, 2, 3};
System.out.println(Arrays.toString(a)); //[1, 2, 3]
int b[][] = {{1, 2, 3}, {4, 5, 6}};
System.out.println(Arrays.toString(b)); //[[I@14ae5a5, [I@7f31245a]]
System.out.println(Arrays.deepToString(b)); //[[1, 2, 3], [4, 5, 6]]
}
- deepHashCode、deepEquals:同上,用于多维数组的比较和基于多维数组的“深度内容”生成哈希值。
- equals、hashCode:内容相等才等,基于内容生成哈希值。
- fill:将指定值赋给指定数组。
- misMatch:返回两数组第一个不匹配的值。若无,则返回-1。
- parallelPrefix:暂时还没研究明白。
- setAll:暂时还没研究明白。
- sort:使用的是Dual-Pivot Quicksort,即 使用两个元素来分割数组。通常比传统 (one-pivot) 快排算法要快。
- spliterator、stream:都没研究明白
- toString:返回数组内容。
String
String类提供了很多有用的方法,基本上能想到的都提供了
- charAt(i):返回第i个字符。
- codePointAt(i):返回第i个字符的unicode码
- compareTo:比较字典序。还有个忽略大小写的比较字典序
- concat:字符串拼接
- startWith、endsWith:判断是否以指定字符串(开头)结尾
- formate:将字符串格式化
- indent(n):调整行缩进
- indexOf、lastIndexOf:返回指定字符串第一次(最后一次)出现的位置
- isBlank:判断字符串中是否包含除空格外的其他值。
- matches:判断字符串是否与指定正则表达式匹配
- regionMatches,判断两字符串是否在给定区间内相等。
- repeat:返回该字符串重复拼接。
- replace:替换字符。
- split:分割字符串
- strip、trim、stripLeading、stripTrailing:去空格
- substring:返回子字符串
- toCharArray():string转char数组
- toLowerCase、toUpperCase:转换大小写。
- valueOf:将传入的参数转换成string
#异常的继承结构
Throwable:Error、Exception
Error:不可处理的错误。
Exception:RuntimeException、其它子类。
RuntimeException:运行时异常,编译阶段可以处理也可以不处理,如空指针异常、类转换异常等。
Exception的其它子类:编译时异常。在编译阶段必须进行处理,否则会报错。也就是说,在编写程序阶段必须对这种异常进行处理。
在自定义异常类时,可以根据需求继承Exception或者RuntimeException。
Java集合
类图
省略了很多抽象类。
ArrayList和LinkList
- ArrayList底层用数组实现,因此具有数组的一系列特征,增删效率低,根据下标查找元素效率高。。数组默认的初始长度为10,扩容算法大致如下:newLength = oldLength + Math.max(oldLength>>1, growLength)。
- LinkedList底层用双向链表实现,因此具有链表的一些特征,增删效率高,根据下标查找元素的效率低。数组默认初始长度为10。当查找第i个元素时,首先判断i在哪一边,然后选择从左边还是右边进行遍历。这样最多只需要遍历一半的节点。
- ArrayList和LinkedList都可以存储null,元素可重复,元素保持插入时的顺序
- ArrayList和LinkedList都是线程不安全的。
- 对LinkedList进行遍历时,因为普通的for循环通过下标查找元素,效率极低。可以使用增强的for循环或者迭代器。也可以用removeFirst和removeLast进行循环。
- 对ArrayList进行遍历时,由于实现了RandomAccess接口,所以支持快速随机访问。使用普通的for循环遍历效率较高。
线程安全的ArrayList
- Vector是ArrayList的一个替代类,Vector为每个方法都加了synchronized,因此并发性低。现在已经逐渐被淘汰了。
- Collections.synchronizedList这种方法在读写的时候都会加锁,不支持多个线程并发读和一个线程写多个线程读,因此并发度也较低。synchronizedList是一个fail-fast iterator,在进行迭代时需要放在synchronized块中。
List list = Collections.synchronizedList(new ArrayList());
synchronized (list) {
Iterator i = list.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
- CopyOnWriteArrayList在读的时候不加锁,仅在写入的时候加锁,但是由于写的操作需要复制数组,因此多使用在数组不怎么被修改的情况下。CopyOnWriteArrayList时fail-safe iterator,可以直接进行迭代,将代码放在synchronized块中。更多细节:为什么线程安全的List推荐使用CopyOnWriteArrayList,而不是Vector
- CopyOnWriteArrayList保证线程安全的主要手段:1)array被volatile修饰,保证了array的可见性。2)在新版本中不再用ReentrantLock修饰lock,而是在需要加锁的地方用synchronized(lock)获得锁。保证了线程安全。以下是将元素添加到数组末尾的源码。
public boolean add(E e) {
synchronized (lock) { //获得锁
Object[] es = getArray();
int len = es.length;
es = Arrays.copyOf(es, len + 1); //对数组进行扩容
es[len] = e;
setArray(es); //将地址指向扩容后的数组
return true;
}
}