Java电话面试题问题,三年工作经验

7 篇文章 0 订阅
2 篇文章 0 订阅

1.最主要的深入了解spring的IOC和aop和常用的注解

2.SpringCloud 的相关的组件

3.SpringbootApplication的作用

1.分布式事务的节点

存在一个节点作为协调者(Coordinator),其他节点作为参与者(Cohorts)。且节点之间可以进行网络通信。
有了解分布式事务如何实现?

答:分布式事务可以采用分布式锁进行实现,目前zookeeper就提供此锁;分布式锁需要牺牲一定性能去实现,若业务支付最终一致性,那此方法是最佳方案。
如在京东下订单,过一会才会告诉你订单审核通过,而不是马上响应订单结果。
zookeeper的工作原理

Zookeeper的核心是原子广播,这个机制保证了各个server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分别是恢复模式和广播模式。

2.orcal和MYSQL的分页查询

①MySql数据库,采用limit语句进行分页
②Oracle数据库,采用rownum的方式进行分页(查询数据库前4条数据)

3.索引失效

1、使用like关键字模糊查询时,% 放在前面索引不起作用,只有“%”不在第一个位置,索引才会生效(like ‘%文’–索引不起作用)
2、使用联合索引时,只有查询条件中使用了这些字段中的第一个字段,索引才会生效
3、使用OR关键字的查询,查询语句的查询条件中只有OR关键字,且OR前后的两个条件中的列都是索引时,索引才会生效,否则索引不生效。
4、尽量避免在where子句中使用!=或<>操作符,否则全表扫描。
5、对查询进行优化,应尽量避免全表扫描,首先应考虑在where以及order by涉及的列上建立索引。
6、应尽量避免在 where 子句中对字段进行表达式操作,否则全表扫描。
7、尽量避免在where子句中对字段进行函数操作,否则全表扫描。
8、不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
9、并不是所有的索引对查询都有效,sql是根据表中的数据来进行查询优化的,当索引列有大量数据重复时,sql查询不会去利用索引
10、索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,
  因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,
11、尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。
  这是因为引擎在处理查询和连接时会 逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。
12、mysql查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。
   因此数据库默认排序可以符合要求的情况下不要使用排序操作,尽量不要包含多个列的排序,如果需要最好给这些列建复合索引。
13、order by 索引 ,不起作用的问题(除了主键索引之外):
  1、 如果select 只查询索引字段,order by 索引字段会用到索引,要不然就是全表排列;
   2、如果有where 条件,比如where vtype=1 order by vtype asc . 这样order by 也会用到索引!

4.Redis持久化

RDB持久化

在默认情况下, Redis 将数据库快照保存在名字为 dump.rdb 的二进制文件中。
AOF持久化
AOF持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录

5.#和$的区别

  1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by “111”, 如果传入的值是id,则解析成的sql为order by “id”.
  2. $将传入的数据直接显示生成在sql中。如:order by u s e r i d user_id userid,如果传入的值是111,那么解析成sql时的值为order by user_id, 如果传入的值是id,则解析成的sql为order by id.
  3. #方式能够很大程度防止sql注入。 
    4. 方 式 无 法 防 止 S q l 注 入 。 5. 方式无法防止Sql注入。 5. Sql5.方式一般用于传入数据库对象,例如传入表名.
    6.一般能用#的就别用 . M y B a t i s 排 序 时 使 用 o r d e r b y 动 态 参 数 时 需 要 注 意 , 用 . MyBatis排序时使用order by 动态参数时需要注意,用 .MyBatis使orderby而不是#

6. 说说数据库性能优化有哪些方法?

1、查询语句中不要使用 *
2、尽量减少子查询,使用关联查询(left join,right join,inner join)替代
3、减少使用IN或者NOT IN ,使用exists,not exists或者关联查询语句替代
4、or 的查询尽量用 union或者union all 代替
(在确认没有重复数据或者不用剔除重复数据时,union all会更好)
5、合理的增加冗余的字段(减少表的联接查询)
6、增加中间表进行优化(这个主要是在统计报表的场景,
后台开定时任务将数据先统计好,尽量不要在查询的时候去统计)
7、建表的时候能使用数字类型的字段就使用数字类型(type,status…),数字类型的字段作为条件查询比字符串的快
8、那些可以过滤掉最大数量记录的条件必须写在WHERE子句的最末尾

