可以,一个汉字在Java中通常需要占用两个char类型的存储空间,即一个汉字需要两个char来表示
list和set同属collection接口,list是有序的集合,可以包含重复元素,实现类有:ArrayList、LinkedList、Vector
set:无序的集合,不包含重复元素,实现类有 HashSet,TreeSet,
map无序不重复,key不可重复,value可以。它是以键值对方式存储的,具体实现类有Hashmap,treemap,hashtable
反射也称类的自省,在运行状态,任何一个类都可以动态获取它的所有属性和方法,任何属性都可以调用它的所有方法和属性。
主要应用:动态加载类和创建对象
动态调用方法和访问属性
获取类结构信息
编写通用框架
缺点:
性能较差: 因为是运行时获取类信息
安全性较差: 涉及到获取私有成员变量等
可读性和维护性差: 反射获取的代码比较复杂
Class
类:代表一个类或接口,在运行时可以通过该类获取类的信息,如类的名称、方法、字段等。可以使用Class.forName()
方法获取一个类的Class
对象。Constructor
类:代表一个构造方法,可以使用Class.getConstructors()
方法获取一个类的所有公共构造方法,或使用Class.getDeclaredConstructors()
方法获取一个类的所有构造方法,包括私有构造方法。Method
类:代表一个方法,可以使用Class.getMethods()
方法获取一个类的所有公共方法,或使用Class.getDeclaredMethods()
方法获取一个类的所有方法,包括私有方法。Field
类:代表一个字段,可以使用Class.getFields()
方法获取一个类的所有公共字段,或使用Class.getDeclaredFields()
方法获取一个类的所有字段,包括私有字段。Modifier
类:提供了一些静态方法,用于获取和操作成员的修饰符,如isPublic()
、isPrivate()
、isStatic()
等。重载是在一个类中,具有相同的方法名,但是它的参数列表必须不同,与返回值类型无关
重写是子类继承父类去重写父类的方法,相同的方法名,相同的参数列表,访问权限必须比父类更好。
加载,将.class字节码文件加载到JVM虚拟机中
验证,验证被加载的类的字节码文件的正确性和安全性。
准备,为静态变量分配内存并设置默认的初始值
解析,将符号引用解析为直接引用
初始化,执行类的初始化代码,包括静态变量的赋值和静态代码块的执行。
父类静态,子类静态,父类方法,子类方法。
String 是不可变的,由final修饰
StringBuffer是线程安全的
StringBuilder效率最快,但他线程不安全
Runable,callable,Thread,线程池
callable,可以捕获受检查的异常,并且可以有返回值
throws抛出的异常 要求调用者必须处理或者继续抛出会导致代码存在过多的异常抛出和处理逻辑增加冗余
异常处理繁琐:当每个方法都需要使用throws
声明异常时,调用栈上的每个方法都需要添加异常的处理逻辑,这样会导致异常处理的代码变得冗长和繁琐,降低代码的可读性和可维护性。
解决方案
对于可以预想到的异常,try-catch捕获处理
用全局异常处理?所有的异常统一使用一个类来处理
日志记录
错误提示
异常处理和回复
抛出新的异常
src/main/java
:用于存放主要的Java源代码文件。src/main/resources
:用于存放主要的资源文件,如配置文件、属性文件等。src/test/java
:用于存放测试相关的Java源代码文件泛型是Java中的一种编程机制,它允许在定义类、接口或方法时使用类型参数,以便在使用该类、接口或方法时指定具体的类型。泛型的主要目的是增加代码的类型安全性和重用性。
通过使用泛型,我们可以在编译时检查类型的一致性,避免了在运行时出现类型转换错误的可能性。泛型还可以提高代码的可读性和可维护性,因为代码中的类型信息更加明确。
七大参数:核心线程数,最大线程使用数,最大线程使用时间单位,线程工厂,拒绝策略。
当线程池的核心线程数已满,并且任务队列也已经满时,线程池会根据配置的拒绝策略来处理新提交的人
Java中的线程池使用ThreadPoolExecutor
类来实现,ThreadPoolExecutor
提供了几种预定义的拒绝策略:
AbortPolicy
(默认):线程池默认的拒绝策略,当线程池无法处理新任务时,会抛出RejectedExecutionException
异常。CallerRunsPolicy
:当线程池无法处理新任务时,会将任务返回给提交任务的线程执行。这样做的效果是,提交任务的线程自己执行任务,可以降低新任务的提交速度,但可能会影响整体性能。DiscardPolicy
:当线程池无法处理新任务时,会直接丢弃该任务,不会抛出异常。DiscardOldestPolicy
:当线程池无法处理新任务时,会丢弃任务队列中最旧的任务,然后尝试重新提交新任务。默认:当线程池无法处理新任务时,会抛出RejectedExecutionException异常。
一个修饰符 用于修饰变量 保证可见性和有序性, 不能保证原子性
被修饰的的变量会有两个特性
适合当多线程共享一个变量时.其中一个修改需要被其他线程所知的场景
只读场景
AQS内部有volatile修饰的变量state
标记状态
多线程用volatile修饰状态标记变量,用于状态标记被修改时,其他线程立刻可见
线程通信
可以使用 “volatile” 修饰共享变量。通过修改共享变量的值,一个线程可以通知其他线程进行相应的操作,保证线程之间的可见性
替换符 : 它将占位符直接替换为参数的值,相当于字符串拼接, :它将占位符直接替换为参数的值,相当于字符串拼接, :它将占位符直接替换为参数的值,相当于字符串拼接,不会对参数进行预编译或者转义,存在sql注入的风险。
占位符#:它会将占位符替换为参数的占位符,并且会对参数进行预编译和转义,以防止SQL注入的风险。
面向切面编程,
主要涉及三个线程:binlog 线程、I/O 线程和 SQL 线程。
binlog 线程 :负责将主服务器上的数据更改写入二进制日志(Binary log)中。
I/O 线程 :负责从主服务器上读取二进制日志,并写入从服务器的重放日志(Relay log)中。
SQL 线程 :负责读取重放日志并重放其中的 SQL 语句。
获取锁:当一个进程需要获取锁时,它会向Redis发送一个SET命令,将一个特定的键作为锁的标识,并设置一个唯一的值作为锁的持有者标识,同时设置一个过期时间,以防止锁被永久持有。
SET lock_key unique_value NX PX expiration_time
NX表示只有在键不存在时才设置成功,确保只有一个进程能够成功获取锁。
释放锁:当一个进程完成任务后,它会向Redis发送一个DEL命令,删除锁的键,释放锁。
DEL lock_key
使用分布式锁时需要注意以下几点:
锁的标识应该是唯一的,可以使用进程ID或者UUID等唯一标识符。
设置适当的过期时间,确保即使持有锁的进程崩溃或异常退出,锁也能够自动释放,避免死锁。
获取锁和释放锁的操作应该是原子的,可以使用Redis的SETNX和DEL命令组合实现原子性操作。
锁的持有时间应该尽量短,以免阻塞其他进程的执行。
需要注意的是,分布式锁并不能完全解决并发控制的问题,仍然可能存在竞态条件和死锁等问题。因此,在使用分布式锁时,需要根据具体情况仔细设计和测试,以确保并发控制的正确性和性能。