2024年Java最全Day322&323,springcloud视频教程

总结

无论是哪家公司,都很重视高并发高可用的技术,重视基础,重视JVM。面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,是不是能真的得到锻炼。其实我写了这么多,只是我自己的总结,并不一定适用于所有人,相信经过一些面试,大家都会有这些感触。

最后我整理了一些面试真题资料,技术知识点剖析教程,还有和广大同仁一起交流学习共同进步,还有一些职业经验的分享。

面试了阿里,滴滴,网易,蚂蚁,最终有幸去了网易【面试题分享】

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

private Singleton4() {

}

private static Singleton4 instance;

public static Singleton4 getInstance() {

if (instance == null) {

synchronized (this) {

instance = new Singleton4();

}

}

return instance;

}

}

不推荐使用性能差


5、懒汉式(线程安全,同步方法)

//懒汉式(线程安全,同步方法)

public class Singleton5 {

private Singleton5() { }

private static Singleton5 instance;

public static synchronized Singleton5 getInstance() {

if (instance == null) {

instance = new Singleton5();

}

return instance;

}

}

不推荐使用性能差


6、双重检查

//双重检查

public class Singleton6 {

private Singleton6() {

}

private static volatile Singleton6 instance;

public Singleton6 getInstance() {

if (instance == null) {

synchronized (this) {

if (instance == null) {

instance = new Singleton6();

}

}

}

return instance;

}

}

线程安全,延迟加载,效率较高


7、静态内部类

//静态内部类

public class Singleton7 {

private Singleton7(){}

private static class SingletonInstance{

private static final Singleton7 INSTANCE = new Singleton7();

}

public Singleton7 getInstance(){

return SingletonInstance.INSTANCE;

}

}

优点

  • 避免了线程不安全,利用静态内部类特点实现延迟加载,效率高

8、枚举

//枚举类

public enum Singleton8 {

INSTANCE;

}

推荐使用

三、工厂模式


1、简单(静态)工厂模式

image-20210708214753738

  • 定义了一个创建对象的类,由这个类来封装实例化对象的行为

使用场景

当我们会用到大量的创建某种、某类或者某批对象 时,就会使用到工厂模式.


2、工厂方法模式

定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类

image-20210708215338950


3、抽象工厂模式

  • 定义了一个 interface 用于创建相关或有依赖关系的对象簇,而无需指明具体的类

  • 可以将简单工厂模式工厂方法模式进行整合

  • 将工厂抽象成两层,AbsFactory(*抽象工厂*) 和 具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇,更利于代码的维护和扩展。

image-20210708215732640

创建对象实例时,不要直接 new 类, 而是把这个 new 类的动作放在一个工厂的方法中,并返回。有的书上说, 变量不要直接持有具体类的引用

四、原型模式


孙大圣拔出猴毛, 变出其它孙大圣

  • 用原型实例指定创建对象的种类,并且通过拷贝克隆这些原型,创建新的对象

image-20210708215945111

代码演示:

image-20210708220046766

五、建造者模式


  • 抽象建造的过程,让具体的实现类去实现各自的建造过程

image-20210708220306676

  • Product(产品角色)

一个具体的产品对象。

  • Builder(抽象建造者)

