把它装进脑子里

1、反射的了解

​ 就是在运行时才知道要操作的类是什么,‌ 是一种允许程序在运行时动态地获取类的信息并操控类对象的机制

2、字符串中常用的方法

  1. length():返回字符串的长度。

    javaString s = "hello";
    int len = s.length(); // 5
    
  2. charAt(int index):返回指定位置的字符。

    javachar c = s.charAt(1); // 'e'
    
  3. substring(int beginIndex, int endIndex):返回子字符串。

    javaString sub = s.substring(1, 4); // "ell"
    
  4. indexOf(String str):返回指定子字符串首次出现的位置。

    javaint index = s.indexOf("l"); // 2
    
  5. toLowerCase():将字符串转换为小写。

    javaString lower = s.toLowerCase(); // "hello"
    
  6. toUpperCase():将字符串转换为大写。

    javaString upper = s.toUpperCase(); // "HELLO"
    
  7. trim():去除字符串两端的空白字符。

    javaString trimmed = "  hello  ".trim(); // "hello"
    
  8. replace(CharSequence target, CharSequence replacement):替换字符串中的指定字符或子字符串。

    javaString replaced = s.replace("l", "x"); // "hexxo"
    
  9. split(String regex):将字符串按指定正则表达式分割成字符串数组。

    javaString[] parts = "a,b,c".split(","); // ["a", "b", "c"]
    
  10. concat(String str):连接两个字符串。

    String result = s.concat(" world")
    

3、StringBuffer和StringBuilder的区别

StringBuffer是线程安全的,方法是同步的,因此在多线程环境中更安全,但性能较低;

StringBuilder是非线程安全的,方法不是同步的,因此在单线程环境中性能更好。

4、重写和重载的区别

重写(Override)

  • 定义:子类重新定义父类中已经存在的方法,以便子类可以提供其特定的实现。
  • 目的:用于实现多态,使得子类可以对父类的方法进行自定义实现。
    • 方法名、返回类型、参数列表必须与父类中的方法完全一致。
    • 方法的访问修饰符不能比父类中的方法更严格(例如,父类中的方法是protected,子类中的重写方法不能是private)。
    • 方法可以抛出与父类方法相同或更少的异常(即,子类方法抛出的异常不能比父类方法更多或更具限制性)。

重载(Overload)

  • 定义:在同一个类中定义多个方法,方法名相同但参数列表不同。
  • 目的:允许同一个方法名用于不同的参数,使得方法可以适应不同的输入。
    • 方法名相同,但参数列表(类型、数量、顺序)不同。
    • 返回类型可以相同或不同,但不能仅通过返回类型来进行重载。
    • 访问修饰符可以不同。
    • 方法可以抛出不同的异常。

5、final关键字作用

用于定义常量、禁止方法重写、禁止类继承。

6、ArrayList和LinkedList的区别

ArrayList基于数组,随机访问快;LinkedList基于链表,插入删除操作快。

7、多态的理解

多态主要通过以下两种方式实现:

  • 方法重写(Override):在子类中重新定义父类的方法。方法的调用由对象的实际类型决定,运行时才确定调用哪个方法的实现。

    示例

    javaclass Animal {
        void makeSound() {
            System.out.println("Some sound");
        }
    }
    
    class Dog extends Animal {
        @Override
        void makeSound() {
            System.out.println("Bark");
        }
    }
    
    class Cat extends Animal {
        @Override
        void makeSound() {
            System.out.println("Meow");
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            Animal a;
            a = new Dog();
            a.makeSound(); // Output: Bark
    
            a = new Cat();
            a.makeSound(); // Output: Meow
        }
    }
    
  • 方法重载(Overload):同一方法名,但参数列表不同。虽然这是方法的一个变种,重载本身并不算是多态的核心,但在某些情况下也会涉及到多态的应用。

2. 多态的类型

  • 编译时多态(静态多态):通过方法重载实现,编译器在编译时就确定了方法的调用。
  • 运行时多态(动态多态):通过方法重写实现,程序在运行时决定调用哪个方法。通常表现为:
    • 父类引用指向子类对象。
    • 调用的方法由对象的实际类型决定,而不是引用的类型

它允许对象以多种形式表现,增强了程序的灵活性和可维护性。通过方法重写和接口实现,多态使得不同的对象可以使用相同的方法调用,并表现出不同的行为。

8、设计模式

设计模式主要分为三类,每类包含多个具体模式,作用是提高代码的复用性、灵活性和可维护性。以下是常见的设计模式及其作用:

