怎样电脑登录网站,乐平网站,客户网站开发全流程图,Godaddy如何建设网站学习计划#xff1a;将目前已经学的知识点串成一个思维导图。在往后的学习过程中#xff0c;不断往思维导图里补充#xff0c;形成自己整个知识体系。对于思维导图里的每个技术知识#xff0c;自己用简洁的话概括出来#xff0c; 训练自己的表达能力。 面向对象三大特性
… 学习计划将目前已经学的知识点串成一个思维导图。在往后的学习过程中不断往思维导图里补充形成自己整个知识体系。对于思维导图里的每个技术知识自己用简洁的话概括出来 训练自己的表达能力。 面向对象三大特性
封装 封装就是使用private修饰属性或方法这样类的对象就没法直接访问或修改属性只能通过get/set方法进行访问或修改。 封装的好处降低代码的耦合度利于维护通过get/set方法访问属性的时候可以增加一些额外的逻辑这是单独访问属性无法做到的。 继承 继承就是子类继承父类子类继承了父类所有的方法和属性。并且子类还可以增加一些自己的属性和方法。 继承的好处是提高代码的复用性比如说一个类想要拥有另一个类的属性和方法就可以采用继承的方式实现。 多态 多态就是父类引用指向子类的实例多态只有在运行时才能确定调用的是哪个类的方法。 多态的好处是提高代码的复用性比如说使用一个方法时将参数设置为父类的引用来接收各种各样的子类实例。这样写一个方法就可以有各种效果。
面向对象的理解
面向对象就是万事万物抽象为对象将一些行为、特点抽象为方法和属性。 面向对象的好处就是使代码的耦合度降低我们要实现什么功能时直接调用对象的方法即可。比如说要实现开门这个动作面向对象的思路就是先抽象出door这个对象然后再抽象出door的一些特征作为属性比如说门的大小、颜色。然后抽象出door的开门、关门的方法。我们如果想要实现开门动作的话就直接调对象的这个方法即可。
重载与重写的区别
重载就是在同一个类中的多个方法方法名相同但是方法参数类型或参数个数不同。在编译期间就可以确定是调用哪个方法。 重写就是子类重写父类的方法。
重载算多态的体现吗
不算重载是编译期间就确定要调用的方法而多态是要在运行时才确定要调用的方法。
反射机制
反射就是获取类在运行时的大Class实例只有获取了这个实例才能获取有关这个类的各种信息比如方法、属性。原理是因为jvm在加载类时都会为这个类在堆中生成大class实例并且指向方法区中有关这个类的各种信息。
泛型
泛型就是规定一种类型。比如说我们创建一个list我们就可以使用泛型规定list里的每个元素的参数类型。 另一方面当方法的形参类型不确定的时候也可以使用泛型这样就可以提高方法的可复用性。方法放进去的是时候取出来的就是什么。相较于多态可以避免强制类型转换的异常。
序列化与反序列化
序列化就是将对象转换为字节流或者json文本格式的过程反序列化就是由字节流或json文本格式转换为对象的过程。 对象只有序列化后才能进行传输和存储。 比如说当我们想要将对象存进redis中的value里我们可以使用json序列化器但是由于序列化为json后会多存储一个类路径浪费空间。因此我们会选择String序列化器首先将对象手动转变为json格式的字符串将字符串转换为字节流传输。
String、StringBuilder、StringBuffer的区别
1、可变性 String是不可变的因为String底层是一个private final修饰的字符数组。final意味这个字符数组的地址值不能改变并不意味着字符数组里的内容不能改变String真正不可变的原因在于这个private。由于是private修饰的并且String没有提供修改这个字符数组的方法因此没有任何渠道能修改这个字符数组因此String是不可变的。 而StringBuilder和StringBuffer底层就只是字符数组因此是可变的。 2、线程安全性 String是不可变的因此String是线程安全的。 由于StringBuilder底层方法没有加锁因此是线程不安全的而StringBuffer底层方法是加了synchronized锁的因此是线程安全的。 3、性能 对于字符串的拼接如果String类型的变量使用“”来拼接底层会新创建一个String对象而原来那个String对象就变成了无引用使得堆中垃圾变多gc时间变多自然影响性能。而对于StringBuilder类型与StringBuffer类型使用append方法不会新创建对象效率更高而StringBuilder性能又会比StringBuffer高因为底层没有加锁。
hashCode() equals()
hashCode方法就是获取对象的哈希码。而哈希码主要用于确定对象在哈希表中的下标位置。比如说就有用在HashMap、HashSet中。 hashCode方法在HashMap或HashSet中经常配合equals方法使用因为hashCode存在哈希碰撞问题所以不同对象的哈希码可能相同那么就需要使用equals进一步判断对象是否相同。另外如果没有hashCode方法只有equals方法时就需要一个一个对象的进行比较效率很低所以hashCode的作用使得查找比较的效率提高。
clone()
浅拷贝与深拷贝 子类直接调用父类也就是Object类的clone的方法就是浅拷贝。浅拷贝会在堆上创建新的对象但是如果对象内部的属性是引用类型的话浅拷贝只会复制这个内部对象的引用地址浅拷贝后的对象与原对象共享这个内部对象。 深拷贝就是需要重写clone方法手动进行深拷贝。深拷贝就是不仅会在堆上创建新对象也会创建新的内部对象。
wait() notify()
共同点这两个方法都可以让线程暂停执行。让线程变成等待态。 不同点 1、sleep方法时间到了线程会自动变成运行态而wait方法需要等待其他线程调用同一个对象的notify方法后线程才会变成运行态。 2、wait方法会使线程释放锁而sleep方法不会使线程释放锁。 3、wait方法是在Object类里的方法而sleep方法是在Thread类里的方法。 为什么wait方法是在object类的
因为wait方法需要释放当前线程所占有的锁又因为这个锁是对象锁因此wait操作的应该是对象而不是线程。
集合框架图 ArrayList ArrayList LinkedList 区别
ArrayList底层是一个数组因此随机访问元素的速度很快但是插入和删除的速度就很慢时间复杂度是O(n)级别的。 LinkedList底层是一个双向链表插入和删除速度快但是随机访问元素的速度就很慢需要依次遍历。 ArrayList初始化
如果在new ArrayList的时候没有指定集合容量那么底层就会初始化一个数组大小为0的空数组当第一次add元素时就会将数组的长度扩容到默认长度10的大小。 启发当我们初始化ArrayList的时候就应该指定好数组容量否则当容量不够时就需要扩容和复制和带来一定的性能损耗。 ArrayList添加元素/扩容机制
当ArrayList add元素时首先会先确保数组长度是足够的因此会将数组长度与list中已经存储的元素个数1进行比较如果数组长度不够那么就需要进行扩容。扩容就是将数组长度扩容为原来的1.5倍然后再将原数组中的元素复制到新数组中。 启发扩容为原来的1.5倍底层源码是通过位运算进行计算比如假设oldCapacity13二进制数是11011101 1 0110 661319。扩容后的长度就是19。使用位运算速度更快。 ArrayList怎么实现复制如何自己实现
有三种方法可以使用ArrayList类里的clone方法这是一个浅拷贝还可以使用ArrayList类里的addAll方法这也是一个浅拷贝还可以使用构造器将原list作为参数装进构造器里就会得到一个新的list这也是一个浅拷贝方法。 自己实现的话首先创建一个新的ArrayList对象然后依次遍历原ArrayList中的每个元素将其添加进新ArrayList对象中。在这个过程中还可以手动实现深拷贝。 ArrayList是线程安全的吗
ArrayList是线程不安全的。举个例子当调用ArrayList里的add方法时在多线程的环境下可能有多个线程拿到同一个size那么就会将各自的元素添加进数组的同一个位置中这样就出现了数据覆盖问题从而导致了线程不安全。 HashMap
HashMap初始化过程
当new一个HashMap时table数组不会被初始化只有等第一次put元素时table数组才会被new出来如果没有指定哈希表大小的话则默认table数组长度为16。如果指定了哈希表大小则会按大于该指定值的2的n次方进行分配。 HashMap put元素过程
首先会根据元素的key通过hashcode方法计算出哈希值再由哈希值计算出哈希槽的索引位置。 接着判断这个索引位置上是否有元素如果没有元素则直接我们的新元素插入 如果这个索引位置上有元素判断这个元素是否为树结点 如果是树结点则走树逻辑 如果不是则依次遍历这个索引位置上的链表结点通过hashcode方法和equals方法判断两个元素的key是否相等。 如果判断出链表上的结点的key与新增元素的key是相等的则用e指针记录这个重复结点最后再用新增元素的value替换这 个重复元素的value。 而如果遍历完链表里的所有结点发现都没有重复的那么就直接在链表结尾插入这个新增元素。 新增完元素后还需要判断哈希表里的元素是否超过阈值阈值就是哈希表容量*负载因子。如果超过了需要进行扩容。 HashMap扩容过程
根据哈希表容量*负载因子可以得到扩容的阈值。如果哈希表里的元素个数超过了阈值那么就会进行扩容。扩容是扩容为原来哈希表大小的两倍。然后在将原哈希表上的所有元素重新计算哈希值尾插法迁移至新的哈希表中。 由于都是两倍两倍的扩容因此我们的哈希表大小一定都是2的n次方。这是为了方便使用位运算计算哈希码对应的数组索引位置。 jdk1.7的HashMap出现的死链问题
死链问题是扩容迁移过程中的头插法导致的。头插法会使链表中元素倒序插入到新表中。如果两个线程同时执行迁移操作同时执行遍历到某个哈希槽的第一个位置其中一个线程使得table数组的链表变成倒序然后另一个线程接着正常执行那么就会出现指针指回前面的结点从而出现循环链表。 HashMap出现的线程不安全问题
1、当新增元素时可能出现线程不安全问题 如果两个线程同时执行put元素操作且都计算出元素所对应的索引下标是同一个位置然后同时判断出这个索引位置没有元素或者同时循环遍历到链表为尾部那么就会出现元素覆盖问题从而导致数据丢失。 2、扩容迁移过程出现的线程不安全问题 情况1当一个线程执行扩容迁移的过程中其他线程仍然可以在原表中进行新增元素如果新增元素落在原表已遍历过的哈希槽上的话迁移遍历完成后当table数组引用指向新表时在原表中新增的元素就会丢失。 情况2当多个线程都在各自内存中扩容迁移也就是说它们各自都含有一个新表当线程迁移完成后会将新表赋值给共享的table数组因此就会出现在新表中插入元素被覆盖的问题。