Java基础面试题总结

Java基础面试包含spring其中的某一部分

JVM
SSM
注意:其中可能有些没有答案只记录了问题,劳烦百度。

1、jdk与jre区别

2、双等于号与equals区别:
对于基本类型==直接对其值进行比较,引用数据类型的变量,内存地址值进行比较。
equals是字面值进行比较。

3、接口和抽象类的区别:
① 接口多实现、不能被实例化,可以继承多个接口,一个类只能继承一个父类,但是可以实现多个接口,间接实现了多继承

②抽象类单继承且不能被实例化也就是不能使用private,只能是protected、public,因为它需要被继承,所以不能是私有的,抽象类是对整体类的抽象,包括了属性和方法,设计方式:首先它要有子类,之后才抽出父类,是一种从下往上的构建法则,

③抽象类可以提供某些方法的部分实现,而接口不可以

4、IO流分为
输入流(字节流):按8位传输以字节为单位输出数据,继承inputStream、OutputStrearm
输出流(字符流):按16位以字符为单位输出数据,继承inputSteamReader、outputStreamWriter

输入出入流可以分为节点流和处理流,节点流有时候被称为低级流,节点流是直接和实际的数据源相互连接的,和实际输入输出点连接。处理流有时候也是高级流,是对已存在的流进行连接或者封装,区分节点流和处理流,只要看给出的参数是什么进行,如果是一个实际的数据源,就是节点流,如果是一个流,就是处理流。

如:PrintStream ps = new PrintStream(new FileOutputStream(“out.txt”));

printStream就是处理流,FileOutputStream是节点流。

Java中的低级流:InputStream、FileInputStream等,高级流DataInputStream和BufferedInputStream,一般高级流要封装低级流,一般以read方法读入。

5、 修饰符的作用范围:
private 同一个类
默认 同一个类、同一个包
protected 同一个类、同一个包、子类
public 同一个类、同一个包、子类、全局

6、 MySQL 左右连接区别:
意思不一样:左连接,只要左边表中有数据就能被检测出来,而右边有的记录必要在左边表中有的记录才能被检索出来。
右连接:只要右边表中有记录,数据技能检测出来。

用法不同:右连接与左连接相反,左连接A LEFT JOIN B,连接查询的数据,在A中必须有,在B中可以有可以没有。内连接A INNER JOIN B ,在A中也有,在B中也有的数据才能查询出来。

空值不一样:
	左连接是已左边表中的数据为基准,若左表有数据右表没有数据,则显示左表中的数据右表中的数据显示为空。

右联接是左向外联接的反向联接。将返回右表的所有行。如果右表的某行在左表中没有匹配行,则将为左表返回空值。

7、 数据库的三大范式:①列的原子性,不可再分其他几列,尽可能合并属性意思属性一致的列。
②满足条件一的情况下,表必须有主键,没有包含在主键的列必须完全依赖于主键,而不是只依赖于主键的一部分,比如这条数据的唯一性是由两个字段来决定的,这种设计容易产生冗余数据(某几个字段的数据重复),可以拆分成两张表来解决。
③满足条件二的情况下,非主键列必须直接依赖于主键,不能传递依赖,也就是不能存在,非主键A依赖于非主键B,非主键B依赖于主键的情况。

主键和唯一主键区别:主键是标识该表中每一行的列,主键对标实施完整性约束。表中只允许使用一个主键,
唯一键,标识某一列值的唯一性不可重复。

8、 Java特性:封装、继承、多态,什么叫封装、继承、多态,多态的在Java的表现形式。
多态:对象在不同情况下的不同表现,比如接口,重写是多态,重载不属于多态,多态必须具备三大特征:子类继承父类,子类覆盖父类,父类指向子类。因为重载针对的是方法,违反了面向对象的概念,所以不是多态。

9、 重载与重写的区别:
重写时子类对父类的允许访问的方法的实现过程进行重写编写,返回值和形参都不能改变,即外壳不变,核心重写
重载:在一个类里面,方法名相同,参数不同,返回的类型与修饰不同不能重载。

10、 操作字符串的类
String:每次操作都会生成新的对象,然后将指针指向新的对象
StringBuilder:可以在原来的基础上操作,线程不安全
Stringbuffer:可以在原来的基础上操作,线程安全,因为所有公开的方法都是synchronized修饰的。

11、String类的常用方法有那些?
replace():字符串替换
trim():去除字符串两端空白
split():分割字符串

12、错误与异常的区别,有哪些异常,为什么会发生这些异常?为什么会发生数组下标越界和空指针异常。
异常:语法错误和语言错误,一个程序在编译和运行时出现的错误我们统一称之为异常,不同的异常类代表不同的异常,但是所有的异常都有一个基类,叫做Exception。
错误:它指一个合理的应用程序不能截获的严重问题,错误是虚拟机的一个故障,所以错误很难处理,一般的开发人员是无法处理这些错误的。比如内存溢出和异常一样,在Java中用错误类来表示错误,不同的错误类代表了不同的错误。 但是在Java中所有的错误都有一个基类,叫做Error。