创建一个 Product 对象的各个部件指定的 接口**/**抽象类。

  • ConcreteBuilder(具体建造者)

实现接口,构建和装配各个部件。

  • Director(指挥者)

构建一个使用 Builder 接口的对象。它主要是用于创建一个复杂的对象。它主要有两个作用,一是:隔离了客户与对象的生产过程,二是:负责控制产品对象的生产过程。

六、适配器模式


  • 将一个类的接口转换成另一种接口.让原本接口不兼容的类可以兼容

image-20210708220550638

  • 类适配器模式

通过类继承

image-20210708221024839

  • 对象适配器模式

通过成员变量聚合关系实现

image-20210708221018715

  • 接口适配器模式

通过一个中间抽象类来空实现,然后子类之间继承中间抽象类,对自己需要实现的方法实现

image-20210708220933342

  • 类适配器:以类给到,在 Adapter 里,就是将 src 当做类,继承
  • 对象适配器:以对象给到,在 Adapter 里,将 src 作为一个对象,持有(组合、聚合)
  • 接口适配器:以接口给到,在 Adapter 里,将 src 作为一个接口,实现

七、桥接模式


  • 实现与抽象放在两个不同的类层次中,使两个层次可以独立改变。

image-20210708221344847

//品牌接口

public interface Brand {

void open();

void close();

void call();

}

桥接类聚合了品牌接口类,然后在构造器中传入具体的品牌实现类,在具体的方法做品牌里面的方法调用

image-20210708221417799

实现了抽象和实现部分的分离,从而极大的提供了系统的灵活性,让抽象部分和实现部分独立开来,这有助于系统进行分层设计,从而产生更好的结构化系统

八、装饰者模式


  • 套娃模式,直接new放构造器里面套把抽象类聚合到它的子类里 该子类(装饰者)构造抽象类的实现(被装饰者)

  • 动态的将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则**(ocp**)

image-20210708222049385

代码实现

image-20210708222108469

image-20210708222127022

image-20210708222222133

九、组合模式


  • 它创建了对象组的树形结构,将对象组合成树状结构以表示“整体-部分”的层次关系

  • 通过组织结构管理,下面的例子采用了 集合管理

image-20210708222436012

代码实现

public abstract class OrganizationComponent {

private String name; // 名 字

private String des; // 说 明

protected void add(OrganizationComponent organizationComponent) {

//默认实现

throw new UnsupportedOperationException();

}

protected void remove(OrganizationComponent organizationComponent) {

//默认实现

throw new UnsupportedOperationException();

}

//构造器

public OrganizationComponent(String name, String des) {

super();

this.name = name; this.des = des;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getDes() {

return des;

}

public void setDes(String des) {

this.des = des;

}

//方法 print, 做成抽象的, 子类都需要实现

protected abstract void print();

}

image-20210708222905896

image-20210708222919758

image-20210708222933128

public class Client {

public static void main(String[] args) {

//从大到小创建对象 学校

OrganizationComponent university = new University(“清华大学”, " 中国顶级大学 ");

//创建 学院

OrganizationComponent computerCollege = new College(" 计 算 机 学 院 ", " 计 算 机 学 院 "); OrganizationComponent infoEngineercollege = new College(“信息工程学院”, " 信息工程学院 ");

//创建各个学院下面的系(专业)

computerCollege.add(new Department(“软件工程”, " 软件工程不错 "));

computerCollege.add(new Department(“网络工程”, " 网络工程不错 "));

computerCollege.add(new Department(“计算机科学与技术”, " 计算机科学与技术是老牌的专业 "));

infoEngineercollege.add(new Department(“通信工程”, " 通信工程不好学 "));

infoEngineercollege.add(new Department(“信息工程”, " 信息工程好学 "));

//将学院加入到 学校

university.add(computerCollege);

university.add(infoEngineercollege);

//university.print();

infoEngineercollege.print();

}

}

需要遍历组织机构,或者处理的对象具有树形结构时, 非常适合使用组合模式.

要求较高的抽象性,如果节点和叶子有很多差异性的话,比如很多方法和属性都不一样,不适合使用组合模式

十、外观模式


  • 外观类就是总控开关,去管理聚合的所有类

  • 解决多个复杂接口带来的使用困难,起到简化用户操作的作用

image-20210708223208692

代码

  • 外观类

集合了需要使用的类,和方法,用户只需要调用这个类的某个方法即可

public class HomeTheaterFacade {

//定义各个子系统对象,聚合关系

private TheaterLight theaterLight;

private Popcorn popcorn;

private Stereo stereo;

private Projector projector;

private Screen screen;

private DVDPlayer dVDPlayer;

//构造器

public HomeTheaterFacade() {

super();

this.theaterLight = TheaterLight.getInstance();

this.popcorn = Popcorn.getInstance();

this.stereo = Stereo.getInstance();

this.projector = Projector.getInstance();

this.screen = Screen.getInstance();

this.dVDPlayer = DVDPlayer.getInstanc();

}

//操作分成 4 步

public void ready() {

popcorn.on();

popcorn.pop();

screen.down();

projector.on();

stereo.on();

dVDPlayer.on();

theaterLight.dim();

}

public void play() {

dVDPlayer.play();

}

public void pause() {

dVDPlayer.pause();

}

public void end() {

popcorn.off();

theaterLight.bright();

screen.up();

projector.off();

stereo.off();

dVDPlayer.off();

}

}

外观模式对外屏蔽了子系统的细节,因此外观模式降低了客户端对子系统使用的复杂性

在维护一个遗留的大型系统时,可能这个系统已经变得非常难以维护和扩展,此时可以考虑为新系统开发一个Facade 类,来提供遗留系统的比较清晰简单的接口,让新系统与 Facade 类交互,提高复用性

十一、享元模式


  • 需要的网站结构相似度很高,而且都不是高访问量网站,如果分成多个虚拟空间来处理,相当于一个相同网站的实例对象很多,造成服务器的资源浪费

  • 运用共享技术有效地支持大量细粒度的对象

  • 避免重新创建,如果没有我们需要的,则创建一个

image-20210708223639374

内部状态 指 :对象共享出来的信息,存储在享元对象内部且不会随环境的改变而改变

外部状态 指 :对象得以依赖的一个标记,是随环境改变而改变的、不可共享的状态


代码

// 网站工厂类,根据需要返回压一个网站

public class WebSiteFactory {

//集合, 充当池的作用

private HashMap<String, ConcreteWebSite> pool = new HashMap<>();

//根据网站的类型,返回一个网站, 如果没有就创建一个网站,并放入到池中,并返回

public WebSite getWebSiteCategory(String type) {

if(!pool.containsKey(type)) {

//就创建一个网站,并放入到池中

pool.put(type, new ConcreteWebSite(type));

}

return (WebSite)pool.get(type);

}

//获取网站分类的总数 (池中有多少个网站类型)

public int getWebSiteCount() {

return pool.size();

}

}

public class Client {

public static void main(String[] args) {

// 创建一个工厂类

WebSiteFactory factory = new WebSiteFactory();

// 客户要一个以新闻形式发布的网站

WebSite webSite1 = factory.getWebSiteCategory(“新闻”);

webSite1.use(new User(“tom”));

// 客户要一个以博客形式发布的网站

WebSite webSite2 = factory.getWebSiteCategory(“博客”);

webSite2.use(new User(“jack”));

// 客户要一个以博客形式发布的网站

WebSite webSite3 = factory.getWebSiteCategory(“博客”);

webSite3.use(new User(“smith”));

// 客户要一个以博客形式发布的网站

WebSite webSite4 = factory.getWebSiteCategory(“博客”);

webSite4.use(new User(“阿昌”));

System.out.println(“网站的分类共=” + factory.getWebSiteCount());

}

}

//具体网站

public class ConcreteWebSite extends WebSite {

//共享的部分,内部状态

private String type = “”; //网站发布的形式(类型)

//构造器

public ConcreteWebSite(String type) {

this.type = type;

}

@Override

public void use(User user) {

System.out.println(“网站的发布形式为:” + type + " 在使用中 … 使用者是" + user.getName());

}

}

@Data

public class User {

private String name;

public User(String name) {

super();

this.name = name;

}

}

public abstract class WebSite {

public abstract void use(User user);//抽象方法

}

享元模式大大减少了对象的创建,降低了程序内存的占用,提高效率

享元模式提高了系统的复杂度。需要分离出内部状态和外部状态,而外部状态具有固化特性,不应该随着内部状态的改变而改变,这是我们使用享元模式需要注意的地方.

使用享元模式时,注意划分内部状态和外部状态,并且需要有一个工厂类加以控制。

十二、代理模式


通过替身去调用传入的被代理对象的方法,而不是直接去调用被代理对象的方法

  • 为一个对象提供一个替身,以控制对这个对象的访问。即通过代理对象访问目标对象.这样做的好处是: 可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能

image-20210709211729264

1、静态代理

  • 静态代理在使用时,需要定义接口或者父类,被代理对象(即目标对象)与代理对象一起实现相同的接口或者是继承相同父类

image-20210709211901996

  • 代码实现

public class Client {

public static void main(String[] args) {

//创建目标对象(被代理对象)

TeacherDao teacherDao = new TeacherDao();

//创建代理对象, 同时将被代理对象传递给代理对象

TeacherDaoProxy teacherDaoProxy = new TeacherDaoProxy(teacherDao);

//通过代理对象,调用到被代理对象的方法

//即:执行的是代理对象的方法,代理对象再去调用目标对象的方法

teacherDaoProxy.teach();

}

}

//接口

public interface ITeacherDao {

void teach(); // 授课的方法

}

public class TeacherDao implements ITeacherDao {

@Override

public void teach() {

System.out.println(" 老师授课中 。。。。。");

}

}

//代理对象,静态代理

public class TeacherDaoProxy implements ITeacherDao{

private ITeacherDao target; //被代理对象,聚合关系

//构造器

public TeacherDaoProxy(ITeacherDao target) {

this.target = target;

}

@Override

public void teach() {

System.out.println("开始代理 完成某些操作。。。。。 ");//方法

target.teach();

System.out.println(“提交。。。。。”);//方法

}

}

代理对象与目标对象要实现相同的接口,然后通过调用相同的方法来调用目标对象的方法

优点

  • 不修改目标对象的功能前提下, 能通过代理对象对目标功能扩展

缺点

  • 因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类

  • 一旦接口增加方法,目标对象与代理对象都要维护


2、动态代理

  • 代理对象, 不需要实现接口,但是目标对象要实现接口,否则不能用动态代理

  • 代理对象的生成,是利用 JDK 的 API,动态的在内存中构建代理对象

image-20210701210805834

public class Client {

public static void main(String[] args) {

//创建目标对象,被代理类

ITeacherDao target = new TeacherDao();

//给目标对象,创建代理对象, 可以转成 ITeacherDao,获取代理类

ITeacherDao proxyInstance = (ITeacherDao)new ProxyFactory(target).getProxyInstance();

// proxyInstance=class com.sun.proxy.$Proxy0 内存中动态生成了代理对象

System.out.println(“proxyInstance=” + proxyInstance.getClass());

//通过代理对象,调用目标对象的方法

//proxyInstance.teach();

proxyInstance.sayHello(" tom ");

}

}

//接口

public interface ITeacherDao {

void teach(); // 授课方法

void sayHello(String name);

}

public class ProxyFactory {

//维护一个目标对象 , Object

private Object target;

//构造器 , 对 target 进行初始化

public ProxyFactory(Object target) {

this.target = target;

}

//给目标对象 生成一个代理对象

public Object getProxyInstance() {

//说明

/*

  • public static Object newProxyInstance(ClassLoader loader,

Class<?>[] interfaces, InvocationHandler h)

//1. ClassLoader loader : 指定当前目标对象使用的类加载器, 获取加载器的方法固定

//2. Class<?>[] interfaces: 目标对象实现的接口类型,使用泛型方法确认类型

//3. InvocationHandler h : 事情处理,执行目标对象的方法时,会触发事情处理器方法, 会把当前执行

的目标对象方法作为参数传入

*/

