查漏补缺(四)

本文介绍了Java中的反射机制,其作用包括动态获取类信息、创建对象、调用方法和修改属性。此外,文章还讨论了线程池的原理和使用,以及MySQL中的InnoDB和MyISAM存储引擎差异,以及Redis在缓存、消息队列等方面的应用。
摘要由CSDN通过智能技术生成

一、什么是java中的反射?

Java中的反射机制是指在运行状态中,对于任意的一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态调用对象的方法的功能成为java的反射机制。

反射其实就是把java类中的各种成分映射成一个个的java对象

二、反射的作用

  1. 运行时动态获取类的信息:在编写代码时,对于类的信息是在编译时确定的,但在运行时,有时需要根据某些条件,动态的获取某个类的信息,这时就可以使用java中的反射机制。
  2. 动态生成对象:反射机制可以在运行时生成对象,这样就可以根据参数的不同,动态的创建不同的类的实例对象。
  3. 动态调用方法:通过反射机制可以调用类中的方法,不论这些方法是否是公共的,也不论这些方法的参数个数和类型是什么,反射机制都具有这样的能力。
  4. 动态修改属性:利用反射机制可以获取到类中的所有成员变量,并可以对其进行修改。
  5. 实现动态代理:利用反射机制可以实现代理模式,通过代理对象完成原对象对某些方法的调用,同时也可以在这些方法的调用前后进行一些额外的处理。

反射的优点

  1. 增加灵活性额扩展性:使用反射机制可以在程序运行时动态加载、修改、创建、调用类和方法等,从而增加程序的灵活性和可扩展性。
  2. 提高代码的通用性:使用反射机制可以动态的获取类信息,从而编写通用的低吗,使得不同的类能够以相同的方式来处理。
  3. 规范代码结构:反射机制可以使代码结构清晰明了,减少了代码中的冗余部分。
  4. 实现框架和插件
  5. 动态代理:可以在不修改原来代码的情况下,通过代理对象对原对象的方法进行增强。

三、通过反射创建类实例

对象.newInstance()

public static void main(String[] args) throws Exception {

//一切反射从类类开始

Class<Student> c1=Student.class;

Student stu=new Student();

//调用无参构造器反射实例化

Object o=c1.newInstance();

System.out.println(o);

//调用1个参数的构造器反射实例化

Constructor<Student> ct = c1.getConstructor(String.class);

Student student = ct.newInstance("5869");

System.out.println(student);

//调用2个参数的构造器反射实例化

 Constructor<Student> ct1 = c1.getConstructor(String.class,String.class);

        Student s2 = ct1.newInstance("66744", "小文子");

        System.out.println(s2);

        //getConstructor方法只能获取到公有的构造器对象

        //调用私有化的构造器反射实例化

        Constructor<Student> ct2 = c1.getDeclaredConstructor(Integer.class);

        //打开私有修饰的访问权限

        ct2.setAccessible(true);

        Student ss = ct2.newInstance(89);

        System.out.println(ss);

}

反射读写属性

getName()  返回属性名

getModifiers() 获取属性的修饰符李彪,返回的修饰符是一个数字,每个数字是修饰符的代号

getClass 以class类型,返回属性类型

Set()  设置属性值

Get() 读取属性值

反射机制应用场景

  1. 框架开发:许多流行的框架,比如spring等,都使用了反射机制,以提供更灵活、可扩展的特性。
  2. 应用程序开发:常常用于某些需要动态加载或访问类信息的应用程序中,比如动态配置、插件管理等
  3. 单元测试:JUnit测试框架中广泛使用反射机制,可以方便的创建测试对象和调用测试方法。
  4. 动态代理:反射机制可以实现动态代理,在不改变原来代码的情况下,对原来对象的方法进行增强。
  5. JavaBean工具:javabean工具中,利用反射机制可以获取类的属性名、属性值、调用属性的setter和getter方法等信息,方便进行对象的序列化和反序列化操作。

四、深拷贝和浅拷贝的区别

深拷贝和浅拷贝就是指对象的拷贝,一个对象中存在两种类型的属性,一种是基本数据类型,一种是实例对象的引用。