综上,我们可以知道异常和错误最本质的区别就是异常能被开发人员处理
而错误时系统本来自带的,一般无法处理也不需要我们程序员来处理。

13、空指针异常的原因:没有对new出来的对象进行实例化,空指针的异常NullPointer 无非是因为对象为null的情况下去调用该对象所拥有的方法或者成员变量造成的,解决办法判断可能为空的变量。

数组下标异常,访问了数组中不存在的角标时发生,

14、hashMap 和 hashTable有什么区别

hashMap去掉了HashTable的contains方法,加上了containsValue()和containsKey()方法,非同步,HashTable是同步的,效率比hashTable要高,允许为空键值,而hashTable不允许。

hashMap jdk 1.7之前使用的是数组+链表,它数据节点是一个Entry节点,是它的一个内部类,数据插入的过程是使用头插法(往HashMap里面put元素时,此时新增在链表上元素的位置为链表头部,也就是数组桶位上的那个位置,故名头插法),头插法危害:Hash Map的容量有限,经过多次元素插入,使得HashMap达到一定的饱和度时,key映射位置发生冲突的几率会逐步提高,这时候hashMap 需要扩展它的长度,也就是resize,影响Resize的因素有两个,capacity(容量默认16)hashMap的当前长度,LoadFactor(负载因子),默认值为0.75f,衡量HashMap是否进入Resize的条件,hashMap.size >= Capacity * LoadFactor,进入resize方法,resize方法会调用一个transfer的方法,把里面的entry进行一个rehash,可能会造成一个链表的循环,在下一次Get的时候出现死循环的情况,因为没有加锁在多个线程并发的情况下,数据不能保证安全,我push进去的值,取出来还是我push进去的值。

jdk1.8:链表+数组+红黑树,把原来的entry节点变成了Node节点,它的整个put 过程做了一个优化,使用尾插法,没有改变原来数据插入的一个顺序,所以不会出现链表循环的过程,如何让它线程安全,一般使用concurrentHashMap线程安全的集合容器。线程安全还有hashTable\加synchronized或lock、collection.synchronized,为什么选择concurrentHashMap,因为concurrentHashMap的并发度是更高的,普通的hashTable是直接对里面的方法进行了一个synchronized,就是加了一个对象锁,concurrentHashMap在jdk1.8的数据结构也变成了数组+链表+红黑树,它只会锁住我目前获取到的那个entry所在的那个节点的一个值,上锁的时候使用了CAS 加 Synchronized,在加上1.6 对synchronized,进行了一个优化锁升级的过程,效率更高,支持的并发度更高,
锁升级的过程:锁是有支持偏向锁的,我当前获取到锁资源的这个线程,我会优先让它再去获取到这个锁,如果没有获取到这个锁,就升级成一个轻量级的,一个cas 的 锁就是一个乐观锁,乐观锁是一个比较有交换的过程,如果cas没有设置成功,它会进行一个自旋,自旋到一定次数之后才会升级成一个synchronized的这么一个重量级的锁,保证了它性能的问题。

list:有序集合,元素可重复
set: 不重复集合,LinkedHashSet按照插入排序、SortedSet可排序、HashSet无序
Map:键值对集合,存储键、值和之间的映射;key无序,不可重复

增删改用HashMap,对于一个有序集合进行遍历,使用treeMap

那些集合是线程安全的,vector、hashTable,enumeration

15、 创建线程的方法
①继承Thread类,重写run方法,调用start()方法来启动垓线程
②通过Runnable接口创建线程类定义runnable接口,重写改接口的run方法并依此实例为Thread的target来创建Thread对象,该Thread对象才是正在的线程对象,调用start()方法来启动。

③通过Callable和Future创建线程创建Callable接口实现类,实现call(),call()作为线程执行体,并且有放回值,创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值,使用FutureTask对象作为Thread对象的targe创建并启动新线程,调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。

线程状态:创建、就绪、运行、阻塞、死亡

sleep()和wait()区别
sleep()方法是线程类(Thread)的静态方法,让出执行机会给其他线程,等待休眠时间结束后线程进入就绪状态和其他线程一起竞争cpu的执行时间,因为sleep()是static静态的方法,他不能改变对象的机锁,当一个synchronization块中调用了sleep()方法,线程虽然进入休眠,但是对象的机锁没有被释放,其他线程依然无法访问这个对象,造成死锁。
wait()是object类的方法,当一个线程执行到wait()时,它就进入到一个该对象相关的等待池,同时释放对象锁,使得其他线程能够访问,可以通过notify,notifyall方法来唤醒等待的线程。