return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),new InvocationHandler() {

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

System.out.println(“JDK 代理开始~~”);

//反射机制调用目标对象的方法

Object returnVal = method.invoke(target, args);

System.out.println(“JDK 代理提交”);

return returnVal;

}

});

}

}

//被代理类

public class TeacherDao implements ITeacherDao {

@Override

public void teach() {

System.out.println(" 老师授课中… ");

}

@Override

public void sayHello(String name) {

System.out.println("hello " + name);

}

}


3、Cglib 代理

  • 是在内存中构建一个子类对象从而实现对目标对象功能扩展, 有些书也将Cglib 代理归属到动态代理。

image-20210709212634199

public class Client {

public static void main(String[] args) {

//创建目标对象

TeacherDao target = new TeacherDao();

//获取到代理对象,并且将目标对象传递给代理对象

TeacherDao proxyInstance = (TeacherDao)new ProxyFactory(target).getProxyInstance();

//执行代理对象的方法,触发 intecept 方法,从而实现 对目标对象的调用

String res = proxyInstance.teach();

System.out.println(“res=” + res);

}

}

public class ProxyFactory implements MethodInterceptor {

//维护一个目标对象 ,聚合关系

private Object target;

//构造器,传入一个被代理的对象

public ProxyFactory(Object target) {

this.target = target;

}

//返回一个代理对象: 是 target 对象的被代理对象

public Object getProxyInstance() {

//1. 创建一个工具类

Enhancer enhancer = new Enhancer();

//2. 设置父类,传入被代理类的class类

enhancer.setSuperclass(target.getClass());

//3. 设置回调函数

enhancer.setCallback(this);

//4. 创建子类对象,即代理对象

return enhancer.create();

}

//重写intercept()方法,会调用目标对象的方法

@Override

public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable {

System.out.println(“Cglib 代理模式 ~~ 开始”);

Object returnVal = method.invoke(target, args);

System.out.println(“Cglib 代理模式 ~~ 提交”);

return returnVal;

}

}

