Java基础
面向对象的语言
三大特点?
- 封装
- 继承
- 多态:重写重载、接口抽象类
与C++差别?
- 解释型语言:编译为字节码文件在jvm上运行所以跨平台、速度慢些
- 单继承、多实现
- 没有指针
- jvm提供垃圾收集
权限修饰符
public | protected | default | private | |
---|---|---|---|---|
本类 | 1 | 1 | 1 | 1 |
本包 | 1 | 1 | 1 | |
子类 | 1 | 1 | ||
通用 | 1 |
基本数据类型
原码、反码、补码(负数:除符号位外取反加1)
- boolean
- byte 范围-128~127
- char 2字节,2的16次方字符
- short 2字节,-2^15~2^15-1
- int 4字节
- float 4字节
- long 8字节
- double 8字节
基本数据类型都有对应的包装器类型,有自动装箱拆箱:自动装箱Integer I=4(=Integer.valueOf(4));自动拆箱int i=I(=I.intValue())
String:引用类型
- 内部是private final char[];不可变(1. 为了实现字符串池,节省空间;2. 不可变使得不能修改,保证安全)
速度:StringBuilder变量>StringBuffer变量(线程安全(synchronized修饰方法))>String常量(对其+操作内部是用StringBuilder的append()方法;intern()获取字符串池中引用)
四种引用类型
为了让coder通过代码实现对象生命周期的控制、方便垃圾回收:
- 强引用:只要强引用关系还存在(可达)就永远不会被垃圾回收,JVM宁愿跑出OOM错误也不会回收,想中断显示的将引用赋值为null
- 软引用:如果一个对象具有软引用,内存空间足够时垃圾回收器就不会回收它,内存空间不足就会回收这些对象的内存,用法A a=new A();SoftReference b=new SoftReference(a); a=null;A anothera=(A)b.get();
- 弱引用:描述非必须对象,当JVM进行垃圾回收时,无论内存是否充足都会回收,WeakReference<A> refer=new WeakReference<A>(new A());A a=refer.get(); 必须只有弱引用与其关联,若A a=new A();WeakReference<A> refer=new WeakReference<A>(a)则不行;
- 虚引用:并不影响对象的生命周期PhantomReference,必须和引用队列ReferenceQueue关联使用
Object类
- hashcode() 通常通过对象的地址值计算出
- equals() 判断两个对象是否相等,业务上判断相等重写时必须重写hashcode()方法(1、约定两个对象相等其hashcode值一定相等;2、hashmap等用hashcode与容量异或算求数组下标不重写会引起错误)
- clone() 实现对象的复制,使用时对象类必须实现cloneable接口重写clone方法,浅复制和深复制区别在于深拷贝除了复制基本数据类型的成员变量值外,还为引用类型的成员变量创建新实例
- tostring()
- notify()、notifyAll()、wait()(和sleep区别:1、object thread、2、释放锁、3、同步代码块中)
- finalize() 方法在对象被回收前调用,完成最后的处理。只保证调用,不保证执行结束,所以自我救赎不一定成功,不怎么使用
集合容器
java容器可以分为三类:
- List 线性表,维持了插入的顺序
ArrayList 底层数组,加了动态扩容;
查询:下标查快,查给定数遍历
插入:插入越靠前,数组移动越多效率越低,删除类似
LinkedList 底层双向链表
查询:位置查,查越中间的数效率越低(选取首尾指针近的一端),查给定数,遍历
插入:首尾O1,插固定位置同样越靠近中间越慢(选首尾指针近的一个遍历到位置),删除类似
同时LinkedList实现了queue和deque,可做栈((建议ArrayDeque)pop push)、队列、双端队列
接口 1、queue:offer入列poll出列 peek取首; 2、deque:queue的子接口,offerFirst pollFirst offerLast pollLast)
- Set 没有重复元素,不维持插入顺序,可以存在空值
TreeSet 底层红黑树(5特性 变色左右旋转维持(左旋:变成自己右孩子的左孩子,右旋:变成自己左孩子的右孩子;左左右旋,右有左旋,左右左旋右旋,右左右旋左旋 )),给元素排序
- Map 键值对的集合,存取速度快
HashMap结构:数组+链表->数组+链表(长度大于阈值(默认为8)时转为红黑树,减小到6转回链表)(哈希冲突解决方案:链地址法、开放寻址法)
put、get的时间复杂度:理想状态没有冲突O1,链表On,红黑树Ologn
扩容:初始大小16 默认负载因子0.75,个数大于length*负载因子,创建一个两倍大小的数组,重新计算各个元素位置(新table大小即为2的N+1次方,则其中元素的table索引为其hash值的后N+1位确定,比原来多了一位,扩容后下标的结果,要不然就和旧的相同,要不然就是新下标等于旧下标加上旧数组的长度)
为何2的次方:用key的hashcode值,然后跟数组的长度-1做一次“与”运算(&)求在数组中位置。当数组长度为2的n次幂的时候,不同的key算得得index相同的几率较小,那么数据在数组上分布就比较均匀,也就是说碰撞的几率小。为什么不安全:1、put的时候导致的多线程数据不一致:A读取桶位置,B读取桶位置,插入,A再插入,覆盖了B的插入。2、扩容时,两个线程同时执行resize,A读取到链表元素,Bresize完,A插入之前赌气读取的和下一个,下一个指向当前,形成环形链表,陷入死循环。
变安全:用hashtable、concurrenthashmap外:用Collections类的synchronizedMap方法包装一下。方法如下:public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) 返回由指定映射支持的线程安全的映射(和hashtable一样锁住整个map)。ConcurrentHashMap
1.7 分段锁技术:由Segment数组结构和HashEntry数组结构组成。Segment是一种可重入锁ReentrantLock,在ConcurrentHashMap里扮演锁的角色,HashEntry则用于存储键值对数据。
1.8 cas乐观锁+synchronized锁
首先cas尝试获取桶的首节点,失败则轮询直到获取,成功后synchronized只锁定当前链表或红黑二叉树的首节点。
Comparable和Comparator
- 自定义要比较的实体类,实现comparable接口,重写compareto方法(传入要比较的对象和当前对象比较),return 1/-1/0
- 不修改实体类(策略模式),通过定义比较器类实现comparator接口,重写compare方法(传入要比较的两个对象)
对于排序有Arrays.sort()和Collections.sort() (sort(实现了comparable接口的集合)或sort(集合,new comparator<t>{})
序列化
java序列化是指将java对象转化为字节序列的过程
使用场景
1. 永久性保存对象,保存对象的字节序列到本地文件或者数据库中
2. 通过序列化以字节流的形式使对象在网络中传递和接收
3. 通过序列化在进程间传递对象
Java的序列化机制
1. 使用Serializable接口实现序列化(重点)
要序列化的实体类继承接口,创建输出流对象,将实体类作为参数传递给输出流对象调用的方法,写入文件。
2. 使用Externalizable接口实现序列化:继承自Serializable接口,需要重写writeExternal()read。。()方法,必须提供public的无参的构造器
深入:serialversionUID,用于序列化对象版本控制;
静态变量不会被序列化,流中不会写入静态变量;
Transient关键字作用:在变量前加上该关键字,可以组织该变量被序列化到文件中,被反序列化后,int变为0,对象型变为null
异常机制
所有异常对象都派生于Throwable类;
1. Error类:Java内部错误,表示jvm出错或者内存不足
2. Exception类:
- RuntimeException:运行时异常(数组下标越界、访问空指针、除数为0)
- CheckedException(必须捕获)IOException,sqlexception
另外一种分类方式
- 非受检异常:Error和RuntimeException
- 受检查异常IOException,sqlexception (处理方式:1、抛出,方法throws 任意throw 2、捕获:try catch finally
IO
基础的输入输出流InputStream、OutputStream
文件流FileInputStream FileOutputStream 按字节处理
流过滤器如DataOutputStream out=new DataOutputStream(new BufferOutputStream(new FileOutputStream("path")))用以读写二进制形式的基本数据类型
在流上建立文本处理 PrintWriter out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(“filepath”))))
BufferedReader readLine()
泛型
为解决集合容器存储内容时,不限制容器内容的类型的话,取用时不知道类型需要强制转换,会出错:ArrayList<E>
- 泛型类,public class MyObject<T>{T t;setT(任意类型的t)}
- 泛型方法,public <T> void show(T t){}
- 通配符?public void test(List<?> list){},此时不能调与类型有关的方法如list.add();多数可以用泛型代替public <T> void test(List<T> list){};通配符上限List<?extends Number>
应用:一般在写DAO时,进行抽象
注解
传统方式用xml配置,现在可以用注解告诉类如何运行
- 基本Annotation:@Override、@Deprecated、@SuppressWarnings...
- 自定义注解:带成员变量的叫元数据Annotation
注解的原理:反射;反射出该类方法、通过方法获得注解上的具体信息、将信息注入到方法上
必须使用@Retention(RetentionPolicy.RUNTIME)
java8新特性
- lambda表达式 (parameters)->expression或者 (parameters)->{statements;} 左侧为参数,可有多个;右侧为方法内容也可以直接是方法的返回值;实际就是匿名函数。 为此出现定义:java中只有一个抽象方法的接口叫功能接口或函数式接口,如Runnable接口,为lambda表达式而生,可用注解@FunctionalInterface标注
- stream流 可以方便的处理集合数据,包括filter()、map()、sorted()、forEach()等操作stream()为集合创建串行流,parallelStream()为集合创建并行流
java11新特性
- 局部变量推断(必须创建时就赋值var)
- 集合加强(Listof用来创建的api,但是不能添加元素了)