run()和start()有什么区别
run()执行体,start()来启动线程,真正的实现多线程,无需等待run()方法执行完毕就可以执行下面的代码,这时此线程属于就绪状态并没有运行,通过run()方法来完成其远行状态,run()方法结束后,此线程终止,然后cpu调用其他线程,调用run方法必须等run()方法执行完毕才能执行代码,所以无法做到多线程,所以在多线程执行时要使用start()方法。

16 、内存模型:
可见性:指线程之间的可见性,一个线程修改的状态对另一个线程是可见的。
原子性:世界最小的单位,具有不可分割性。synchronized块之间的操作就具备原子性,volatile定义的变量就可以做到这一点,还有两个关键字可以实现可见性,synchronized、final
有序性:如果在本线程内观察,所有操作都是有序的,如果在一个线程中观察另外一个线程,所有的线程操作都是无序,前半句指“线程内表现为串行语义”,后半句是指“指令重排序”现象和“工作内存与主内存头部延迟”现象,Java语言提供了volatile和synchronized两个关键字来保证线程之间操作的有序性。

synchronization能够实现多线程原子性(同步)和可见性
jvm关于synchronized的两条规定:
线程解锁前,必须把共享变量的最新值刷新到主内存中
线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中从小读取最新的值(加锁与解锁需要同一把钥匙)

synchronized和volatile的区别是什么?

volatile:本质告诉JVM当前变量在寄存器(工作内存)中的值不确定,需要从主内存中读取,仅能使用变量级别、实现变量的修改可见性,不能保证原子性,不会造成线程阻塞,标记的变量不会被编译器优化

synchronized:则是锁定当前遍历,只有当前线程可以访问该变量,其他线程被阻塞住;可以使用在变量、方法、和类级别的;可以保证变量的修改可见性和原子性,可能会造成线程阻塞,标记的变量可以被编译器优化。

缺锁的理解,稍后补充。

17、什么是反射?
反射主要指程序可以访问、检测和修改它本省状态或行为的一种能力Java反射,在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法Java反射机制主要提供一下功能:在远行时判断任意一个对象所属的类,构造任意一个的对象,判断任意一个类所具有的成员变量和方法,运行时调用任意一个对象的方法。

18、session和cookie(用来跟踪用户的整个会话,常用的就是session,cookie)
由于HTTP协议时无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识别具体的用户,这个机制就是session,session时保存在服务的的,有一个唯一标识,保存session的方法有很多、内存、数据库、文件等,集群的时候也要考虑session的转移,
cookie机制:
在程序中,会话跟踪是很重要的事情。理论上,一个用户的所有请求操作都应该属于同一个会话,而另一个用户的所有请求操作则应该属于另一个会话,二者不能混淆。例如,用户A在超市购买的任何商品都应该放在A的购物车内,不论是用户A什么时间购买的,这都是属于同一个会话的,不能放入用户B或用户C的购物车内,这不属于同一个会话。

而Web应用程序是使用HTTP协议传输数据的。HTTP协议是无状态的协议。一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。这就意味着服务器无法从连接上跟踪会话。即用户A购买了一件商品放入购物车内,当再次购买商品时服务器已经无法判断该购买行为是属于用户A的会话还是用户B的会话了。要跟踪该会话,必须引入一种机制。

Cookie就是这样的一种机制。它可以弥补HTTP协议无状态的不足。在Session出现之前,基本上所有的网站都采用Cookie来跟踪会话。

什么是cookie:
	https://blog.csdn.net/fangaoxin/article/details/6952954

19、spring框架的理解和spring有那些模块。
spring是一款轻量级、低侵入性、IOC控制反转、AOP切面编程的容器框架,

20、Ioc是一种设计思想,DI依赖注入是实现IOC的一种方法,没有IOC的程序中,我们使用面向对象编程对象的创建与对象之间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象移交给第三方spring管理。依赖注入的特点,将组件关系透明化,降低耦合度。
包含的模块:
核心容器(core):提供spring框架基本功能,主要组件是BeanFactory,他是工厂模式的实现,BeanFactory使用控制反转模式将应用程序的配置和依赖性规范与实际应用程序代发分开。
spring上下文()context:spring上下文是一个配置文件,向spring框架提供上下文信息,列如:JDNI、电子邮件、国际化、校验调度功能
AOP:提供事务管理
Dao:JDBC,管理异常处理和不同数据库供应商抛出的错误信息,
ORM:spring插入了若干个ORM,从而提供ORM的对象关系工具,其中包括JDO、hibernate、Batis SQL Map,
Spring web模块:
Spring mvc:

21、spring 常用注解及应用场景
首先开启注解功能<context:component-scan base-package=“packageName”/>