public class TeacherDao {

public String teach() {

System.out.println(" 老师授课中 , 我是 cglib 代理,不需要实现接口 "); return “hello”;

}

}

在 AOP 编程中如何选择代理模式

  1. 目标对象需要实现接口,用 JDK 代理

  2. 目标对象不需要实现接口,用 Cglib 代理

十三、模版模式


  • 在一个抽象类公开定义了执行它的方法的模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。

  • 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构,就可以重定义该算法的某些特定步骤

image-20210709213022266

  • 代码演示

//抽象类,表示豆浆

public abstract class SoyaMilk {

//模板方法, make ,

//模板方法可以做成 final , 不让子类去覆盖重写

final void make() {

select();

addCondiments();

soak();

beat();

}

//选材料

void select() {

System.out.println("第一步:选择好的新鲜黄豆 ");

}

//添加不同的配料, 抽象方法, 子类具体实现

abstract void addCondiments();

//浸泡

1200页Java架构面试专题及答案

小编整理不易,对这份1200页Java架构面试专题及答案感兴趣劳烦帮忙转发/点赞

百度、字节、美团等大厂常见面试题

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

hod, Object[] args, MethodProxy arg3) throws Throwable {

System.out.println(“Cglib 代理模式 ~~ 开始”);

Object returnVal = method.invoke(target, args);

System.out.println(“Cglib 代理模式 ~~ 提交”);

return returnVal;

}

}