1. 创建型模式

  • 单例模式(Singleton):确保一个类只有一个实例,并提供全局访问点。
  • 工厂方法模式(Factory Method):定义一个接口用于创建对象,但由子类决定实例化哪个类。
  • 抽象工厂模式(Abstract Factory):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
  • 建造者模式(Builder):分步骤构建一个复杂对象,允许不同的表示方法。
  • 原型模式(Prototype):通过复制现有对象来创建新对象,而不是通过实例化。

2. 结构型模式

  • 适配器模式(Adapter):将一个类的接口转换成客户希望的另一种接口。
  • 装饰器模式(Decorator):动态地给对象添加额外的职责。
  • 外观模式(Facade):为子系统中的一组接口提供一个一致的接口。
  • 组合模式(Composite):将对象组合成树形结构以表示部分-整体层次结构。
  • 代理模式(Proxy):为其他对象提供一个代理以控制对这个对象的访问。

3. 行为型模式

  • 观察者模式(Observer):定义对象之间的一对多依赖,使得当一个对象改变状态时,其所有依赖者都会收到通知并自动更新。
  • 策略模式(Strategy):定义一系列算法,将每一个算法封装起来,使它们可以互换。
  • 迭代器模式(Iterator):提供一种方法顺序访问一个集合对象中的元素,而不暴露该对象的内部表示。
  • 中介者模式(Mediator):定义一个对象来封装一组对象的交互,使得对象之间不需要显式地互相引用。
  • 备忘录模式(Memento):在不暴露对象实现细节的情况下,捕获对象的内部状态,并在以后恢复它。
  • 解释器模式(Interpreter):为语言定义一个表示,并定义一个解释器来解释该语言的句子。

9、Web开发中转发和重定向有什么区别

转发在服务器内部发生,重定向是浏览器发起新请求;转发不会改变URL,重定向会。

10、cookie和session有什么区别

cookie存储在客户端,session存储在服务器;sessioncookie安全,但不适合存储大量数据。

11、过滤器和拦截器的区别

过滤器用于处理请求和响应,拦截器用于处理业务逻辑;过滤器在请求前后执行,拦截器在方法调用前后执行。

12、Ajax的理解

定义

Asynchronous JavaScript And Xml的缩写

浏览器在不刷新全部页面的情况下,和服务端进行通信的过程

Ajax就是实现局部刷新的异步通信技术

工作原理

通过XmlHttpRequest对象和服务端进行通信,浏览器收到服务端的返回值后,对局部区域的内容进行设置

13、MVC架子模型 特点

  1. Model(模型):负责应用程序的数据和业务逻辑。它直接与数据源交互(如数据库),并处理数据的获取和存储。

  2. View(视图):负责数据的呈现和用户界面的展示。它从模型获取数据并将其展示给用户。

  3. Controller(控制器):充当模型和视图之间的中介,处理用户输入并更新模型和视图。控制器接收用户请求,调用模型进行处理,然后选择视图进行呈现。

    特点:提高代码的可维护性 增强代码的可重用性 提高用户界面的灵活性 支持多种视图

14、Mybatis中一级缓存和二级缓存

1. 一级缓存(Local Cache)

  • 定义:一级缓存是 MyBatis 的默认缓存机制,它是基于 SqlSession 的缓存,也被称为会话缓存
  • 作用域:缓存的作用域限于一个 SqlSession 对象。换句话说,一级缓存仅在同一个 SqlSession 的生命周期内有效。不同的 SqlSession 之间是不会共享一级缓存的。
  • 特点
    • 当一个 SqlSession 查询同样的 SQL 语句时,MyBatis 会首先检查一级缓存,如果缓存中有数据,则直接返回缓存数据而不执行数据库查询。
    • 一级缓存的数据会在 SqlSession 关闭时被清空。
    • 插入、更新或删除操作会清空一级缓存,以确保数据的一致性。
  • 配置:一级缓存是 MyBatis 的默认行为,不需要额外的配置。要使用一级缓存,只需正常使用 SqlSession