7.Redis缓存穿透,缓存雪崩,缓存击穿

缓存穿透,是指查询一个数据库一定不存在的数据。正常的使用缓存流程大致是,
数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查询,并把查询到的对象,放进缓存。如果数据库查询对象为空,则不放进缓存.
解决方案:缓存空值,设置一个较短的缓存时间

缓存雪崩,是指在某一个时间段,缓存集中过期失效
解决方案:一般是采取不同分类,缓存不同周期。在同一分类中,加上一个随机因子。
这样能尽可能分散缓存过期时间,而且,热门类目缓存时间长一些,冷门类目缓存时间短一些,也能节省缓存服务的资源。

缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,
就像在一个屏障上凿开了一个洞。
对于非常热点的key直接设为永不过期/mutex key互斥锁

8.HashMap和ConcurrentHashMap

基于JDK1.8,ConcurrentHashMap、HashMap是基于Node<K,V>[]数组和链表/红黑树实现的。不同点在于HashMap线程不安全
,ConcurrentHashMap通过使用CAS+Synchronized(1.8以前使用分段锁)来保证线程安全的。

9.数据库索引

数据库索引是数据库管理系统中的一个排序的数据结构,以协助快速查询,更新数据库表中数据,索引的实现通常使用B树(B-tree)以及其变种B+tree(一些高效率的算法)

10.分布式环境如何保证session一致性

1.ngnix的iphash可以
2.使用spring-session框架来解决,底层采用重写httpclient保证数据共享
3.使用token令牌代替session功能,把数据存放在redis中,每次从redis中获取数据

12.springcloud什么情况下会触发保护机制、

1.EurekaClient会定时向EurekaServer端发送心跳,如果EurekaServer在一定时间内没有收到EurekaClient发送的心跳,便会把该实例从注册服务列表中剔除(默认是90秒),但是在短时间内丢失大量的实例心跳,这时候EurekaServer会开启自我保护机制,Eureka不会剔除该服务。
2.高并发情况下,大量的请求堆积在一个服务上,超过服务线程池(默认为tomcat自带的线程池)处理的最大线程数,导致其他服务没有线程进行接受请求

13.springbootapplication的作用

@Configuration:表示将该类作用springboot配置文件类。

@EnableAutoConfiguration:表示程序启动时,自动加载springboot默认的配置。

@ComponentScan:表示程序启动是,自动扫描当前包及子包下所有类。

14.数据库中char和varchar的区别为:长度不同、效率不同、存储不同。

一、长度不同

1、char类型:char类型的长度是固定的。

2、varchar类型:varchar类型的长度是可变的。
二、效率不同

1、char类型:char类型每次修改的数据长度相同,效率更高。

2、varchar类型:varchar类型每次修改的数据长度不同,效率更低。
三、存储不同

1、char类型:char类型存储的时候是初始预计字符串再加上一个记录字符串长度的字节,占用空间较大。

2、varchar类型:varchar类型存储的时候是实际字符串再加上一个记录字符串长度的字节,占用空间较小。

15.String和StringBuffer、StringBuilder的区别是什么?String为什么是不可变的

String中的对象是不可变的,也就可以理解为常量,线程安全。AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,
定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。
StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。

如何保证同步

一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在 java里边就是拿到某个同步对象的锁(一个对象只有一把锁); 如果这个时候同步对象的锁被其他线程拿走了,他(这个线程)就只能等了(线程阻塞在锁池 等待队列中)。 取到锁后,他就开始执行同步代码(被synchronized修饰的代码);线程执行完同步代码后马上就把锁还给同步对象,其他在锁池中 等待的某个线程就可以拿到锁执行同步代码了。这样就保证了同步代码在统一时刻只有一个线程在执行。
同步机制实现方式包括但不限于:
①ThreadLocal ② synchronized( ) ③ wait() 与 notify() ④ volatile

