1.JDK 和 JRE 有什么区别
JDK(Java Development Kit),Java开发工具包
JRE(Java Runtime Environment),Java运行环境
JDK中包含JRE,JDK中有一个名为jre的目录,里面包含两个文件夹bin和lib,bin就是JVM,lib就是JVM工作所需要的类库
2.== 和 equals 的区别是什么
== :
基本类型:比较值是否相等
引用类型:比较内存地址值是否相等
equals :
引用类型:默认情况下,比较内存地址值是否相等。
3.final 在 java 中有什么作用?
(1 )用来修饰一个引用
如果引用为基本数据类型,则该引用为常量,该值无法修改;
如果引用为引用数据类型,比如对象、数组,则该对象、数组本身可以修改,但指向该对象或数组的地址的引用不能修改。
如果引用时类的成员变量,则必须当场赋值,否则编译会报错。
(2 )用来修饰一个方法
当使用final修饰方法时,这个方法将成为最终方法,无法被子类重写。但是,该方法仍然可以被继承。
(3 )用来修饰类
当用final修改类时,该类成为最终类,无法被继承。
比如常用的String类就是最终类。
4.String 属于基础的数据类型吗?
是引用类型
八种基本数据类型:byte、short 、char 、int 、long 、double 、float 、boolean
5.String 类的常用方法
indexOf ( ) :返回指定字符的索引。
charAt ( ) :返回指定索引处的字符。
replace ( ) :字符串替换。
trim ( ) :去除字符串两端空白。
split ( ) :分割字符串,返回一个分割后的字符串数组。
getBytes ( ) :返回字符串的 byte 类型数组。
length ( ) :返回字符串长度。
toLowerCase ( ) :将字符串转成小写字母。
toUpperCase ( ) :将字符串转成大写字符。
substring ( ) :截取字符串。
equals ( ) :字符串比较。
6.如何将字符串反转?
添加到StringBuilder中,然后调用reverse ( ) 。
7.普通类和抽象类有哪些区别?
抽象类不能被实例化;
抽象类可以有抽象方法,只需申明,无须实现;
有抽象方法的类一定是抽象类;
抽象类的子类必须实现抽象类中的所有抽象方法,否则子类仍然是抽象类;
抽象方法不能声明为静态、不能被static 、final修饰。
8.普通类和抽象类有哪些区别?
(1 )接口
接口使用interface修饰;
接口不能实例化;
类可以实现多个接口;
①java8之前,接口中的方法都是抽象方法,省略了public abstract。②java8之后;接口中可以定义静态方法,静态方法必须有方法体,普通方法没有方法体,需要被实现;
(2 )抽象类
抽象类使用abstract修饰;
抽象类不能被实例化;
抽象类只能单继承;
抽象类中可以包含抽象方法和非抽象方法,非抽象方法需要有方法体;
如果一个类继承了抽象类,①如果实现了所有的抽象方法,子类可以不是抽象类;②如果没有实现所有的抽象方法,子类仍然是抽象类。
9.java 中 IO 流分为几种?
(1 )按流划分,可以分为输入流和输出流;
(2 )按单位划分,可以分为字节流和字符流;
字节流:inputStream、outputStream;
字符流:reader、writer;
10.java 中 IO 流分为几种?
exist
createFile
createDirectory
write
read
copy
size
delete
move
11.什么是反射?
所谓反射,是java在运行时进行自我观察的能力,通过class、constructor、field、method四个方法获取一个类的各个组成部分。
在Java运行时环境中,对任意一个类,可以知道类有哪些属性和方法。这种动态获取类的信息以及动态调用对象的方法的功能来自于反射机制
在运行时判断任意一个对象所属的类。
在运行时构造任意一个类的对象。
在运行时判断任意一个类所具有的成员变量和方法。
在运行时调用任意一个对象的方法。
12.什么是 java 序列化?什么情况下需要序列化?
序列化就是一种用来处理对象流的机制。将对象的内容流化,将流化后的对象传输于网络之间。
序列化是通过实现serializable接口,该接口没有需要实现的方法,implement Serializable只是为了标注该对象是可被序列化的,使用一个输出流(FileOutputStream)来构造一个ObjectOutputStream对象,接着使用ObjectOutputStream对象的writeObejct(Object object)方法就可以将参数的obj对象到磁盘,需要恢复的时候使用输入流。
序列化是将对象转换为容易传输的格式的过程。
例如,可以序列化一个对象,然后通过HTTP通过Internet在客户端和服务器之间传输该对象。在另一端,反序列化将从流中心构造成对象。
一般程序在运行时,产生对象,这些对象随着程序的停止而消失,但我们想将某些对象保存下来,这时,我们就可以通过序列化将对象保存在磁盘,需要使用的时候通过反序列化获取到。
对象序列化的最主要目的就是传递和保存对象,保存对象的完整性和可传递性。
譬如通过网络传输或者把一个对象保存成本地一个文件的时候,需要使用序列化。
13.throw 和 throws 的区别?
作用在方法内,表示抛出具体异常,由方法体内的语句处理;
一定抛出了异常;
(2 )throws
作用在方法的声明上,表示抛出异常,由调用者来进行异常处理;
可能出现异常,不一定会发生异常;
14.final、finally、finalize 有什么区别?
final可以修饰类,变量,方法,修饰的类不能被继承,修饰的变量不能重新赋值,修饰的方法不能被重写
finally用于抛异常,finally代码块内语句无论是否发生异常,都会在执行finally,常用于一些流的关闭。
finalize方法用于垃圾回收。
一般情况下不需要我们实现finalize,当对象被回收的时候需要释放一些资源,比如socket链接,在对象初始化时创建,整个生命周期内有效,那么需要实现finalize方法,关闭这个链接。
但是当调用finalize方法后,并不意味着gc会立即回收该对象,所以有可能真正调用的时候,对象又不需要回收了,然后到了真正要回收的时候,因为之前调用过一次,这次又不会调用了,产生问题。所以,不推荐使用finalize方法。
15.常见的异常类有哪些?
NullPointerException:空指针异常;
SQLException:数据库相关的异常;
IndexOutOfBoundsException:数组下角标越界异常;
FileNotFoundException:打开文件失败时抛出;
IOException:当发生某种IO异常时抛出;
ClassCastException:当试图将对象强制转换为不是实例的子类时,抛出此异常;
NoSuchMethodException:无法找到某一方法时,抛出;
ArrayStoreException:试图将错误类型的对象存储到一个对象数组时抛出的异常;
NumberFormatException:当试图将字符串转换成数字时,失败了,抛出;
IllegalArgumentException 抛出的异常表明向方法传递了一个不合法或不正确的参数。
ArithmeticException当出现异常的运算条件时,抛出此异常。例如,一个整数“除以零”时,抛出此类的一个实例。
16.ArrayList和linkedList区别?
ArrayList:查询速度很快。但是增删稍慢。线程不同步。 删除一个元素后,该元素后面的所有元素前移
linkedList:增删速度很快,查询慢。线程不同步
17.List、Map、Set的区别
List、Map、Set三个接口,存取元素时,各有什么特点?
List 以特定次序来持有元素,可有重复元素;
Set 无法拥有重复元素, 内部排序(无序);
Map 保存key- value值,value可多值。
Hashmap可以存重复键,重复值吗? 不能存重复键
18.HashMap和Hashtable的区别?
Hashtable是线程安全的 不可以存入null键null值
HashMap线程不安全 可以存入null键null值
19.Collection 和 Collections的区别?
Collection是集合类的上级接口, 继承与他的接口主要有Set 和List.
Collections是工具类
20.线程的三种创建方法
1. 继承Thread类,重写父类run ( ) 方法
2. 实现runnable接口
3. 使用ExecutorService、Callable、Future实现有返回结果的多线程( JDK5. 0 以后)
21.线程的三种创建方法
线程在执行过程中,可以处于下面几种状态:
就绪( Runnable) : 线程准备运行,不一定立马就能开始执行。
运行中( Running) :进程正在执行线程的代码。
等待中( Waiting) : 线程处于阻塞的状态,等待外部的处理结束。
睡眠中( Sleeping) :线程被强制睡眠。
I/ O阻塞( Blocked on I/ O) :等待I/ O操作完成。
同步阻塞( Blocked on Synchronization) :等待获取锁。
死亡( Dead) :线程完成了执行。
22.sql三大查询
1 )左连接(左外连接)以左表为基准进行查询, 左表数据会全部显示出来, 右表如果和左表匹配的数据则显示相应字段的数据, 如果不匹配, 则显示为NULL ;
2 )右连接(右外连接)以右表为基准进行查询, 右表数据会全部显示出来, 右表如果和左表匹配的数据则显示相应字段的数据, 如果不匹配, 则显示为NULL ;
3 )全连接就是先以左表进行左外连接,然后以右表进行右外连接。
4 ) 内连接:显示表之间有连接匹配的所有行。
23.mysql性能优化
1 ) 当只要一行数据时使用 LIMIT 1
当你查询表的有些时候,你已经知道结果只会有一条结果,在这种情况下,加上 LIMIT 1 可以增加性能。这样一样,MySQL数据库引擎会在找到一条数据后停止搜索,而不是继续往后查少下一条符合记录的数据。
2 )选择正确的存储引擎
在 MySQL 中有两个存储引擎 MyISAM 和 InnoDB,每个引擎都有利有弊。
MyISAM 适合于一些需要大量查询的应用,但其对于有大量写操作并不是很好。甚至你只是需要update一个字段,整个表都会被锁起来,而别的进程,就算是读进程都无法操作直到读操作完成。另外,MyISAM 对于 SELECT COUNT ( * ) 这类的计算是超快无比的。
InnoDB 的趋势会是一个非常复杂的存储引擎,对于一些小的应用,它会比 MyISAM 还慢。他是它支持“行锁” ,于是在写操作比较多的时候,会更优秀。并且,他还支持更多的高级应用,比如:事务。
3 )用Not Exists 代替Not In
Not Exists允许用户使用相关子查询已排除一个表中能够与另一个表成功连接的所有记录。Not Exists用到了连接,能够发挥已经建好的索引的作用,而Not In不能使用索引。Not In是最慢的方式,要同每条记录比较,在数据量比较大的查询中不建议使用这种方式。
Select a. mobileid from Log_user a where not exists ( select b. mobileid from magazineitem b where b. mobileid= a. mobileid) ;
4 )对操作符的优化 尽量不采用不利用索引的操作符
如:in ,not in , is nul, is not null,< > 等
24.@Resource和@Autowired的区别
@Resource 由jdk提供
@Autowired 由spring提供
@Autowired
@Qualifier ( "cusInfoService" )
@Resource ( name= "cusInfoService" )
25.高并发解决方案
1. 针对同一个用户id来实现,前端js控制一个客户端几秒之内只能发送同一个请求,后端校验同一个uid在几秒之内返回同一个页面
2. 针对同一个ip来实现,进行ip检测,同一个ip几秒之内不发送请求或者只返回同一个页面
3. 针对多用户多ip来实现,依靠数据分析
4. 为了避免用户直接访问下单页面URL,需要将改URL动态化,即使秒杀系统的开发者也无法在秒杀开始前访问下单页面的URL。办法是在下单页面URL加入由服务器端生成的随机数作为参数,在秒杀开始的时候才能得到。
4. 后端层面:
1. 加入缓存redis:
因为秒杀是典型的读多写少的场景,适合操作内存而非操作硬盘;缓存工具redis本身的操作是保证原子性的,所以可以保证请求了redis的写的操作的线程安全性。
2. 加入消息队列,利用队列进行削峰:
将用户请求放置于一个或多个队列中,队列中元素总和等于该商品库存总和,未进入队列的请求均失败。利用多线程轮询分别从一个或多个队列中取出用户请求。操作redis进行减库存操作,成功减库存之后返回成功,并将用户信息与商品信息存入另一个队列当中,进行生成订单的操作。利用两个队列异步处理业务减轻秒杀高峰时期服务器负载。
3. 程序计数器:
队列与缓存为了保证请求redis的次数不超过总的库存量,利用一个程序计数器来这一点。程序计数器用JUC包下原子类可以实现。
4. 分布式锁
分布式情况下可以利用分布式锁来解决任务每次只能由一次服务来执行且不能重复执行。
分布式锁的实现:zk、redis
分布式锁的优化:先考虑是否可以去锁,然后考虑尽可能多用乐观锁,少用悲观锁。这里有一个问题,乐观锁如果每一次都会有并发冲突的话性能反而不如悲观锁,那么难道真的多用乐观锁性能会比悲观锁高吗?选举考虑ha,比如心跳检测。
5. 分布式去锁 方案
利用集群并发加入队列,选举队列处理服务单点执行,这样可以保证并发实现和加锁一样的并发量但不会影响性能。
26.redis哪些地方用到了?
redis 是一款开源的 Key- Value 数据库,运行在内存中,由 ANSI C 编写。企业开发通常 采用 Redis 来实现缓存。
Redis在本系统中主要体现在:缓存和解决session共享
作为内存数据库,用作缓存时redis基本使用,我们在商品分页查询已经首页轮播图的展示时均使用了redis作为缓存数据库,当查询请求过来时,首先回去redis查询是否有相关数据,如果有,直接返回,反之,会发送sql语句给数据库,将相关数据查询出来,并将数据写入redis中,最终返回给前端页面。
另外使用redis的地方就是在解决我们单点登录系统时候出现的session共享问题,何为session共享。我们都知道用户登陆成功后,用户信息是存储到session中的,而我们的系统在分布式系统,每个模块都是一个独立的web工程,也就是说,每个模块时部署在不同的tomcat服务器中的。但是每个服务器的session是不共享的,这样就会出现一个问题,当我从登陆登入首页时,会重新跳转到登陆页面,因为单点登录系统中的用户信息无法传递到前台系统中。即:session共享问题。由于redis是k- v数据库,session同样是存储k- v的,可以用redis来模拟session,将redis部署到服务器中,这样就可以使得每个系统在运行的时候,回去服务器中请求加载存储到redis的用户信息,session共享问题引刃而解。
27.redis五种类型
String:字符串类型
List:列表类型
Set:无序集合类型
ZSet:有序集合类型
Hash:哈希表类型
28.StringBuffer 和 StringBuilder区别
StringBuffer:线程安全,
StringBuilder:线程不安全,k v可以存null
29.final 在 java 中有什么作用?
final 修饰的类叫最终类,该类不能被继承。
final 修饰的方法不能被重写。
final 修饰的变量叫常量,常量必须初始化,初始化之后值就不能被修改。
30.抽象类能使用 final 修饰吗?
不能,定义抽象类就是让其他类继承的,如果定义为 final 该类就不能被继承,这样彼此就会产生矛盾,所以 final 不能修饰抽象类
31.接口和抽象类有什么区别?
实现:抽象类的子类使用 extends 来继承;接口必须使用 implements 来实现接口。
构造函数:抽象类可以有构造函数;接口不能有。
main 方法:抽象类可以有 main 方法,并且我们能运行它;接口不能有 main 方法。
实现数量:类可以实现很多个接口;但是只能继承一个抽象类。
访问修饰符:接口中的方法默认使用 public 修饰;抽象类中的方法可以是任意访问修饰符。
32.java 中 IO 流分为几种?
按功能来分:输入流(input)、输出流(output)。
按类型来分:字节流和字符流。
字节流和字符流的区别是:字节流按 8 位传输以字节为单位输入输出数据,字符流按 16 位传输以字符为单位输入输出数据。
33.java 容器都有哪些?