2. 二级缓存(Global Cache)

  • 定义:二级缓存是 MyBatis 提供的全局缓存机制,它是基于 Mapper 的缓存,也被称为全局缓存
  • 作用域:二级缓存的作用域超出了单个 SqlSession,在整个 Mapper 的作用域内共享。即,二级缓存可以跨 SqlSession 实例共享缓存数据。
  • 特点
    • 当一个 SqlSession 关闭时,数据会被存入二级缓存。其他 SqlSession 可以共享这些缓存数据,从而避免对数据库的重复查询。
    • 二级缓存的数据会在 SqlSession 关闭时依然保持,直到缓存被刷新或被清空。
    • 插入、更新或删除操作会使相关的数据从二级缓存中失效。
  1. 配置
    1. 启用二级缓存:需要在 MyBatis 的配置文件中启用二级缓存。具体来说,需要在 mapper XML 文件中添加 <cache/> 元素。
    2. 配置缓存:可以在 mybatis-config.xml 文件中进行全局的缓存配置,或者在每个 Mapper 的 XML 文件中单独配置缓存。
    3. 缓存实现:默认的缓存实现是基于 HashMap 的简单缓存实现。也可以自定义缓存实现,或者使用第三方缓存框架(如 Ehcache、Redis 等)。

15、Comparable和Comparator 接口的区别?

在这里插入图片描述

16、Redis 是一个开源的内存数据存储系统,因其高性能和快速响应而被广泛使用。其速度快的原因主要包括以下几个方面:

1. 内存存储

Redis 将数据存储在内存中,而不是传统的磁盘存储。内存访问速度比磁盘快得多,减少了数据的读写延迟。虽然 Redis 也可以将数据持久化到磁盘,但其主要的读写操作都是在内存中完成的。

2. 单线程模型

Redis 使用单线程事件循环模型处理所有请求。单线程模型的优点包括:

  • 避免了上下文切换:多线程模型中线程上下文切换会带来额外的开销。Redis 的单线程模型通过避免这种切换来减少延迟。
  • 简化了并发编程:单线程避免了多线程编程中的复杂性,如竞态条件和锁问题,从而减少了调试和性能调优的难度。

3. 高效的数据结构

Redis 提供了多种高效的数据结构,如字符串、列表、集合、有序集合和哈希等。每种数据结构都有经过优化的操作方法,使得常见的数据操作(如插入、删除、查找)可以在常量时间(O(1))或对数时间(O(log n))内完成。

4. 事件驱动和非阻塞I/O

Redis 使用了事件驱动的非阻塞 I/O 模型,通过 epoll(在 Linux 上)或 kqueue(在 BSD 系统上)等机制,能够处理大量并发连接而不会阻塞。这种方式允许 Redis 在高并发环境中高效地处理大量请求。

17、Redis采用的过期策略

Redis采用的过期策略是惰性删除+定期删除同时使用

惰性删除:当尝试访问一个过期的键时,Redis 会检查该键是否已经过期。如果是,Redis 会将其从数据库中删除并返回一个空值 这种策略即为惰性删除,它的优点是避免了不必要的计算开销,但缺点是可能会导致一些过期键在访问时才被删除,增加了访问延迟。

定期删除:Redis 会定期扫描数据库中的过期键。默认情况下,Redis 每隔 100 毫秒会随机检查一部分键的过期情况,并删除那些过期的键。

当 Redis 达到内存限制时,除了过期键的删除策略,Redis 还提供了内存淘汰策略,以保证 Redis 继续正常运行

Redis 通过设置键的过期时间和应用多种过期策略来管理数据的生命周期。这些策略帮助 Redis 处理过期数据、优化内存使用,并确保系统高效稳定运行