16.常用的连接池:

DBCP数据源
  DBCP 是 Apache 软件基金组织下的开源连接池实现,要使用DBCP数据源,需要应用程序应在系统中增加如下两个 jar 文件:

Commons-dbcp.jar:连接池的实现
Commons-pool.jar:连接池实现的依赖库
  Tomcat 的连接池正是采用该连接池来实现的。该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。
常见的连接池有哪些?
3.3、C3P0数据源(重点)
  C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。C3P0数据源在项目开发中使用得比较多。

c3p0与dbcp区别

dbcp默认不自动回收空闲连接,需要手动开启
c3p0默认自动回收空闲连接功能

分布式锁
Hashmap的底层实现原理

17.抽象类和接口的对比:

相同点
1.接口和抽象类都不能实例化
2.都位于继承的顶端,用于被其他实现和继承
3.都包含抽象方法,其子类都必须复写这些抽象方法

不用点
声明:
抽象类:使用abstract关键字声明
接口:用interface关键字声明
实现;
抽象类:用extends,如果子类不是抽象类,他必须提供抽象列的
声明和方法的实现
接口:implements

构造器:
抽象类:可以有
接口:不能有构造器

访问修饰符:
抽象类:可以是任意
接口:默认是public

多继承:
一个类可以继承一个抽象类,可以继承多个接口
字段声明:
抽象类:字段声明是任意的
接口:只能是static和final

成员变量和局部变量
作用域
成:作用整个类
局:方法内部
存储位置
成:随对象的创建而创建,在堆内存中
局:方法调用创建,在栈内存中

声明周期:
成:随类的创建创建,类的消失而消失
局:方法的调用创建,方法结束释放

初始化
成,有默认初始值
局:没有默认初始值,使用前必须赋值

使用原则:
就近原则
abstract:在既需要统一的接口,又需要实例变量或缺省的方法的情况下,使用abstract;

interface:使用: 类与类之前需要特定的接口进行协调,而不在乎其如何实现。
作为能 够实现特定功能的标识存在,也可以是什么接口方法都没有的纯粹标识。需要将一组类 视为单一的类,而调用者只通过接口来与这组类发生联系。
需要实现特定的多项功能, 而这些功能之间可能完全没有任何联系。

18.构造方法有哪些特性:

名字和类相同
没有返回值,不能用void声明构造函数
生成类的对象时自动执行,无需调用

19.静态变量和实例化变量的区别

静态变量:不属于任何实例化对象
属于类,所以在内存中只有一份,在类加载中
分配一次内存空间
实例化变量:没次创建对象时创建,没次创建对象分配成员
变量内存空间,实例化变量属于实例化对象,创建几次对象就有几分成员变量

在一个静态方法内调用一个非静态成员为什么是非法的?

由于静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非静态变量,也不可以访问非静态变量成员。
重写与重载
构造器(constructor)是否可被重写(override)

构造器不能被继承,因此不能被重写,但可以被重载。

20.重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?

方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。

重载:发生在同一个类中,方法名相同参数列表不同(参数类型不同、个数不同、顺序不同),与方法返回值和访问修饰符无关,即重载的方法不能根据返回类型进行区分

重写:发生在父子类中,方法名、参数列表必须相同,返回值小于等于父类,抛出的异常小于等于父类,访问修饰符大于等于父类(里氏代换原则);如果父类方法访问修饰符为private则子类中就不是重写。

21.== 和 equals 的区别是什么

==?: 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象。(基本数据类型 == 比较的是值,引用数据类型 == 比较的是内存地址)

equals()?: 它的作用也是判断两个对象是否相等。但它一般有两种使用情况:

情况1:类没有覆盖 equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。

情况2:类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来两个对象的内容相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)。

22.值传递和引用传递有什么区别

值传递:指的是在方法调用时,传递的参数是按值的拷贝传递,传递的是值的拷贝,也就是说传递后就互不相关了。