public class TeacherDao {

public String teach() {

System.out.println(" 老师授课中 , 我是 cglib 代理,不需要实现接口 "); return “hello”;

}

}

在 AOP 编程中如何选择代理模式

  1. 目标对象需要实现接口,用 JDK 代理

  2. 目标对象不需要实现接口,用 Cglib 代理

十三、模版模式


  • 在一个抽象类公开定义了执行它的方法的模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。

  • 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构,就可以重定义该算法的某些特定步骤

image-20210709213022266

  • 代码演示

//抽象类,表示豆浆

public abstract class SoyaMilk {

//模板方法, make ,

//模板方法可以做成 final , 不让子类去覆盖重写

final void make() {

select();

addCondiments();

soak();

beat();

}

//选材料

void select() {

System.out.println("第一步:选择好的新鲜黄豆 ");

}

//添加不同的配料, 抽象方法, 子类具体实现

abstract void addCondiments();

//浸泡

1200页Java架构面试专题及答案

小编整理不易,对这份1200页Java架构面试专题及答案感兴趣劳烦帮忙转发/点赞

[外链图片转存中…(img-nH1TkdNU-1714850636055)]

[外链图片转存中…(img-JFoxsMTE-1714850636056)]

百度、字节、美团等大厂常见面试题

[外链图片转存中…(img-f7kghPBv-1714850636056)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值