18、@Bean 注解在 Spring 框架中用于定义一个 Spring 容器管理的 Bean。它通常用于以下场景:

  1. 配置类中定义 Bean:在 @Configuration 注解的类中使用 @Bean 注解来显式定义和配置 Bean。这允许你在 Java 代码中控制 Bean 的创建和配置,而不是通过 XML 配置文件。

  2. 替代 XML 配置:使用 @Bean 可以代替传统的 XML 配置方式,使配置更具可读性和可维护性,同时也支持 Java 编程模型。

  3. 依赖注入:定义的 Bean 可以通过依赖注入注入到其他组件中,确保 Spring 容器能够管理它们的生命周期和依赖关系。

  4. 创建第三方库的 Bean:对于没有使用 @Component 注解的第三方类或不方便修改的类,使用 @Bean 可以在配置类中创建和配置这些 Bean。

  5. 条件创建 Bean:结合 @Conditional 注解,@Bean 可以用于在特定条件下创建 Bean,这在配置多环境或条件 Bean 时特别有用。

    19、使用 Redis 存储数据可以应对高并发负载和提供快速访问速度。以下是一些优化 Redis 存储的策略:

    1. 数据分片:利用 Redis 集群功能,将数据分片到不同的节点上,以提高存储容量和并发处理能力。

    2. 内存管理:配置适当的内存策略和淘汰机制(如 LRU、LFU)以避免内存溢出,并确保 Redis 持续高效运行。

    3. 持久化设置:根据需要配置 RDB 快照和 AOF 日志,以在 Redis 重启时恢复数据,但要权衡持久化开销和性能。

    4. 缓存策略:使用 Redis 作为缓存层来减少数据库的读负载。可以设置适当的过期时间和缓存失效策略。

    5. 异步操作:对于写入操作,可以使用 Redis 的异步写入功能,以提高写入性能并减少阻塞。

    6. 监控与调优:监控 Redis 性能指标,如内存使用、命令执行时间等,进行定期调优以维持最佳性能。

    7. 数据结构优化:选择适合的数据结构(如哈希表、集合、列表等)来存储数据,优化存储和操作效率。

    20、基于Redis的分布式锁

    • 原理:使用Redis的原子操作(如SETNX)来实现分布式锁。常见的实现方式是使用Redis的SET key value NX PX expire命令,这个命令会在键不存在时设置键的值,并设置键的过期时间,从而实现锁的获取。
    • 优点:性能高,支持高并发。Redis的SETNX命令原子性保证了锁的唯一性。
    • 缺点需要处理网络分区和Redis故障带来的锁失效问题。常见的解决方案包括使用Redisson库提供的高级锁功能,或在锁失效时使用Lua脚本等方式确保锁的正确释放。

21、看门狗机制工作原理:

  1. 锁获取: 当一个进程或线程希望获取分布式锁时,它会尝试在分布式锁服务中申请锁。如果成功获得锁,它会得到一个锁的标识符(ID)和一个锁的过期时间(TTL, Time-To-Live)。
  2. 启动看门狗: 获取锁的进程或线程会启动一个看门狗线程或定时任务,这个看门狗线程会周期性地向锁服务发送续期请求,以延长锁的有效期。
  3. 续期操作: 看门狗线程会定期更新锁的过期时间,以确保锁不会因为超时而自动释放。如果看门狗线程无法按时进行续期操作,分布式锁服务会认为持有者可能已经失效,进而释放锁。
  4. 锁释放: 当锁持有者完成对共享资源的操作后,它会主动释放锁,或者在看门狗机制无法再续期时,锁会在过期后自动释放,允许其他进程或线程获取锁。

通过Timeout,每10s钟,内部执行lua脚本,判断是否存在指定的key和filed,如果存在,说明业务还没有执行完,将锁的超时时间设置为30s

如下方法中,如果第二个参数设置为0,内部默认使用30s的过期时间,而且看门狗机制会生效

lock.tryLock(0, 0, TimeUnit.SECONDS)

                            
   private void renewExpiration() {
        RedissonBaseLock.ExpirationEntry ee = (RedissonBaseLock.ExpirationEntry)EXPIRATION_RENEWAL_MAP.get(this.getEntryName());
        if (ee != null) {
            Timeout task = this.commandExecutor.getConnectionManager().newTimeout(new TimerTask() {
                public void run(Timeout timeout) throws Exception {
                    RedissonBaseLock.ExpirationEntry ent = (RedissonBaseLock.ExpirationEntry)RedissonBaseLock.EXPIRATION_RENEWAL_MAP.get(RedissonBaseLock.this.getEntryName());
                    if (ent != null) {
                        Long threadId = ent.getFirstThreadId();
                        if (threadId != null) {
                            CompletionStage<Boolean> future = RedissonBaseLock.this.renewExpirationAsync(threadId);
                            future.whenComplete((res, e) -> {
                                if (e != null) {
                                    RedissonBaseLock.log.error("Can't update lock " + RedissonBaseLock.this.getRawName() + " expiration", e);
                                    RedissonBaseLock.EXPIRATION_RENEWAL_MAP.remove(RedissonBaseLock.this.getEntryName());
                                } else {
                                    if (res) {
                                        RedissonBaseLock.this.renewExpiration();
                                    } else {
                                        RedissonBaseLock.this.cancelExpirationRenewal((Long)null);
                                    }                         
                            }
                        });
                    }
                }
            }
        }, this.internalLockLeaseTime / 3L, TimeUnit.MILLISECONDS);
        ee.setTimeout(task);
    }
}
    RedissonBaseLock.this.cancelExpirationRenewal((Long)null);
                                }                         
                        }
                    });
                }
            }
        }
    }, this.internalLockLeaseTime / 3L, TimeUnit.MILLISECONDS);
    ee.setTimeout(task);
}

}


## 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值