引用传递:指的是在方法调用时,传递的参数是按引用进行传递,其实传递的引用的地址,
也就是变量所对应的内存空间的地址。传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)。
面试问题
User a= new User();
a.setName=’zhang’
b=a;
如果改变b的Name那么a里面的值改变吗?
这是一个引用类型的浅复制,所以是指向同一个地址,所以a的值也会变

23.String 类是 final 类,不可以被继承。 String str="i"与 String str=new String(“i”)一样吗?

不一样,因为内存的分配方式不一样。String str="i"的方式,java 虚拟机会将其分配到常量池中;而 String str=new String(“i”) 则会被分到堆内存中。

String s = new String(“xyz”);创建了几个字符串对象

两个对象,一个是静态区的"xyz",一个是用new创建在堆上的对象。

24.如何将字符串反转?

使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。

数组有没有 length()方法?String 有没有 length()方法

数组没有 length()方法 ,有 length 的属性。String 有 length()方法。JavaScript中,获得字符串的长度是通过 length 属性得到的,这一点容易和 Java 混淆。

25.常见的 RuntimeException 有哪些?

ClassCastException(类转换异常)
IndexOutOfBoundsException(数组越界)
NullPointerException(空指针)
ArrayStoreException(数据存储异常,操作数组时类型不一致)
还有IO操作的BufferOverflowException异常

26.如何保证同步

一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在 java里边就是拿到某个同步对象的锁(一个对象只有一把锁);
如果这个时候同步对象的锁被其他线程拿走了,他(这个线程)就只能等了(线程阻塞在锁池 等待队列中)。
取到锁后,他就开始执行同步代码(被synchronized修饰的代码);
线程执行完同步代码后马上就把锁还给同步对象,其他在锁池中 等待的某个线程就可以拿到锁执行同步代码了。
这样就保证了同步代码在统一时刻只有一个线程在执行。
同步机制实现方式包括但不限于:
①ThreadLocal ② synchronized( ) ③ wait() 与 notify() ④ volatile

27.创建对象的方法:

1.new方法
2.使用构造器,构造函数创建
3.使用反序列化
4.使用Clone的方法

28.MySQL的数据引擎

1.InnoDB存储引擎
InnoDB是事务型数据库的首选引擎,支持事务安全表(ACID),支持行锁定和外键,
2.MyISAM存储引擎

MyISAM基于ISAM存储引擎,并对其进行扩展。它是在Web、数据仓储和其他应用环境下最常使用的存储引擎之一。MyISAM拥有较高的插入、查询速度,但不支持事物。
3.MEMORY存储引擎

MEMORY存储引擎将表中的数据存储到内存中,未查询和引用其他表数据提供快速访问。

了解内容:
选择哪种数据库索引:
如果要提供提交、回滚、崩溃恢复能力的事物安全(ACID兼容)能力,并要求实现并发控制,InnoDB是一个好的选择

如果数据表主要用来插入和查询记录,则MyISAM引擎能提供较高的处理效率

如果只是临时存放数据,数据量不大,并且不需要较高的数据安全性,可以选择将数据保存在内存中的Memory引擎,MySQL中使用该引擎作为临时表,存放查询的中间结果

如果只有INSERT和SELECT操作,可以选择Archive,Archive支持高并发的插入操作,但是本身不是事务安全的。Archive非常适合存储归档数据,如记录日志信息可以使用Archive

使用哪一种引擎需要灵活选择,一个数据库中多个表可以使用不同引擎以满足各种性能

29.jdk1.8新特性

速度更快 – 红黑树
代码更少 – Lambda
强大的Stream API – Stream
便于并行 – Parallel
最大化减少空指针异常 – Optional

1:HashMap
有人会在问你HashMap的时候会问你JDK1.7和1.8有什么变化;
主要还是HashMap中链长度大于8时采取红黑树的结构存储。(1.7的时候是链表结构)
红黑树,除了添加,效率高于链表结构。

