JAVA基础

  1. 抽象,封装,继承,多态
  2. 深拷贝:对象A中有对象B的引用,浅拷贝A对象,会将对象A的值赋给对象C,且还是B的引用;深拷贝A对象,会将A对象的值赋给对象C,且将对象B的值赋值给对象D,此时C中就是D的引用而不是B的引用。实现方法:
    1. 构造函数
    2. 重载clone()方法
    3. 序列化
  3. 强引用,软引用,弱引用,虚引用
    1. 强引用:new出来的对象,只要引用存在就不会被垃圾回收
    2. 软引用:内存不足时回收,基于SoftReference创建:
      SoftReference<String> softReference = new SoftReference<String>("abc");
    3. 弱引用:每次执行垃圾回收算法,发现只存在软引用的对象就清除,基于WeakReference创建:
      WeakReference<String> weakReference = new WeakReference<String>("abc");
    4. 虚引用:虚引用不会决定对象的生命周期,如果一个对象仅持有需虚引用,则他任何时候都可能被垃圾回收,且不能通过虚引用去获得对象。虚引用的唯一目的就是,执行gc时能收到一个系统通知。基于PhantomReference实现,且必须和引用队列ReferenceQueue联用。
      ReferenceQueue<String> queue = new ReferenceQueue<String>();
      PhantomReference<String> pr = new PhantomReference<String>("abc", queue);
      
  4. 设计模式
    1. 六大原则:
      1. 开闭原则:对扩展开发,对修改关闭
      2. 里氏替换原则:子类可以替换父类
      3. 依赖倒装原则:多使用接口
      4. 接口隔离原则:使用多个隔离的接口,比使用单个接口要好
      5. 迪米特法则,最少知道原则:一个实体应当尽量少地与其他实体之间发生相互作用,模块化
      6. 合成复用原则:尽量使用合成/聚合的方式,而不是使用继承
    2. 单例模式(Singleton):最简单的设计模式之一,一个类只有唯一一个类供其他对象使用。基本方式为,其构造函数私有化,定义这个类的私有静态对象,通过方法调用这个静态对象
      1. 懒汉模式:对象延迟加载,申明对象后不实例化,调用方法的时候再实例化,线程不安全
        public class Single {
            private static Single single = null;//静态私用成员,没有初始化
            private Single(){}
            public static synchronized Single getsingle(){
                if(single == null){
                    single = new Single();
                }
                return single;
            }
        }
      2. 饿汉模式:对象预先加载,申明对象的同时就实例化,线程安全
        public class Single {
            private static Single single = new Single();
            private Single(){}
            public static Single getsingle(){
                return single;
            }
        }
    3. 工厂模式(简单工厂模式)(Factory):一种创建对象的模式,使用一个专门的类(工厂类)来实现实例化的过程
      1. 基本方式是:
        1. 创建一个接口
        2. 定义多个此接口的实现类
        3. 创捷工厂类,此工厂类会根据用户的需求创建对应的实现类的对象。
      2. 抽象工厂模式:使用一个专门的类(抽象工厂类)来实现工厂实例化的过程,此工厂能实现多个产品的实例化,每个产品也是一个工厂。
        1. 实现过程:
          1. 创建多个工厂
          2. 创建包含多个工厂实例化的抽象类
          3. 定义多个抽象类的子类,实现具体工厂的实现方法
          4. 创建一个工厂类,使用户更加需求,选择不同的工厂
    4. 适配器模式(Adapter):为两个不相融的接口提供桥梁,一种结构形模式。实现过程:在一个接口A的实现类A1中定义另一个接口B实现类的对象,再使用这个A的另一个实现类A2调用类实现类A1。用户只需调用A2就可以使用两个接口的内容。
    5. 装饰器模式(Decorator):向一个现有的对象添加功能,一种结构形模式。实现过程:创建抽象类,调用需要扩展功能的类的
    6. 代理模式(Proxy):用一个类代表另外一个类的功能,一种构造形模式。实现过程:创建一个接口,创建多个他的实现类,调用的时候根据情况调用他的实现类
    7. 观察者模式(Observer):一对多关系,当一个对象被修改会通知其他依赖他的对象
    8. 策略模式(Strategy):一个类的行为或其算法可以在运行时更改
  5. 集合(Collection, Map):
    1. Collection:
      1. List(有序,有索引,元素可重复):
        1. ArrayList:线程不安全,支持序列化,底层是数组,能够动态扩容(将数组复制到一个1.5倍长的新数组中,初始默认长为10)
        2. LinkedList:底层是双向链表,线程不安全,支持栈和队列
        3. Vector:线程安全(synchronized),动态扩容的长度是2倍。
        4. CopyOnWriteArrayList:线程安全(synchronized修饰代码块,读取不加锁),修改添加,将原数组拷贝,再拷贝后的数组进行修改,修改后替换原数组,这个阶段加锁。
      2. Set(无序,无索引,元素不可重复):
        1. HashSet:底层是HashMap,将需要存放的元素作为HashMap里面的键,所有HashMap的值是一个静态的Object类的对象。
          1. LinkedHashSet:HashSet的之类,底层是LinkedHashMap,与HashSet的最大区别就是记录了插入顺序(不能根据下标获取,能保证迭代输出的顺序)
        2. TreeSet:底层是TreeMap,存储与HashSet类似
    2. Map:
      1. HashMap:
        1. 键可以是null,值也可以是null,如果键是null,则他对应的hashCode为0,计算hashCode要用native关键字,调用本地方法接口。
        2. JDK1.8之前,HashMap采用位桶+链表存储数据,而JDK1.8时,HashMap采用数组+链表+红黑树实现,当链表长度超过阈值8时,将链表转换为红黑树。少于6时转换为链表。
        3. HashMap默认初始容量为16,负载因子为0.75(负载因子越大,发生碰撞的概率就越大,时间复杂度就越高),当元素数量大小 > 初始容量 * 负载因子,HashMap就会进行扩容。容量上限为2^30。
        4. 扩容时,创建一个新的对象数组,大小为原来的两倍,将之前元素放到新的数组中去,不要重新计算hash值,只需通过hash值响应最高位(16 -> 32, 最高位为第5位)的是0,还是1去判断,元素是在原位置,还是在原位置加之前的数组的长度。
        5. 线程不安全
          1. 多线程同时进行put,若hash冲突发生在莫一个没有值得下标下。多个线程会认为此下标没有数据,直接赋值,就会发生覆盖的情况,产生数据冲突
          2. JDK1.7的时候,扩容可能会照成死循环,采用头插法。
        6. LinkedHashMap:在HashMap的基础上使用双向链表保存数据的插入删除顺序。
      2. HashTable:与HashMap基本类似
        1. 值不能是null,键也不能为空,因为Hashtable直接使用key值计算hash值,调用本地方法接口,所有key不能为空。
        2. 线程安全,使用synchronized修饰
        3. 初始容器大小为11
        4. 扩容长度为2倍 + 1,计算下标的方式跟hashmap不一样,采用取模(数组长)运算,以此减少hash冲突,所以数组长度最好为素数或奇数。所以扩容时2倍加1。
      3. TreeMap:
        1. 红黑树,
        2. 三个指针(父节点,左节点,右节点)
        3. 键不能为null,值可以为null。
      4. ConcurrentMap:
        1. ConcurrentHashMap
          1. 线程安全;JDK1.7的时候采用segment分段锁,每个分段都是一个数组。JDK1.8,存储结构为:数组+链表+红黑树,存在hash冲突就使用synchronized同步代码块加对象锁,锁住数组对应下标。
          2. 键值均不能为空
  6. String,StringBuffer,StringBuilder
    1. String:由final修饰的类,不可继承,不可改变。当我们对String对象进行修改时,不是对原本的对象进行修改,而是新建一个修改后的对象
    2. StringBuilder:由final修饰,线程不安全。由字节数组存储,默认初始字节容器大小为16,扩容时,新长度 = 旧长度 * 2 + 2(+2原因,可能是因为初始长度可以为0)
    3. StringBuffer:与StringBuilder基本类似,但线程安全,由synchronized关键字修饰方法。
  7. java8特性
    1. lambda表达式(闭包),将函数当成方法参数,(参数列表(变量类型可省略)) -> 表达式;(参数列表) -> {表达式}
    2. 方法引用,对象名::方法名。类名::方法名
    3. 函数式接口,仅仅只有一个抽象方法的接口
    4. 默认方法,接口中的方法,可以通过default实现自己的默认方法。
    5. 日期时间API
    6. Stream流
    7. Base64编码
  8. equals和==的区别:==比较的是两个对象的地址是否是一样的,而equals继承自Object类,如果不对其进行重写,也是比较对象的地址,和==没有实际区别。String类就重写了equals方法,所以比较的是对象中的内容,而不是对象的地址。
  9. 重写equals方法还需重新hashcode方法:为了提高效率和节省空间,如果两个对象的地址相同,就不需要比较对象中的内容了,而相同对象通常情况下也不需要开辟额外的空间存放。
  10. 快速失败,安全失败
    1. 快速失败:使用迭代器遍历集合时,对集合中的内容进行增删改,就会抛出异常。原理:遍历时,使用modCount变量,集合改变,modCount就会改变,下一次遍历时,modCount改变直接终止遍历,抛出异常。
    2. 安全失败:采用安全失败机制的集合容器,在遍历时不是直接在集合内容上进行访问,而是先复制原有集合内容,在拷贝的集合上进行遍历。Concurrent下的容器都是安全失败。
  11. 内存泄漏和内存溢出:
    1. 内存泄漏:程序申请内存后,无法释放已申请的内存空间,例:强引用
    2. 内存溢出:执行多此GC后,内存还是不能满足需求
  12. 类锁和对象锁
    1. 对象锁:防止在同一个时刻多个线程访问同一个对象的synchronized块。类中非静态方法上的锁;同步代码块,以对象做锁
    2. 类锁:类的所有对象用同一把锁。类中静态方法;同步代码块,以类做锁。
  13. 泛型:参数化类型,将类型由原来的具体类型参数化,包括泛型类,泛型接口,泛型方法。ArrayList等集合类就是用的泛型,这样才可以存储不同类型的变量。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值