前言:本节内容长期更新,专门为了扫清盲点复习。采取小标题加链接方式,毕竟明珠在前。内容较为杂碎。
参考链接: Java基础知识面试题(2020最新版) 1、Java开发基础面试知识点 2、equals和HashCode深入理解以及Hash算法原理 3、MyISAM与InnoDB 的区别(9个不同点) 4、MySQL中的全文索引(InnoDB存储引擎)
自己动手实现Java注解(Java Annotation in Action)
手写一个生产者/消费者模式(三种方式实现) 注:感觉麻烦了点,还需改
// 公共阻塞队列,生产和消费都从这里拿 public class PublicQueue<T>{ private BlockingDeque<T> blockingDeque = null; private int capacity; public PublicQueue(int capacity) { this.blockingDeque = new LinkedBlockingDeque<>(capacity); this.capacity = capacity; } public void add(T msg){ if(blockingDeque.size() < capacity){ try{ blockingDeque.push(msg); }catch (Exception e){ e.printStackTrace(); } System.out.println("生产一个商品:" + msg); }else{ System.out.println("队列已满..."); } } public T remove(){ T take = null; if(!blockingDeque.isEmpty()){ try { take = blockingDeque.take(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("消费一个商品:" + take); }else{ System.out.println("队列已空"); } return take; } } // 生产任务 class ProducerRunnable implements Runnable { private PublicQueue publicQueue; private String name; ProducerRunnable(){} ProducerRunnable(PublicQueue publicQueue, String name){ this.publicQueue = publicQueue; this.name = name; } @Override public void run() { for(int i = 0; i < 20; i++){ publicQueue.add(name + " "+i); // 生产 } } } // 消费任务 class ComsumerRunnable implements Runnable { private PublicQueue publicQueue; private String name; ComsumerRunnable(){} ComsumerRunnable(PublicQueue publicQueue){ this.publicQueue = publicQueue; } @Override public void run() { for(int i = 0; i <20 ; i++){ name = (String) publicQueue.remove(); } } } public class Main { public static void main(String[] args) { PublicQueue publicQueue = new PublicQueue(20); new Thread(new ProducerRunnable(publicQueue, "apple")).start(); new Thread(new ComsumerRunnable(publicQueue)).start(); } }注:深拷贝后比较equals需要注意 java实现克隆的三种(很最全面) JAVA clone方法-深复制(深克隆)&浅复制(浅克隆)
Java设计模式----适配器模式
// 被适配器类,已存在,具有特殊功能,但不符合我们的标准接口的类 public class Adaptee { public void specificRequest(){ System.out.println("被适配器类的特殊功能执行..."); } } // 标准接口或目标接口,不能将就,无法更改 interface Target{ void request(); } // 具体目标类,只实现了普通功能 class ConcreteTarget implements Target{ @Override public void request() { System.out.println("标准功能执行..."); } }1、类适配器,单继承+实现,+父类调用
// 适配器类,继承了被适配类,并实现了标准接口 class Adapter extends Adaptee implements Target{ @Override public void request() { super.specificRequest(); // 从标准接口的实现方法中调用特殊功能接口 } } // 客户,测试类 class Client{ public static void main(String[] args) { // 普通功能类,执行普通功能 Target concreteTarget = new ConcreteTarget(); concreteTarget.request(); // 适配器类,执行特殊功能 Target adapter = new Adapter(); // 继承被适配类,实现标准接口,方法中父类调用 //Target adapter = new Adapter(new Adaptee()); // 直接实现标准接口,方法中通过被适配对象调用 adapter.request(); } }2、对象适配器,实现+对象调用
// 适配器类直接实现标准接口 class Adapter implements Target{ private Adaptee adaptee; public Adapter(Adaptee adaptee) { this.adaptee = adaptee; } @Override public void request() { adaptee.specificRequest(); } } // 客户,测试类 class Client{ public static void main(String[] args) { // 普通功能类,执行普通功能 Target concreteTarget = new ConcreteTarget(); concreteTarget.request(); // 适配器类,执行特殊功能 //Target adapter = new Adapter(); // 继承被适配类,实现标准接口,方法中父类调用 Target adapter = new Adapter(new Adaptee()); // 直接实现标准接口,方法中通过被适配对象调用 adapter.request(); } }注:还有工厂方法模式、抽象工厂模式 知乎:抽象工厂模式和工厂模式的区别? java设计模式之工厂模式
package factory; /* 1、简单工厂模式或静态工厂模式:抽象产品、具体产品、通用工厂 2、工厂(方法)模式:抽象产品、具体产品、抽象工厂、具体工厂 3、抽象工厂模式,类似于上面的工厂模式, 有多个抽象产品(产品簇),工厂生产一整套即多个产品 * */ // 抽象可以是接口或抽象类 interface Fruit{ void desc(); } class Apple implements Fruit{ @Override public void desc() { System.out.println("this is apple..."); } } class Orange implements Fruit{ @Override public void desc() { System.out.println("this is orange..."); } } // 枚举类,定义形式 enum FruitTypeEnum{ // 核心,定义枚举实例,充当固定常量, 一般定义枚举实例都会加对应介绍 /* 如果打算自定义自己的方法,那么必须在enum实例序列的最后添加一个分号。 而且 Java 要求必须先定义 enum 实例,且枚举类型的构造方法必须为私有方法。*/ APPLE(1, "apple"), ORANGE(2, "orange"); private int state; private String stateInfo; // 枚举类的本质就是提供有限个实例,因此构造器必须私有,不写也是默认私有 private FruitTypeEnum(int state, String stateInfo) { this.state = state; this.stateInfo = stateInfo; } /*后续的方法视需求情况而定*/ public int getState() { return state; } public String getStateInfo() { return stateInfo; } // 静态方法,拿到枚举对象 public static FruitTypeEnum stateOf(int state){ for(FruitTypeEnum fruitTypeEnum : FruitTypeEnum.values()){ if(fruitTypeEnum.state == state){ return fruitTypeEnum; } } return null; } } // 简单工厂类,扩展性查,增加水果种类,需要新增实现类并要更改工厂类方法 public class SimpleStaticFactory { // 简单工厂模式,create方法一般是static,也称为静态工厂 public static Fruit createFruit(FruitTypeEnum fruitTypeEnum){ Fruit fruit = null; switch(fruitTypeEnum){ // 这里为了复习枚举类 case APPLE: fruit = new Apple(); break; case ORANGE: fruit = new Orange(); break; default: fruit = new Apple(); } return fruit; } public static void main(String[] args) { Fruit fruit1 = createFruit(FruitTypeEnum.APPLE); fruit1.desc(); Fruit fruit2 = createFruit(FruitTypeEnum.stateOf(2)); fruit2.desc(); } }JAVA设计模式总结之六大设计原则
注:开单依里接迪特
1、单一职责 一个类只负责一项职责,代码级别、方法级别
2、里氏替换原则 原话:所有引用基类(父类)的地方必须能透明的使用其子类的对象 通俗:子类可以扩展父类的功能,但不能改变父类原有的功能。重写很容易碰到。
3、依赖倒置原则(Dependence Inversion Principle) 面向接口 依赖于抽象,不要依赖于具体
4、接口隔离原则(Interface Segregation Principle) 精简单一 做法是拆分接口,原因是:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上
5、迪米特法则(最少知道原则) (Demeter Principle) 降低耦合 通俗:一个类对自己依赖的类知道的越少越好
6、开闭原则(Open Close Principle) 对扩展开放,对修改关闭 用抽象构建框架,用实现扩展细节
撒的发生的
注:public interface Externalizable extends java.io.Serializable Java序列化,如何实现序列化和反序列化,常见的序列化协议有哪些?
分布式系统中一致性哈希算法
线程池的工作原理与源码解读及各常用线程池的执行流程图
java.util.concurrent JUC锁框架_ ReentrantLock原理分析 AbstractQueuedSynchronizer超详细原理解析 Java多线程系列–“JUC锁”01之 框架
设计模式分类:创建型模式,结构型模式,行为型模式 架构设计&分布式&数据结构与算法面试题(2020最新版)
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构 理解:抽象类实现一个接口,在抽象类中设置一个接口引用,重写接口方法但方法中仍调用原接口方法。套一个盒子而已。可以继承抽象类后添加具体的逻辑功能。
运行速度: StringBuilder > StringBuffer > String 注:两变一不变 线程安全: StringBuilder是线程不安全的,而StringBuffer是线程安全的
定义:多态是同一个行为具有多个不同表现形式或形态的能力
C++虚函数的存在是为了多态。
Java 中其实没有虚函数的概念,它的普通函数就相当于 C++ 的虚函数,动态绑定是Java的默认行为。 如果 Java 中不希望某个函数具有虚函数特性,可以加上 final 关键字变成非虚函数。
多态存在的三个必要条件: 继承或实现 重写 父类引用指向子类对象(注:这样只能调用公共方法,要想调用子类特有方法需要类型转换)
Java-IO流
怎么打破双亲委派 先前总结的双亲委派
ThreadLocal提供线程本地变量 ThreadLocal 的用法以及内存泄露(内存溢出)
select、poll、epoll之间的区别总结[整理] NIO详解(三):IO多路复用模型之select、poll、epoll 聊聊IO多路复用之select、poll、epoll详解
漫画:什么是CAS机制
ThreadLocal 的用法以及内存泄露(内存溢出)
Java并发——Executor框架详解(Executor框架结构与框架成员)
jstat -gcutil 本地虚拟机的唯一Id 1000(查询时间间隔) Java内存泄漏的排查总结
Atomic(原子性):指整个数据库事务是不可分割的工作单位。只有使据库中所有的操作执行成功,才算整个事务成功;事务中任何一个SQL语句执行失败,那么已经执行成功的SQL语句也必须撤销,数据库状态应该退回到执行事务前的状态。
Consistency(一致性):指数据库事务不能破坏 关系数据的完整性以及 业务逻辑上的一致性。例如对银行转帐事务,不管事务成功还是失败,应该保证事务结束后ACCOUNTS表中Tom和Jack的存款总额为2000元。
Isolation(隔离性):指的是在并发环境中,当 不同的事务同时操纵 相同的数据时,每个事务都有各自的完整数据空间。
Durability(持久性):指的是只要事务成功结束,它对数据库所做的更新就必须 永久保存下来。即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。
聚簇索引与非聚簇索引(也叫二级索引)
innodb引擎的4大特性
MySQL使用全文索引(fulltext index)
mysql 行级锁的使用以及死锁的预防
mysql视图的作用(详细)
MySQL 游标的使用
mysql存储过程学习笔记
【Mysql】多表联合查询、连接查询、子查询
MySQL中 in 和 exists 区别
mysql-覆盖索引
mysqldump和xtrabackup备份原理实现说明
redis的持久化和缓存机制
Redis中set类型的交集、并集、差集
Redis:一致性Hash算法
Redis与LRU
Reactor模式
大量数据去重:Bitmap和布隆过滤器(Bloom Filter) 漫画:什么是Bitmap算法? 分布式缓存击穿(布隆过滤器 Bloom Filter)
Jedis与Redisson选型对比
Redis之Redis事务
Spring面试题(2020最新版)
IOC,把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。 所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器,即IOC容器。
对象之间很多存在依赖关系,麻烦 IOC容器 创建并管理对象,同时维护依赖关系 解耦,由容器去维护具体的对象 托管类的产生,如代理,只关心使用,不关心如何生成
依赖注入(Dependency Injection),即组件之间的依赖关系由容器在应用系统运行期来决定,也就是由容器动态地将某种依赖关系的目标对象实例注入到应用系统中的各个关联的组件之中。 组件不做定位查询,即组件只提供普通的Java方法让容器去决定依赖关系。
IOC控制反转 Inversion of control 上层建筑依赖下层建筑 IOC容器会从当前层逐层往下直到底找config,从底层往上注入 DI注入,4种,Setter注入、构造器Constructor注入、接口注入 、注解注入(与注入区分开) 注:其中接口注入由于在灵活性和易用性比较差,现在从Spring4开始已被废弃
Spring将管理对象称为Bean,组件
spring core和spring context
spring beans:提供了BeanFactory(接口)
BeanFactory和ApplicationContext(仍是接口并继承了更多接口)
工厂模式:BeanFactory 单例模式:Bean默认为单例模式 代理模式AOP
模板方法RestTemplate
观察者模式ApplicationListener
依赖关系、加载方式、创建方式、注册方式
BeanFactory 简单粗暴,可以理解为就是个 HashMap,Key 是 BeanName,Value 是 Bean 实例
ApplicationContext 可以称之为 “高级容器”,代表着整个大容器的所有功能。该接口定义了一个 refresh 方法,此方法是所有阅读 Spring 源码的人的最熟悉的方法,用于刷新整个容器,即重新加载/刷新所有的 bean。
ClassPathXmlApplicationContext 类路径
FileSystemXmlApplicationContext 和WebXmlApplicationContext
singleton(默认) 、prototype request、session、global-session 后三种基于web的Spring ApplicationContext情形下有效
不是, 实际上大部分时候 spring bean 无状态的(比如 dao 类),所有某种程度上来说 bean 也是安全的,但如果 bean 有状态的话(比如 view model 对象),那就要开发者自己去保证线程安全了
在一般情况下,只有无状态的Bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为singleton作用域,因为Spring对一些Bean中非线程安全状态采用ThreadLocal进行处理,解决线程安全问题。
主要是:实例化+填充属性(值和bean的引用注入到bean对应的属性中)+。。。
bean装载到Spring应用上下文中,将一直驻留在应用上下文中,直到该应用上下文被销毁。当然也可以提前销毁。
bean 标签有两个重要的属性(init-method和destroy-method)。用它们你可以自己定制初始化和注销方法。对应的注解(@PostConstruct和@PreDestroy)
分为xml中自动装配和注解@Autowired自动装配
注解@Autowired: 首先根据bean类型,多个相同bean类型实例则根据名称,仍找不到报异常
AOP,即将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证、日志、事务处理等
AOP织入方式三种,编译时织入(静态代理)、类加载织入、运行时织入(动态代理,Spring采用这种)
静态代理的代表为AspectJ;动态代理则以Spring AOP为代表。
Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理
JDK动态代理只提供接口的代理,不支持类的代理。
CGLIB(Code Generation Library),通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
Spring的aop代理,先去查看当前类是否有接口,有接口就去JdkDynamicAopProxy(config)代理,没有就去ObjenesisCglibAopProxy(config)代理
前置、 后置(不论该方法是否异常都执行)、 返回(在方法正常结束时执行,可以访问到方法的返回值)、 异常(可以访问到异常对象,且可以指定在出现特定异常时再执行)、 环绕(需携带ProceedingJoinPoint类型参数,类似动态代理中的全过程或可实现前面的4个通知,必须有返回值)
连接点,代表具体的一个方法的执行或者认为程序执行的点 Spring AOP只支持方法级别的连接点。方法之外的连接点拦截功能,我们可以利用Aspect来补充。 暂时理解是细粒度不够高,但一般够用
切入点,匹配通知所要织入的一个或多个连接点或者认为是匹配很多连接点的断言或者表达式
关注点,具体某个想实现的功能, 横切关注点,整个应用都可能会使用
spring 有五大隔离级别,默认值为 ISOLATION_DEFAULT(使用数据库的设置),其他四个隔离级别和数据库的隔离级别一致 即多了个和数据库同样的隔离配置而已,不算真正的5个隔离级别
spring编程式事务管理的环境搭建及实例 编程式事务管理:通过编程的方式管理事务,给你带来极大的灵活性,但是难维护。
声明式事务管理:可以将业务代码和事务管理分离,你只需用注解和XML配置来管理事务
没懂
@Required 注解,表明bean的属性必须在配置的时候设置,通过一个bean定义的显式的属性值或通过自动装配。若@Required注解的bean属性未被设置,容器将抛出BeanInitializationException。
@Autowired和@Resource之间的区别: @Autowired默认是按照类型装配注入的 @Resource默认是按照名称来装配注入的
@Bean注解,它表示此方法将要返回一个对象,作为一个bean注册进Spring应用上下文
@Component:这将 java 类标记为 bean。它是任何 Spring 管理组件的通用构造型。spring 的组件扫描机制现在可以将其拾取并将其拉入应用程序环境中。
@Controller:这将一个类标记为 Spring Web MVC 控制器。标有它的 Bean 会自动导入到 IoC 容器中。
@Service:此注解是组件注解的特化。它不会对 @Component 注解提供任何其他行为。您可以在服务层类中使用 @Service 而不是 @Component,因为它以更好的方式指定了意图。
@Repository:这个注解是具有类似用途和功能的 @Component 注解的特化。它为 DAO 提供了额外的好处。它将 DAO 导入 IoC 容器,并使未经检查的异常有资格转换为 Spring DataAccessException。