1. 浅拷贝是指,只会拷贝基本数据类型的值,以及实例对象的引用地址,并不会复制一份引用地址所指向的对象,也就是浅拷贝出来的对象,内部的类属性指向的是同一个对象

2. 深拷贝是指,既会拷贝基本数据类型的值,也会针对实例对象的引用地址所指向的对象进行复制,深拷贝出来的对象,内部的类执行指向的不是同一个对象

五、线程池的作用

线程池就是事先将多个线程对象放到一个容器中,当使用的时候就不用 new 线程而是直接去池中拿线程即可,节省了开辟子线程的时间,提高的代码执行效率

生成多种线程池的静态方法

1.. newCachedThreadPool

创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

这种类型的线程池特点是:

工作线程的创建数量几乎没有限制(其实也有限制的,数目为Interger. MAX_VALUE), 这样可灵活的往线程池中添加线程。

如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默认为1分钟),则该工作线程将自动终止。终止后,如果你又提交了新的任务,则线程池重新创建一个工作线程。

在使用CachedThreadPool时,一定要注意控制任务的数量,否则,由于大量线程同时运行,很有会造成系统瘫痪。

2.. newFixedThreadPool

创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。

FixedThreadPool是一个典型且优秀的线程池,它具有线程池提高程序效率和节省创建线程时所耗的开销的优点。但是,在线程池空闲时,即线程池中没有可运行任务时,它不会释放工作线程,还会占用一定的系统资源。

3.. newSingleThreadExecutor

创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。如果这个线程异常结束,会有另一个取代它,保证顺序执行。单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。

4... newScheduleThreadPool

创建一个定长的线程池,而且支持定时的以及周期性的任务执行。例如延迟3秒执行。

为什么要使用线程池

1. 线程池做的工作主要是控制运行的线程数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过了最大数量,超出数量的线程排队等候,等其它线程执行完毕,再从队列中取出任务来执行。

2. 主要特点:线程复用;控制最大并发数:管理线程。

第一:降低资源消耗。通过重复利用己创建的线程降低线程创建和销毁造成的消耗。

第二:提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。

第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进 行统一的分配,调优和监控

六、用过什么数据库

关系型数据库:mysql、(SQL Server、Oracle、PostgreSQL)

非关系型数据库 :redis、(MongoDB等)

七、mysql存储引擎

常用的InnoDB 和MyISAM 还有CSV、Archive、Memory、

MyISAM :默认表类型,它是基于传统的ISAM类型,ISAM是Indexed Sequential Access Method (有索引的顺序访问方法) 的缩写,它是存储记录和文件的标准方法。不是事务安全的,而且不支持外键,如果执行大量的select,insert MyISAM比较适合。

InnoDB :支持事务安全的引擎,支持外键、行锁、事务是他的最大特点。如果有大量的update和insert,建议使用InnoDB,特别是针对多个并发和QPS较高的情况。

注: 在MySQL 5.5之前的版本中,默认的搜索引擎是MyISAM,从MySQL 5.5之后的版本中,默认的搜索引擎变更为InnoDB。

MyISAM和InnoDB的区别:

1.InnoDB支持事务,MyISAM不支持。对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务;

2.InnoDB支持外键,而MyISAM不支持。

3.InnoDB是聚集索引,使用B+Tree作为索引结构,数据文件是和(主键)索引绑在一起的(表数据文件本身就是按B+Tree组织的一个索引结构),必须要有主键,通过主键索引效率很高。MyISAM是非聚集索引,也是使用B+Tree作为索引结构,索引和数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。

4.InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描。而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快。

5.Innodb不支持全文索引,而MyISAM支持全文索引,查询效率上MyISAM要高;5.7以后的InnoDB支持全文索引了。

6.InnoDB支持表、行级锁(默认),而MyISAM支持表级锁。

7.InnoDB表必须有主键(用户没有指定的话会自己找或生产一个主键),而Myisam可以没有。

8.Innodb存储文件有frm、ibd,而Myisam是frm、MYD、MYI。

Innodb:frm是表定义文件,ibd是数据文件。

Myisam:frm是表定义文件,myd是数据文件,myi是索引文件。

八、数据库索引的作用

数据库索引是一种数据结构,它可以帮助数据库系统快速查找和检索数据。索引可以加速对数据库表的查询操作,从而提高系统的性能。