2:ConcurrentHashMap
Jdk1.7时隔壁级别CocnurrentLevel(锁分段机制)默认为16。

JDK1.8采取了CAS算法
CAS原理主要涉及的有:锁机制、CAS 操作;具体可以参考CAS原理分析

Jdk1.8没有永久区,取而代之的是MetaSpace元空间,用的是物理内存。
(当你跟面试官聊到JVM的时候可以聊到1.8后用就去是被取代了,这回事一个加分项)
3、Lambda表达式
1、Lambda表达式的基础语法:Java8引入了一个新的操作符“->”,该操作符成为箭头操作符或者Lambda操作符,箭头操作符将Lambda表达式拆分成两部分

左侧:Lambda表达式的参数列表
右侧:Lambda表达式中所需执行的功能,即Lambda体。

4、并行流
Fork/Join框架:
在必要的情况下,将一个大任务进行必要的拆分Fork成若干个小任务,再将小任务的运算结果进行Join汇总。

5、Optional类
Optional 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用null 表示一个值不存在,现在Optional 可以更好的表达这个概念。并且可以避免空指针异常。

创建线程的方法

(1)继承Thread类

(2)实现Runnable接口或者Callable接口

30.Object有哪些方法

1.clone方法

保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常。

主要是JAVA里除了8种基本类型传参数是值传递,其他的类对象传参数都是引用传递,我们有时候不希望在方法里讲参数改变,这是就需要在类中复写clone方法。

2.getClass方法

final方法,获得运行时类型。

3.toString方法

该方法用得比较多,一般子类都有覆盖。

4.finalize方法

该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用。

5.equals方法

该方法是非常重要的一个方法。一般equals和==是不一样的,但是在Object中两者是一样的。子类一般都要重写这个方法。

6.hashCode方法

该方法用于哈希查找,可以减少在查找中使用equals的次数,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。

一般必须满足obj1.equals(obj2)==true。可以推出obj1.hash- Code()==obj2.hashCode(),但是hashCode相等不一定就满足equals。不过为了提高效率,应该尽量使上面两个条件接近等价。

如果不重写hashcode(),在HashSet中添加两个equals的对象,会将两个对象都加入进去。

7.wait方法

wait方法就是使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。wait()方法一直等待,直到获得锁或者被中断。wait(long timeout)设定一个超时间隔,如果在规定时间内没有获得锁就返回。

调用该方法后当前线程进入睡眠状态,直到以下事件发生。

(1)其他线程调用了该对象的notify方法。

(2)其他线程调用了该对象的notifyAll方法。

(3)其他线程调用了interrupt中断该线程。

(4)时间间隔到了。

此时该线程就可以被调度了,如果是被中断的话就抛出一个InterruptedException异常。

8.notify方法

该方法唤醒在该对象上等待的某个线程。

9.notifyAll方法

该方法唤醒在该对象上等待的所有线程。

31.finalize()的作用

Java允许在类中定义一个名为finalize()的方法。它的工作原理是:一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用其finalize()方法。并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存。

关于垃圾回收,有三点需要记住:

1、对象可能不被垃圾回收。只要程序没有濒临存储空间用完的那一刻,对象占用的空间就总也得不到释放。

2、垃圾回收并不等于“析构”。

3、垃圾回收只与内存有关。使用垃圾回收的唯一原因是为了回收程序不再使用的内存。

finalize()的用途:
  无论对象是如何创建的,垃圾回收器都会负责释放对象占据的所有内存。这就将对finalize()的需求限制到一种特殊情况,即通过某种创建对象方式以外的方式为对象分配了存储空间。不过这种情况一般发生在使用“本地方法”的情况下,本地方法是一种在Java中调用非Java代码的方式。

32.为什么不能显示直接调用finalize方法?

如前文所述,finalize方法在垃圾回收时一定会被执行,而如果在此之前显示执行的话,也就是说finalize会被执行两次以上,而在第一次资源已经被释放,那么在第二次释放资源时系统一定会报错,因此一般finalize方法的访问权限和父类保持一致,为protected。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值