bean的定义:
@Component后面三个是它的衍生注解功能一样、
@Controller注解Controler、
@Service注解Service、
@Repository注解Dao

22、bean的作用域注解
@Scope定义bean的作用域默认为singleton单例模式

bean的作用域:singleton单例模式,只有一个实例
prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例
request:每次HTTP请求,使用request定义的Bean都将产生一个新的实例,即每次HTTP请求将会产生不同的Bean实例,只有在web应用中使用spring时,才有效。
session:对于每次HTTP Session,使用session定义的Bean都将产生一个新实例。同样只有在Web应用中使用Spring时,该作用域才有效

bean生命周期注解
@PostConstruct初始化、@PreDestroy销毁

加载第三方资源
@Bean必须被spring扫描加载,否则无法生效

bean的非引用类型属性注入
@Value

bean的引用类型属性注入
@Autowired、@Qualifiler

第三方bean配置与管理
@import

bean加载控制
@DependsOn 控制bean的加载顺序,使其在指定bean加载完毕后在加载

@Order控制配置类的加载顺序

@Lazy 控制bean加载的时机,使其延迟加载

23、servlet生命周期及实现原理(JSP经过编译后本质教师servlet)
生命周期:初始化-》服务-》销毁
① 、 初始化时servlet容器装载Servlet:servlet容器启动时自动装载某些servlet,实现它只需要在web.XML 文件中的标签中加入

Init org.xl.servlet.InitServlet 1

servlet启动后,客户首次向servlet发送请求
servlet类文件被更新后,重新装载servlet,装载后,servlet容器创建一个servlet实例并且调用servlet的init方法初始化,在servlet的整个生命周期,init方法只被调用过一次。

②、服务阶段调用service()方法,他是servlet的核心,负责响应客户端的请求,每当一个客户请求一个HttpServlet对象,该对象的service()方法就要被调用,而且传递给整个方法一个请求(ServletRequest)对象和一个响应对象(ServletResponse)对象作为参数

③ 、销毁,调用destory()方法,当servlet对象退出生命周期时,负责释放占用的资源,一个servlet在运行service()方法时可能会产生其他的线程,因此需要确认在调用destory()方法时,这个线程已经终止或者完成。

24、 servlet接收和响应客户端请求的过程:
①、客户发送请求,servlet调用service()方法进行请求响应,service()方法中对请求的方式进行匹配,选择调用doGet、doPost等这些方法,然后再进入对应的方法中调用逻辑层的方法,实现对客户的响应,在servlet接口和GenericServlet中是没有doGet和doPost方法的,HttpServlet中定义了这些方法,但是都是返回error信息,所以每次定义一个servlet的时候,都必须实现doGet或者doPost这些方法。
②、每一个自定义的servlet都必须实现servlet的接口,servlet接口中定义了五个方法,其中重要的三个教师init、service、destroy方法,HttpServlet继承与GenenricServlet,因此httpServlet也实现了servlet接口,所以我们定义的时候只需要继承HttpServlet即可

③、servlet接口和GenericSerlvet是不特定与任何协议,而HttpServlet是特定于Http协议的类,所以HTTP Servlet实现了service()方法,并请求ServletRequest、ServletResponse强转为HttpRequest和HttpResponse。

总结:在web.xml文件中,某些servlet中有《servlet》元素,没有《servlet-mapping》元素,这样我们无法通过url的方式访问这些servlet,这种servlet通常会在《servlet》元素中配置一个《load-on-startup》子元素,让容器在启动的时候自动加载这些servlet并调用init()方法,完成一些全局性的初始化工作。然后调用service()方法处理业务流程,最后将结果返回给客户端,释放资源。

26、 什么是线程安全:只有存在共享数据时才需要考虑线程安全问题,

线程安全在三个方面体现:原子性,提供互斥,同一时刻只能有一个线程对数据操作
有序性,一个线程观察其他线程中的指令执行顺序,由于指令重新排序的存在,该观察结果一般无序。
可见性,一个线程对主内存的修改可以及时被其他线程观察到。

27、 接口的修饰符可以为:abstract
接口中可以定义变量常量

28、二维数组: 0 1
0 {1,2}
1 {3,4}
2 {5,6} 所以a[1][1]=4;

29、一个类的构造方法有什么用,对类对象初始化,没有声名会有默认的构造方法,特点,方法名和类名一样,没有返回值,不能用void修饰。

30、为什么要重写equals方法必须要重写hashCode方法,hashCode方法会返回一个int类型的值,也就是哈希值,用来确认对象在hash表里面的位置,因为散列表储存是键值对,根据哈希值来找到vale,如果这两个对象相同的话,他们的hashCode也是相同的。

31、mysql索引有哪些:哈希索引(数据结构是哈希表,在查询单条记录的时候使用,查询性能高),B+树索引(其他情况)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值