在数据库中,索引通常被用于以下情况:

快速查找特定值:当您需要查找表中的特定值时,索引可以帮助您快速找到该值。例如,如果您需要查找表中某个特定客户的姓名或电子邮件地址,则可以使用索引来快速查找该值。

快速匹配特定模式:当您需要对包含大量数据的表进行查询时,索引可以帮助您快速匹配特定的模式。例如,如果您需要查找包含特定单词的文档,则可以使用索引来快速找到该单词。

优化排序和连接操作:索引还可以帮助优化排序和连接操作。在进行这些操作时,索引可以提供指向相关数据的指针,从而减少查询的开销。

九、索引底层实现原理

数据库索引是存储在磁盘上的,当数据量大时,就不能把整个索引全部加载到内存了,只能逐一加载每一个磁盘块(对应索引树的节点),索引树越低,越矮胖,磁盘IO次数就少。

MySQL支持两种索引,一种的B-树(但实际上MySQL采用的是B+树结构)索引,一种是哈希索引,B-树和哈希表在数据查询时的效率是非常高的。

十、redis的作用

Redis是一种开源的NoSQL内存数据库,用于高性能的数据存储和访问。Redis支持多种数据类型,包括字符串、哈希、列表、集合和有序集合,并且支持分布式存储和操作。Redis的特点包括快速、高可用和易扩展等,适用于各种应用场景。

应用场景:

  1. 缓存:适合用作缓存的存储层。Redis可以缓存数据的计算结果、页面内容、数据库查询结果等,通过提高数据访问速度和响应速度,提升系统性能和用户体验。
  2. 消息队列:可以作为一种高性能的消息队列使用,实现异步处理和解耦。Redis支持列表数据类型,可以将消息存储在列表中,并且支持阻塞式操作,可以实现消息队列的等待和通知机制。
  3. 分布式锁:可以作为一种分布式锁的存储层,通过缓存锁信息和锁状态,实现分布式锁和并发控制。Redis支持多种数据类型,包括字符串、哈希、列表、集合和有序集合,可以根据不同的场景选择合适的数据类型来实现分布式锁。
  4. 计数器:可以作为一种计数器的存储层,通过原子操作实现计数器的自增和自减,支持高并发的计数操作。Redis还支持多种数据类型,包括哈希、列表、集合和有序集合,可以实现多维度的计数功能。
  5. 数据库:作为一种轻量级的数据库使用,支持持久化和数据备份,可以用于存储少量的数据和应用场景。Redis支持多种数据类型,可以根据不同的数据特性和访问模式选择合适的数据类型来存储数据。
  6. 其它:还可以用于实现分布式缓存、实时统计、推荐系统、热点数据存储、地理位置存储和时序数据存储等应用场景,具有非常广泛的应用前景。

使用redis的注意事项

Redis是一种内存数据库,所以需要合理的规划对应的内存优化策略。

1、控制key的长度,当key的量级很大的时候,合理的控制key的长度可以节省很大的空间。

2、避免存储bigkey,除了控制key的长度,value的大小也要关注,string的大小控制在10kb以下,list、hash、set、zset也要控制。

3、合理的选择数据类型

String、Set 在存储 int 数据时,会采用整数编码存储。Hash、ZSet 在元素数量比较少时(可配置),会采用压缩列表(ziplist)存储,在存储比较多的数据时,才会转换为哈希表和跳表。

String、Set:尽可能存储 int 类型数据

Hash、ZSet:存储的元素数量控制在转换阈值之下,以压缩列表存储,节约内存

4、把redis尽可能的当成缓存使用

5、实例设置maxmemory+淘汰策略

虽然使用redis的时候会设置key的过期时间,但是如果业务写入量比较大的话,那么短期内redis的内存依旧会快速增加。需要提前预估业务数据量,然后给实例设置maxmemory控制实例的内存上限,然后需要设置内存过期策略。

volatile-lru / allkeys-lru:优先保留最近访问过的数据

volatile-lfu / allkeys-lfu:优先保留访问次数最频繁的数据(4.0+版本支持)

volatile-ttl :优先淘汰即将过期的数据

volatile-random / allkeys-random:随机淘汰数据

6、数据压缩后写入redis

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值