寒假复习第1天
一、Java面向对象有哪些特征?
1、继承:子类继承父类的属性。
优点:增加了代码的可重用性。(公有属性写在父类)
2、封装:封装类内部的实现机制,在不改变接口的情况下,改变类的内部结构。
优点:1、有助于保障数据安全;
2、增加了代码的可重用性;(封装好的类可重复使用)
3、增加代码可维护性,便于代码修改。
3、多态:
多态三要素(必备):
1、继承;
2、重写;
3、父类引用指向子类对象。
优点:1、增加了代码的可移植性;
2、增加了代码的健壮性;
3、增加了代码的灵活性。(实现随便变)
二、ArrayList和LinkedList的区别?
ArrayList和LinkedList都实现了List接口,但是它们的底层实现方式不一样。
1、ArrayList的底层是用数组来实现的;
特点:查询数据比较快;插入、删除数据比较慢。
2、LinkedList的底层是用链表来实现的。
特点:插入、删除数据比较快;查询数据比较慢。
三、高并发中的集合有哪些问题?
第一代线程安全集合类
Vector、Hashtable
线程安全:使用synchronized修饰方法。(锁)
缺点:效率低下
第二代线程非安全集合类
ArrayList、HashMap
线程不安全,但是性能好,用来替代Vector、Hashtable
使用ArrayList、HashMap,需要线程安全怎么办?
使用Collections.synchronizedList(list);Collections.synchronizedMap(list)。
底层使用synchronized代码块锁 虽然也能锁住所有代码,但是锁在方法里边,还是不够灵活。
第三代线程安全集合类
在大量并发情况下如何提高集合的效率与安全呢?
java.util.concurrent.*
ConcurrentHashMap:
CopyOnWriteArrayList:
CopyOnWriteArraySet:(不是CopyOnWriteHashSet*)
底层大都采用Lock锁(1.8的CopyOnWriteHashSet不使用Lock锁),保障安全的同时,性能也很高。
四、JDK1.8的新特性有哪些?
1、接口的默认方法
Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用default关键字即可,这个特征又叫做扩展方法。(实现默认方法是为了兼容Lambda表达式)
2、Lambda表达式(最重要)
面向函数式编程
3、函数式接口
lambda表达式是如何在Java的类型系统中表示的呢?
每一个lambda表达式都对应一个类型,通常是接口类型。而“函数式接口”是指仅仅包含一个抽象方法的接口,每一个该类型的lambda表达式都会被匹配到这个抽象方法。因为 默认方法 不算抽象方法,所以也可以给函数式接口添加默认方法。
我们可以将lambda表达式当作任意只包含一个抽象方法的接口类型。确保接口一定要达到这个要求,只需给接口添加@Functionallnterface注解,编译器如果发现标注该注解的接口多于一个抽象方法时会报错。
4、方法与构造函数引用
Java 8中允许使用 ::关键字来传递方法或者构造体引用。
5、Lambda作用域
在lambda表达式中访问外层作用域和老版本的匿名对象中的方式很相似,可以直接访问标志了final的外层局部变量,或者实例的字段以及静态变量。不需要声明final,也不可以被修改。
6、访问局部变量
Java 8中允许直接在lambda表达式中访问外层的局部变量。
7、访问对象字段与静态变量
与本地变量不同,lambda表达式内部对于实例字段以及静态变量是即可读又可写的,该行为与匿名函数一致。
8、访问接口的默认方法(新方法)
9、Date API(新类)
10、Annotation注解
Java 8中支持多重注解。
五、Java接口和抽象类有哪些区别?
相同:
1、不能够实例化;
2、可以将抽象类和接口类作为引用类型;
3、一个类如果继承了某个抽象类或者实现了某个接口都需要对其中的抽象方法全部进行实现,否则该类仍然需要被声明为抽象类。
不同:
抽象类:
1、抽象类中可以定义构造器;
2、可以有抽象方法和具体方法;
3、接口中的成员变量修饰符都是public;
4、抽象类中可以定义成员变量;
5、有抽象方法的类必须被声明为抽象类,而抽象类未必要有抽象方法;
6、抽象类中可以包含静态方法;
7、一个类只能继承一个抽象类。
接口:
1、接口中不能定义构造器;
2、方法全部都是抽象方法;
3、抽象类中的成员变量访问修饰符全都可以用;
4、接口中定义的变量实际上都是常量;
5、接口中不能有静态方法;
6、一个类可以实现多个接口;
语意区别
抽象类:人类普遍认知的抽象概念。(如:狗、车、人)
接口:描述事物的某一个特征。(如:会飞、有皮毛)
六、分布式ID的生成方案有哪些?
1、UUID
UUID是通用唯一标识码的缩写,其目的是让分布式系统中的所有元素都有唯一的辨识信息,而不需要通过中央控制器来指定唯一标识。
优点:
1、降低全局节点的压力,使得主键生成速度更快;
2、生成的主键全局唯一;
3、跨服务器合并数据方便。
缺点:
1、UUID占用16个字符,空间占用较多;
2、不是递增有序的的数字,数据写入IO随机性很大,且索引效率下降。
2、数据库主键自增
MySQL数据库设置主键且主键自动增长。
优点:
1、int和bigint类型占用空间较小;
2、主键自动增长,IO写入连续性好;
3、数字类型查询优于字符串。
缺点:
1、并发性能不高,受限于数据库性能;
2、分库分表情况下,需要改造,比较复杂;
3、自增:数据和数据量泄露。
3、Redis自增
Redis计数器,原子性自增。
优点:
1、使用内存,并发性能好。
缺点:
1、数据丢失;
2、自增:数据泄露。
4、雪花算法(snowflake)
大名鼎鼎的雪花算法,分布式ID的经典解决方案。
优点:
1、不依赖外部组件;
2、性能好。
缺点:
1、时钟回拨,可能重复。
七、雪花算法生成的ID由哪些部分组成?
1、符号位,占用 1 bit;
2、时间戳,占用 41 bit;
3、工作机器ID,占用 10 bit;
4、序列号,占用 12 bit。
一共占用 64 位。
八、分布式锁在项目中有哪些应用场景?
使用分布式锁的场景一般满足以下条件:
1、系统是一个分布式系统,Java的锁已经锁不住;
2、多个系统操作共享资源,比如库里唯一的用户数据;
3、同步访问,即多个进程同时操作共享资源。
九、分布式锁有哪些解决方案?
1、Redis的分布式锁,很多大公司会基于Redis做扩展开发。setnx,Redisson。
2、Zookeeper,顺序临时结点;
3、基于数据库,如:MySQL,主键或唯一索引的唯一性。